diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 00000000..4837a4ae --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,41 @@ +name: Test + +on: + push: + branches: [ feat/sdk-v2 ] + pull_request: + branches: [ feat/sdk-v2 ] + workflow_dispatch: + +jobs: + lint_and_test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Use Node.js 20 + uses: actions/setup-node@v3 + with: + node-version: 20 + + - name: Install depencies + shell: bash + run: npm install + + - name: Run prettier check + shell: bash + run: npm run fmt-check + + - name: Install spin + uses: engineerd/configurator@v0.0.8 + with: + name: "spin" + url: "https://github.com/fermyon/spin/releases/download/v2.5.0/spin-v2.5.0-linux-amd64.tar.gz" + pathInArchive: "spin" + + - name: Run Test + shell: bash + run: | + cd test + ./test.sh \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..f4ee1249 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "semi": true, + "singleQuote": true, + "arrowParens": "avoid" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a533d5d7..1e4b8920 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@fermyon/spin-sdk", - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@fermyon/spin-sdk", - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "license": "ISC", "dependencies": { - "@bytecodealliance/componentize-js": "file:/Users/karthik_ganeshram/Work/adobe/aio-experiments/ComponentizeJS", + "@bytecodealliance/componentize-js": "^0.8.3", "itty-router": "^3.0.12", "yargs": "^17.7.2" }, @@ -17,10 +17,12 @@ "j2w": "bin/j2w.mjs" }, "devDependencies": { + "prettier": "^3.2.5", "typescript": "^5.4.3" } }, "../../../adobe/aio-experiments/ComponentizeJS": { + "name": "@bytecodealliance/componentize-js", "version": "0.8.3", "workspaces": [ "." @@ -39,6 +41,14 @@ "resolved": "../../../adobe/aio-experiments/ComponentizeJS", "link": true }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -66,14 +76,6 @@ "node": ">=12" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -92,17 +94,6 @@ "node": ">=8" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -148,6 +139,21 @@ "resolved": "https://registry.npmjs.org/itty-router/-/itty-router-3.0.12.tgz", "integrity": "sha512-s98XTPhle6GGbaFf0kYrOD3Q8gyhnqvOqkwYijC3AmkceNKqWUp13YHg6dWmqmVv4pP7l7c94XI92I0EXVGO0w==" }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -156,6 +162,17 @@ "node": ">=0.10.0" } }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -185,14 +202,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -211,17 +220,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -255,14 +253,6 @@ "node": ">=12" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -280,17 +270,6 @@ "engines": { "node": ">=8" } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } } } } diff --git a/package.json b/package.json index e897c563..2890292a 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,14 @@ }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", + "fmt": "prettier --write \"src/**/*.{ts,tsx,js,jsx}\"", + "fmt-check": "prettier --check \"src/**/*.{ts,tsx,js,jsx}\"", "build": "tsc && cp -r src/types ./lib/" }, "author": "", "license": "Apache-2.0", "devDependencies": { + "prettier": "^3.2.5", "typescript": "^5.4.3" }, "dependencies": { diff --git a/src/inboundHttp.ts b/src/inboundHttp.ts index a85b54e3..84d8c5fe 100644 --- a/src/inboundHttp.ts +++ b/src/inboundHttp.ts @@ -1,183 +1,215 @@ -// @ts-ignore -import { ResponseOutparam, Fields, OutgoingResponse, OutgoingBody } from 'wasi:http/types@0.2.0' -import { headers, IncomingRequest, OutputStream, OutgoingResponse as OutgoingResponseType, OutgoingBody as OutgoingBodyType } from './types/wasi-http' - -const decoder = new TextDecoder() -const encoder = new TextEncoder() +import { + ResponseOutparam, + Fields, + OutgoingResponse, + OutgoingBody, + // @ts-ignore +} from 'wasi:http/types@0.2.0'; +import { + headers, + IncomingRequest, + OutputStream, + OutgoingResponse as OutgoingResponseType, + OutgoingBody as OutgoingBodyType, +} from './types/wasi-http'; + +const decoder = new TextDecoder(); +const encoder = new TextEncoder(); const MAX_BLOCKING_BODY_READ_SIZE = 16 * 1024; const MAX_BLOCKING_BODY_WRITE_SIZE = 4 * 1024; export abstract class HttpHandler { - abstract handleRequest(req: HttpRequest, res: ResponseBuilder): Promise; - - handle = async (request: IncomingRequest, responseOut: OutputStream): Promise => { - let method = request.method() - - let requestBody = request.consume() - let requestStream = requestBody.stream() - let body = new Uint8Array() - - while (true) { - try { - body = new Uint8Array([...body, ...requestStream.blockingRead(MAX_BLOCKING_BODY_READ_SIZE)]) - } catch (e: any) { - if (e.payload?.tag === "closed") { - break - } - throw (e) - } - } - - let requestUri = request.pathWithQuery() - let url = requestUri ? requestUri : "/" - - let headers = new Headers(); - request.headers().entries().forEach(([key, value]) => { - headers.append(key, decoder.decode(value)); - }); - - let req: HttpRequest = { - method: method.tag.toString().toUpperCase(), - uri: url, - headers: headers, - body: body, - text: () => { return decoder.decode(body) }, - json: (): any => { return JSON.parse(decoder.decode(body)) }, + abstract handleRequest(req: HttpRequest, res: ResponseBuilder): Promise; + + handle = async ( + request: IncomingRequest, + responseOut: OutputStream, + ): Promise => { + let method = request.method(); + + let requestBody = request.consume(); + let requestStream = requestBody.stream(); + let body = new Uint8Array(); + + while (true) { + try { + body = new Uint8Array([ + ...body, + ...requestStream.blockingRead(MAX_BLOCKING_BODY_READ_SIZE), + ]); + } catch (e: any) { + if (e.payload?.tag === 'closed') { + break; } + throw e; + } + } - let res = new ResponseBuilder(responseOut) - try { - await this.handleRequest(req, res) - } - catch (e: any) { - console.log(e.message) - } + let requestUri = request.pathWithQuery(); + let url = requestUri ? requestUri : '/'; + + let headers = new Headers(); + request + .headers() + .entries() + .forEach(([key, value]) => { + headers.append(key, decoder.decode(value)); + }); + + let req: HttpRequest = { + method: method.tag.toString().toUpperCase(), + uri: url, + headers: headers, + body: body, + text: () => { + return decoder.decode(body); + }, + json: (): any => { + return JSON.parse(decoder.decode(body)); + }, + }; + + let res = new ResponseBuilder(responseOut); + try { + await this.handleRequest(req, res); + } catch (e: any) { + console.log(e.message); } + }; } export interface WasiHttpRequest { - method: string, - uri: string, - headers: Headers - body?: Uint8Array + method: string; + uri: string; + headers: Headers; + body?: Uint8Array; } export interface HttpRequest extends WasiHttpRequest { - text: () => string - json: () => any + text: () => string; + json: () => any; } - // FormData and Blob need to be added -export type BodyInit = BufferSource | URLSearchParams | ReadableStream | USVString; +export type BodyInit = + | BufferSource + | URLSearchParams + | ReadableStream + | USVString; export type USVString = string | ArrayBuffer | ArrayBufferView; export class ResponseBuilder { - headers: Headers - private hasWrittenHeaders: boolean - private hasSentResponse: boolean - private responseOut: OutputStream - private statusCode: number - private responseBody: OutgoingBodyType | undefined - private responseStream: OutputStream | undefined - private response: OutgoingResponseType | undefined - - constructor(responseOut: OutputStream) { - this.responseOut = responseOut - this.statusCode = 200 - this.headers = new Headers() - this.hasWrittenHeaders = false - this.hasSentResponse = false + headers: Headers; + private hasWrittenHeaders: boolean; + private hasSentResponse: boolean; + private responseOut: OutputStream; + private statusCode: number; + private responseBody: OutgoingBodyType | undefined; + private responseStream: OutputStream | undefined; + private response: OutgoingResponseType | undefined; + + constructor(responseOut: OutputStream) { + this.responseOut = responseOut; + this.statusCode = 200; + this.headers = new Headers(); + this.hasWrittenHeaders = false; + this.hasSentResponse = false; + } + status(code: number): ResponseBuilder { + if (this.hasWrittenHeaders) { + throw new Error('Headers and Status already sent'); } - status(code: number): ResponseBuilder { - if (this.hasWrittenHeaders) { - throw new Error("Headers and Status already sent") - } - this.statusCode = code - return this + this.statusCode = code; + return this; + } + getStatus(): number { + return this.statusCode; + } + set( + arg1: string | { [key: string]: string }, + arg2?: string, + ): ResponseBuilder { + if (this.hasWrittenHeaders) { + throw new Error('Headers already sent'); } - getStatus(): number { - return this.statusCode + if (typeof arg1 === 'string' && typeof arg2 === 'string') { + this.headers.set(arg1, arg2); + } else if (typeof arg1 === 'object' && arg2 === undefined) { + for (const key in arg1) { + this.headers.set(key, arg1[key]); + } + } else { + throw new Error('Invalid arguments'); } - set(arg1: string | { [key: string]: string }, arg2?: string): ResponseBuilder { - if (this.hasWrittenHeaders) { - throw new Error("Headers already sent") - } - if (typeof arg1 === 'string' && typeof arg2 === 'string') { - this.headers.set(arg1, arg2); - } else if (typeof arg1 === 'object' && arg2 === undefined) { - for (const key in arg1) { - this.headers.set(key, arg1[key]); - } - } else { - throw new Error('Invalid arguments'); - } - return this + return this; + } + send(value: BodyInit = new Uint8Array()) { + if (this.hasSentResponse) { + throw new Error('Response has already been sent'); } - send(value: BodyInit = new Uint8Array()) { - if (this.hasSentResponse) { - throw new Error("Response has already been sent") - } - this.write(value) - this.end() - this.hasSentResponse = true + this.write(value); + this.end(); + this.hasSentResponse = true; + } + write(value: BodyInit) { + if (this.hasSentResponse) { + throw new Error('Response has already been sent'); } - write(value: BodyInit) { - if (this.hasSentResponse) { - throw new Error("Response has already been sent") - } - if (!this.hasWrittenHeaders) { - let headers = new Fields() as headers; - this.headers.forEach((value, key) => { - headers.append(key, encoder.encode(value)); - }); - this.response = new OutgoingResponse(headers) as OutgoingResponseType - this.responseBody = this.response.body() - this.responseStream = this.responseBody.write() - this.response.setStatusCode(this.statusCode) - ResponseOutparam.set(this.responseOut, { tag: "ok", val: this.response }) - this.hasWrittenHeaders = true - } - writeBytesToOutputStream(value, this.responseStream!) + if (!this.hasWrittenHeaders) { + let headers = new Fields() as headers; + this.headers.forEach((value, key) => { + headers.append(key, encoder.encode(value)); + }); + this.response = new OutgoingResponse(headers) as OutgoingResponseType; + this.responseBody = this.response.body(); + this.responseStream = this.responseBody.write(); + this.response.setStatusCode(this.statusCode); + ResponseOutparam.set(this.responseOut, { tag: 'ok', val: this.response }); + this.hasWrittenHeaders = true; } - end() { - if (this.hasSentResponse) { - throw new Error("Response has already been sent") - } - // The OutgoingBody here is untyped because I have not figured out how to do that in typescript yet. - this.responseStream?.[Symbol.dispose]() - OutgoingBody.finish(this.responseBody!, { tag: "none" }); - this.hasSentResponse = true + writeBytesToOutputStream(value, this.responseStream!); + } + end() { + if (this.hasSentResponse) { + throw new Error('Response has already been sent'); } + // The OutgoingBody here is untyped because I have not figured out how to do that in typescript yet. + this.responseStream?.[Symbol.dispose](); + OutgoingBody.finish(this.responseBody!, { tag: 'none' }); + this.hasSentResponse = true; + } } -function writeBytesToOutputStream(body: BodyInit, responseStream: OutputStream) { - let bytes = convertToUint8Array(body) - let offset = 0 - while (offset < bytes.length) { - const count = Math.min(bytes.length - offset, MAX_BLOCKING_BODY_WRITE_SIZE) - responseStream.blockingWriteAndFlush(bytes.slice(offset, offset + count)) - offset += count - } +function writeBytesToOutputStream( + body: BodyInit, + responseStream: OutputStream, +) { + let bytes = convertToUint8Array(body); + let offset = 0; + while (offset < bytes.length) { + const count = Math.min(bytes.length - offset, MAX_BLOCKING_BODY_WRITE_SIZE); + responseStream.blockingWriteAndFlush(bytes.slice(offset, offset + count)); + offset += count; + } } function convertToUint8Array(body: BodyInit): Uint8Array { - if (body instanceof ArrayBuffer) { - return new Uint8Array(body); - } else if (ArrayBuffer.isView(body)) { - return new Uint8Array(body.buffer, body.byteOffset, body.byteLength); - } else if (typeof body === 'string') { - const encoder = new TextEncoder(); - const utf8Array = encoder.encode(body); - return utf8Array; - } else if (body instanceof URLSearchParams) { - const encoder = new TextEncoder(); - const bodyString = body.toString(); - const utf8Array = encoder.encode(bodyString); - return utf8Array; - } else { - throw new Error('Unsupported body type'); - } + if (body instanceof ArrayBuffer) { + return new Uint8Array(body); + } else if (ArrayBuffer.isView(body)) { + return new Uint8Array(body.buffer, body.byteOffset, body.byteLength); + } else if (typeof body === 'string') { + const encoder = new TextEncoder(); + const utf8Array = encoder.encode(body); + return utf8Array; + } else if (body instanceof URLSearchParams) { + const encoder = new TextEncoder(); + const bodyString = body.toString(); + const utf8Array = encoder.encode(bodyString); + return utf8Array; + } else { + throw new Error('Unsupported body type'); + } } diff --git a/src/inboundRedis.ts b/src/inboundRedis.ts index 9765c802..48ba1fdd 100644 --- a/src/inboundRedis.ts +++ b/src/inboundRedis.ts @@ -1,3 +1,3 @@ export abstract class RedisHandler { - abstract handleMessage(msg: Uint8Array): Promise; + abstract handleMessage(msg: Uint8Array): Promise; } diff --git a/src/index.ts b/src/index.ts index a6d7e4d2..ff58884c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,27 @@ -import { ResponseBuilder, HttpHandler, HttpRequest } from "./inboundHttp"; -import { RedisHandler } from "./inboundRedis"; +import { ResponseBuilder, HttpHandler, HttpRequest } from './inboundHttp'; +import { RedisHandler } from './inboundRedis'; import * as Llm from './llm'; import * as Variables from './variables'; import * as Redis from './redis'; import * as Kv from './keyValue'; import * as Sqlite from './sqlite'; -import * as Postgres from "./postgres"; -import * as Mysql from "./mysql"; -import * as Mqtt from "./mqtt" -import { Router } from "./router"; - -export { HttpHandler, Router, Llm, Variables, Redis, Kv, Sqlite, Postgres, Mysql, Mqtt, RedisHandler, ResponseBuilder, HttpRequest } +import * as Postgres from './postgres'; +import * as Mysql from './mysql'; +import * as Mqtt from './mqtt'; +import { Router } from './router'; +export { + HttpHandler, + Router, + Llm, + Variables, + Redis, + Kv, + Sqlite, + Postgres, + Mysql, + Mqtt, + RedisHandler, + ResponseBuilder, + HttpRequest, +}; diff --git a/src/keyValue.ts b/src/keyValue.ts index 2707f84e..1844eb3e 100644 --- a/src/keyValue.ts +++ b/src/keyValue.ts @@ -1,55 +1,54 @@ //@ts-ignore -import * as spinKv from "fermyon:spin/key-value@2.0.0" +import * as spinKv from 'fermyon:spin/key-value@2.0.0'; -const encoder = new TextEncoder() -const decoder = new TextDecoder() +const encoder = new TextEncoder(); +const decoder = new TextDecoder(); export interface Store { - get: (key: string) => Uint8Array | null - set: (key: string, value: Uint8Array | string | object) => void - delete: (key: string) => void - exists: (key: string) => boolean - getKeys: () => string[] - getJson: (key: string) => any - setJson: (key: string, value: any) => void + get: (key: string) => Uint8Array | null; + set: (key: string, value: Uint8Array | string | object) => void; + delete: (key: string) => void; + exists: (key: string) => boolean; + getKeys: () => string[]; + getJson: (key: string) => any; + setJson: (key: string, value: any) => void; } function createKvStore(store: spinKv.store): Store { - let kv = { - get: (key: string) => { - return store.get(key) - }, - set: (key: string, value: Uint8Array | string | object) => { - if (typeof (value) === "string") { - value = encoder.encode(value) - } else if (typeof (value) === "object") { - value = encoder.encode(JSON.stringify(value)) - } - store.set(key, value) - }, - delete: (key: string) => { - store.delete(key) - }, - exists: (key: string) => { - return store.exists(key) - }, - getKeys: () => { - return store.getKeys() - }, - getJson: (key: string) => { - return JSON.parse(decoder.decode(store.get(key) || new Uint8Array)) - }, - setJson: (key: string, value: any) => { - store.set(key, encoder.encode(JSON.stringify(value))) - } - } - return kv + let kv = { + get: (key: string) => { + return store.get(key); + }, + set: (key: string, value: Uint8Array | string | object) => { + if (typeof value === 'string') { + value = encoder.encode(value); + } else if (typeof value === 'object') { + value = encoder.encode(JSON.stringify(value)); + } + store.set(key, value); + }, + delete: (key: string) => { + store.delete(key); + }, + exists: (key: string) => { + return store.exists(key); + }, + getKeys: () => { + return store.getKeys(); + }, + getJson: (key: string) => { + return JSON.parse(decoder.decode(store.get(key) || new Uint8Array())); + }, + setJson: (key: string, value: any) => { + store.set(key, encoder.encode(JSON.stringify(value))); + }, + }; + return kv; } - export function open(label: string): Store { - return createKvStore(spinKv.Store.open(label)) + return createKvStore(spinKv.Store.open(label)); } export function openDefault(): Store { - return createKvStore(spinKv.Store.open("default")) + return createKvStore(spinKv.Store.open('default')); } diff --git a/src/llm.ts b/src/llm.ts index a7bf35e0..405ecc42 100644 --- a/src/llm.ts +++ b/src/llm.ts @@ -1,63 +1,73 @@ -//@ts-ignore -import { infer as llmInfer, generateEmbeddings as llmGenerateEmbeddings } from "fermyon:spin/llm@2.0.0" +import { + infer as llmInfer, + generateEmbeddings as llmGenerateEmbeddings, + //@ts-ignore +} from 'fermyon:spin/llm@2.0.0'; export enum InferencingModels { - Llama2Chat = "llama2-chat", - CodellamaInstruct = "codellama-instruct" + Llama2Chat = 'llama2-chat', + CodellamaInstruct = 'codellama-instruct', } export enum EmbeddingModels { - AllMiniLmL6V2 = "all-minilm-l6-v2" + AllMiniLmL6V2 = 'all-minilm-l6-v2', } export interface InferencingOptions { - maxTokens?: number, - repeatPenalty?: number, - repeatPenaltyLastNTokenCount?: number, - temperature?: number, - topK?: number, - topP?: number + maxTokens?: number; + repeatPenalty?: number; + repeatPenaltyLastNTokenCount?: number; + temperature?: number; + topK?: number; + topP?: number; } export interface InternalInferencingOptions { - maxTokens?: number, - repeatPenalty?: number, - repeatPenaltyLastNTokenCount?: number, - temperature?: number, - topK?: number, - topP?: number + maxTokens?: number; + repeatPenalty?: number; + repeatPenaltyLastNTokenCount?: number; + temperature?: number; + topK?: number; + topP?: number; } export interface InferenceUsage { - promptTokenCount: number, - generatedTokenCount: number + promptTokenCount: number; + generatedTokenCount: number; } export interface InferenceResult { - text: string - usage: InferenceUsage + text: string; + usage: InferenceUsage; } export interface EmbeddingUsage { - promptTokenCount: number + promptTokenCount: number; } export interface EmbeddingResult { - embeddings: Array> - usage: EmbeddingUsage + embeddings: Array>; + usage: EmbeddingUsage; } -export function infer(model: InferencingModels | string, prompt: string, options?: InferencingOptions): InferenceResult { - let inference_options: InternalInferencingOptions = { - maxTokens: options?.maxTokens || 100, - repeatPenalty: options?.repeatPenalty || 1.1, - repeatPenaltyLastNTokenCount: options?.repeatPenaltyLastNTokenCount || 64, - temperature: options?.temperature || 0.8, - topK: options?.topK || 40, - topP: options?.topP || 0.9 - } - return llmInfer(model, prompt, inference_options) +export function infer( + model: InferencingModels | string, + prompt: string, + options?: InferencingOptions, +): InferenceResult { + let inference_options: InternalInferencingOptions = { + maxTokens: options?.maxTokens || 100, + repeatPenalty: options?.repeatPenalty || 1.1, + repeatPenaltyLastNTokenCount: options?.repeatPenaltyLastNTokenCount || 64, + temperature: options?.temperature || 0.8, + topK: options?.topK || 40, + topP: options?.topP || 0.9, + }; + return llmInfer(model, prompt, inference_options); } -export const generateEmbeddings = (model: EmbeddingModels | string, text: Array): EmbeddingResult => { - return llmGenerateEmbeddings(model, text) -} +export const generateEmbeddings = ( + model: EmbeddingModels | string, + text: Array, +): EmbeddingResult => { + return llmGenerateEmbeddings(model, text); +}; diff --git a/src/mqtt.ts b/src/mqtt.ts index 03e437f7..e7390283 100644 --- a/src/mqtt.ts +++ b/src/mqtt.ts @@ -1,15 +1,25 @@ //@ts-ignore -import * as spinMqtt from "fermyon:spin/mqtt@2.0.0" +import * as spinMqtt from 'fermyon:spin/mqtt@2.0.0'; export enum QoS { - AtMostOnce = "at-most-once", - AtLeastOnce = "at-least-once", - ExactlyOnce = "exactly-once" + AtMostOnce = 'at-most-once', + AtLeastOnce = 'at-least-once', + ExactlyOnce = 'exactly-once', } export interface MqttConnection { - publish: (topic: string, payload: Uint8Array, qos: QoS) => void + publish: (topic: string, payload: Uint8Array, qos: QoS) => void; } -export function open(address: string, username: string, password: string, keepAliveIntervalInSecs: number): MqttConnection { - return spinMqtt.Connection.open(address, username, password, keepAliveIntervalInSecs) +export function open( + address: string, + username: string, + password: string, + keepAliveIntervalInSecs: number, +): MqttConnection { + return spinMqtt.Connection.open( + address, + username, + password, + keepAliveIntervalInSecs, + ); } diff --git a/src/mysql.ts b/src/mysql.ts index b598a799..0b91bb8b 100644 --- a/src/mysql.ts +++ b/src/mysql.ts @@ -1,38 +1,46 @@ //@ts-ignore -import * as spinMysql from "fermyon:spin/mysql@2.0.0" -import { RdbmsParameterValue, RdbmsRow, RdbmsRowSet, SpinRdbmsRowSet } from "./types/rdbms" -import { convertRdbmsToWitTypes } from "./rdbmsHelper" +import * as spinMysql from 'fermyon:spin/mysql@2.0.0'; +import { + RdbmsParameterValue, + RdbmsRow, + RdbmsRowSet, + SpinRdbmsRowSet, +} from './types/rdbms'; +import { convertRdbmsToWitTypes } from './rdbmsHelper'; export interface MysqlConnection { - query: (statement: string, params: RdbmsParameterValue[]) => RdbmsRowSet - execute: (statement: string, params: RdbmsParameterValue[]) => number + query: (statement: string, params: RdbmsParameterValue[]) => RdbmsRowSet; + execute: (statement: string, params: RdbmsParameterValue[]) => number; } -function createMysqlConnection(connection: spinMysql.Connection): MysqlConnection { - return { - query: (statement: string, params: RdbmsParameterValue[]) => { - let santizedParams = convertRdbmsToWitTypes(params) - let ret = connection.query(statement, santizedParams) as SpinRdbmsRowSet - let results: RdbmsRowSet = { - columns: ret.columns, - rows: [] - } - ret.rows.map((k: RdbmsRow, rowIndex: number) => { - results.rows.push({}) - k.map((val, valIndex: number) => { - results.rows[rowIndex][results.columns[valIndex].name] = (val.tag == "db-null" || val.tag == "unsupported") ? null : val.val - }) - }) - return results - }, - execute: (statement: string, params: RdbmsParameterValue[]) => { - let santizedParams = convertRdbmsToWitTypes(params) - let ret = connection.execute(statement, santizedParams) as number - return ret - } - } +function createMysqlConnection( + connection: spinMysql.Connection, +): MysqlConnection { + return { + query: (statement: string, params: RdbmsParameterValue[]) => { + let santizedParams = convertRdbmsToWitTypes(params); + let ret = connection.query(statement, santizedParams) as SpinRdbmsRowSet; + let results: RdbmsRowSet = { + columns: ret.columns, + rows: [], + }; + ret.rows.map((k: RdbmsRow, rowIndex: number) => { + results.rows.push({}); + k.map((val, valIndex: number) => { + results.rows[rowIndex][results.columns[valIndex].name] = + val.tag == 'db-null' || val.tag == 'unsupported' ? null : val.val; + }); + }); + return results; + }, + execute: (statement: string, params: RdbmsParameterValue[]) => { + let santizedParams = convertRdbmsToWitTypes(params); + let ret = connection.execute(statement, santizedParams) as number; + return ret; + }, + }; } export function open(address: string): MysqlConnection { - return createMysqlConnection(spinMysql.Connection.open(address)) + return createMysqlConnection(spinMysql.Connection.open(address)); } diff --git a/src/postgres.ts b/src/postgres.ts index df23892e..c9999d73 100644 --- a/src/postgres.ts +++ b/src/postgres.ts @@ -1,38 +1,47 @@ //@ts-ignore -import * as spinPg from "fermyon:spin/postgres@2.0.0" -import { RdbmsParameterValue, RdbmsRow, RdbmsRowSet, SpinRdbmsParameterValue, SpinRdbmsRowSet } from "./types/rdbms" -import { convertRdbmsToWitTypes } from "./rdbmsHelper" +import * as spinPg from 'fermyon:spin/postgres@2.0.0'; +import { + RdbmsParameterValue, + RdbmsRow, + RdbmsRowSet, + SpinRdbmsParameterValue, + SpinRdbmsRowSet, +} from './types/rdbms'; +import { convertRdbmsToWitTypes } from './rdbmsHelper'; export interface PostgresConnection { - query: (statement: string, params: RdbmsParameterValue[]) => RdbmsRowSet - execute: (statement: string, params: RdbmsParameterValue[]) => number + query: (statement: string, params: RdbmsParameterValue[]) => RdbmsRowSet; + execute: (statement: string, params: RdbmsParameterValue[]) => number; } -function createPostgresConnection(connection: spinPg.Connection): PostgresConnection { - return { - query: (statement: string, params: RdbmsParameterValue[]) => { - let santizedParams = convertRdbmsToWitTypes(params) - let ret = connection.query(statement, santizedParams) as SpinRdbmsRowSet - let results: RdbmsRowSet = { - columns: ret.columns, - rows: [] - } - ret.rows.map((k: RdbmsRow, rowIndex: number) => { - results.rows.push({}) - k.map((val, valIndex: number) => { - results.rows[rowIndex][results.columns[valIndex].name] = (val.tag == "db-null" || val.tag == "unsupported") ? null : val.val - }) - }) - return results - }, - execute: (statement: string, params: RdbmsParameterValue[]) => { - let santizedParams = convertRdbmsToWitTypes(params) - let ret = connection.execute(statement, santizedParams) as number - return ret - } - } +function createPostgresConnection( + connection: spinPg.Connection, +): PostgresConnection { + return { + query: (statement: string, params: RdbmsParameterValue[]) => { + let santizedParams = convertRdbmsToWitTypes(params); + let ret = connection.query(statement, santizedParams) as SpinRdbmsRowSet; + let results: RdbmsRowSet = { + columns: ret.columns, + rows: [], + }; + ret.rows.map((k: RdbmsRow, rowIndex: number) => { + results.rows.push({}); + k.map((val, valIndex: number) => { + results.rows[rowIndex][results.columns[valIndex].name] = + val.tag == 'db-null' || val.tag == 'unsupported' ? null : val.val; + }); + }); + return results; + }, + execute: (statement: string, params: RdbmsParameterValue[]) => { + let santizedParams = convertRdbmsToWitTypes(params); + let ret = connection.execute(statement, santizedParams) as number; + return ret; + }, + }; } export function open(address: string): PostgresConnection { - return createPostgresConnection(spinPg.Connection.open(address)) + return createPostgresConnection(spinPg.Connection.open(address)); } diff --git a/src/rdbmsHelper.ts b/src/rdbmsHelper.ts index fc19f9ae..a9094d4e 100644 --- a/src/rdbmsHelper.ts +++ b/src/rdbmsHelper.ts @@ -1,40 +1,44 @@ -import { RdbmsParameterValue, SpinRdbmsParameterValue } from "./types/rdbms" +import { RdbmsParameterValue, SpinRdbmsParameterValue } from './types/rdbms'; -export function convertRdbmsToWitTypes(parameters: RdbmsParameterValue[]): SpinRdbmsParameterValue[] { - let sanitized: SpinRdbmsParameterValue[] = [] - for (let k of parameters) { - if (typeof (k) === "object") { - sanitized.push(k as SpinRdbmsParameterValue) - continue - } - if (typeof (k) === "string") { - sanitized.push({ tag: "str", val: k }) - continue - } - if (typeof (k) === null) { - sanitized.push({ tag: "db-null" }) - continue - } - if (typeof (k) === "boolean") { - sanitized.push({ tag: "boolean", val: k }) - continue - } - if (typeof (k) === "bigint") { - sanitized.push({ tag: "int64", val: k }) - continue - } - if (typeof (k) === "number") { - isFloat(k) ? sanitized.push({ tag: "floating64", val: k }) : sanitized.push({ tag: "int32", val: k }) - continue - } - if (k as any instanceof Uint8Array) { - sanitized.push({ tag: "binary", val: k }) - continue - } +export function convertRdbmsToWitTypes( + parameters: RdbmsParameterValue[], +): SpinRdbmsParameterValue[] { + let sanitized: SpinRdbmsParameterValue[] = []; + for (let k of parameters) { + if (typeof k === 'object') { + sanitized.push(k as SpinRdbmsParameterValue); + continue; } - return sanitized + if (typeof k === 'string') { + sanitized.push({ tag: 'str', val: k }); + continue; + } + if (typeof k === null) { + sanitized.push({ tag: 'db-null' }); + continue; + } + if (typeof k === 'boolean') { + sanitized.push({ tag: 'boolean', val: k }); + continue; + } + if (typeof k === 'bigint') { + sanitized.push({ tag: 'int64', val: k }); + continue; + } + if (typeof k === 'number') { + isFloat(k) + ? sanitized.push({ tag: 'floating64', val: k }) + : sanitized.push({ tag: 'int32', val: k }); + continue; + } + if ((k as any) instanceof Uint8Array) { + sanitized.push({ tag: 'binary', val: k }); + continue; + } + } + return sanitized; } function isFloat(number: number) { - return number % 1 !== 0; -} \ No newline at end of file + return number % 1 !== 0; +} diff --git a/src/redis.ts b/src/redis.ts index 0e3e8842..e5d321bb 100644 --- a/src/redis.ts +++ b/src/redis.ts @@ -1,22 +1,22 @@ //@ts-ignore -import * as spinRedis from "fermyon:spin/redis@2.0.0" +import * as spinRedis from 'fermyon:spin/redis@2.0.0'; -export type payload = Uint8Array -export type redisParameter = number | Uint8Array -export type redisResult = number | Uint8Array | null | string +export type payload = Uint8Array; +export type redisParameter = number | Uint8Array; +export type redisResult = number | Uint8Array | null | string; export interface RedisConnection { - publish: (channel: string, payload: payload) => void - get: (key: string) => payload | null - set: (key: string, value: payload) => void - incr: (key: string) => number - del: (key: string) => number - sadd: (key: string, value: string[]) => number - smembers: (key: string) => string[] - srem: (key: string, value: string[]) => number - execute: (command: string, args: redisParameter[]) => redisResult[] + publish: (channel: string, payload: payload) => void; + get: (key: string) => payload | null; + set: (key: string, value: payload) => void; + incr: (key: string) => number; + del: (key: string) => number; + sadd: (key: string, value: string[]) => number; + smembers: (key: string) => string[]; + srem: (key: string, value: string[]) => number; + execute: (command: string, args: redisParameter[]) => redisResult[]; } export function open(address: string): RedisConnection { - return spinRedis.Connection.open(address) + return spinRedis.Connection.open(address); } diff --git a/src/router.ts b/src/router.ts index 1cb328b8..4731eacf 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,97 +1,148 @@ -import { Router as _router } from 'itty-router' -import { HttpRequest, ResponseBuilder } from './inboundHttp' +import { Router as _router } from 'itty-router'; +import { HttpRequest, ResponseBuilder } from './inboundHttp'; declare type GenericTraps = { - [key: string]: any; + [key: string]: any; }; export declare type RequestLike = { - method: string; - url: string; + method: string; + url: string; } & GenericTraps; declare type IRequest = { - method: string; - url: string; - params: { - [key: string]: string; - }; - query: { - [key: string]: string | string[] | undefined; - }; - proxy?: any; + method: string; + url: string; + params: { + [key: string]: string; + }; + query: { + [key: string]: string | string[] | undefined; + }; + proxy?: any; } & GenericTraps; interface RouteHandler { - (request: IRequest, ...args: any): any; + (request: IRequest, ...args: any): any; } interface SpinRouteHandler { - (metadata: IRequest, req: HttpRequest, res: ResponseBuilder, ...args: any): any; + ( + metadata: IRequest, + req: HttpRequest, + res: ResponseBuilder, + ...args: any + ): any; } declare type RouteEntry = [string, RegExp, RouteHandler[]]; -declare type Route = (path: string, ...handlers: RouteHandler[]) => T; +declare type Route = ( + path: string, + ...handlers: RouteHandler[] +) => T; declare type RouterHints = { - all: Route; - delete: Route; - get: Route; - options: Route; - patch: Route; - post: Route; - put: Route; + all: Route; + delete: Route; + get: Route; + options: Route; + patch: Route; + post: Route; + put: Route; }; declare type RouterType = { - __proto__: RouterType; - routes: RouteEntry[]; - handle: (request: RequestLike, ...extra: any) => Promise; + __proto__: RouterType; + routes: RouteEntry[]; + handle: (request: RequestLike, ...extra: any) => Promise; } & RouterHints; interface routerType { - all(path: string, ...handlers: SpinRouteHandler[]): RouterType - delete(path: string, ...handlers: SpinRouteHandler[]): RouterType - get(path: string, ...handlers: SpinRouteHandler[]): RouterType - handle(request: RequestLike, ...extras: any): Promise - handleRequest(request: HttpRequest, response: ResponseBuilder, ...extras: any): Promise - options(path: string, ...handlers: SpinRouteHandler[]): RouterType - patch(path: string, ...handlers: SpinRouteHandler[]): RouterType - post(path: string, ...handlers: SpinRouteHandler[]): RouterType - put(path: string, ...handlers: SpinRouteHandler[]): RouterType - routes: RouteEntry[] + all(path: string, ...handlers: SpinRouteHandler[]): RouterType; + delete(path: string, ...handlers: SpinRouteHandler[]): RouterType; + get(path: string, ...handlers: SpinRouteHandler[]): RouterType; + handle(request: RequestLike, ...extras: any): Promise; + handleRequest( + request: HttpRequest, + response: ResponseBuilder, + ...extras: any + ): Promise; + options(path: string, ...handlers: SpinRouteHandler[]): RouterType; + patch(path: string, ...handlers: SpinRouteHandler[]): RouterType; + post(path: string, ...handlers: SpinRouteHandler[]): RouterType; + put(path: string, ...handlers: SpinRouteHandler[]): RouterType; + routes: RouteEntry[]; } /** @internal */ function Router(): routerType { - let _spinRouter = _router() + let _spinRouter = _router(); - return { - all: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.all(path, ...wrapRouteHandler(handlers)) }, - delete: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.delete(path, ...wrapRouteHandler(handlers)) }, - get: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.get(path, ...wrapRouteHandler(handlers)) }, - handle: function (request: RequestLike, ...extra: any): Promise { return _spinRouter.handle(request, ...extra) }, - handleRequest: function (request: HttpRequest, response: ResponseBuilder, ...a: any): Promise { - return _spinRouter.handle({ - method: request.method, - url: request.headers.get("spin-full-url") || "" - }, request, response, ...a) + return { + all: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { + return _spinRouter.all(path, ...wrapRouteHandler(handlers)); + }, + delete: function ( + path: string, + ...handlers: SpinRouteHandler[] + ): RouterType { + return _spinRouter.delete(path, ...wrapRouteHandler(handlers)); + }, + get: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { + return _spinRouter.get(path, ...wrapRouteHandler(handlers)); + }, + handle: function (request: RequestLike, ...extra: any): Promise { + return _spinRouter.handle(request, ...extra); + }, + handleRequest: function ( + request: HttpRequest, + response: ResponseBuilder, + ...a: any + ): Promise { + return _spinRouter.handle( + { + method: request.method, + url: request.headers.get('spin-full-url') || '', }, - options: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.options(path, ...wrapRouteHandler(handlers)) }, - patch: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.patch(path, ...wrapRouteHandler(handlers)) }, - post: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.post(path, ...wrapRouteHandler(handlers)) }, - put: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { return _spinRouter.put(path, ...wrapRouteHandler(handlers)) }, - routes: _spinRouter.routes - } + request, + response, + ...a, + ); + }, + options: function ( + path: string, + ...handlers: SpinRouteHandler[] + ): RouterType { + return _spinRouter.options(path, ...wrapRouteHandler(handlers)); + }, + patch: function ( + path: string, + ...handlers: SpinRouteHandler[] + ): RouterType { + return _spinRouter.patch(path, ...wrapRouteHandler(handlers)); + }, + post: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { + return _spinRouter.post(path, ...wrapRouteHandler(handlers)); + }, + put: function (path: string, ...handlers: SpinRouteHandler[]): RouterType { + return _spinRouter.put(path, ...wrapRouteHandler(handlers)); + }, + routes: _spinRouter.routes, + }; } function wrapRouteHandler(handlers: SpinRouteHandler[]): RouteHandler[] { - let h: RouteHandler[] = [] - for (let handler of handlers) { - let fn = async (metadata: IRequest, req: HttpRequest, res: ResponseBuilder, ...args: any) => { - return handler(metadata, req, res, args) - } - h.push(fn) - } - return h + let h: RouteHandler[] = []; + for (let handler of handlers) { + let fn = async ( + metadata: IRequest, + req: HttpRequest, + res: ResponseBuilder, + ...args: any + ) => { + return handler(metadata, req, res, args); + }; + h.push(fn); + } + return h; } -export { Router, routerType } +export { Router, routerType }; diff --git a/src/sqlite.ts b/src/sqlite.ts index 1fef2bad..8ab8bdee 100644 --- a/src/sqlite.ts +++ b/src/sqlite.ts @@ -1,109 +1,132 @@ //@ts-ignore -import * as spinSqlite from "fermyon:spin/sqlite@2.0.0" +import * as spinSqlite from 'fermyon:spin/sqlite@2.0.0'; -export type sqliteValues = ValueInteger | ValueReal | ValueText | ValueBlob | ValueNull -export type ParameterValue = sqliteValues | number | bigint | null | string | Uint8Array -type SqliteRowResultItem = { tag: string, val: number | bigint | string | Uint8Array | null } -type SqliteRowResult = { values: SqliteRowResultItem[] } -export type ValueInteger = { tag: "integer", val: number | bigint } -export type ValueReal = { tag: "real", val: number | bigint } -export type ValueText = { tag: "text", val: string } -export type ValueBlob = { tag: "blob", val: Uint8Array } -export type ValueNull = { tag: "null" } +export type sqliteValues = + | ValueInteger + | ValueReal + | ValueText + | ValueBlob + | ValueNull; +export type ParameterValue = + | sqliteValues + | number + | bigint + | null + | string + | Uint8Array; +type SqliteRowResultItem = { + tag: string; + val: number | bigint | string | Uint8Array | null; +}; +type SqliteRowResult = { values: SqliteRowResultItem[] }; +export type ValueInteger = { tag: 'integer'; val: number | bigint }; +export type ValueReal = { tag: 'real'; val: number | bigint }; +export type ValueText = { tag: 'text'; val: string }; +export type ValueBlob = { tag: 'blob'; val: Uint8Array }; +export type ValueNull = { tag: 'null' }; interface SpinSqliteResult { - columns: string[] - rows: SqliteRowResult[] + columns: string[]; + rows: SqliteRowResult[]; } export interface SqliteResult { - columns: string[] - rows: { [key: string]: number | bigint | null | string | Uint8Array }[] + columns: string[]; + rows: { [key: string]: number | bigint | null | string | Uint8Array }[]; } export interface SqliteConnection { - execute: (statement: string, parameters: ParameterValue[]) => SqliteResult + execute: (statement: string, parameters: ParameterValue[]) => SqliteResult; } -function createSqliteConnection(connection: spinSqlite.Connection): SqliteConnection { - return { - execute: (statement: string, parameters: ParameterValue[]): SqliteResult => { - let santizedParams = convertToWitTypes(parameters) - let ret = connection.execute(statement, santizedParams) as SpinSqliteResult - let results: SqliteResult = { - columns: ret.columns, - rows: [] - } - ret.rows.map((k: SqliteRowResult, rowIndex: number) => { - results.rows.push({}) - k.values.map((val, valIndex: number) => { - results.rows[rowIndex][results.columns[valIndex]] = val.val - }) - }) - return results - } - } +function createSqliteConnection( + connection: spinSqlite.Connection, +): SqliteConnection { + return { + execute: ( + statement: string, + parameters: ParameterValue[], + ): SqliteResult => { + let santizedParams = convertToWitTypes(parameters); + let ret = connection.execute( + statement, + santizedParams, + ) as SpinSqliteResult; + let results: SqliteResult = { + columns: ret.columns, + rows: [], + }; + ret.rows.map((k: SqliteRowResult, rowIndex: number) => { + results.rows.push({}); + k.values.map((val, valIndex: number) => { + results.rows[rowIndex][results.columns[valIndex]] = val.val; + }); + }); + return results; + }, + }; } export function open(label: string): SqliteConnection { - return createSqliteConnection(spinSqlite.Connection.open(label)) + return createSqliteConnection(spinSqlite.Connection.open(label)); } export function openDefault(): SqliteConnection { - return createSqliteConnection(spinSqlite.Connection.open("default")) + return createSqliteConnection(spinSqlite.Connection.open('default')); } const valueInteger = (value: number | bigint): ValueInteger => { - return { tag: "integer", val: value } -} + return { tag: 'integer', val: value }; +}; const valueReal = (value: number | bigint): ValueReal => { - return { tag: "real", val: value } -} + return { tag: 'real', val: value }; +}; const valueText = (value: string): ValueText => { - return { tag: "text", val: value } -} + return { tag: 'text', val: value }; +}; const valueBlob = (value: Uint8Array): ValueBlob => { - return { tag: "blob", val: value } -} + return { tag: 'blob', val: value }; +}; const valueNull = (): ValueNull => { - return { tag: "null" } -} + return { tag: 'null' }; +}; function convertToWitTypes(parameters: ParameterValue[]): sqliteValues[] { - let sanitized: sqliteValues[] = [] - for (let k of parameters) { - if (typeof (k) === "object") { - - sanitized.push(k as sqliteValues) - continue - } - if (typeof (k) === "number") { - isFloat(k) ? sanitized.push(valueReal(k)) : sanitized.push(valueInteger(k)) - continue - } - if (typeof (k) === "bigint") { - sanitized.push(valueInteger(k)) - continue - } - if (typeof (k) === "string") { - sanitized.push(valueText(k)) - continue - } - if (k === null) { - sanitized.push(valueNull()) - continue - } - if (k as any instanceof Uint8Array) { - sanitized.push(valueBlob(k)); - continue; - } + let sanitized: sqliteValues[] = []; + for (let k of parameters) { + if (typeof k === 'object') { + sanitized.push(k as sqliteValues); + continue; + } + if (typeof k === 'number') { + isFloat(k) + ? sanitized.push(valueReal(k)) + : sanitized.push(valueInteger(k)); + continue; + } + if (typeof k === 'bigint') { + sanitized.push(valueInteger(k)); + continue; + } + if (typeof k === 'string') { + sanitized.push(valueText(k)); + continue; + } + if (k === null) { + sanitized.push(valueNull()); + continue; + } + if ((k as any) instanceof Uint8Array) { + sanitized.push(valueBlob(k)); + continue; } - return sanitized + } + return sanitized; } function isFloat(number: number) { - return number % 1 !== 0; + return number % 1 !== 0; } diff --git a/src/types/rdbms.d.ts b/src/types/rdbms.d.ts index 2478853a..2f4b5ea5 100644 --- a/src/types/rdbms.d.ts +++ b/src/types/rdbms.d.ts @@ -1,100 +1,108 @@ -export type RdbmsValueBoolean = { tag: "boolean"; val: boolean }; -export type RdbmsValueInt8 = { tag: "int8"; val: number }; -export type RdbmsValueInt16 = { tag: "int16"; val: number }; -export type RdbmsValueInt32 = { tag: "int32"; val: number }; -export type RdbmsValueInt64 = { tag: "int64"; val: bigint }; -export type RdbmsValueUint8 = { tag: "uint8"; val: number }; -export type RdbmsValueUint16 = { tag: "uint16"; val: number }; -export type RdbmsValueUint32 = { tag: "uint32"; val: number }; -export type RdbmsValueUint64 = { tag: "uint64"; val: bigint }; -export type RdbmsValueFloating32 = { tag: "floating32"; val: number }; -export type RdbmsValueFloating64 = { tag: "floating64"; val: number }; -export type RdbmsValueStr = { tag: "str"; val: string }; -export type RdbmsValueBinary = { tag: "binary"; val: Uint8Array }; -export type RdbmsValueDbNull = { tag: "db-null" }; +export type RdbmsValueBoolean = { tag: 'boolean'; val: boolean }; +export type RdbmsValueInt8 = { tag: 'int8'; val: number }; +export type RdbmsValueInt16 = { tag: 'int16'; val: number }; +export type RdbmsValueInt32 = { tag: 'int32'; val: number }; +export type RdbmsValueInt64 = { tag: 'int64'; val: bigint }; +export type RdbmsValueUint8 = { tag: 'uint8'; val: number }; +export type RdbmsValueUint16 = { tag: 'uint16'; val: number }; +export type RdbmsValueUint32 = { tag: 'uint32'; val: number }; +export type RdbmsValueUint64 = { tag: 'uint64'; val: bigint }; +export type RdbmsValueFloating32 = { tag: 'floating32'; val: number }; +export type RdbmsValueFloating64 = { tag: 'floating64'; val: number }; +export type RdbmsValueStr = { tag: 'str'; val: string }; +export type RdbmsValueBinary = { tag: 'binary'; val: Uint8Array }; +export type RdbmsValueDbNull = { tag: 'db-null' }; export type SpinRdbmsParameterValue = - | RdbmsValueBoolean - | RdbmsValueInt8 - | RdbmsValueInt16 - | RdbmsValueInt32 - | RdbmsValueInt64 - | RdbmsValueUint8 - | RdbmsValueUint16 - | RdbmsValueUint32 - | RdbmsValueUint64 - | RdbmsValueFloating32 - | RdbmsValueFloating64 - | RdbmsValueStr - | RdbmsValueBinary - | RdbmsValueDbNull; + | RdbmsValueBoolean + | RdbmsValueInt8 + | RdbmsValueInt16 + | RdbmsValueInt32 + | RdbmsValueInt64 + | RdbmsValueUint8 + | RdbmsValueUint16 + | RdbmsValueUint32 + | RdbmsValueUint64 + | RdbmsValueFloating32 + | RdbmsValueFloating64 + | RdbmsValueStr + | RdbmsValueBinary + | RdbmsValueDbNull; -export type RdbmsParameterValue = SpinRdbmsParameterValue | number | bigint | boolean | null | Uint8Array | string +export type RdbmsParameterValue = + | SpinRdbmsParameterValue + | number + | bigint + | boolean + | null + | Uint8Array + | string; export interface RdbmsColumn { - name: string - dataType: RdbmsDataType[] + name: string; + dataType: RdbmsDataType[]; } -export type RdbmsRow = RdbmsDbValue[] +export type RdbmsRow = RdbmsDbValue[]; export interface SpinRdbmsRowSet { - columns: RdbmsColumn[] - rows: RdbmsRow[] + columns: RdbmsColumn[]; + rows: RdbmsRow[]; } export interface RdbmsRowSet { - columns: RdbmsColumn[] - rows: { [key: string]: number | boolean | bigint | null | string | Uint8Array }[] + columns: RdbmsColumn[]; + rows: { + [key: string]: number | boolean | bigint | null | string | Uint8Array; + }[]; } -export type RdbmsDbBoolean = { tag: "boolean"; val: boolean }; -export type RdbmsDbInt8 = { tag: "int8"; val: number }; -export type RdbmsDbInt16 = { tag: "int16"; val: number }; -export type RdbmsDbInt32 = { tag: "int32"; val: number }; -export type RdbmsDbInt64 = { tag: "int64"; val: number }; -export type RdbmsDbUint8 = { tag: "uint8"; val: number }; -export type RdbmsDbUint16 = { tag: "uint16"; val: number }; -export type RdbmsDbUint32 = { tag: "uint32"; val: number }; -export type RdbmsDbUint64 = { tag: "uint64"; val: number }; -export type RdbmsDbFloating32 = { tag: "floating32"; val: number }; -export type RdbmsDbFloating64 = { tag: "floating64"; val: number }; -export type RdbmsDbStr = { tag: "str"; val: string }; -export type RdbmsDbBinary = { tag: "binary"; val: Uint8Array }; -export type RdbmsDbNull = { tag: "db-null" }; -export type RdbmsDbUnsupported = { tag: "unsupported" }; +export type RdbmsDbBoolean = { tag: 'boolean'; val: boolean }; +export type RdbmsDbInt8 = { tag: 'int8'; val: number }; +export type RdbmsDbInt16 = { tag: 'int16'; val: number }; +export type RdbmsDbInt32 = { tag: 'int32'; val: number }; +export type RdbmsDbInt64 = { tag: 'int64'; val: number }; +export type RdbmsDbUint8 = { tag: 'uint8'; val: number }; +export type RdbmsDbUint16 = { tag: 'uint16'; val: number }; +export type RdbmsDbUint32 = { tag: 'uint32'; val: number }; +export type RdbmsDbUint64 = { tag: 'uint64'; val: number }; +export type RdbmsDbFloating32 = { tag: 'floating32'; val: number }; +export type RdbmsDbFloating64 = { tag: 'floating64'; val: number }; +export type RdbmsDbStr = { tag: 'str'; val: string }; +export type RdbmsDbBinary = { tag: 'binary'; val: Uint8Array }; +export type RdbmsDbNull = { tag: 'db-null' }; +export type RdbmsDbUnsupported = { tag: 'unsupported' }; export type RdbmsDbValue = - | RdbmsDbBoolean - | RdbmsDbInt8 - | RdbmsDbInt16 - | RdbmsDbInt32 - | RdbmsDbInt64 - | RdbmsDbUint8 - | RdbmsDbUint16 - | RdbmsDbUint32 - | RdbmsDbUint64 - | RdbmsDbFloating32 - | RdbmsDbFloating64 - | RdbmsDbStr - | RdbmsDbBinary - | RdbmsDbNull - | RdbmsDbUnsupported; - + | RdbmsDbBoolean + | RdbmsDbInt8 + | RdbmsDbInt16 + | RdbmsDbInt32 + | RdbmsDbInt64 + | RdbmsDbUint8 + | RdbmsDbUint16 + | RdbmsDbUint32 + | RdbmsDbUint64 + | RdbmsDbFloating32 + | RdbmsDbFloating64 + | RdbmsDbStr + | RdbmsDbBinary + | RdbmsDbNull + | RdbmsDbUnsupported; export enum RdbmsDataType { - RdbmsBoolean = "boolean", - RdbmsInt8 = "int8", - RdbmsInt16 = "int16", - RdbmsInt32 = "int32", - RdbmsInt64 = "int64", - RdbmsUint8 = "uint8", - RdbmsUint16 = "uint16", - RdbmsUint32 = "uint32", - RdbmsUint64 = "uint64", - RdbmsFloating32 = "floating32", - RdbmsFloating64 = "floating64", - RdbmsStr = "str", - RdbmsBinary = "binary", - RdbmsOther = "other" -} \ No newline at end of file + RdbmsBoolean = 'boolean', + RdbmsInt8 = 'int8', + RdbmsInt16 = 'int16', + RdbmsInt32 = 'int32', + RdbmsInt64 = 'int64', + RdbmsUint8 = 'uint8', + RdbmsUint16 = 'uint16', + RdbmsUint32 = 'uint32', + RdbmsUint64 = 'uint64', + RdbmsFloating32 = 'floating32', + RdbmsFloating64 = 'floating64', + RdbmsStr = 'str', + RdbmsBinary = 'binary', + RdbmsOther = 'other', +} diff --git a/src/types/wasi-http.d.ts b/src/types/wasi-http.d.ts index 4b3303a2..be4852cb 100644 --- a/src/types/wasi-http.d.ts +++ b/src/types/wasi-http.d.ts @@ -1,123 +1,136 @@ export interface method { - tag: "get" | "head" | "post" | "put" | "delete" | "connect" | "options" | "trace" | "patch" | { kind: "other", value: string } + tag: + | 'get' + | 'head' + | 'post' + | 'put' + | 'delete' + | 'connect' + | 'options' + | 'trace' + | 'patch' + | { kind: 'other'; value: string }; } export interface schema { - tag: "HTTP" | "HTTPS" | { kind: "other", value: string } + tag: 'HTTP' | 'HTTPS' | { kind: 'other'; value: string }; } -export type FieldValue = Uint8Array -export type FieldKey = string +export type FieldValue = Uint8Array; +export type FieldKey = string; export declare class headers { - constructor() - static fromList: (entries: [FieldKey, FieldValue][]) => headers - get: (name: FieldKey) => FieldValue[] - has: (name: FieldKey) => boolean - set: (name: FieldKey, value: FieldValue) => void - delete: (name: FieldKey) => void - append: (name: FieldKey, value: FieldValue) => void - entries: () => [FieldKey, FieldValue][] - clone: () => headers + constructor(); + static fromList: (entries: [FieldKey, FieldValue][]) => headers; + get: (name: FieldKey) => FieldValue[]; + has: (name: FieldKey) => boolean; + set: (name: FieldKey, value: FieldValue) => void; + delete: (name: FieldKey) => void; + append: (name: FieldKey, value: FieldValue) => void; + entries: () => [FieldKey, FieldValue][]; + clone: () => headers; } -export type trailers = headers | { tag: "none" } +export type trailers = headers | { tag: 'none' }; export interface Pollable { - read: () => boolean - block: () => void + read: () => boolean; + block: () => void; } export interface InputStream { - read: (len: number) => Uint8Array - blockingRead: (len: number) => Uint8Array - skip: (len: number) => Uint8Array - blockingSkip: (len: number) => Uint8Array - subscribe: () => Pollable + read: (len: number) => Uint8Array; + blockingRead: (len: number) => Uint8Array; + skip: (len: number) => Uint8Array; + blockingSkip: (len: number) => Uint8Array; + subscribe: () => Pollable; } export interface FutureTrailers { - subscribe: () => Pollable - get: () => trailers | null + subscribe: () => Pollable; + get: () => trailers | null; } export declare class IncomingBody { - stream: () => InputStream - static finish: (incomingBody: IncomingBody) => FutureTrailers + stream: () => InputStream; + static finish: (incomingBody: IncomingBody) => FutureTrailers; } export interface OutputStream { - checkWrite: () => bigint - write: (content: Uint8Array) => void - blockingWriteAndFlush: (content: Uint8Array) => void - flush: () => void - blockingFlush: () => void - subscribe: () => Pollable - writeZeros: (len: number) => void - blockingWriteZerosAndFlush: (len: number) => void - splice: (src: InputStream, len: number) => number - blockingSplice: (src: InputStream, len: number) => number - [Symbol.dispose](): void + checkWrite: () => bigint; + write: (content: Uint8Array) => void; + blockingWriteAndFlush: (content: Uint8Array) => void; + flush: () => void; + blockingFlush: () => void; + subscribe: () => Pollable; + writeZeros: (len: number) => void; + blockingWriteZerosAndFlush: (len: number) => void; + splice: (src: InputStream, len: number) => number; + blockingSplice: (src: InputStream, len: number) => number; + [Symbol.dispose](): void; } export declare class OutgoingBody { - write: () => OutputStream - static finish: (outgoingBody: OutgoingBody, trailers: trailers | null) => void + write: () => OutputStream; + static finish: ( + outgoingBody: OutgoingBody, + trailers: trailers | null, + ) => void; } export interface IncomingRequest { - method: () => method; - - /// Returns the path with query parameters from the request, as a string. - pathWithQuery: () => string | null; - - /// Returns the protocol scheme from the request. - scheme: () => scheme; - - /// Returns the authority from the request, if it was present. - authority: () => string; - - /// Get the `headers` associated with the request. - /// - /// The returned `headers` resource is immutable: `set`, `append`, and - /// `delete` operations will fail with `header-error.immutable`. - /// - /// The `headers` returned are a child resource: it must be dropped before - /// the parent `incoming-request` is dropped. Dropping this - /// `incoming-request` before all children are dropped will trap. - headers: () => headers; - - /// Gives the `incoming-body` associated with this request. Will only - /// return success at most once, and subsequent calls will return error. - consume: () => IncomingBody; + method: () => method; + + /// Returns the path with query parameters from the request, as a string. + pathWithQuery: () => string | null; + + /// Returns the protocol scheme from the request. + scheme: () => scheme; + + /// Returns the authority from the request, if it was present. + authority: () => string; + + /// Get the `headers` associated with the request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// The `headers` returned are a child resource: it must be dropped before + /// the parent `incoming-request` is dropped. Dropping this + /// `incoming-request` before all children are dropped will trap. + headers: () => headers; + + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + consume: () => IncomingBody; } export declare class OutgoingResponse { - constructor(headers: headers) - /// Get the HTTP Status Code for the Response. - statusCode: () => number; - - /// Set the HTTP Status Code for the Response. Fails if the status-code - /// given is not a valid http status code. - setStatusCode: (statusCode: number) => void; - - /// Get the headers associated with the Request. - /// - /// The returned `headers` resource is immutable: `set`, `append`, and - /// `delete` operations will fail with `header-error.immutable`. - /// - /// This headers resource is a child: it must be dropped before the parent - /// `outgoing-request` is dropped, or its ownership is transfered to - /// another component by e.g. `outgoing-handler.handle`. - headers: () => headers; - - /// Returns the resource corresponding to the outgoing Body for this Response. - /// - /// Returns success on the first call: the `outgoing-body` resource for - /// this `outgoing-response` can be retrieved at most once. Subsequent - /// calls will return error. - body: () => OutgoingBody; + constructor(headers: headers); + /// Get the HTTP Status Code for the Response. + statusCode: () => number; + + /// Set the HTTP Status Code for the Response. Fails if the status-code + /// given is not a valid http status code. + setStatusCode: (statusCode: number) => void; + + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transfered to + /// another component by e.g. `outgoing-handler.handle`. + headers: () => headers; + + /// Returns the resource corresponding to the outgoing Body for this Response. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-response` can be retrieved at most once. Subsequent + /// calls will return error. + body: () => OutgoingBody; } export declare class ResponseOutparam { - static set: (param: ResponseOutparam, response: OutgoingResponse) => void -} \ No newline at end of file + static set: (param: ResponseOutparam, response: OutgoingResponse) => void; +} diff --git a/src/variables.ts b/src/variables.ts index 50f37ca1..33bd4049 100644 --- a/src/variables.ts +++ b/src/variables.ts @@ -1,10 +1,10 @@ //@ts-ignore -import { get as spinGet } from "fermyon:spin/variables@2.0.0" +import { get as spinGet } from 'fermyon:spin/variables@2.0.0'; export function get(key: string): string | null { - try { - return spinGet(key) - } catch (e) { - return null - } + try { + return spinGet(key); + } catch (e) { + return null; + } } diff --git a/test/test-app/.gitignore b/test/test-app/.gitignore new file mode 100644 index 00000000..1ba44682 --- /dev/null +++ b/test/test-app/.gitignore @@ -0,0 +1,5 @@ +node_modules +dist +target +.spin/ +dist.js \ No newline at end of file diff --git a/test/test-app/package-lock.json b/test/test-app/package-lock.json new file mode 100644 index 00000000..29a8dd37 --- /dev/null +++ b/test/test-app/package-lock.json @@ -0,0 +1,2154 @@ +{ + "name": "test-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "test-app", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@fermyon/spin-sdk": "^2.0.0-alpha.1" + }, + "devDependencies": { + "@bytecodealliance/componentize-js": "^0.8.3", + "mkdirp": "^3.0.1", + "ts-loader": "^9.4.1", + "typescript": "^4.8.4", + "webpack": "^5.74.0", + "webpack-cli": "^4.10.0", + "yargs": "^17.7.2" + } + }, + "node_modules/@bytecodealliance/componentize-js": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@bytecodealliance/componentize-js/-/componentize-js-0.8.3.tgz", + "integrity": "sha512-QyEHRtVg/Cg6RsA75AvRSbSOr0u+FLuXqB89X4Sys44K/VT5g/S9eMn8gqTotfuXVU3btS3Z4QAiyHSF2bja3w==", + "workspaces": [ + "." + ], + "dependencies": { + "@bytecodealliance/jco": "1.1.1", + "@bytecodealliance/wizer": "^3.0.1", + "es-module-lexer": "^1.4.1" + } + }, + "node_modules/@bytecodealliance/jco": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/jco/-/jco-1.1.1.tgz", + "integrity": "sha512-s8Zz6GFPlo2g+dsGp1OMIWXSZnM4FyIloxNAc4grF5TZwFoD00Gj8b0xvpmFSeZj36X/bJPa7x3za3j7Cfeetw==", + "workspaces": [ + "packages/preview2-shim" + ], + "dependencies": { + "@bytecodealliance/preview2-shim": "^0.16.1", + "binaryen": "^116.0.0", + "chalk-template": "^1", + "commander": "^12", + "mkdirp": "^3", + "ora": "^8", + "terser": "^5" + }, + "bin": { + "jco": "src/jco.js" + } + }, + "node_modules/@bytecodealliance/preview2-shim": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.2.tgz", + "integrity": "sha512-36MwesmbLSf3Y5/OHcS85iBaF0N92CQ4gpjtDVKSbrjxmrBKCWlWVfoQ03F/cqDg8k5K7pzVaVBH0XBIbTCfTQ==" + }, + "node_modules/@bytecodealliance/wizer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer/-/wizer-3.0.1.tgz", + "integrity": "sha512-f0NBiBHCNBkbFHTPRbA7aKf/t4KyNhi2KvSqw3QzCgi8wFF/uLZ0dhejj93rbiKO/iwWbmU7v9K3SVkW81mcjQ==", + "bin": { + "wizer": "wizer.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@bytecodealliance/wizer-darwin-arm64": "3.0.1", + "@bytecodealliance/wizer-darwin-x64": "3.0.1", + "@bytecodealliance/wizer-linux-arm64": "3.0.1", + "@bytecodealliance/wizer-linux-s390x": "3.0.1", + "@bytecodealliance/wizer-linux-x64": "3.0.1", + "@bytecodealliance/wizer-win32-x64": "3.0.1" + } + }, + "node_modules/@bytecodealliance/wizer-darwin-arm64": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer-darwin-arm64/-/wizer-darwin-arm64-3.0.1.tgz", + "integrity": "sha512-/8KYSajyhO9koAE3qQhYfC6belZheJw9X3XqW7hrizTpj6n4z4OJFhhqwJmiYFUUsPtC7OxcXMFFPbTuSQPBcw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "bin": { + "wizer-darwin-arm64": "wizer" + } + }, + "node_modules/@bytecodealliance/wizer-darwin-x64": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer-darwin-x64/-/wizer-darwin-x64-3.0.1.tgz", + "integrity": "sha512-bMReultN/r+W/BRXV0F+28U5dZwbQT/ZO0k4icZlhUhrv5/wpQJix7Z/ZvBnVQ+/JHb0QDUpFk2/zCtgkRXP6Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "bin": { + "wizer-darwin-x64": "wizer" + } + }, + "node_modules/@bytecodealliance/wizer-linux-arm64": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer-linux-arm64/-/wizer-linux-arm64-3.0.1.tgz", + "integrity": "sha512-35ZhAeYxWK3bTqqgwysbBWlGlrlMNKNng3ZITQV2PAtafpE7aCeqywl7VAS4lLRG5eTb7wxNgN7zf8d3wiIFTQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "bin": { + "wizer-linux-arm64": "wizer" + } + }, + "node_modules/@bytecodealliance/wizer-linux-s390x": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer-linux-s390x/-/wizer-linux-s390x-3.0.1.tgz", + "integrity": "sha512-Smvy9mguEMtX0lupDLTPshXUzAHeOhgscr1bhGNjeCCLD1sd8rIjBvWV19Wtra0BL1zTuU2EPOHjR/4k8WoyDg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "bin": { + "wizer-linux-s390x": "wizer" + } + }, + "node_modules/@bytecodealliance/wizer-linux-x64": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer-linux-x64/-/wizer-linux-x64-3.0.1.tgz", + "integrity": "sha512-uUue78xl7iwndsGgTsagHLTLyLBVHhwzuywiwHt1xw8y0X0O8REKRLBoB7+LdM+pttDPdFtKJgbTFL4UPAA7Yw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "bin": { + "wizer-linux-x64": "wizer" + } + }, + "node_modules/@bytecodealliance/wizer-win32-x64": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/wizer-win32-x64/-/wizer-win32-x64-3.0.1.tgz", + "integrity": "sha512-ycd38sx1UTZpHZwh8IfH/4N3n0OQUB8awxkUSLXf9PolEd088YbxoPB3noHy4E+L2oYN7KZMrg9517pX0z2RhQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "bin": { + "wizer-win32-x64": "wizer" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@fermyon/spin-sdk": { + "version": "2.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/@fermyon/spin-sdk/-/spin-sdk-2.0.0-alpha.1.tgz", + "integrity": "sha512-XKLUDgWQfbPYpxVdWjwN1K5nXJVK9KR9G3zfm2VDA8u4QUAWpWXd0PzoHZrrkMDCfTtRUBmyTBJfCoosFZ92hA==", + "dependencies": { + "@bytecodealliance/componentize-js": "^0.8.3", + "itty-router": "^3.0.12", + "yargs": "^17.7.2" + }, + "bin": { + "j2w": "bin/j2w.mjs" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/binaryen": { + "version": "116.0.0", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-116.0.0.tgz", + "integrity": "sha512-Hp0dXC6Cb/rTwWEoUS2BRghObE7g/S9umKtxuTDt3f61G6fNTE/YVew/ezyy3IdHcLx3f17qfh6LwETgCfvWkQ==", + "bin": { + "wasm-opt": "bin/wasm-opt", + "wasm2js": "bin/wasm2js" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001618", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001618.tgz", + "integrity": "sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", + "dependencies": { + "chalk": "^5.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", + "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.769", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.769.tgz", + "integrity": "sha512-bZu7p623NEA2rHTc9K1vykl57ektSPQYFFqQir8BOYf6EKOB+yIsbFB9Kpm7Cgt6tsLr9sRkqfqSZUw7LP1XxQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/enhanced-resolve": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", + "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.2.tgz", + "integrity": "sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA==" + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/itty-router": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/itty-router/-/itty-router-3.0.12.tgz", + "integrity": "sha512-s98XTPhle6GGbaFf0kYrOD3Q8gyhnqvOqkwYijC3AmkceNKqWUp13YHg6dWmqmVv4pP7l7c94XI92I0EXVGO0w==" + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", + "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.91.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", + "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.16.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/test/test-app/package.json b/test/test-app/package.json new file mode 100644 index 00000000..9d3a5cc4 --- /dev/null +++ b/test/test-app/package.json @@ -0,0 +1,25 @@ +{ + "name": "test-app", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "npx webpack --mode=production && npx mkdirp target && npx j2w -i dist.js -n spin-http -o target/test-app.wasm", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "mkdirp": "^3.0.1", + "ts-loader": "^9.4.1", + "typescript": "^4.8.4", + "webpack": "^5.74.0", + "webpack-cli": "^4.10.0", + "@bytecodealliance/componentize-js": "^0.8.3", + "yargs": "^17.7.2" + }, + "dependencies": { + "@fermyon/spin-sdk": "^2.0.0-alpha.1" + } +} \ No newline at end of file diff --git a/test/test-app/spin.toml b/test/test-app/spin.toml new file mode 100644 index 00000000..f6d0f76e --- /dev/null +++ b/test/test-app/spin.toml @@ -0,0 +1,18 @@ +spin_manifest_version = 2 + +[application] +authors = ["karthik2804 "] +description = "" +name = "test-app" +version = "0.1.0" + +[[trigger.http]] +route = "/..." +component = "test-app" + +[component.test-app] +source = "target/test-app.wasm" +exclude_files = ["**/node_modules"] +[component.test-app.build] +command = "npm run build" +watch = ["src/**/*.ts", "package.json"] \ No newline at end of file diff --git a/test/test-app/src/index.ts b/test/test-app/src/index.ts new file mode 100644 index 00000000..a5e46e5e --- /dev/null +++ b/test/test-app/src/index.ts @@ -0,0 +1,11 @@ +import { HttpRequest, ResponseBuilder, Router } from "@fermyon/spin-sdk"; +import { testFunctionality, health } from "./test"; + +let router = Router() + +router.get("/", async (_, req, res) => { await testFunctionality(req, res) }) +router.get("/health", async (_, req, res) => { await health(req, res) }) + +export async function handler(req: HttpRequest, res: ResponseBuilder) { + await router.handleRequest(req, res) +} diff --git a/test/test-app/src/spin.ts b/test/test-app/src/spin.ts new file mode 100644 index 00000000..609ed478 --- /dev/null +++ b/test/test-app/src/spin.ts @@ -0,0 +1,10 @@ +import { HttpHandler, HttpRequest, ResponseBuilder } from "@fermyon/spin-sdk"; +import { handler } from "."; + +class App extends HttpHandler { + handleRequest(req: HttpRequest, res: ResponseBuilder): Promise { + return handler(req, res) + } +} + +export const incomingHandler = new App() diff --git a/test/test-app/src/test.ts b/test/test-app/src/test.ts new file mode 100644 index 00000000..5237b482 --- /dev/null +++ b/test/test-app/src/test.ts @@ -0,0 +1,20 @@ +import { HttpRequest, ResponseBuilder } from "@fermyon/spin-sdk"; + +const encoder = new TextEncoder() +const decoder = new TextDecoder() + +function health(req: HttpRequest, res: ResponseBuilder) { + res.status(200) + res.send("Server is healthy") +} + +async function testFunctionality(req: HttpRequest, res: ResponseBuilder) { + //TODO: Add tests once fetch is available + res.status(200) + res.send("test completed successfully") +} + +export { + health, + testFunctionality +} \ No newline at end of file diff --git a/test/test-app/tsconfig.json b/test/test-app/tsconfig.json new file mode 100644 index 00000000..8d86d98b --- /dev/null +++ b/test/test-app/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "outDir": "./dist/", + "noImplicitAny": true, + "module": "es6", + "target": "es2020", + "jsx": "react", + "skipLibCheck": true, + "lib": [ + "ES2015" + ], + "allowJs": true, + "strict": true, + "noImplicitReturns": true, + "moduleResolution": "node" + } +} \ No newline at end of file diff --git a/test/test-app/webpack.config.js b/test/test-app/webpack.config.js new file mode 100644 index 00000000..6b624f55 --- /dev/null +++ b/test/test-app/webpack.config.js @@ -0,0 +1,35 @@ +const path = require('path'); +const SpinSdkPlugin = require("@fermyon/spin-sdk/plugins/webpack") + +module.exports = { + entry: './src/spin.ts', + experiments: { + outputModule: true, + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + }, + output: { + path: path.resolve(__dirname, './'), + filename: 'dist.js', + module: true, + library: { + type: "module", + } + }, + plugins: [ + new SpinSdkPlugin() + ], + optimization: { + minimize: false + }, +}; \ No newline at end of file diff --git a/test/test.sh b/test/test.sh new file mode 100755 index 00000000..eb1e0256 --- /dev/null +++ b/test/test.sh @@ -0,0 +1,39 @@ +set -euo pipefail + +# Build the npm package +cd .. +npm install +npm run build +cd - + +isFailed=false +# Build test app +echo "Building the test app" +cd test-app +npm install > /dev/null +spin build > /dev/null +echo "built the test app successfully" + + +# Start the spin app in the background +echo "Starting Spin app" +spin up & + +# wait for app to be up and running +echo "Waiting for Spin app to be ready" +timeout 60s bash -c 'until curl --silent -f http://localhost:3000/health > /dev/null; do sleep 2; done' + +# start the test +echo "Starting test\n" +curl -f http://localhost:3000 || isFailed=true +echo "\n\nTest completed" + +# kill the spin app +echo "Stopping Spin" +killall spin + + +if [ "$isFailed" = true ] ; then + echo "Some tests failed" + exit 1 +fi \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 5a898ecf..e11bf930 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,6 +19,7 @@ "exclude": [ "templates/**/*", "lib/**/*", - "bin/**/*" + "bin/**/*", + "test/**/*" ] } \ No newline at end of file