screeps-api
    Preparing search index...

    This example uses the WebSocket API to stream console output and the HTTP API to evaluate expressions on the console.

    All console expressions are evaluated on ScreepsClientConfig.defaultShard. If it is undefined, the script will abort with an error after any console expression is sent.

    Type exit or press Ctrl+C / Cmd+C to quit.

    import readline from 'node:readline'
    import { fileURLToPath } from 'node:url'
    import util from 'node:util'
    // If installed from npm, use:
    // import { ... } from 'screeps-api'
    import { ScreepsHttpClient, ServerAuthEvent, ServerAuthStatuses, UserConsoleEvent } from '../src'

    // Run this with DEBUG=screepsapi:socket to enable debug logging

    // Load server/app names from env vars
    const serverName = process.env.SCREEPS_SERVER ?? 'main'
    const appName = process.env.SCREEPS_APP ?? 'example'
    export const api = await ScreepsHttpClient.fromConfig(serverName, { app: appName })

    export const input = process.stdin
    export const output = process.stdout
    export const rl = readline.createInterface({
    input,
    output,
    prompt: `${api.appConfig.defaultShard ?? ''}> `
    })

    // Monkeypatch console to work with readline.Interface
    const rlLog = function (...args: unknown[]) {
    const t = Math.ceil((rl.line.length + 3) / output.columns)
    const text = util.format.apply(console, args)
    output.write('\n\x1B[' + t + 'A\x1B[0J')
    output.write(text + '\n')
    output.write(new Array(t).join('\n\x1B[E'))
    rl.prompt(true)
    }

    console.log = rlLog
    console.debug = rlLog
    console.info = rlLog
    console.warn = rlLog
    console.error = rlLog

    /**
    * Strip HTML tags from a string to make it more readable.
    * This is not suitable for sanitizing untrusted input.
    */
    export function stripTags (text: string): string {
    return text.replaceAll(/<\s*?\/?\s*?\w+?(?:[\w\s=]+?'[^>]*'?|[\w\s=]+?"[^>]*"?|[\w\s=]+?`[^>]*`?|[\w\s]+?)*>/g, '')
    }

    export function quit (message = 'Bye') {
    console.log(message)
    process.exit(0)
    }

    function run() {
    rl.on('close', () => quit('I/O closed. Bye!'))
    rl.on('SIGINT', () => quit('Keyboard interrupt. Bye!'))

    rl.on('line', (line) => {
    line = line.trim()
    if (line == 'exit') {
    quit()
    }

    api.userConsole(line).catch(console.error)
    })

    api.socket.on('connected', () => {
    console.log('Console connected')
    rl.prompt()
    })

    api.socket.on('auth', (event: ServerAuthEvent) => {
    if (event.data.status === ServerAuthStatuses.Ok) {
    api.socket.subscribe('/console')
    console.log('Console authenticated')
    } else {
    console.error(`WebSocket API authentication failed`)
    }
    })

    api.socket.subscribe('console', (event: UserConsoleEvent) => {
    const { messages, error, shard } = event.data
    const shardTag = shard ? `[${shard}] ` : ''
    if (error) console.error(shardTag, error)

    if (!messages) return
    messages.log.forEach((msg: string) => console.log(`${shardTag}${stripTags(msg)}`))
    messages.results.forEach((msg: string) => console.log('<', msg))
    })

    console.debug('Console connecting')
    api.socket.connect()
    }

    if (fileURLToPath(import.meta.url) === process.argv[1]) {
    run()
    }