Skip to main content
Glama

Convex MCP server

Official
by get-convex
08_text_encoding.ts7.61 kB
// The initial implementation taken from Deno. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // https://github.com/denoland/deno/blob/main/LICENSE.md import { performOp } from "udf-syscall-ffi"; import { copyBuffer } from "./crypto/helpers.js"; import inspect from "object-inspect"; class TextEncoder { get encoding() { return "utf-8"; } encode(text = "") { if (typeof text !== "string") text = (text as any).toString(); return performOp("textEncoder/encode", text); } encodeInto(input: string, dest: Uint8Array) { const space = dest.length; const output = performOp("textEncoder/encodeInto", input, space); const { bytes, read, written } = output; dest.set(bytes, 0); return { read, written }; } get [Symbol.toStringTag]() { return "TextEncoder"; } } class TextDecoder { #encoding: string; #fatal: boolean; #ignoreBOM: boolean; #rid: string | null; constructor(label = "utf-8", options: TextDecoderOptions = {}) { const { label: encoding, error } = performOp( "textEncoder/normalizeLabel", label, ); if (error) { throw new DOMException(error, "RangeError"); } this.#encoding = encoding; this.#fatal = options.fatal || false; this.#ignoreBOM = options.ignoreBOM || false; this.#rid = null; } get encoding() { return this.#encoding; } get fatal() { return this.#fatal; } get ignoreBOM() { return this.#ignoreBOM; } decode(buffer?: ArrayBufferView | ArrayBuffer, options?: TextDecodeOptions) { if (buffer === undefined) { return ""; } let stream = false; if (options !== undefined) { stream = options.stream ?? false; } try { if (!stream && this.#rid === null) { const { text } = performOp("textEncoder/decodeSingle", { bytes: copyBuffer(buffer), encoding: this.encoding, fatal: this.fatal, ignoreBOM: this.ignoreBOM, }); return text; } if (this.#rid === null) { const { result } = performOp( "textEncoder/newDecoder", this.#encoding, this.#fatal, this.#ignoreBOM, ); this.#rid = result; } const { text } = performOp( "textEncoder/decode", copyBuffer(buffer), this.#rid, stream, ); return text; } finally { if (!stream && this.#rid !== null) { performOp("textEncoder/cleanup", this.#rid); } } } get [Symbol.toStringTag]() { return "TextDecoder"; } } function atob(encoded: string): string { const { decoded, error } = performOp("atob", String(encoded)); if (error) { throw new DOMException( `Failed to execute 'atob': ${error}`, "InvalidCharacterError", ); } return decoded; } function btoa(text: string): string { const { encoded, error } = performOp("btoa", String(text)); if (error) { throw new DOMException( `Failed to execute 'btoa': ${error}`, "InvalidCharacterError", ); } return encoded; } class TextDecoderStream { /** @type {TextDecoder} */ #decoder; /** @type {TransformStream<BufferSource, string>} */ #transform; /** * @param {string} label * @param {TextDecoderOptions} options */ constructor(label = "utf-8", options = {}) { label = String(label); // TODO: validate options this.#decoder = new TextDecoder(label, options); this.#transform = new TransformStream({ // The transform and flush functions need access to TextDecoderStream's // `this`, so they are defined as functions rather than methods. transform: (chunk, controller) => { try { const decoded = this.#decoder.decode(chunk, { stream: true }); if (decoded) { controller.enqueue(decoded); } return Promise.resolve(); } catch (err) { return Promise.reject(err); } }, flush: (controller) => { try { const final = this.#decoder.decode(); if (final) { controller.enqueue(final); } return Promise.resolve(); } catch (err) { return Promise.reject(err); } }, cancel: (_reason) => { try { const _ = this.#decoder.decode(); return Promise.resolve(); } catch (err) { return Promise.reject(err); } }, }); } /** @returns {string} */ get encoding() { return this.#decoder.encoding; } /** @returns {boolean} */ get fatal() { return this.#decoder.fatal; } /** @returns {boolean} */ get ignoreBOM() { return this.#decoder.ignoreBOM; } /** @returns {ReadableStream<string>} */ get readable() { return this.#transform.readable; } /** @returns {WritableStream<BufferSource>} */ get writable() { return this.#transform.writable; } get [Symbol.toStringTag]() { return "TextDecoderStream"; } inspect() { const properties = { encoding: this.encoding, fatal: this.fatal, ignoreBOM: this.ignoreBOM, readable: this.readable, writable: this.writable, }; return `TextDecoderStream ${inspect(properties)}`; } } class TextEncoderStream { /** @type {string | null} */ #pendingHighSurrogate: string | null = null; /** @type {TransformStream<string, Uint8Array>} */ #transform; constructor() { this.#transform = new TransformStream({ // The transform and flush functions need access to TextEncoderStream's // `this`, so they are defined as functions rather than methods. transform: (chunk: string, controller) => { try { if (chunk === "") { return Promise.resolve(); } if (this.#pendingHighSurrogate !== null) { chunk = this.#pendingHighSurrogate + chunk; } const lastCodeUnit = chunk.charCodeAt(chunk.length - 1); if (0xd800 <= lastCodeUnit && lastCodeUnit <= 0xdbff) { this.#pendingHighSurrogate = chunk.slice(-1); chunk = chunk.slice(0, -1); } else { this.#pendingHighSurrogate = null; } if (chunk) { controller.enqueue(performOp("textEncoder/encode", chunk)); } return Promise.resolve(); } catch (err) { return Promise.reject(err); } }, flush: (controller) => { try { if (this.#pendingHighSurrogate !== null) { controller.enqueue(new Uint8Array([0xef, 0xbf, 0xbd])); } return Promise.resolve(); } catch (err) { return Promise.reject(err); } }, }); } /** @returns {string} */ get encoding() { return "utf-8"; } /** @returns {ReadableStream<Uint8Array>} */ get readable() { return this.#transform.readable; } /** @returns {WritableStream<string>} */ get writable() { return this.#transform.writable; } get [Symbol.toStringTag]() { return "TextEncoderStream"; } inspect() { const properties = { encoding: this.encoding, readable: this.readable, writable: this.writable, }; return `TextEncoderStream ${inspect(properties)}`; } } export const setupTextEncoding = (global: any) => { global.atob = atob; global.btoa = btoa; global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; global.TextDecoderStream = TextDecoderStream; global.TextEncoderStream = TextEncoderStream; };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-convex/convex-backend'

If you have feedback or need assistance with the MCP directory API, please join our Discord server