UNPKG

crosis

Version:
8 lines (7 loc) 19.3 kB
{ "version": 3, "sources": ["../../src/lib/crosis.ts"], "sourcesContent": ["import _protocol from \"@replit/protocol\";\nimport protocol = _protocol.api;\n\nimport { WebSocket } from \"ws\";\n\nimport type { CrosisOptions, Adapter } from \"./types\";\nimport { Channel } from \"./channel.cjs\";\n\nimport { EventEmitter } from \"events\";\n\nimport { normalize as normalizePath } from \"path\";\n\nconst defaultOptions: CrosisOptions = {};\n\ndeclare interface Crosis {\n on(event: \"connect\", listener: () => void): this;\n on(event: \"disconnect\", listener: () => void): this;\n on(event: \"message\", listener: (message: protocol.Command) => void): this;\n on(event: \"messageSent\", listener: (message: protocol.Command) => void): this;\n on(event: \"openChannel\", listener: (channel: Channel) => void): this;\n on(\n event: \"closeChannel\",\n listener: (closeChanRes: protocol.CloseChannelRes) => void\n ): this;\n on(event: \"toast\", listener: (message: string) => void): this;\n on(event: string, listener: Function): this;\n}\n\nclass Crosis extends EventEmitter {\n private url: string | null;\n private adapter: Adapter | null;\n private ws: WebSocket | null;\n private debug: boolean;\n private refHandlers: Record<string, (message: protocol.Command) => void>;\n private channels: Record<number, Channel>;\n private channelsByName: Record<string, number>;\n private utilFuncsChannels: Record<string, number>;\n private otStatuses: Record<string, protocol.OTStatus>;\n private execUtilResolve: ((output: string) => void) | null;\n private execUtilReject: ((error: string | Error) => void) | null;\n private execUtilOutput: string | null;\n bootStatus: protocol.BootStatus.Stage | null;\n containerState: protocol.ContainerState.State | null;\n\n constructor(options: CrosisOptions) {\n if (!options.url && !options.adapter) {\n throw new Error(\"Either url or adapter must be specified\");\n }\n\n super();\n\n options = {\n ...defaultOptions,\n ...options,\n };\n\n this.adapter = options.adapter || null;\n\n this.url = options.url || undefined;\n this.ws = null;\n\n this.debug = options.debug || false;\n\n this.refHandlers = {};\n\n this.channels = {};\n this.channelsByName = {};\n\n this.utilFuncsChannels = {};\n\n this.otStatuses = {};\n\n this.bootStatus = null;\n this.containerState = null;\n\n this.execUtilResolve = null;\n this.execUtilReject = null;\n this.execUtilOutput = null;\n }\n\n /**\n * Sets the adapter to use.\n *\n * Usually you'll want to specify the adapter\n * when instantiating Crosis, but you can also\n * set it later on.\n */\n setAdapter(adapter: Adapter | null) {\n // Don't allow changing adapter while connected\n if (this.wsReadyState != WebSocket.CLOSED) {\n throw new Error(\"Cannot change adapter while connected\");\n }\n\n this.adapter = adapter;\n }\n\n /**\n * Sets the Goval URL to use when connecting.\n * Note that this will be overridden if an\n * adapter is specified.\n */\n setUrl(url: string | null) {\n // Don't allow changing URL while connected\n if (this.wsReadyState != WebSocket.CLOSED) {\n throw new Error(\"Cannot change URL while connected\");\n }\n\n this.url = url;\n }\n\n /**\n * Returns the WebSocket ready state.\n */\n get wsReadyState() {\n return this.ws?.readyState ?? WebSocket.CLOSED;\n }\n\n /**\n * Connects to the WebSocket server, waits for\n * the WebSocket to be ready, and sets up all\n * required event listeners.\n *\n * When a connection is successful, the \"connect\"\n * event is emitted, which can be listened to\n * with `crosis.on(\"connect\", () => { ... })`.\n */\n async connect() {\n const adapterResult = this.adapter ? await this.adapter() : null;\n\n if (adapterResult?.url) {\n this.url = adapterResult.url;\n }\n\n this.ws = new WebSocket(this.url);\n\n // Wait for the WebSocket to be ready\n await new Promise((resolve) => {\n this.ws.onopen = resolve;\n });\n\n // Add event listeners\n this.ws.onmessage = (event) => {\n if (typeof event.data == \"string\") {\n return;\n }\n\n let data: Uint8Array;\n if (event.data instanceof Uint8Array) {\n data = event.data;\n } else if (\n event.data instanceof ArrayBuffer ||\n event.data instanceof Buffer\n ) {\n data = new Uint8Array(event.data);\n } else {\n return;\n }\n\n const message = protocol.Command.decode(data);\n const channel = this.channels[message.channel];\n\n if (this.debug) {\n console.log(message);\n }\n\n // Save boot status\n if (typeof message.bootStatus?.stage == \"number\") {\n this.bootStatus = message.bootStatus.stage;\n }\n\n // Save container state\n if (typeof message.containerState?.state == \"number\") {\n this.containerState = message.containerState.state;\n }\n\n // Exec util\n if (message.channel == this.utilFuncsChannels.exec) {\n if (message.output) {\n this.execUtilOutput += message.output;\n } else if (message.ok) {\n this.execUtilResolve(this.execUtilOutput);\n this.execUtilResolve = null;\n this.execUtilReject = null;\n this.execUtilOutput = null;\n }\n }\n\n // OT utils\n if (channel?.service == \"ot\") {\n if (message.otstatus) {\n this.otStatuses[message.otstatus.linkedFile.path] = message.otstatus;\n }\n }\n\n // Run handler for this ref\n if (message.ref && this.refHandlers[message.ref]) {\n this.refHandlers[message.ref](message);\n }\n\n // Emit events\n this.emit(\"message\", message);\n\n if (message.toast) {\n this.emit(\"toast\", message.toast.text);\n }\n };\n\n // Emit events\n this.emit(\"connect\");\n }\n\n /**\n * Generates a random message ref.\n */\n private generateRef() {\n // Return a random string\n return Math.random().toString(36).substring(2);\n }\n\n /**\n * Encodes the message, sends it, and returns a promise\n * that resolves to the response message.\n *\n * The response message is determined by the ref field.\n * It will have the same ref as the original sent message.\n *\n * If the message does not have a ref, one will be generated,\n * unless autoRef is set to false.\n */\n send(\n message: any,\n autoRef = true,\n throwErrors = true\n ): Promise<protocol.Command> {\n if (autoRef && !message.ref) {\n message.ref = this.generateRef();\n }\n\n this.ws.send(\n protocol.Command.encode(protocol.Command.create(message)).finish()\n );\n\n // Emit events\n this.emit(\"messageSent\", message);\n\n return new Promise((resolve, reject) => {\n this.refHandlers[message.ref] = (message) => {\n if (throwErrors && message.error) {\n reject(message.error);\n }\n\n resolve(message);\n };\n });\n }\n\n /**\n * Requests opening a channel for a specified service,\n * with an optional unique channel name.\n *\n * Returns a promise that resolves to a Channel object\n * if the channel was successfully opened. Otherwise,\n * an error is thrown.\n */\n async openChannel(\n service: string,\n name?: string,\n action?: protocol.OpenChannel.Action\n ) {\n const openChanRes = await this.send({\n channel: 0,\n openChan: {\n service,\n name: name || \"\",\n action: action || protocol.OpenChannel.Action.ATTACH_OR_CREATE,\n },\n });\n\n const channel = new Channel(this, openChanRes.openChanRes, service, name);\n\n this.channels[openChanRes.openChanRes.id] = channel;\n\n // Make findable by channel name later on\n if (name) {\n if (name in this.channelsByName) {\n throw new Error(`Channel already exists with name \"${name}\"`);\n }\n\n this.channelsByName[name] = openChanRes.openChanRes.id;\n }\n\n // Emit events\n this.emit(\"openChannel\", channel);\n\n return channel;\n }\n\n /**\n * Requests closing a channel with the specified ID.\n *\n * Returns a promise that resolves to a CloseChannelRes\n * object, no matter the outcome.\n */\n async closeChannel(id: number, action?: protocol.CloseChannel.Action) {\n const closeChanRes = await this.send({\n channel: 0,\n closeChan: {\n id,\n action: action || protocol.CloseChannel.Action.TRY_CLOSE,\n },\n });\n\n delete this.channels[id];\n\n // Emit events\n this.emit(\"closeChannel\", closeChanRes.closeChanRes);\n\n return closeChanRes.closeChanRes;\n }\n\n /**\n * Disconnects the WebSocket, and closes all\n * previously opened channels.\n *\n * If we're already disconnected, this will return\n * `false` and do nothing.\n *\n * @param autoClose Whether to automatically close\n * all the channels that were opened\n *\n * @returns Whether the WebSocket was disconnected\n */\n async disconnect(autoClose = true) {\n // If already disconnected, do nothing\n if (this.wsReadyState == WebSocket.CLOSED) {\n return false;\n }\n\n // Close all channels\n if (autoClose) {\n for (const channel of Object.values(this.channels)) {\n await channel.close();\n }\n }\n\n this.ws.close();\n\n // Reset exec util\n this.execUtilReject?.(\"Disconnected\");\n this.execUtilResolve = null;\n this.execUtilReject = null;\n this.execUtilOutput = null;\n\n // Emit events\n this.emit(\"disconnect\");\n\n return true;\n }\n\n /**\n * Returns the ID of the channel with the\n * specified name.\n */\n getChannelIdByName(name: string) {\n return this.channelsByName[name];\n }\n\n /**\n * Requests opening a channel for util functions to use.\n * If a channel for the specified service already exists,\n * it will be returned instead.\n */\n private async startUtil(...args: Parameters<Crosis[\"openChannel\"]>) {\n const service = args[0];\n\n if (service in this.utilFuncsChannels) {\n return this.channels[this.utilFuncsChannels[service]];\n } else {\n const channel = await this.openChannel(...args);\n this.utilFuncsChannels[service] = channel.id;\n return channel;\n }\n }\n\n /**\n * Reads a file using GCSFiles.\n */\n async readFile(path: string) {\n const chan = await this.startUtil(\"gcsfiles\");\n\n const resp = await chan.send({\n read: {\n path,\n },\n });\n\n return resp.file?.content;\n }\n\n /**\n * Writes a file using GCSFiles.\n */\n async writeFile(path: string, data: string | Buffer | Uint8Array) {\n const chan = await this.startUtil(\"gcsfiles\");\n\n return await chan.send({\n write: {\n path,\n content: data,\n },\n });\n }\n\n /**\n * Stat a file using GCSFiles.\n */\n async statFile(path: string) {\n const chan = await this.startUtil(\"gcsfiles\");\n\n const resp = await chan.send({\n stat: {\n path,\n },\n });\n\n return resp.statRes;\n }\n\n /**\n * Lists files in a directory using GCSFiles.\n */\n async readDir(path: string) {\n const chan = await this.startUtil(\"gcsfiles\");\n\n const resp = await chan.send({\n readdir: {\n path,\n },\n });\n\n return resp.files.files;\n }\n\n /**\n * Creates a directory using GCSFiles.\n */\n async createDir(path: string) {\n const chan = await this.startUtil(\"gcsfiles\");\n\n return await chan.send({\n mkdir: {\n path,\n },\n });\n }\n\n /**\n * Executes a shell command.\n *\n * Note that this is blocking, meaning that only\n * one command can be executed at a time.\n */\n async exec(args: string[], env?: Record<string, string>) {\n if (this.execUtilResolve) {\n throw new Error(\"Cannot execute multiple commands at once\");\n }\n\n const chan = await this.startUtil(\"exec\");\n\n this.execUtilOutput = \"\";\n\n const promises = await Promise.all([\n new Promise((resolve, reject) => {\n this.execUtilResolve = resolve;\n this.execUtilReject = reject;\n }),\n chan.send({\n exec: {\n args,\n env,\n },\n }),\n ]);\n\n return promises[0];\n }\n\n /**\n * Gets the edit history of a file.\n * @param path The path of the file\n * @param from From which version to start\n * @param to Until which version to get\n * @returns An array of OT packets\n */\n async getFileHistory(path: string, from = 1, to?: number) {\n path = normalizePath(path);\n\n // If no to version is specified, get until\n // the latest version that we know about\n to = to ?? this.getLatestFileVersion(path);\n\n const chan = await this.startUtil(\"ot\", `ot:${path}`);\n\n const resp = await chan.send({\n otFetchRequest: {\n versionFrom: from,\n versionTo: to,\n },\n });\n\n return resp.otFetchResponse?.packets;\n }\n\n /**\n * Gets the latest version of a file\n * that this client knows about. Meaning\n * that if the file was edited by another\n * client, this will not return the latest\n * version until we've received the OT\n * packets from the other client.\n *\n * Will return null if the client hasn't\n * received any OT packets for the file.\n */\n getLatestFileVersion(path: string): number | null {\n path = normalizePath(path);\n\n return this.otStatuses[path]?.version ?? null;\n }\n}\n\nexport { Crosis };\n"], "mappings": "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", "names": ["crosis_exports", "__export", "Crosis", "__toCommonJS", "import_protocol", "import_ws", "import_channel", "import_events", "import_path", "protocol", "_protocol", "defaultOptions", "options", "adapter", "url", "_a", "_b", "adapterResult", "resolve", "event", "data", "message", "channel", "autoRef", "throwErrors", "reject", "service", "name", "action", "openChanRes", "id", "closeChanRes", "autoClose", "args", "path", "env", "chan", "from", "to", "normalizePath"] }