@screepts/screeps-api 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["DEFAULTS"],"sources":["../src/Socket.ts","../src/RawAPI.ts","../src/ConfigManager.ts","../src/ScreepsAPI.ts"],"sourcesContent":["import { EventEmitter } from \"eventemitter3\"\nimport Debug from \"debug\"\nimport type { ScreepsAPI } from \"./ScreepsAPI\"\n\nconst debug = Debug(\"screepsapi:socket\")\n\nconst DEFAULTS = {\n reconnect: true,\n resubscribe: true,\n keepAlive: true,\n maxRetries: 10,\n maxRetryDelay: 60 * 1000, // in milli-seconds\n}\n\nexport interface Message {\n channel: string\n type: string\n id?: string\n data: any\n}\n\nexport class Socket extends EventEmitter<\n {\n connected: []\n disconnected: []\n error: [Error | (Event & { error: Error })]\n message: [Message]\n token: [token: string]\n auth: [Message & { data: { status: string; token?: string } }]\n authed: []\n subscribe: [path: string]\n unsubscribe: [path: string]\n } & { [channel: string]: [Message] }\n> {\n ws?: WebSocket\n api: ScreepsAPI\n opts: typeof DEFAULTS\n authed = false\n connected = false\n reconnecting = false\n keepAliveInter: number | NodeJS.Timeout = 0\n // pending messages (to send once authenticated)\n __queue: string[] = []\n // pending subscriptions (to request once authenticated)\n __subQueue: string[] = []\n // number of callbacks for each subscription\n __subs: Record<string, number> = {}\n\n constructor(api: ScreepsAPI) {\n super()\n this.api = api\n this.opts = Object.assign({}, DEFAULTS)\n this.on(\"error\", () => {}) // catch to prevent unhandled-exception errors\n this.reset()\n this.on(\"auth\", (ev) => {\n if (ev.data.status === \"ok\") {\n while (this.__queue.length) {\n this.ws?.send(this.__queue.shift()!)\n }\n clearInterval(this.keepAliveInter)\n if (this.opts.keepAlive) {\n this.keepAliveInter = setInterval(() => this.ws && this.ws.send(\"\"), 10000)\n }\n }\n })\n }\n\n reset() {\n this.authed = false\n this.connected = false\n this.reconnecting = false\n clearInterval(this.keepAliveInter)\n this.keepAliveInter = 0\n this.__queue = []\n this.__subQueue = []\n this.__subs = {}\n }\n\n async connect(opts = {}) {\n Object.assign(this.opts, opts)\n if (!this.api.token) {\n throw new Error(\"No token! Call api.auth() before connecting the socket!\")\n }\n return new Promise((resolve, reject) => {\n const baseURL = this.api.opts.url.replace(\"http\", \"ws\")\n const wsurl = new URL(\"socket/websocket\", baseURL)\n this.ws = new WebSocket(wsurl)\n this.ws.addEventListener(\"open\", () => {\n this.connected = true\n this.reconnecting = false\n if (this.opts.resubscribe) {\n this.__subQueue.push(...Object.keys(this.__subs))\n }\n debug(\"connected\")\n this.emit(\"connected\")\n resolve(this.auth(this.api.token!))\n })\n this.ws.onclose = () => {\n clearInterval(this.keepAliveInter)\n this.authed = false\n this.connected = false\n debug(\"disconnected\")\n this.emit(\"disconnected\")\n if (this.opts.reconnect) {\n this.reconnect().catch(() => {\n /* error emitted in reconnect() */\n })\n }\n }\n this.ws.addEventListener(\"error\", (err) => {\n this.ws?.close()\n this.emit(\"error\", err)\n debug(`error ${err.error || err}`)\n if (!this.connected) {\n reject(err)\n }\n })\n this.ws.addEventListener(\"message\", (data) => this.handleMessage(data))\n })\n }\n\n async reconnect() {\n if (this.reconnecting) {\n return\n }\n this.reconnecting = true\n let retries = 0\n let retry\n do {\n let time = Math.pow(2, retries) * 100\n if (time > this.opts.maxRetryDelay) time = this.opts.maxRetryDelay\n await this.sleep(time)\n if (!this.reconnecting) return // reset() called in-between\n try {\n await this.connect()\n retry = false\n } catch {\n retry = true\n }\n retries++\n debug(`reconnect ${retries}/${this.opts.maxRetries}`)\n } while (retry && retries < this.opts.maxRetries)\n if (retry) {\n const err = new Error(`Reconnection failed after ${this.opts.maxRetries} retries`)\n this.reconnecting = false\n debug(\"reconnect failed\")\n this.emit(\"error\", err)\n throw err\n } else {\n // Resume existing subscriptions on the new socket\n Object.keys(this.__subs).forEach((sub) => this.subscribe(sub))\n }\n }\n\n disconnect() {\n debug(\"disconnect\")\n clearInterval(this.keepAliveInter)\n if (this.ws) {\n this.ws.onclose = null // remove listeners first or we may trigger reconnection & Co.\n this.ws.close()\n }\n this.reset()\n this.emit(\"disconnected\")\n }\n\n sleep(time: number) {\n return new Promise((resolve) => setTimeout(resolve, time))\n }\n\n handleMessage(ev: MessageEvent) {\n const msg = this.api.gz(ev.data || ev) // Handle ws/browser difference\n debug(`message ${msg}`)\n if (msg[0] === \"[\") {\n const arr: [string, any] = JSON.parse(msg)\n let [, type, id, channel] = arr[0].match(/^(.+):(.+?)(?:\\/(.+))?$/) as [\n unknown,\n string,\n string,\n string?,\n ]\n channel = channel || type\n const event = { channel, id, type, data: arr[1] }\n this.emit(msg[0], event)\n this.emit(event.channel, event)\n this.emit(\"message\", event)\n } else {\n const [channel, ...data] = msg.split(\" \")\n const event: Message = { type: \"server\", channel, data }\n if (channel === \"auth\") {\n event.data = { status: data[0], token: data[1] }\n }\n if ([\"protocol\", \"time\", \"package\"].includes(channel)) {\n event.data = { [channel]: data[0] }\n }\n this.emit(channel, event)\n this.emit(\"message\", event)\n }\n }\n\n async gzip(bool: boolean) {\n await this.send(`gzip ${bool ? \"on\" : \"off\"}`)\n }\n\n async send(data: string) {\n if (!this.connected) {\n this.__queue.push(data)\n } else {\n this.ws!.send(data)\n }\n }\n\n async auth(token: string) {\n const waitAuth = new Promise<{\n data: {\n status: string\n token: string\n }\n }>((resolve) => this.once(\"auth\", resolve))\n await this.send(`auth ${token}`)\n const { data } = await waitAuth\n if (data.status !== \"ok\") throw new Error(\"socket auth failed\")\n\n this.authed = true\n this.emit(\"token\", data.token)\n this.emit(\"authed\")\n while (this.__subQueue.length) {\n await this.send(this.__subQueue.shift()!)\n }\n }\n\n async subscribe(path: string, cb?: (...args: any[]) => void) {\n if (!path) return\n const userID = await this.api.userID()\n if (!path.match(/^(\\w+):(.+?)$/)) {\n path = `user:${userID}/${path}`\n }\n if (this.authed) {\n await this.send(`subscribe ${path}`)\n } else {\n this.__subQueue.push(`subscribe ${path}`)\n }\n this.emit(\"subscribe\", path)\n this.__subs[path] = this.__subs[path] || 0\n this.__subs[path]++\n if (cb) this.on(path, cb)\n }\n\n async unsubscribe(path: string) {\n if (!path) return\n const userID = await this.api.userID()\n if (!path.match(/^(\\w+):(.+?)$/)) {\n path = `user:${userID}/${path}`\n }\n await this.send(`unsubscribe ${path}`)\n this.emit(\"unsubscribe\", path)\n if (this.__subs[path]) this.__subs[path]--\n }\n}\n","import { EventEmitter } from \"eventemitter3\"\nimport { inflate } from \"pako\"\nimport Debug from \"debug\"\nimport type { HeaderRecord } from \"undici-types/header\"\n\nconst debugHttp = Debug(\"screepsapi:http\")\nconst debugRateLimit = Debug(\"screepsapi:ratelimit\")\n\nconst DEFAULT_SHARD = \"shard0\"\nconst OFFICIAL_HISTORY_INTERVAL = 100\nconst PRIVATE_HISTORY_INTERVAL = 20\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))\n\nconst mapToShard = <T>(res: T & { list?: any; rooms?: any; shards?: any }) => {\n if (!res.shards) {\n res.shards = {\n privSrv: res.list || res.rooms,\n }\n }\n return res\n}\n\ninterface RawOpts extends URL {\n url: string | URL\n path: string\n token: string\n}\nexport class RawAPI extends EventEmitter<{\n token: [token: string]\n auth: []\n rateLimit: [ReturnType<typeof RawAPI.prototype.buildRateLimit>]\n response: [Response]\n}> {\n opts: {\n url: string\n host?: string\n port?: string\n pathname?: string\n email?: string\n password?: string\n experimentalRetry429?: boolean\n } & AdditonalKeys\n token?: string\n private __authed = false\n\n constructor(opts: Partial<RawOpts> = {}) {\n super()\n this.opts = {} as any\n this.setServer(opts)\n }\n\n readonly raw = {\n token: undefined as string | undefined,\n /**\n * GET /api/version\n */\n version: (): Res<\n {\n package: number\n protocol: number\n serverData: AtLeast<{\n customObjectTypes: object\n historyChunkSize: number\n features: AtLeast<{ name: string; version: number }>[]\n shards: string[]\n }>\n users: number\n } & Partial<{\n currentSeason: string | undefined\n seasonAccessCost: string | undefined\n decorationConvertationCost: number | undefined\n decorationPixelizationCost: number | undefined\n }>\n > => this.req(\"GET\", \"/api/version\"),\n /**\n * GET /api/authmod\n */\n authmod: (): Res<{ name: string; version?: any }> => {\n if (this.isOfficialServer()) {\n return Promise.resolve({ ok: 1, name: \"official\" })\n }\n return this.req(\"GET\", \"/api/authmod\")\n },\n /**\n * Official:\n * GET /room-history/${shard}/${room}/${tick}.json\n * Private:\n * GET /room-history\n */\n history: (\n room: string,\n tick: number,\n shard = DEFAULT_SHARD,\n ): Promise<{\n /** milliseconds since the Unix epoch */\n timestamp: number\n room: string\n base: number\n ticks: { [time: string]: AdditonalKeys }\n }> => {\n if (this.isOfficialServer()) {\n tick -= tick % OFFICIAL_HISTORY_INTERVAL\n return this.req(\"GET\", `/room-history/${shard}/${room}/${tick}.json`)\n } else {\n tick -= tick % PRIVATE_HISTORY_INTERVAL\n return this.req(\"GET\", \"/room-history\", { room, time: tick })\n }\n },\n servers: {\n /**\n * POST /api/servers/list\n * A list of community servers\n */\n list: (): Res<{\n servers: {\n _id: string\n settings: {\n host: string\n port: string\n pass: string\n }\n name: string\n status: string\n likeCount: number\n }[]\n }> => this.req(\"POST\", \"/api/servers/list\", {}),\n },\n auth: {\n /**\n * POST /api/auth/signin\n */\n signin: (email: string, password: string): Res<{ token: string }> =>\n this.req(\"POST\", \"/api/auth/signin\", { email, password }),\n /**\n * POST /api/auth/steam-ticket\n */\n steamTicket: (ticket: any, useNativeAuth = false): UndocumentedRes =>\n this.req(\"POST\", \"/api/auth/steam-ticket\", { ticket, useNativeAuth }),\n /**\n * GET /api/auth/me\n */\n me: (): Res<Me> => this.req(\"GET\", \"/api/auth/me\"),\n /**\n * GET /api/auth/query-token\n */\n queryToken: (token: string): UndocumentedRes =>\n this.req(\"GET\", \"/api/auth/query-token\", { token }),\n },\n register: {\n /**\n * GET /api/register/check-email\n */\n checkEmail: (email: string): UndocumentedRes =>\n this.req(\"GET\", \"/api/register/check-email\", { email }),\n /**\n * GET /api/register/check-username\n */\n checkUsername: (username: string): UndocumentedRes =>\n this.req(\"GET\", \"/api/register/check-username\", { username }),\n /**\n * POST /api/register/set-username\n */\n setUsername: (username: string): UndocumentedRes =>\n this.req(\"POST\", \"/api/register/set-username\", { username }),\n /**\n * POST /api/register/submit\n */\n submit: (username: string, email: string, password: string, modules: any): UndocumentedRes =>\n this.req(\"POST\", \"/api/register/submit\", { username, email, password, modules }),\n },\n userMessages: {\n /**\n * GET /api/user/messages/list?respondent={userId}\n * @param respondent the long `_id` of the user, not the username\n */\n list: (\n respondent: string,\n ): Res<{\n messages: { _id: string; date: string; type: string; text: string; unread: boolean }[]\n }> => this.req(\"GET\", \"/api/user/messages/list\", { respondent }),\n /**\n * GET /api/user/messages/index\n */\n index: (): Res<{\n messages: {\n _id: string\n message: {\n _id: string\n user: string\n respondent: string\n date: string\n type: string\n text: string\n unread: boolean\n }\n }[]\n users: { [userId: string]: { _id: string; username: string; badge: Badge } }\n }> => this.req(\"GET\", \"/api/user/messages/index\"),\n /**\n * GET /api/user/messages/unread-count\n */\n unreadCount: (): Res<{ count: number }> => this.req(\"GET\", \"/api/user/messages/unread-count\"),\n /**\n * POST /api/user/messages/send\n * @param respondent the long `_id` of the user, not the username\n */\n send: (respondent: string, text: string): Res<{}> =>\n this.req(\"POST\", \"/api/user/messages/send\", { respondent, text }),\n /**\n * POST /api/user/messages/mark-read\n */\n markRead: (id: string): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/messages/mark-read\", { id }),\n },\n game: {\n /**\n * @param rooms An array of room names\n * The return type is not mapped correctly\n */\n mapStats: (\n rooms: string[],\n statName: \"owner0\" | \"claim0\" | StatKey,\n shard = DEFAULT_SHARD,\n ): Res<{\n stats: {\n [roomName: string]: {\n status: string\n novice: string\n own: { user: string; level: number }\n } & { [key in StatKey]: { user: string; value: number }[] }\n }\n users: { [userId: string]: { _id: string; username: string; badge: Badge } }\n }> => this.req(\"POST\", \"/api/game/map-stats\", { rooms, statName, shard }),\n /**\n * POST /api/game/gen-unique-object-name\n */\n genUniqueObjectName: (type: \"flag\" | \"spawn\", shard = DEFAULT_SHARD): Res<{ name: string }> =>\n this.req(\"POST\", \"/api/game/gen-unique-object-name\", { type, shard }),\n /**\n * POST /api/game/check-unique-object-name\n */\n checkUniqueObjectName: (type: string, name: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"POST\", \"/api/game/check-unique-object-name\", { type, name, shard }),\n /**\n * POST /api/game/place-spawn\n */\n placeSpawn: (\n room: string,\n x: number,\n y: number,\n name: string,\n shard = DEFAULT_SHARD,\n ): UndocumentedRes => this.req(\"POST\", \"/api/game/place-spawn\", { name, room, x, y, shard }),\n /**\n * POST /api/game/create-flag\n * - if the name is new, result.upserted[0]._id is the game id of the created flag\n * - if not, this moves the flag and the response does not contain the id (but the id doesn't change)\n * - `connection` looks like some internal MongoDB thing that is irrelevant to us\n */\n createFlag: (\n room: string,\n x: number,\n y: number,\n name: string,\n color: FlagColor = 1,\n secondaryColor: FlagColor = 1,\n shard = DEFAULT_SHARD,\n ): DbResponse =>\n this.req(\"POST\", \"/api/game/create-flag\", {\n name,\n room,\n x,\n y,\n color,\n secondaryColor,\n shard,\n }),\n /**\n * POST/api/game/gen-unique-flag-name\n */\n genUniqueFlagName: (shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"POST\", \"/api/game/gen-unique-flag-name\", { shard }),\n /**\n * POST /api/game/check-unique-flag-name\n */\n checkUniqueFlagName: (name: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"POST\", \"/api/game/check-unique-flag-name\", { name, shard }),\n /**\n * POST /api/game/change-flag-color\n */\n changeFlagColor: (\n color: FlagColor = 1,\n secondaryColor: FlagColor = 1,\n shard = DEFAULT_SHARD,\n ): DbResponse =>\n this.req(\"POST\", \"/api/game/change-flag-color\", { color, secondaryColor, shard }),\n /**\n * POST /api/game/remove-flag\n */\n removeFlag: (room: string, name: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"POST\", \"/api/game/remove-flag\", { name, room, shard }),\n /**\n * POST /api/game/add-object-intent\n * [Missing parameter] _id is the game id of the object to affect (except for destroying structures), room is the name of the room it's in\n * this method is used for a variety of actions, depending on the `name` and `intent` parameters\n * @example remove flag: name = \"remove\", intent = {}\n * @example destroy structure: _id = \"room\", name = \"destroyStructure\", intent = [ {id: <structure id>, roomName, <room name>, user: <user id>} ]\n can destroy multiple structures at once\n * @example suicide creep: name = \"suicide\", intent = {id: <creep id>}\n * @example unclaim controller: name = \"unclaim\", intent = {id: <controller id>}\n intent can be an empty object for suicide and unclaim, but the web interface sends the id in it, as described\n * @example remove construction site: name = \"remove\", intent = {}\n */\n addObjectIntent: (\n room: string,\n name: string,\n intent: string,\n shard = DEFAULT_SHARD,\n ): DbResponse =>\n this.req(\"POST\", \"/api/game/add-object-intent\", { room, name, intent, shard }),\n /**\n * POST /api/game/create-construction\n * @returns {{ ok, result: { ok, n }, ops: [ { type, room, x, y, structureType, user, progress, progressTotal, _id } ], insertedCount, insertedIds }}\n */\n createConstruction: (\n room: string,\n x: number,\n y: number,\n structureType: string,\n name: string,\n shard = DEFAULT_SHARD,\n ): DbInsertResponse<{\n ops: {\n type: string\n room: string\n x: number\n y: number\n structureType: string\n user: string\n progress: number\n progressTotal: number\n _id: string\n }[]\n }> =>\n this.req(\"POST\", \"/api/game/create-construction\", {\n room,\n x,\n y,\n structureType,\n name,\n shard,\n }),\n /**\n * POST /api/game/set-notify-when-attacked\n */\n setNotifyWhenAttacked: (_id: string, enabled = true, shard = DEFAULT_SHARD): DbResponse =>\n this.req(\"POST\", \"/api/game/set-notify-when-attacked\", { _id, enabled, shard }),\n /**\n * POST /api/game/create-invader\n */\n createInvader: (\n room: string,\n x: number,\n y: number,\n size: any,\n type: any,\n boosted = false,\n shard = DEFAULT_SHARD,\n ): UndocumentedRes =>\n this.req(\"POST\", \"/api/game/create-invader\", {\n room,\n x,\n y,\n size,\n type,\n boosted,\n shard,\n }),\n /**\n * POST /api/game/remove-invader\n */\n removeInvader: (_id: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"POST\", \"/api/game/remove-invader\", { _id, shard }),\n /**\n * GET /api/game/time\n */\n time: (shard = DEFAULT_SHARD): Res<{ time: number }> =>\n this.req(\"GET\", \"/api/game/time\", { shard }),\n /**\n * GET /api/game/world-size\n */\n worldSize: (shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"GET\", \"/api/game/world-size\", { shard }),\n /**\n * GET /api/game/room-decorations\n */\n roomDecorations: (room: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"GET\", \"/api/game/room-decorations\", { room, shard }),\n /**\n * GET /api/game/room-objects\n */\n roomObjects: (room: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"GET\", \"/api/game/room-objects\", { room, shard }),\n /**\n * GET /api/game/room-terrain\n * terrain is a string of digits, giving the terrain left-to-right and top-to-bottom\n * 0: plain, 1: wall, 2: swamp, 3: also wall\n */\n roomTerrain: (\n room: string,\n encoded = 1,\n shard = DEFAULT_SHARD,\n ):\n | Res<{\n terrain: { room: string; x: number; y: number; type: \"wall\" | \"swamp\" }[]\n }>\n | Res<{\n terrain: { _id: string; room: string; terrain: string; type: \"wall\" | \"swamp\" }[]\n }> => this.req(\"GET\", \"/api/game/room-terrain\", { room, encoded, shard }),\n /**\n * GET /api/game/room-status\n * if the room is in a novice area, novice will contain the Unix timestamp of the end of the protection (otherwise it is absent)\n */\n roomStatus: (\n room: string,\n shard = DEFAULT_SHARD,\n ): Promise<{\n _id: string\n status: \"normal\" | \"out of borders\"\n novice?: string\n }> => this.req(\"GET\", \"/api/game/room-status\", { room, shard }),\n /**\n * GET /api/game/room-overview\n */\n roomOverview: (room: string, interval = 8, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"GET\", \"/api/game/room-overview\", { room, interval, shard }),\n\n market: {\n /**\n * GET /api/game/market/orders-index\n * - _id is the resource type, and there will only be one of each type.\n * - `count` is the number of orders.\n */\n ordersIndex: (\n shard = DEFAULT_SHARD,\n ): Res<{\n list: { _id: string; count: number }[]\n }> => this.req(\"GET\", \"/api/game/market/orders-index\", { shard }),\n /**\n * GET /api/game/market/my-orders\n * `resourceType` is one of the RESOURCE_* constants.\n */\n myOrders: (): Res<{\n list: MarketOrder[]\n }> => this.req(\"GET\", \"/api/game/market/my-orders\").then(mapToShard),\n /**\n * GET /api/game/market/orders\n * @param resourceType one of the RESOURCE_* constants.\n * `resourceType` is one of the RESOURCE_* constants.\n */\n orders: (\n resourceType: string,\n shard = DEFAULT_SHARD,\n ): Res<{\n list: MarketOrder[]\n }> => this.req(\"GET\", \"/api/game/market/orders\", { resourceType, shard }),\n /**\n * GET /api/game/market/stats\n */\n stats: (resourceType: string, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"GET\", \"/api/game/market/stats\", { resourceType, shard }),\n },\n shards: {\n /**\n * GET /api/game/shards/info\n */\n info: (): Res<{\n shards: {\n name: string\n lastTicks: number[]\n cpuLimit: number\n rooms: number\n users: number\n tick: number\n }[]\n }> => this.req(\"GET\", \"/api/game/shards/info\"),\n },\n },\n leaderboard: {\n /**\n * GET /api/leaderboard/list\n */\n list: (\n limit = 10,\n mode: \"world\" | \"power\" = \"world\",\n offset = 0,\n season?: string,\n ): Res<{\n list: { _id: string; season: string; user: string; score: number; rank: number }[]\n count: number\n users: { [userId: string]: User }\n }> => {\n if (mode !== \"world\" && mode !== \"power\") throw new Error(\"incorrect mode parameter\")\n if (!season) season = this.currentSeason()\n return this.req(\"GET\", \"/api/leaderboard/list\", { limit, mode, offset, season })\n },\n /**\n * GET /api/leaderboard/find\n * @param season An optional date in the format YYYY-MM, if not supplied all ranks in all seasons is returned.\n * - `user` (not `_id`) is the user's _id, as returned by `me` and `user/find`\n * - `rank` is 0-based\n */\n find: (\n username: string,\n mode: string = \"world\",\n season: string = \"\",\n ): Res<{\n _id: string\n season: string\n user: string\n score: number\n rank: number\n }> => this.req(\"GET\", \"/api/leaderboard/find\", { season, mode, username }),\n /**\n * GET /api/leaderboard/seasons\n * The _id returned here is used for the season name in the other leaderboard calls\n */\n seasons: (): Res<{\n seasons: { _id: string; name: string; date: string }[]\n }> => this.req(\"GET\", \"/api/leaderboard/seasons\"),\n },\n user: {\n /**\n * POST /api/user/badge\n */\n badge: (\n badge: Badge,\n ): Promise<{\n ok?: number\n error?: string\n }> => this.req(\"POST\", \"/api/user/badge\", { badge }),\n /**\n * POST /api/user/respawn\n */\n respawn: (): UndocumentedRes => this.req(\"POST\", \"/api/user/respawn\"),\n /**\n * POST /api/user/set-active-branch\n */\n setActiveBranch: (branch: string, activeName: string): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/set-active-branch\", { branch, activeName }),\n /**\n * POST /api/user/clone-branch\n */\n cloneBranch: (branch = \"\", newName: string, defaultModules: CodeList): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/clone-branch\", { branch, newName, defaultModules }),\n /**\n * POST /api/user/delete-branch\n */\n deleteBranch: (branch: string): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/delete-branch\", { branch }),\n /**\n * POST /api/user/notify-prefs\n */\n notifyPrefs: (prefs: any): UndocumentedRes =>\n // disabled,disabledOnMessages,sendOnline,interval,errorsInterval\n this.req(\"POST\", \"/api/user/notify-prefs\", prefs),\n /**\n * POST /api/user/tutorial-done\n */\n tutorialDone: (): UndocumentedRes => this.req(\"POST\", \"/api/user/tutorial-done\"),\n /**\n * POST /api/user/email\n */\n email: (email: string): UndocumentedRes => this.req(\"POST\", \"/api/user/email\", { email }),\n /**\n * GET /api/user/world-start-room\n */\n worldStartRoom: (shard: string): UndocumentedRes =>\n this.req(\"GET\", \"/api/user/world-start-room\", { shard }),\n /**\n * GET /api/user/world-status\n * returns a world status\n * - 'normal'\n * - 'lost' when you loose all your spawns\n * - 'empty' when you have respawned and not placed your spawn yet\n */\n worldStatus: (): Res<{\n status: \"normal\" | \"lost\" | \"empty\"\n }> => this.req(\"GET\", \"/api/user/world-status\"),\n /**\n * GET /api/user/branches\n */\n branches: (): Res<{\n list: {\n _id: string\n branch: string\n activeWorld: boolean\n activeSim: boolean\n }[]\n }> => this.req(\"GET\", \"/api/user/branches\"),\n code: {\n /**\n * GET /api/user/code\n * for pushing or pulling code, as documented at http://support.screeps.com/hc/en-us/articles/203022612\n * @returns code\n */\n get: (branch: string): Res<{ modules: CodeList }> =>\n this.req(\"GET\", \"/api/user/code\", { branch }),\n /**\n * POST /api/user/code\n * for pushing or pulling code, as documented at http://support.screeps.com/hc/en-us/articles/203022612\n */\n set: (branch: string, modules: CodeList, _hash?: any): UndocumentedRes => {\n if (!_hash) _hash = Date.now()\n return this.req(\"POST\", \"/api/user/code\", { branch, modules, _hash })\n },\n },\n decorations: {\n /**\n * GET /api/user/decorations/inventory\n */\n inventory: (): UndocumentedRes => this.req(\"GET\", \"/api/user/decorations/inventory\"),\n /**\n * GET /api/user/decorations/themes\n */\n themes: (): UndocumentedRes => this.req(\"GET\", \"/api/user/decorations/themes\"),\n /**\n * POST /api/user/decorations/convert\n */\n convert: (decorations: number[]): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/decorations/convert\", { decorations }),\n /**\n * POST /api/user/decorations/pixelize\n */\n pixelize: (count: number, theme = \"\"): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/decorations/pixelize\", { count, theme }),\n /**\n * POST /api/user/decorations/activate\n */\n activate: (_id: string, active: any): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/decorations/activate\", { _id, active }),\n /**\n * POST /api/user/decorations/deactivate\n */\n deactivate: (decorations: string[]): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/decorations/deactivate\", { decorations }),\n },\n /**\n * GET /api/user/respawn-prohibited-rooms\n * - `rooms` is an array, but seems to always contain only one element\n */\n respawnProhibitedRooms: (): Res<{ rooms: string[] }> =>\n this.req(\"GET\", \"/api/user/respawn-prohibited-rooms\"),\n\n memory: {\n /**\n * GET /api/user/memory?path={path}\n * @param path the path may be empty or absent to retrieve all of Memory, Example: flags.Flag1\n * @returns gz: followed by base64-encoded gzipped JSON encoding of the requested memory path\n */\n get: (path = \"\", shard = DEFAULT_SHARD): Res<{ data: string }> =>\n this.req(\"GET\", \"/api/user/memory\", { path, shard }),\n /**\n * POST /api/user/memory\n * @param path the path may be empty or absent to retrieve all of Memory, Example: flags.Flag1\n */\n set: (\n path: string,\n value: any,\n shard = DEFAULT_SHARD,\n ): DbInsertResponse<{\n ops: { user: string; expression: string; hidden: boolean }[]\n data: any\n }> => this.req(\"POST\", \"/api/user/memory\", { path, value, shard }),\n\n segment: {\n /**\n * GET /api/user/memory-segment?segment=[0-99]\n * @param segment A number from 0-99\n */\n get: (segment: number, shard = DEFAULT_SHARD): Res<{ data: string }> =>\n this.req(\"GET\", \"/api/user/memory-segment\", { segment, shard }),\n /**\n * POST /api/user/memory-segment\n * @param segment A number from 0-99\n */\n set: (segment: number, data: any, shard = DEFAULT_SHARD): UndocumentedRes =>\n this.req(\"POST\", \"/api/user/memory-segment\", { segment, data, shard }),\n },\n },\n /**\n * GET /api/user/find?username={username}\n */\n find: (username: string): Res<{ user: User }> =>\n this.req(\"GET\", \"/api/user/find\", { username }),\n /**\n * GET /api/user/find?id={userId}\n */\n findById: (id: string): Res<{ user: User }> => this.req(\"GET\", \"/api/user/find\", { id }),\n /**\n * GET /api/user/stats\n */\n stats: (interval: number): UndocumentedRes =>\n this.req(\"GET\", \"/api/user/stats\", { interval }),\n /**\n * GET /api/user/rooms\n */\n rooms: (id: string): UndocumentedRes =>\n this.req(\"GET\", \"/api/user/rooms\", { id }).then(mapToShard),\n /**\n * GET /api/user/overview?interval={interval}&statName={statName}\n * @param statName energyControl\n */\n overview: (interval: number, statName: string): UndocumentedRes =>\n this.req(\"GET\", \"/api/user/overview\", { interval, statName }),\n /**\n * GET /api/user/money-history\n */\n moneyHistory: (\n page = 0,\n ): Res<{\n page: number\n hasMore: boolean\n list: {\n _id: string\n date: string\n tick: number\n user: string\n type: string\n balance: number\n change: number\n market:\n | {\n order: {\n type: string\n resourceType: string\n price: number\n totalAmount: number\n roomName: string\n }\n }\n | { extendOrder: { orderId: string; addAmount: number } }\n | {\n resourceType: string\n roomName: string\n targetRoomName: string\n price: number\n npc: boolean\n amount: number\n }\n | { changeOrderPrice: { orderId: string; oldPrice: number; newPrice: number } }\n }[]\n }> => this.req(\"GET\", \"/api/user/money-history\", { page }),\n /**\n * POST /api/user/console\n */\n console: (\n expression: any,\n shard = DEFAULT_SHARD,\n ): DbInsertResponse<{\n ops: { user: string; expression: any; _id: string }[]\n }> => this.req(\"POST\", \"/api/user/console\", { expression, shard }),\n /**\n * GET /api/user/name\n */\n name: (): UndocumentedRes => this.req(\"GET\", \"/api/user/name\"),\n },\n experimental: {\n // https://screeps.com/api/experimental/pvp?start=14787157 seems to not be implemented in the api\n /**\n * time is the current server tick\n * _id contains the room name for each room, and lastPvpTime contains the last tick pvp occurred\n * if neither a valid interval nor a valid start argument is provided, the result of the call is still ok, but with an empty rooms array.\n */\n pvp: (\n interval = 100,\n ): Res<{\n time: number\n rooms: { _id: string; lastPvpTime: number }[]\n }> => this.req(\"GET\", \"/api/experimental/pvp\", { interval }).then(mapToShard),\n /**\n * GET /api/experimental/nukes\n */\n nukes: (): Res<{\n nukes: {\n [shard: string]: {\n _id: string\n type: \"nuke\"\n room: string\n x: number\n y: number\n landTime: number\n launchRoomName: string\n }\n }\n }> => this.req(\"GET\", \"/api/experimental/nukes\").then(mapToShard),\n },\n warpath: {\n /**\n * GET /api/warpath/battles\n */\n battles: (interval = 100): UndocumentedRes =>\n this.req(\"GET\", \"/api/warpath/battles\", { interval }),\n },\n scoreboard: {\n /**\n * GET /api/scoreboard/list\n */\n list: (limit = 20, offset = 0): UndocumentedRes =>\n this.req(\"GET\", \"/api/scoreboard/list\", { limit, offset }),\n },\n }\n\n currentSeason() {\n const now = new Date()\n const year = now.getFullYear()\n let month = (now.getUTCMonth() + 1).toString()\n if (month.length === 1) month = `0${month}`\n return `${year}-${month}`\n }\n\n isOfficialServer() {\n return this.opts.url.match(/screeps\\.com/) !== null\n }\n\n mapToShard = mapToShard\n\n setServer(opts: Partial<RawOpts>) {\n if (!this.opts) {\n this.opts = {} as any\n }\n Object.assign(this.opts, opts)\n if (opts.path && !opts.pathname) {\n this.opts.pathname = opts.path\n }\n if (opts.port) {\n this.opts.port = String(opts.port)\n if (opts.hostname) {\n this.opts.host = `${opts.hostname}:${opts.port}`\n }\n }\n if (!opts.url) {\n this.opts.url = urlFormat(this.opts)\n if (!this.opts.url.endsWith(\"/\")) this.opts.url += \"/\"\n }\n if (opts.token) {\n this.token = opts.token\n }\n }\n\n async auth(email: string, password: string, opts: Partial<RawOpts> = {}) {\n this.setServer(opts)\n if (email && password) {\n Object.assign(this.opts, { email, password })\n }\n const res = await this.raw.auth.signin(this.opts.email!, this.opts.password!)\n this.emit(\"token\", res.token)\n this.emit(\"auth\")\n this.__authed = true\n return res\n }\n\n async req(method: string, path: string, body: any = {}): UndocumentedRes {\n let url = new URL(path, this.opts.url)\n const opts: RequestInit & { headers: HeaderRecord } = {\n method,\n headers: {},\n }\n if (debugHttp.enabled) {\n debugHttp(`${method} ${path}`)\n }\n if (this.token) {\n Object.assign(opts.headers, {\n \"X-Token\": this.token,\n \"X-Username\": this.token,\n })\n }\n if (method === \"GET\") {\n Object.entries(body).forEach(([key, value]) => {\n if (value !== undefined) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n url.searchParams.append(key, String(value))\n }\n })\n } else {\n opts.body = body\n if (typeof body === \"object\") {\n opts.body = JSON.stringify(body)\n opts.headers[\"Content-Type\"] = \"application/json\"\n }\n }\n\n const res: Response & { data?: any } = await fetch(url, opts)\n\n const token = res.headers.get(\"x-token\")\n if (token) {\n this.emit(\"token\", token)\n }\n\n const rateLimit = this.buildRateLimit(method, path, res)\n this.emit(\"rateLimit\", rateLimit)\n debugRateLimit(\n `${method} ${path} ${rateLimit.remaining}/${rateLimit.limit} ${rateLimit.toReset}s`,\n )\n\n if (res.headers.get(\"content-type\")?.includes(\"application/json\")) {\n res.data = await res.json()\n } else {\n res.data = await res.text()\n }\n\n if (!res.ok) {\n if (res.status === 401) {\n if (this.__authed && this.opts.email && this.opts.password) {\n this.__authed = false\n await this.auth(this.opts.email, this.opts.password)\n return this.req(method, path, body)\n } else {\n throw new Error(\"Not Authorized\")\n }\n } else if (\n res.status === 429 &&\n !res.headers.get(\"x-ratelimit-limit\") &&\n this.opts.experimentalRetry429\n ) {\n await sleep(Math.floor(Math.random() * 500) + 200)\n return this.req(method, path, body)\n }\n throw new Error(res.data)\n }\n\n this.emit(\"response\", res)\n return res.data!\n }\n\n gz(data: string) {\n if (!data.startsWith(\"gz:\")) return data\n const buf = Buffer.from(data.slice(3), \"base64\")\n return inflate(buf, { to: \"string\" })\n }\n\n inflate(data: string) {\n return JSON.parse(this.gz(data))\n }\n\n buildRateLimit(method: string, path: string, res: Response) {\n const limit = Number(res.headers.get(\"x-ratelimit-limit\"))\n const remaining = Number(res.headers.get(\"x-ratelimit-remaining\"))\n const reset = Number(res.headers.get(\"x-ratelimit-reset\"))\n return {\n method,\n path,\n limit,\n remaining,\n reset,\n toReset: reset - Math.floor(Date.now() / 1000),\n }\n }\n}\n\n/** Based on Node.js built-in URL format */\nfunction urlFormat(obj: Partial<URL>) {\n let protocol = obj.protocol || \"\"\n if (protocol && !protocol.endsWith(\":\")) {\n protocol += \":\"\n }\n\n let pathname = obj.pathname || \"\"\n let host = \"\"\n\n if (obj.host) {\n host = obj.host\n } else if (obj.hostname) {\n host =\n obj.hostname.includes(\":\") &&\n (obj.hostname[0] !== \"[\" || obj.hostname[obj.hostname.length - 1] !== \"]\")\n ? \"[\" + obj.hostname + \"]\"\n : obj.hostname\n if (obj.port) {\n host += \":\" + obj.port\n }\n }\n\n if (pathname.includes(\"#\") || pathname.includes(\"?\")) {\n let newPathname = \"\"\n let lastPos = 0\n const len = pathname.length\n for (let i = 0; i < len; i++) {\n const code = pathname.charAt(i)\n if (code === \"#\" || code === \"?\") {\n if (i > lastPos) {\n newPathname += pathname.slice(lastPos, i)\n }\n newPathname += code === \"#\" ? \"%23\" : \"%3F\"\n lastPos = i + 1\n }\n }\n if (lastPos < len) {\n newPathname += pathname.slice(lastPos)\n }\n pathname = newPathname\n }\n\n if (host) {\n if (pathname && pathname[0] !== \"/\") pathname = \"/\" + pathname\n host = \"//\" + host\n }\n\n return protocol + host + pathname\n}\n\ntype Res<T extends object> = Promise<T & { ok: number }>\nexport type UndocumentedRes = Promise<any>\n\ntype AdditonalKeys<T = any> = Partial<Record<string, T>>\ntype AtLeast<T extends object> = T & AdditonalKeys\n\ntype DbResponse = Res<{\n result: {\n nModified: number\n ok: number\n upserted?: { index: number; _id: string }[]\n n: number\n }\n connection: { host: string; id: string; port: number }\n}>\ntype DbInsertResponse<T> = Res<\n {\n result: { ok: number; n: number }\n insertedCount: number\n insertedIds: string[]\n } & T\n>\n\nexport interface Badge {\n color1: string\n color2: string\n color3: string\n flip: boolean\n param: number\n type: number | { path1: string; path2: string }\n}\n\n/**\n * - Red = 1,\n * - Purple = 2,\n * - Blue = 3,\n * - Cyan = 4,\n * - Green = 5,\n * - Yellow = 6,\n * - Orange = 7,\n * - Brown = 8,\n * - Grey = 9,\n * - White = 10\n */\ntype FlagColor = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10\n\ntype StatKey =\n | \"creepsLost\"\n | \"creepsProduced\"\n | \"energyConstruction\"\n | \"energyControl\"\n | \"energyCreeps\"\n | \"energyHarvested\"\n\nexport interface MarketOrder {\n _id: string\n created: string\n user: string\n active: boolean\n type: \"buy\" | \"sell\"\n amount: number\n remainingAmount: number\n resourceType: string\n price: number\n totalAmount: number\n roomName: string\n}\n\nexport interface Me extends User {\n email: string\n cpu: number\n password: string\n notifyPrefs: {\n sendOnline: any\n errorsInterval: any\n disabledOnMessages: any\n disabled: any\n interval: any\n }\n credits: number\n lastChargeTime: any\n lastTweetTime: any\n github: { id: any; username: any }\n twitter: { username: string; followers_count: number }\n}\n\nexport interface User {\n _id: string\n username: string\n badge: Badge\n gcl: number\n}\n\ninterface BinaryModule {\n /** base64 encoded binary data */\n binary: string\n}\nexport interface CodeList {\n [fileName: string]: string | BinaryModule\n}\n","import yaml from \"js-yaml\"\n\n/**\n * Unified Credentials File v1.0.\n * A standardized format for storing credentials and configuration for Screeps World related tools.\n * @link https://github.com/screepers/screepers-standards/blob/master/SS3-Unified_Credentials_File.md\n */\nexport interface UnifiedConfig {\n servers: Partial<Record<string, ServerConfig>>\n configs?: Partial<Record<string, any>>\n [metadata: string]: any\n}\ninterface ServerConfig {\n host: string\n /** override standard TCP port */\n port?: number\n /** use SSL */\n secure?: boolean\n /** authorization token */\n token?: string\n /** is only supported on private servers */\n username?: string\n /** is only supported on private servers */\n password?: string\n /** additional metadata like ptr flag */\n [metadata: string]: any\n}\n\n/**\n * Utility class for loading Unified Credentials Files from disk, environment variables, or other sources.\n * Only platforms without filesystem access, {@link ConfigManager.setConfig}, must be used to provide the config data directly.\n */\nexport class ConfigManager {\n path?: string\n private _config: UnifiedConfig | null = null\n\n /** Custom environment variables, useful for platforms without process.env */\n env: Record<string, string | undefined> = globalThis.process?.env || {}\n /** Custom file reading function, useful for platforms with a virtual filesystem */\n readFile?: (path: string, options: { encoding: \"utf8\" }) => Promise<string>\n\n setConfig(data: unknown, path?: string) {\n if (!data || typeof data !== \"object\" || !(\"servers\" in data)) {\n throw new Error(`Invalid config: 'servers' object does not exist in '${path}'`)\n }\n this._config = data as UnifiedConfig\n this.path = path\n return this._config\n }\n\n async refresh() {\n this._config = null\n await this.getConfig()\n }\n\n async getServers() {\n const conf = await this.getConfig()\n return conf ? Object.keys(conf.servers) : []\n }\n\n async getConfig() {\n if (this._config) {\n return this._config\n }\n\n const paths = []\n if (this.env.SCREEPS_CONFIG) {\n paths.push(this.env.SCREEPS_CONFIG)\n }\n const dirs = [\"\", import.meta.dirname]\n for (const dir of dirs) {\n paths.push(join(dir, \".screeps.yaml\"))\n paths.push(join(dir, \".screeps.yml\"))\n }\n if (process.platform === \"win32\" && this.env.APPDATA) {\n paths.push(join(this.env.APPDATA, \"screeps/config.yaml\"))\n paths.push(join(this.env.APPDATA, \"screeps/config.yml\"))\n } else {\n if (this.env.XDG_CONFIG_HOME) {\n paths.push(join(this.env.XDG_CONFIG_HOME, \"screeps/config.yaml\"))\n paths.push(join(this.env.XDG_CONFIG_HOME, \"screeps/config.yml\"))\n }\n if (this.env.HOME) {\n paths.push(join(this.env.HOME, \".config/screeps/config.yaml\"))\n paths.push(join(this.env.HOME, \".config/screeps/config.yml\"))\n paths.push(join(this.env.HOME, \".screeps.yaml\"))\n paths.push(join(this.env.HOME, \".screeps.yml\"))\n }\n }\n\n for (const path of paths) {\n const data = await this.loadConfig(path)\n if (data) return data\n }\n return null\n }\n\n async loadConfig(path: string) {\n if (!this.readFile) {\n const { readFile } = await import(\"fs/promises\")\n this.readFile = readFile\n }\n let contents: string\n try {\n contents = await this.readFile(path, { encoding: \"utf8\" })\n } catch (e: unknown) {\n if ((e as { code?: string }).code === \"ENOENT\") {\n return null\n } else {\n throw e\n }\n }\n const data = yaml.load(contents)\n return this.setConfig(data, path)\n }\n}\n\nfunction join(a: string, b: string) {\n return a + (a.endsWith(\"/\") ? \"\" : \"/\") + b\n}\n","import { Socket } from \"./Socket\"\nimport { RawAPI, type CodeList, type Me, type UndocumentedRes, type User } from \"./RawAPI\"\nexport type { CodeList, Me, User, Badge, MarketOrder, UndocumentedRes } from \"./RawAPI\"\nimport { ConfigManager } from \"./ConfigManager\"\nexport { ConfigManager } from \"./ConfigManager\"\n\nconst DEFAULTS = {\n protocol: \"https\",\n hostname: \"screeps.com\",\n port: 443,\n path: \"/\",\n}\n\nconst configManager = new ConfigManager()\n\ninterface RateLimit {\n limit: number\n period: string\n remaining: number\n reset: number\n toReset: number\n}\n\nexport class ScreepsAPI extends RawAPI {\n socket: Socket\n\n appConfig: { [metadata: string]: any } = {}\n rateLimits: {\n global: RateLimit\n GET: { [path: string]: RateLimit }\n POST: { [path: string]: RateLimit }\n }\n\n private _user?: (Me | User) & { ok: number }\n private _tokenInfo?: { full: boolean }\n\n static async fromConfig(server = \"main\", config: string | false = false, opts = {}) {\n const data = await configManager.getConfig()\n\n if (!data) throw new Error(\"No valid config found\")\n if (!server && process.stdin.isTTY && process.stdout.isTTY) {\n const { select, isCancel } = await import(\"@clack/prompts\")\n const selectedServer = await select({\n message: \"Select a server:\",\n withGuide: false,\n options: Object.entries(data.servers).map(([value, args]) => ({\n value,\n hint: args!.host,\n })),\n })\n if (isCancel(selectedServer)) throw new Error(\"Server selection cancelled\")\n server = selectedServer\n }\n\n const conf = data.servers[server]\n if (!conf) throw new Error(`Server '${server}' does not exist in '${configManager.path}'`)\n\n if (conf.ptr) conf.path = \"/ptr\"\n if (conf.season) conf.path = \"/season\"\n const api = new ScreepsAPI(\n Object.assign(\n {\n hostname: conf.host,\n protocol: conf.secure ? \"https\" : \"http\",\n path: \"/\",\n },\n conf,\n opts,\n ),\n )\n\n api.appConfig = (data.configs && data.configs[config as string]) || {}\n\n if (!conf.token && conf.username && conf.password) {\n await api.auth(conf.username, conf.password)\n }\n\n return api\n }\n\n constructor(opts = {}) {\n opts = Object.assign({}, DEFAULTS, opts)\n super(opts)\n this.on(\"token\", (token) => {\n this.token = token\n this.raw.token = token\n })\n const defaultLimit = (limit: number, period: string) => ({\n limit,\n period,\n remaining: limit,\n reset: 0,\n toReset: 0,\n })\n this.rateLimits = {\n global: defaultLimit(120, \"minute\"),\n GET: {\n \"/api/game/room-terrain\": defaultLimit(360, \"hour\"),\n \"/api/user/code\": defaultLimit(60, \"hour\"),\n \"/api/user/memory\": defaultLimit(1440, \"day\"),\n \"/api/user/memory-segment\": defaultLimit(360, \"hour\"),\n \"/api/game/market/orders-index\": defaultLimit(60, \"hour\"),\n \"/api/game/market/orders\": defaultLimit(60, \"hour\"),\n \"/api/game/market/my-orders\": defaultLimit(60, \"hour\"),\n \"/api/game/market/stats\": defaultLimit(60, \"hour\"),\n \"/api/game/user/money-history\": defaultLimit(60, \"hour\"),\n },\n POST: {\n \"/api/user/console\": defaultLimit(360, \"hour\"),\n \"/api/game/map-stats\": defaultLimit(60, \"hour\"),\n \"/api/user/code\": defaultLimit(240, \"day\"),\n \"/api/user/set-active-branch\": defaultLimit(240, \"day\"),\n \"/api/user/memory\": defaultLimit(240, \"day\"),\n \"/api/user/memory-segment\": defaultLimit(60, \"hour\"),\n },\n }\n this.on(\"rateLimit\", (limits) => {\n const rates = (\n this.rateLimits as Partial<Record<string, RateLimit | Partial<Record<string, RateLimit>>>>\n )[limits.method] as Partial<Record<string, RateLimit>> | undefined\n const rate = rates?.[limits.path] || this.rateLimits.global\n const copy: Partial<typeof limits> = Object.assign({}, limits)\n delete copy.path\n delete copy.method\n Object.assign(rate, copy)\n })\n this.socket = new Socket(this)\n }\n\n getRateLimit(method: \"GET\" | \"POST\", path: string) {\n return this.rateLimits[method][path] || this.rateLimits.global\n }\n\n get rateLimitResetUrl() {\n return `https://screeps.com/a/#!/account/auth-tokens/noratelimit?token=${this.token!.slice(\n 0,\n 8,\n )}`\n }\n\n async me() {\n if (this._user) return this._user\n const tokenInfo = await this.tokenInfo()\n if (tokenInfo.full) {\n this._user = await this.raw.auth.me()\n } else {\n const { username } = await this.raw.user.name()\n const { ok, user } = await this.raw.user.find(username)\n this._user = { ...user, ok }\n }\n return this._user\n }\n\n async tokenInfo() {\n if (this._tokenInfo) {\n return this._tokenInfo\n }\n if (\"token\" in this.opts) {\n const { token } = await this.raw.auth.queryToken(this.token!)\n this._tokenInfo = token\n } else {\n this._tokenInfo = { full: true }\n }\n return this._tokenInfo!\n }\n\n async userID() {\n const user = await this.me()\n return user._id\n }\n\n readonly registerUser = this.raw.register.submit\n\n readonly history = this.raw.history\n readonly authmod = this.raw.authmod\n readonly version = this.raw.version\n readonly time = this.raw.game.time\n readonly leaderboard = this.raw.leaderboard\n readonly market = this.raw.game.market\n readonly console = this.raw.user.console\n\n readonly code = codeRepository(this)\n\n readonly memory = {\n ...this.raw.user.memory,\n /** Unlike raw.user.memory.get, this method returns uncompressed memory */\n get: async (path?: string, shard?: string) => {\n const { data } = await this.raw.user.memory.get(path, shard)\n return this.gz(data)\n },\n }\n readonly segment = this.raw.user.memory.segment\n}\n\nconst codeRepository = ({ raw: { user } }: RawAPI) => ({\n get: user.code.get,\n /** Unlike raw.code.set, this method will create a new branch if it doesn't exist */\n set: async (branch: string, code: CodeList): UndocumentedRes => {\n const { list } = await user.branches()\n if (list.some((b) => b.branch == branch)) {\n return user.code.set(branch, code)\n } else {\n return user.cloneBranch(\"\", branch, code)\n }\n },\n branches: user.branches,\n cloneBranch: user.cloneBranch,\n deleteBranch: user.deleteBranch,\n setActiveBranch: user.setActiveBranch,\n})\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@screepts/screeps-api",
3
+ "version": "1.0.0",
4
+ "description": "A JavaScript API client for the Screeps World server",
5
+ "license": "ISC",
6
+ "contributors": [
7
+ {
8
+ "name": "Adam Shumann"
9
+ },
10
+ {
11
+ "name": "Shu"
12
+ }
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/screepts/screeps-api.git"
17
+ },
18
+ "bin": {
19
+ "screeps-api": "bin/screeps-api.js"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "type": "module",
25
+ "types": "./dist/index.d.mts",
26
+ "exports": {
27
+ ".": "./dist/index.mjs",
28
+ "./package.json": "./package.json"
29
+ },
30
+ "scripts": {
31
+ "build": "tsdown",
32
+ "prepublishOnly": "node --run build",
33
+ "lint": "oxlint --type-check --type-aware",
34
+ "fmt": "oxfmt",
35
+ "fmt:check": "oxfmt --check",
36
+ "test:e2e": "vitest run --typecheck",
37
+ "test": "node --run fmt:check && node --run lint"
38
+ },
39
+ "dependencies": {
40
+ "@clack/prompts": "^1.1.0",
41
+ "commander": "^14.0.3",
42
+ "debug": "^4.4.3",
43
+ "eventemitter3": "^5.0.4",
44
+ "js-yaml": "^4.1.1",
45
+ "pako": "^2.1.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/debug": "^4.1.12",
49
+ "@types/js-yaml": "^4.0.9",
50
+ "@types/node": "^25.5.0",
51
+ "@types/pako": "^2.0.4",
52
+ "oxfmt": ">=0.40.0 <2.0.0",
53
+ "oxlint": "^1.55.0",
54
+ "oxlint-tsgolint": ">=0.17.0 <2.0.0",
55
+ "tsdown": ">=0.21.1 <2.0.0",
56
+ "typescript": "^5.9.3",
57
+ "vitest": "^4.1.0"
58
+ },
59
+ "engines": {
60
+ "node": ">=21.0.0"
61
+ }
62
+ }