diff --git a/.depcheckrc.yml b/.depcheckrc.yml index e384655d5..8e0cd2291 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -39,6 +39,9 @@ ignores: - 'typescript' - 'typescript-plugin-css-modules' + # Used by @ocap/nodejs to build the sqlite3 bindings + - 'node-gyp' + # These are peer dependencies of various modules we actually do # depend on, which have been elevated to full dependencies (even # though we don't actually depend on them) in order to work around a diff --git a/package.json b/package.json index 7d50b773e..31153b036 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "test": "vitest run", "test:clean": "yarn test --no-cache --coverage.clean", "test:dev": "yarn test --coverage false", + "test:e2e:ci": "yarn workspaces foreach --all run test:e2e:ci", "test:verbose": "yarn test --reporter verbose", "test:watch": "vitest", "why:batch": "./scripts/why-batch.sh" diff --git a/packages/nodejs/CHANGELOG.md b/packages/nodejs/CHANGELOG.md new file mode 100644 index 000000000..0c82cb1ed --- /dev/null +++ b/packages/nodejs/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +[Unreleased]: https://github.com/MetaMask/ocap-kernel/ diff --git a/packages/nodejs/README.md b/packages/nodejs/README.md new file mode 100644 index 000000000..0910528ff --- /dev/null +++ b/packages/nodejs/README.md @@ -0,0 +1,35 @@ +# `@ocap/nodejs` + +For running Ocap Kernel experiments in a Node.js environment + +## Installation + +`yarn add @ocap/nodejs` + +or + +`npm install @ocap/nodejs` + +## Contributing + +This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/ocap-kernel#readme). + +## End-to-End Tests + +Navigate to package root. + +```sh +cd ~/path/to/ocap-kernel/packages/nodejs +``` + +If it's not already running, start the `@ocap/cli` in `extension/src/vats/`. + +```sh +yarn ocap start ../extension/src/vats +``` + +Then, run the end to end tests. + +```sh +yarn test:e2e +``` diff --git a/packages/nodejs/package.json b/packages/nodejs/package.json new file mode 100644 index 000000000..80dd95739 --- /dev/null +++ b/packages/nodejs/package.json @@ -0,0 +1,90 @@ +{ + "name": "@ocap/nodejs", + "version": "0.0.0", + "private": true, + "description": "For running Ocap Kernel experiments in a Node.js environment", + "homepage": "https://github.com/MetaMask/ocap-kernel/tree/main/packages/nodejs#readme", + "bugs": { + "url": "https://github.com/MetaMask/ocap-kernel/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/MetaMask/ocap-kernel.git" + }, + "type": "module", + "exports": { + "./package.json": "./package.json" + }, + "files": [ + "dist/" + ], + "scripts": { + "build": "ts-bridge --project tsconfig.build.json --clean && yarn build:sqlite3", + "build:e2e": "ts-bridge --project tsconfig.build.json --clean && yarn build:sqlite3 -f", + "build:sqlite3": "scripts/build-sqlite3.sh", + "build:docs": "typedoc", + "changelog:validate": "../../scripts/validate-changelog.sh @ocap/nodejs", + "clean": "rimraf --glob './*.tsbuildinfo' ./dist ./.eslintcache", + "lint": "yarn lint:ts && yarn lint:eslint && yarn lint:misc --check && yarn constraints && yarn lint:dependencies", + "lint:dependencies": "depcheck", + "lint:eslint": "eslint . --cache", + "lint:fix": "yarn lint:ts && yarn lint:eslint --fix && yarn lint:misc --write && yarn constraints --fix && yarn lint:dependencies", + "lint:misc": "prettier --no-error-on-unmatched-pattern '**/*.json' '**/*.md' '**/*.html' '!**/CHANGELOG.old.md' '**/*.yml' '!.yarnrc.yml' '!merged-packages/**' --ignore-path ../../.gitignore", + "lint:ts": "tsc --project tsconfig.lint.json", + "publish:preview": "yarn npm publish --tag preview", + "test": "vitest run --config vitest.config.ts", + "test:e2e": "vitest run --config vitest.config.e2e.ts", + "test:e2e:ci": "./scripts/test-e2e-ci.sh", + "test:clean": "yarn test --no-cache --coverage.clean", + "test:dev": "yarn test --coverage false", + "test:verbose": "yarn test --reporter verbose", + "test:watch": "vitest --config vitest.config.ts" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.16.4", + "@metamask/auto-changelog": "^4.0.0", + "@metamask/eslint-config": "^14.0.0", + "@metamask/eslint-config-nodejs": "^14.0.0", + "@metamask/eslint-config-typescript": "^14.0.0", + "@ocap/cli": "workspace:^", + "@ts-bridge/cli": "^0.6.2", + "@ts-bridge/shims": "^0.1.1", + "@types/better-sqlite3": "^7.6.12", + "@typescript-eslint/eslint-plugin": "^8.8.1", + "@typescript-eslint/parser": "^8.8.1", + "@typescript-eslint/utils": "^8.8.1", + "@vitest/eslint-plugin": "^1.1.24", + "depcheck": "^1.4.7", + "eslint": "^9.12.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-import-x": "^4.3.1", + "eslint-plugin-jsdoc": "^50.3.1", + "eslint-plugin-n": "^17.11.1", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-promise": "^7.1.0", + "node-gyp": "^11.0.0", + "prettier": "^3.3.3", + "rimraf": "^6.0.1", + "typedoc": "^0.26.8", + "typescript": "~5.5.4", + "typescript-eslint": "^8.8.1", + "vite": "^5.3.5", + "vitest": "2.1.8" + }, + "engines": { + "node": "^20 || >=22" + }, + "dependencies": { + "@endo/exo": "^1.5.4", + "@endo/patterns": "^1.4.4", + "@endo/promise-kit": "^1.1.6", + "@metamask/utils": "^11.0.1", + "@ocap/kernel": "workspace:^", + "@ocap/shims": "workspace:^", + "@ocap/streams": "workspace:^", + "@ocap/utils": "workspace:^", + "better-sqlite3": "^11.7.2", + "ses": "^1.9.0" + } +} diff --git a/packages/nodejs/scripts/build-sqlite3.sh b/packages/nodejs/scripts/build-sqlite3.sh new file mode 100755 index 000000000..9f36e0e9d --- /dev/null +++ b/packages/nodejs/scripts/build-sqlite3.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# set -x +set -e +set -o pipefail + +dir=$(pwd) + +package_root="$(dirname "$0")/.." +cd "$package_root" +package_root=$(pwd) +monorepo_root="$package_root/../.." + +while getopts ":ab:" _; do + case $OPTARG in + f) force=1 ;; + \?) echo "Invalid option: -$OPTARG"; exit 1 ;; + esac +done + +if ! [ "$force" = "1" ] && [ -f "node_modules/better-sqlite3/build/better_sqlite3.node" ]; then + echo "Found better-sqlite3 bindings." + exit 0 +fi + +echo "Building better-sqlite3 bindings." + +# build better-sqlite at the monorepo root +cd "$monorepo_root" +cd node_modules/better-sqlite3 +yarn build-release + +# move back to the source folder +cd "$package_root" + +# copy the build to this package +mkdir -p node_modules/better-sqlite3/build/ +cp -r ../../node_modules/better-sqlite3/build/Release/ node_modules/better-sqlite3/build/ + +cd "$dir" diff --git a/packages/nodejs/scripts/test-e2e-ci.sh b/packages/nodejs/scripts/test-e2e-ci.sh new file mode 100755 index 000000000..56920fb1e --- /dev/null +++ b/packages/nodejs/scripts/test-e2e-ci.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -x +set -e +set -o pipefail + +# force build sqlite3 so it aligns with node version +yarn build:e2e + +# We borrow the vat definition from extension for now +yarn ocap bundle "../extension/src/vats" + +# Start the server in background and capture its PID +yarn ocap serve "../extension/src/vats" & +SERVER_PID=$! + +function cleanup() { + # Kill the server if it's still running + if kill -0 $SERVER_PID 2>/dev/null; then + kill $SERVER_PID + fi +} +# Ensure we always close the server +trap cleanup EXIT + +yarn test:e2e diff --git a/packages/nodejs/src/env/endoify.ts b/packages/nodejs/src/env/endoify.ts new file mode 100644 index 000000000..58ad152ae --- /dev/null +++ b/packages/nodejs/src/env/endoify.ts @@ -0,0 +1 @@ +import '@ocap/shims/endoify'; diff --git a/packages/nodejs/src/env/kernel-worker-trusted-prelude.js b/packages/nodejs/src/env/kernel-worker-trusted-prelude.js new file mode 100644 index 000000000..dad2cb379 --- /dev/null +++ b/packages/nodejs/src/env/kernel-worker-trusted-prelude.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import-x/no-unresolved +import './endoify.js'; diff --git a/packages/nodejs/src/kernel/VatWorkerService.test.ts b/packages/nodejs/src/kernel/VatWorkerService.test.ts new file mode 100644 index 000000000..d665cecfb --- /dev/null +++ b/packages/nodejs/src/kernel/VatWorkerService.test.ts @@ -0,0 +1,12 @@ +import '@ocap/shims/endoify'; + +import { describe, expect, it } from 'vitest'; + +import { NodejsVatWorkerService } from './VatWorkerService.js'; + +describe('NodejsVatWorkerService', () => { + it('constructs an instance without any arguments', () => { + const instance = new NodejsVatWorkerService(); + expect(instance).toBeInstanceOf(NodejsVatWorkerService); + }); +}); diff --git a/packages/nodejs/src/kernel/VatWorkerService.ts b/packages/nodejs/src/kernel/VatWorkerService.ts new file mode 100644 index 000000000..4692ebb9b --- /dev/null +++ b/packages/nodejs/src/kernel/VatWorkerService.ts @@ -0,0 +1,65 @@ +import { makePromiseKit } from '@endo/promise-kit'; +import type { VatWorkerService, VatId } from '@ocap/kernel'; +import { NodeWorkerMultiplexer, StreamMultiplexer } from '@ocap/streams'; +import { makeLogger } from '@ocap/utils'; +import type { Logger } from '@ocap/utils'; +import { Worker as NodeWorker } from 'node:worker_threads'; + +// Worker file loads from the built dist directory, requires rebuild after change +// Note: Worker runs in same process and may be subject to spectre-style attacks +const workerFileURL = new URL('../../dist/vat/vat-worker.mjs', import.meta.url) + .pathname; + +export class NodejsVatWorkerService implements VatWorkerService { + readonly #logger: Logger; + + workers = new Map< + VatId, + { worker: NodeWorker; multiplexer: StreamMultiplexer } + >(); + + /** + * The vat worker service, intended to be constructed in + * the kernel worker. + * + * @param logger - An optional {@link Logger}. Defaults to a new logger labeled '[vat worker client]'. + */ + constructor(logger?: Logger) { + this.#logger = logger ?? makeLogger('[vat worker service]'); + } + + async launch(vatId: VatId): Promise { + const { promise, resolve } = makePromiseKit(); + this.#logger.debug('launching', vatId); + const worker = new NodeWorker(workerFileURL, { + env: { + NODE_VAT_ID: vatId, + }, + }); + this.#logger.debug('launched', vatId); + worker.once('online', () => { + const multiplexer = new NodeWorkerMultiplexer(worker, 'vat'); + this.workers.set(vatId, { worker, multiplexer }); + resolve(multiplexer); + this.#logger.debug('connected', vatId); + }); + return promise; + } + + async terminate(vatId: VatId): Promise { + const workerEntry = this.workers.get(vatId); + assert(workerEntry, `No worker found for vatId ${vatId}`); + const { worker, multiplexer } = workerEntry; + await multiplexer.return(); + await worker.terminate(); + this.workers.delete(vatId); + return undefined; + } + + async terminateAll(): Promise { + for (const vatId of this.workers.keys()) { + await this.terminate(vatId); + } + } +} +harden(NodejsVatWorkerService); diff --git a/packages/nodejs/src/kernel/kernel-worker.ts b/packages/nodejs/src/kernel/kernel-worker.ts new file mode 100644 index 000000000..302bcb80f --- /dev/null +++ b/packages/nodejs/src/kernel/kernel-worker.ts @@ -0,0 +1,87 @@ +import '@ocap/shims/endoify'; +import type { NonEmptyArray } from '@metamask/utils'; +import type { KernelCommand, KernelCommandReply, VatId } from '@ocap/kernel'; +import { Kernel, VatCommandMethod } from '@ocap/kernel'; +import { NodeWorkerDuplexStream } from '@ocap/streams'; +import { MessagePort as NodeMessagePort } from 'worker_threads'; + +import { makeSQLKVStore } from './sqlite-kv-store.js'; +import { NodejsVatWorkerService } from './VatWorkerService.js'; + +/** + * The main function for the kernel worker. + * + * @param port - The kernel's end of a node:worker_threads MessageChannel + * @returns The kernel, initialized. + */ +export async function makeKernel(port: NodeMessagePort): Promise { + const nodeStream = new NodeWorkerDuplexStream< + KernelCommand, + KernelCommandReply + >(port); + const vatWorkerClient = new NodejsVatWorkerService(); + + // Initialize kernel store. + const kvStore = await makeSQLKVStore(); + + // Create and start kernel. + const kernel = new Kernel(nodeStream, vatWorkerClient, kvStore); + await kernel.init(); + + return kernel; +} + +/** + * Runs the full lifecycle of an array of vats, including their creation, + * restart, message passing, and termination. + * + * @param kernel The kernel instance. + * @param vats An array of VatIds to be managed. + */ +export async function runVatLifecycle( + kernel: Kernel, + vats: NonEmptyArray, +): Promise { + console.log('runVatLifecycle Start...'); + const vatLabel = vats.join(', '); + console.time(`Created vats: ${vatLabel}`); + await Promise.all( + vats.map( + async () => + await kernel.launchVat({ + bundleSpec: 'http://localhost:3000/sample-vat.bundle', + parameters: { name: 'Nodeen' }, + }), + ), + ); + console.timeEnd(`Created vats: ${vatLabel}`); + const knownVats = kernel.getVatIds() as NonEmptyArray; + const knownVatsLabel = knownVats.join(', '); + console.log('Kernel vats:', knownVatsLabel); + + // Restart a randomly selected vat from the array. + console.time(`Restart vats: ${knownVatsLabel}`); + await Promise.all( + knownVats.map(async (vatId: VatId) => await kernel.restartVat(vatId)), + ); + console.timeEnd(`Restart vats: ${knownVatsLabel}`); + + // Send a "Ping" message to a randomly selected vat. + console.time(`Ping vats: ${knownVatsLabel}`); + await Promise.all( + knownVats.map( + async (vatId: VatId) => + await kernel.sendMessage(vatId, { + method: VatCommandMethod.ping, + params: null, + }), + ), + ); + console.timeEnd(`Ping vats "${knownVatsLabel}"`); + + console.time(`Terminated vats: ${knownVatsLabel}`); + await kernel.terminateAllVats(); + console.timeEnd(`Terminated vats: ${knownVatsLabel}`); + + console.log(`Kernel has ${kernel.getVatIds().length} vats`); +} diff --git a/packages/nodejs/src/kernel/sqlite-kv-store.ts b/packages/nodejs/src/kernel/sqlite-kv-store.ts new file mode 100644 index 000000000..010a2245f --- /dev/null +++ b/packages/nodejs/src/kernel/sqlite-kv-store.ts @@ -0,0 +1,142 @@ +import { hasProperty, isObject } from '@metamask/utils'; +import type { KVStore } from '@ocap/kernel'; +import { makeLogger } from '@ocap/utils'; +// eslint-disable-next-line @typescript-eslint/naming-convention +import Sqlite from 'better-sqlite3'; +import { mkdir } from 'fs/promises'; +import { tmpdir } from 'os'; +import { join } from 'path'; + +const dbRoot = join(tmpdir(), './db'); + +/** + * Ensure that SQLite is initialized. + * + * @param logger - An optional logger to pass to the Sqlite constructor. + * @returns The SQLite database object. + */ +async function initDB( + logger?: ReturnType, +): Promise { + const dbPath = join(dbRoot, 'store.db'); + console.log('dbPath:', dbPath); + await mkdir(dbRoot, { recursive: true }); + return new Sqlite(dbPath, { + verbose: (logger ?? console).info, + }); +} + +/** + * Makes a {@link KVStore} for low-level persistent storage. + * + * @param label - A logger prefix label. Defaults to '[sqlite]'. + * @returns The key/value store to base the kernel store on. + */ +export async function makeSQLKVStore( + label: string = '[sqlite]', +): Promise { + const logger = makeLogger(label); + const db = await initDB(logger); + + const sqlKVInit = db.prepare(` + CREATE TABLE IF NOT EXISTS kv ( + key TEXT, + value TEXT, + PRIMARY KEY(key) + ) + `); + + sqlKVInit.run(); + + const sqlKVGet = db.prepare(` + SELECT value + FROM kv + WHERE key = ? + `); + + /** + * Read a key's value from the database. + * + * @param key - A key to fetch. + * @param required - True if it is an error for the entry not to be there. + * @returns The value at that key. + */ + function kvGet(key: string, required: boolean): string { + const result = sqlKVGet.get(key); + if (isObject(result) && hasProperty(result, 'value')) { + const value = result.value as string; + logger.debug(`kernel get '${key}' as '${value}'`); + return value; + } + if (required) { + throw Error(`no record matching key '${key}'`); + } + // Sometimes, we really lean on TypeScript's unsoundness + return undefined as unknown as string; + } + + const sqlKVSet = db.prepare(` + INSERT INTO kv (key, value) + VALUES (?, ?) + ON CONFLICT DO UPDATE SET value = excluded.value + `); + + /** + * Set the value associated with a key in the database. + * + * @param key - A key to assign. + * @param value - The value to assign to it. + */ + function kvSet(key: string, value: string): void { + logger.debug(`kernel set '${key}' to '${value}'`); + sqlKVSet.run(key, value); + } + + const sqlKVDelete = db.prepare(` + DELETE FROM kv + WHERE key = ? + `); + + /** + * Delete a key from the database. + * + * @param key - The key to remove. + */ + function kvDelete(key: string): void { + logger.debug(`kernel delete '${key}'`); + sqlKVDelete.run(key); + } + + const sqlKVDrop = db.prepare(` + DROP TABLE kv + `); + + /** + * Delete all keys and values from the database. + */ + function kvTruncate(): void { + logger.debug(`kernel truncate`); + sqlKVDrop.run(); + sqlKVInit.run(); + } + + /** + * Execute an arbitrary query and return the results. + * + * @param sql - The query to execute. + * @returns The results + */ + function kvExecuteQuery(sql: string): Record[] { + const query = db.prepare(sql); + return query.all() as Record[]; + } + + return { + get: (key) => kvGet(key, false), + getRequired: (key) => kvGet(key, true), + set: kvSet, + delete: kvDelete, + executeQuery: kvExecuteQuery, + truncate: db.transaction(kvTruncate), + }; +} diff --git a/packages/nodejs/src/vat/vat-worker.ts b/packages/nodejs/src/vat/vat-worker.ts new file mode 100644 index 000000000..6d3a4f47d --- /dev/null +++ b/packages/nodejs/src/vat/vat-worker.ts @@ -0,0 +1,48 @@ +import '@ocap/shims/endoify'; + +import { makeExo } from '@endo/exo'; +import { M } from '@endo/patterns'; +import type { Json } from '@metamask/utils'; +import { VatSupervisor } from '@ocap/kernel'; +import type { VatCommand, VatCommandReply } from '@ocap/kernel'; +import { NodeWorkerMultiplexer } from '@ocap/streams'; +import { makeLogger } from '@ocap/utils'; +import { parentPort } from 'node:worker_threads'; + +// eslint-disable-next-line n/no-process-env +const logger = makeLogger(`[vat-worker (${process.env.NODE_VAT_ID})]`); + +main().catch(logger.error); + +/** + * The main function for the iframe. + */ +async function main(): Promise { + logger.debug('started main'); + + if (!parentPort) { + const errMsg = 'Expected to run in Node Worker with parentPort.'; + logger.error(errMsg); + throw new Error(errMsg); + } + const multiplexer = new NodeWorkerMultiplexer(parentPort, 'vat'); + multiplexer.start().catch(logger.error); + const commandStream = multiplexer.createChannel( + 'command', + ); + const capTpStream = multiplexer.createChannel('capTp'); + const bootstrap = makeExo( + 'TheGreatFrangooly', + M.interface('TheGreatFrangooly', {}, { defaultGuards: 'passable' }), + { whatIsTheGreatFrangooly: () => 'Crowned with Chaos' }, + ); + + const supervisor = new VatSupervisor({ + id: 'iframe', + commandStream, + capTpStream, + bootstrap, + }); + + logger.log(supervisor.evaluate('["Hello", "world!"].join(" ");')); +} diff --git a/packages/nodejs/test/e2e/kernel-worker.test.ts b/packages/nodejs/test/e2e/kernel-worker.test.ts new file mode 100644 index 000000000..25dc13f4c --- /dev/null +++ b/packages/nodejs/test/e2e/kernel-worker.test.ts @@ -0,0 +1,30 @@ +import '@ocap/shims/endoify'; + +import { MessageChannel as NodeMessageChannel } from 'node:worker_threads'; +import { describe, it, expect, vi } from 'vitest'; + +import { makeKernel, runVatLifecycle } from '../../src/kernel/kernel-worker.js'; + +vi.mock('node:process', () => ({ + exit: vi.fn((reason) => { + throw new Error(`process.exit: ${reason}`); + }), +})); + +describe('Kernel Worker', () => { + it('should handle the lifecycle of multiple vats', async () => { + console.log('Started test.'); + const kernelChannel = new NodeMessageChannel(); + const { port1: kernelPort } = kernelChannel; + console.log('Creating kernel...'); + const kernel = await makeKernel(kernelPort); + console.log('Kernel created.'); + + console.log('Handling the lifecycle of multiple vats...'); + await runVatLifecycle(kernel, ['v1', 'v2', 'v3']); + console.log('Lifecycle of multiple vats handled.'); + + console.log('Test passed.'); + expect(true).toBe(true); + }); +}); diff --git a/packages/nodejs/tsconfig.build.json b/packages/nodejs/tsconfig.build.json new file mode 100644 index 000000000..7799c75f6 --- /dev/null +++ b/packages/nodejs/tsconfig.build.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.packages.build.json", + "compilerOptions": { + "allowJs": true, + "baseUrl": "./", + "emitDeclarationOnly": false, + "lib": ["DOM", "ES2022"], + "noEmit": true, + "rootDir": "./src", + "types": ["chrome", "ses"] + }, + "references": [ + { "path": "../streams/tsconfig.build.json" }, + { "path": "../kernel/tsconfig.build.json" }, + { "path": "../utils/tsconfig.build.json" } + ], + "include": [ + "./src/**/*.ts", + "./src/**/*-trusted-prelude.js", + "./src/env/dev-console.js" + ] +} diff --git a/packages/nodejs/tsconfig.json b/packages/nodejs/tsconfig.json new file mode 100644 index 000000000..32e19aef6 --- /dev/null +++ b/packages/nodejs/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.packages.json", + "compilerOptions": { + "allowJs": true, + "baseUrl": "./", + "isolatedModules": true, + "lib": ["DOM", "ES2022"], + "noEmit": true, + "skipLibCheck": true, + "types": ["chrome", "ses", "vitest"] + }, + "references": [ + { "path": "../streams" }, + { "path": "../test-utils" }, + { "path": "../utils" }, + { "path": "../kernel" } + ], + "include": [ + "../../vitest.config.packages.ts", + "../../vitest.workspace.ts", + "./src/**/*.ts", + "./src/**/*-trusted-prelude.js", + "./test/**/*.ts", + "./vitest.config.ts", + "./vitest.config.e2e.ts" + ] +} diff --git a/packages/nodejs/tsconfig.lint.json b/packages/nodejs/tsconfig.lint.json new file mode 100644 index 000000000..76734f289 --- /dev/null +++ b/packages/nodejs/tsconfig.lint.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": false, + "noEmit": true, + "skipLibCheck": true + }, + "exclude": [] +} diff --git a/packages/nodejs/typedoc.json b/packages/nodejs/typedoc.json new file mode 100644 index 000000000..f8eb78ae1 --- /dev/null +++ b/packages/nodejs/typedoc.json @@ -0,0 +1,8 @@ +{ + "entryPoints": [], + "excludePrivate": true, + "hideGenerator": true, + "out": "docs", + "tsconfig": "./tsconfig.build.json", + "projectDocuments": ["documents/*.md"] +} diff --git a/packages/nodejs/vitest.config.e2e.ts b/packages/nodejs/vitest.config.e2e.ts new file mode 100644 index 000000000..9531b4c8d --- /dev/null +++ b/packages/nodejs/vitest.config.e2e.ts @@ -0,0 +1,30 @@ +// eslint-disable-next-line spaced-comment +/// + +import path from 'path'; +import { defineConfig, mergeConfig } from 'vite'; + +import defaultConfig from '../../vitest.config.js'; + +const config = mergeConfig( + defaultConfig, + defineConfig({ + optimizeDeps: { include: ['better-sqlite3'] }, + test: { + name: 'nodejs:e2e', + pool: 'forks', + alias: [ + { + find: '@ocap/shims/endoify', + replacement: path.resolve('../shims/src/endoify.js'), + customResolver: (id) => ({ external: true, id }), + }, + ], + include: ['./test/e2e/**/*.test.ts'], + exclude: ['./src/**/*'], + }, + }), +); + +delete config.test.coverage.thresholds; +export default config; diff --git a/packages/nodejs/vitest.config.ts b/packages/nodejs/vitest.config.ts new file mode 100644 index 000000000..7e149b0e5 --- /dev/null +++ b/packages/nodejs/vitest.config.ts @@ -0,0 +1,28 @@ +import path from 'node:path'; +import { defineProject, mergeConfig } from 'vitest/config'; + +import defaultConfig from '../../vitest.config.js'; + +const config = mergeConfig( + defaultConfig, + defineProject({ + optimizeDeps: { include: ['better-sqlite3'] }, + test: { + name: 'nodejs', + pool: 'forks', + alias: [ + { + find: '@ocap/shims/endoify', + replacement: path.resolve('../shims/src/endoify.js'), + customResolver: (id) => ({ external: true, id }), + }, + ], + include: ['./src/**/*.test.ts'], + exclude: ['./test/e2e/'], + }, + }), +); + +config.test.coverage.thresholds = true; + +export default config; diff --git a/tsconfig.build.json b/tsconfig.build.json index ee2abfa86..7b6bd7682 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,6 +5,7 @@ { "path": "./packages/cli/tsconfig.build.json" }, { "path": "./packages/errors/tsconfig.build.json" }, { "path": "./packages/kernel/tsconfig.build.json" }, + { "path": "./packages/nodejs/tsconfig.build.json" }, { "path": "./packages/streams/tsconfig.build.json" }, { "path": "./packages/utils/tsconfig.build.json" } ] diff --git a/tsconfig.json b/tsconfig.json index cf8cab333..241c90b13 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,7 @@ { "path": "./packages/errors" }, { "path": "./packages/extension" }, { "path": "./packages/kernel" }, + { "path": "./packages/nodejs" }, { "path": "./packages/shims" }, { "path": "./packages/streams" }, { "path": "./packages/test-utils" }, diff --git a/vitest.config.ts b/vitest.config.ts index 8a96b48f2..638897443 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -72,6 +72,12 @@ export default defineConfig({ branches: 63.71, lines: 78.44, }, + 'packages/nodejs/**': { + statements: 4.08, + functions: 4.76, + branches: 15.38, + lines: 4.08, + }, 'packages/shims/**': { statements: 0, functions: 0, diff --git a/yarn.lock b/yarn.lock index f5c55dea3..7e33ea643 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1159,6 +1159,15 @@ __metadata: languageName: node linkType: hard +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5 + languageName: node + linkType: hard + "@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": version: 0.1.3 resolution: "@istanbuljs/schema@npm:0.1.3" @@ -1766,6 +1775,19 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10/775c9a7eb1f88c195dfb3bce70c31d0fe2a12b28b754e25c08a3edb4bc4816bfedb7ac64ef1e730579d078ca19dacf11630e99f8f3c3e0fd7b23caa5fd6d30a6 + languageName: node + linkType: hard + "@npmcli/fs@npm:^3.1.0": version: 3.1.1 resolution: "@npmcli/fs@npm:3.1.1" @@ -1775,6 +1797,15 @@ __metadata: languageName: node linkType: hard +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10/405c4490e1ff11cf299775449a3c254a366a4b1ffc79d87159b0ee7d5558ac9f6a2f8c0735fd6ff3873cef014cb1a44a5f9127cb6a1b2dbc408718cca9365b5a + languageName: node + linkType: hard + "@npmcli/git@npm:^5.0.0": version: 5.0.8 resolution: "@npmcli/git@npm:5.0.8" @@ -2096,6 +2127,53 @@ __metadata: languageName: unknown linkType: soft +"@ocap/nodejs@workspace:packages/nodejs": + version: 0.0.0-use.local + resolution: "@ocap/nodejs@workspace:packages/nodejs" + dependencies: + "@arethetypeswrong/cli": "npm:^0.16.4" + "@endo/exo": "npm:^1.5.4" + "@endo/patterns": "npm:^1.4.4" + "@endo/promise-kit": "npm:^1.1.6" + "@metamask/auto-changelog": "npm:^4.0.0" + "@metamask/eslint-config": "npm:^14.0.0" + "@metamask/eslint-config-nodejs": "npm:^14.0.0" + "@metamask/eslint-config-typescript": "npm:^14.0.0" + "@metamask/utils": "npm:^11.0.1" + "@ocap/cli": "workspace:^" + "@ocap/kernel": "workspace:^" + "@ocap/shims": "workspace:^" + "@ocap/streams": "workspace:^" + "@ocap/utils": "workspace:^" + "@ts-bridge/cli": "npm:^0.6.2" + "@ts-bridge/shims": "npm:^0.1.1" + "@types/better-sqlite3": "npm:^7.6.12" + "@typescript-eslint/eslint-plugin": "npm:^8.8.1" + "@typescript-eslint/parser": "npm:^8.8.1" + "@typescript-eslint/utils": "npm:^8.8.1" + "@vitest/eslint-plugin": "npm:^1.1.24" + better-sqlite3: "npm:^11.7.2" + depcheck: "npm:^1.4.7" + eslint: "npm:^9.12.0" + eslint-config-prettier: "npm:^9.1.0" + eslint-import-resolver-typescript: "npm:^3.6.3" + eslint-plugin-import-x: "npm:^4.3.1" + eslint-plugin-jsdoc: "npm:^50.3.1" + eslint-plugin-n: "npm:^17.11.1" + eslint-plugin-prettier: "npm:^5.2.1" + eslint-plugin-promise: "npm:^7.1.0" + node-gyp: "npm:^11.0.0" + prettier: "npm:^3.3.3" + rimraf: "npm:^6.0.1" + ses: "npm:^1.9.0" + typedoc: "npm:^0.26.8" + typescript: "npm:~5.5.4" + typescript-eslint: "npm:^8.8.1" + vite: "npm:^5.3.5" + vitest: "npm:2.1.8" + languageName: unknown + linkType: soft + "@ocap/shims@workspace:^, @ocap/shims@workspace:packages/shims": version: 0.0.0-use.local resolution: "@ocap/shims@workspace:packages/shims" @@ -2914,6 +2992,15 @@ __metadata: languageName: node linkType: hard +"@types/better-sqlite3@npm:^7.6.12": + version: 7.6.12 + resolution: "@types/better-sqlite3@npm:7.6.12" + dependencies: + "@types/node": "npm:*" + checksum: 10/a442231518f1a3e28e0ee6efe2581807e5cfaa88a8af4513da34e6ae303ce82f5666e8a0048a1d2738fa248b1b369ee28e59a75189ae0b43e28e44a243a2f24b + languageName: node + linkType: hard + "@types/bn.js@npm:^5.1.5": version: 5.1.6 resolution: "@types/bn.js@npm:5.1.6" @@ -4058,6 +4145,17 @@ __metadata: languageName: node linkType: hard +"better-sqlite3@npm:^11.7.2": + version: 11.7.2 + resolution: "better-sqlite3@npm:11.7.2" + dependencies: + bindings: "npm:^1.5.0" + node-gyp: "npm:latest" + prebuild-install: "npm:^7.1.1" + checksum: 10/49e1d8847560058d00c87177dfa6ef6bf713cb0122795c8f43143ac3154608f2ff83d4180ab00c7c24f5c23f0bcfe96bb47ac08b3ef5081ed41f46869df594f6 + languageName: node + linkType: hard + "bin-links@npm:4.0.4": version: 4.0.4 resolution: "bin-links@npm:4.0.4" @@ -4077,7 +4175,7 @@ __metadata: languageName: node linkType: hard -"bindings@npm:^1.4.0": +"bindings@npm:^1.4.0, bindings@npm:^1.5.0": version: 1.5.0 resolution: "bindings@npm:1.5.0" dependencies: @@ -4086,6 +4184,17 @@ __metadata: languageName: node linkType: hard +"bl@npm:^4.0.3": + version: 4.1.0 + resolution: "bl@npm:4.1.0" + dependencies: + buffer: "npm:^5.5.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.4.0" + checksum: 10/b7904e66ed0bdfc813c06ea6c3e35eafecb104369dbf5356d0f416af90c1546de3b74e5b63506f0629acf5e16a6f87c3798f16233dcff086e9129383aa02ab55 + languageName: node + linkType: hard + "blueimp-md5@npm:^2.10.0": version: 2.19.0 resolution: "blueimp-md5@npm:2.19.0" @@ -4149,6 +4258,16 @@ __metadata: languageName: node linkType: hard +"buffer@npm:^5.5.0": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10/997434d3c6e3b39e0be479a80288875f71cd1c07d75a3855e6f08ef848a3c966023f79534e22e415ff3a5112708ce06127277ab20e527146d55c84566405c7c6 + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -4200,6 +4319,26 @@ __metadata: languageName: node linkType: hard +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" + dependencies: + "@npmcli/fs": "npm:^4.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^7.0.2" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + unique-filename: "npm:^4.0.0" + checksum: 10/ea026b27b13656330c2bbaa462a88181dcaa0435c1c2e705db89b31d9bdf7126049d6d0445ba746dca21454a0cfdf1d6f47fd39d34c8c8435296b30bc5738a13 + languageName: node + linkType: hard + "call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1": version: 1.0.1 resolution: "call-bind-apply-helpers@npm:1.0.1" @@ -4412,6 +4551,13 @@ __metadata: languageName: node linkType: hard +"chownr@npm:^1.1.1": + version: 1.1.4 + resolution: "chownr@npm:1.1.4" + checksum: 10/115648f8eb38bac5e41c3857f3e663f9c39ed6480d1349977c4d96c95a47266fcacc5a5aabf3cb6c481e22d72f41992827db47301851766c4fd77ac21a4f081d + languageName: node + linkType: hard + "chownr@npm:^2.0.0": version: 2.0.0 resolution: "chownr@npm:2.0.0" @@ -4419,6 +4565,13 @@ __metadata: languageName: node linkType: hard +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10/b63cb1f73d171d140a2ed8154ee6566c8ab775d3196b0e03a2a94b5f6a0ce7777ee5685ca56849403c8d17bd457a6540672f9a60696a6137c7a409097495b82c + languageName: node + linkType: hard + "chunkd@npm:^2.0.1": version: 2.0.1 resolution: "chunkd@npm:2.0.1" @@ -4887,6 +5040,15 @@ __metadata: languageName: node linkType: hard +"decompress-response@npm:^6.0.0": + version: 6.0.0 + resolution: "decompress-response@npm:6.0.0" + dependencies: + mimic-response: "npm:^3.1.0" + checksum: 10/d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 + languageName: node + linkType: hard + "deep-eql@npm:^5.0.1": version: 5.0.2 resolution: "deep-eql@npm:5.0.2" @@ -4894,6 +5056,13 @@ __metadata: languageName: node linkType: hard +"deep-extend@npm:^0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 10/7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 + languageName: node + linkType: hard + "deep-freeze-strict@npm:^1.1.1": version: 1.1.1 resolution: "deep-freeze-strict@npm:1.1.1" @@ -5214,6 +5383,15 @@ __metadata: languageName: node linkType: hard +"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: "npm:^1.4.0" + checksum: 10/530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b + languageName: node + linkType: hard + "enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": version: 5.18.0 resolution: "enhanced-resolve@npm:5.18.0" @@ -6064,6 +6242,13 @@ __metadata: languageName: node linkType: hard +"expand-template@npm:^2.0.3": + version: 2.0.3 + resolution: "expand-template@npm:2.0.3" + checksum: 10/588c19847216421ed92befb521767b7018dc88f88b0576df98cb242f20961425e96a92cbece525ef28cc5becceae5d544ae0f5b9b5e2aa05acb13716ca5b3099 + languageName: node + linkType: hard + "expand-tilde@npm:^2.0.0, expand-tilde@npm:^2.0.2": version: 2.0.2 resolution: "expand-tilde@npm:2.0.2" @@ -6304,6 +6489,13 @@ __metadata: languageName: node linkType: hard +"fs-constants@npm:^1.0.0": + version: 1.0.0 + resolution: "fs-constants@npm:1.0.0" + checksum: 10/18f5b718371816155849475ac36c7d0b24d39a11d91348cfcb308b4494824413e03572c403c86d3a260e049465518c4f0d5bd00f0371cdfcad6d4f30a85b350d + languageName: node + linkType: hard + "fs-extra@npm:^11.1.0": version: 11.2.0 resolution: "fs-extra@npm:11.2.0" @@ -6530,6 +6722,13 @@ __metadata: languageName: node linkType: hard +"github-from-package@npm:0.0.0": + version: 0.0.0 + resolution: "github-from-package@npm:0.0.0" + checksum: 10/2a091ba07fbce22205642543b4ea8aaf068397e1433c00ae0f9de36a3607baf5bcc14da97fbb798cfca6393b3c402031fca06d8b491a44206d6efef391c58537 + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -6548,7 +6747,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.4.1": +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.1": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -6942,7 +7141,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 10/d9f2557a59036f16c282aaeb107832dc957a93d73397d89bbad4eb1130560560eb695060145e8e6b3b498b15ab95510226649a0b8f52ae06583575419fe10fc4 @@ -7027,14 +7226,14 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3": +"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10/cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 languageName: node linkType: hard -"ini@npm:^1.3.4": +"ini@npm:^1.3.4, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: 10/314ae176e8d4deb3def56106da8002b462221c174ddb7ce0c49ee72c8cd1f9044f7b10cc555a7d8850982c3b9ca96fc212122749f5234bc2b6fb05fb942ed566 @@ -8062,6 +8261,25 @@ __metadata: languageName: node linkType: hard +"make-fetch-happen@npm:^14.0.3": + version: 14.0.3 + resolution: "make-fetch-happen@npm:14.0.3" + dependencies: + "@npmcli/agent": "npm:^3.0.0" + cacache: "npm:^19.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^12.0.0" + checksum: 10/fce0385840b6d86b735053dfe941edc2dd6468fda80fe74da1eeff10cbd82a75760f406194f2bc2fa85b99545b2bc1f84c08ddf994b21830775ba2d1a87e8bdf + languageName: node + linkType: hard + "markdown-it@npm:^14.1.0": version: 14.1.0 resolution: "markdown-it@npm:14.1.0" @@ -8305,6 +8523,13 @@ __metadata: languageName: node linkType: hard +"mimic-response@npm:^3.1.0": + version: 3.1.0 + resolution: "mimic-response@npm:3.1.0" + checksum: 10/7e719047612411fe071332a7498cf0448bbe43c485c0d780046c76633a771b223ff49bd00267be122cedebb897037fdb527df72335d0d0f74724604ca70b37ad + languageName: node + linkType: hard + "min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -8348,7 +8573,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f @@ -8379,6 +8604,21 @@ __metadata: languageName: node linkType: hard +"minipass-fetch@npm:^4.0.0": + version: 4.0.0 + resolution: "minipass-fetch@npm:4.0.0" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^3.0.1" + dependenciesMeta: + encoding: + optional: true + checksum: 10/4b0772dbee77727b469dc5bfc371541d9aba1e243fbb46ddc1b9ff7efa4de4a4cf5ff3a359d6a3b3a460ca26df9ae67a9c93be26ab6417c225e49d63b52b2801 + languageName: node + linkType: hard + "minipass-flush@npm:^1.0.5": version: 1.0.5 resolution: "minipass-flush@npm:1.0.5" @@ -8422,7 +8662,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 @@ -8439,6 +8679,23 @@ __metadata: languageName: node linkType: hard +"minizlib@npm:^3.0.1": + version: 3.0.1 + resolution: "minizlib@npm:3.0.1" + dependencies: + minipass: "npm:^7.0.4" + rimraf: "npm:^5.0.5" + checksum: 10/622cb85f51e5c206a080a62d20db0d7b4066f308cb6ce82a9644da112367c3416ae7062017e631eb7ac8588191cfa4a9a279b8651c399265202b298e98c4acef + languageName: node + linkType: hard + +"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": + version: 0.5.3 + resolution: "mkdirp-classic@npm:0.5.3" + checksum: 10/3f4e088208270bbcc148d53b73e9a5bd9eef05ad2cbf3b3d0ff8795278d50dd1d11a8ef1875ff5aea3fa888931f95bfcb2ad5b7c1061cfefd6284d199e6776ac + languageName: node + linkType: hard + "mkdirp@npm:^1.0.3": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -8448,6 +8705,15 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba + languageName: node + linkType: hard + "mrmime@npm:^2.0.0": version: 2.0.0 resolution: "mrmime@npm:2.0.0" @@ -8535,6 +8801,13 @@ __metadata: languageName: node linkType: hard +"napi-build-utils@npm:^1.0.1": + version: 1.0.2 + resolution: "napi-build-utils@npm:1.0.2" + checksum: 10/276feb8e30189fe18718e85b6f82e4f952822baa2e7696f771cc42571a235b789dc5907a14d9ffb6838c3e4ff4c25717c2575e5ce1cf6e02e496e204c11e57f6 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -8561,6 +8834,22 @@ __metadata: languageName: node linkType: hard +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 + languageName: node + linkType: hard + +"node-abi@npm:^3.3.0": + version: 3.71.0 + resolution: "node-abi@npm:3.71.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10/0a1cef5106c43d67f9f8a911b0c9d5ee08971eda002ba466606c8e6164964456f5211f37966717efc3d5d49bae32f0cf9290254b1286bf71f0ba158a4f8a9846 + languageName: node + linkType: hard + "node-addon-api@npm:^7.0.0": version: 7.1.1 resolution: "node-addon-api@npm:7.1.1" @@ -8627,6 +8916,26 @@ __metadata: languageName: node linkType: hard +"node-gyp@npm:^11.0.0": + version: 11.0.0 + resolution: "node-gyp@npm:11.0.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^14.0.3" + nopt: "npm:^8.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.4.3" + which: "npm:^5.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10/5d07430e887a906f85c7c6ed87e8facb7ecd4ce42d948a2438c471df2e24ae6af70f4def114ec1a03127988d164648dda8d75fe666f3c4b431e53856379fdf13 + languageName: node + linkType: hard + "node-releases@npm:^2.0.18": version: 2.0.18 resolution: "node-releases@npm:2.0.18" @@ -8663,6 +8972,17 @@ __metadata: languageName: node linkType: hard +"nopt@npm:^8.0.0": + version: 8.0.0 + resolution: "nopt@npm:8.0.0" + dependencies: + abbrev: "npm:^2.0.0" + bin: + nopt: bin/nopt.js + checksum: 10/2d137f64b6f9331ec97047dd1cbbe4dcd9a61ceef4fd0f2252c0bbac1d69ba15671e6fd83a441328824b3ca78afe6ebe1694f12ebcd162b73a221582a06179ff + languageName: node + linkType: hard + "normalize-package-data@npm:^6.0.0": version: 6.0.2 resolution: "normalize-package-data@npm:6.0.2" @@ -8847,7 +9167,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.4.0": +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -9354,6 +9674,28 @@ __metadata: languageName: node linkType: hard +"prebuild-install@npm:^7.1.1": + version: 7.1.2 + resolution: "prebuild-install@npm:7.1.2" + dependencies: + detect-libc: "npm:^2.0.0" + expand-template: "npm:^2.0.3" + github-from-package: "npm:0.0.0" + minimist: "npm:^1.2.3" + mkdirp-classic: "npm:^0.5.3" + napi-build-utils: "npm:^1.0.1" + node-abi: "npm:^3.3.0" + pump: "npm:^3.0.0" + rc: "npm:^1.2.7" + simple-get: "npm:^4.0.0" + tar-fs: "npm:^2.0.0" + tunnel-agent: "npm:^0.6.0" + bin: + prebuild-install: bin.js + checksum: 10/32d5c026cc978dd02762b9ad3c765178aee8383aeac4303fed3cd226eff53100db038d4791b03ae1ebc7d213a7af392d26e32095579cedb8dba1d00ad08ecd46 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -9421,6 +9763,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10/35610bdb0177d3ab5d35f8827a429fb1dc2518d9e639f2151ac9007f01a061c30e0c635a970c9b00c39102216160f6ec54b62377c92fac3b7bfc2ad4b98d195c + languageName: node + linkType: hard + "process@npm:^0.11.10": version: 0.11.10 resolution: "process@npm:0.11.10" @@ -9477,6 +9826,16 @@ __metadata: languageName: node linkType: hard +"pump@npm:^3.0.0": + version: 3.0.2 + resolution: "pump@npm:3.0.2" + dependencies: + end-of-stream: "npm:^1.1.0" + once: "npm:^1.3.1" + checksum: 10/e0c4216874b96bd25ddf31a0b61a5613e26cc7afa32379217cf39d3915b0509def3565f5f6968fafdad2894c8bbdbd67d340e84f3634b2a29b950cffb6442d9f + languageName: node + linkType: hard + "punycode.js@npm:^2.3.1": version: 2.3.1 resolution: "punycode.js@npm:2.3.1" @@ -9526,6 +9885,20 @@ __metadata: languageName: node linkType: hard +"rc@npm:^1.2.7": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: "npm:^0.6.0" + ini: "npm:~1.3.0" + minimist: "npm:^1.2.0" + strip-json-comments: "npm:~2.0.1" + bin: + rc: ./cli.js + checksum: 10/5c4d72ae7eec44357171585938c85ce066da8ca79146b5635baf3d55d74584c92575fa4e2c9eac03efbed3b46a0b2e7c30634c012b4b4fa40d654353d3c163eb + languageName: node + linkType: hard + "react-dom@npm:^18.3.1": version: 18.3.1 resolution: "react-dom@npm:18.3.1" @@ -9575,7 +9948,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": +"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -9829,6 +10202,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:^5.0.5": + version: 5.0.10 + resolution: "rimraf@npm:5.0.10" + dependencies: + glob: "npm:^10.3.7" + bin: + rimraf: dist/esm/bin.mjs + checksum: 10/f3b8ce81eecbde4628b07bdf9e2fa8b684e0caea4999acb1e3b0402c695cd41f28cd075609a808e61ce2672f528ca079f675ab1d8e8d5f86d56643a03e0b8d2e + languageName: node + linkType: hard + "rimraf@npm:^6.0.1": version: 6.0.1 resolution: "rimraf@npm:6.0.1" @@ -9947,7 +10331,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": +"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 @@ -10241,6 +10625,24 @@ __metadata: languageName: node linkType: hard +"simple-concat@npm:^1.0.0": + version: 1.0.1 + resolution: "simple-concat@npm:1.0.1" + checksum: 10/4d211042cc3d73a718c21ac6c4e7d7a0363e184be6a5ad25c8a1502e49df6d0a0253979e3d50dbdd3f60ef6c6c58d756b5d66ac1e05cda9cacd2e9fc59e3876a + languageName: node + linkType: hard + +"simple-get@npm:^4.0.0": + version: 4.0.1 + resolution: "simple-get@npm:4.0.1" + dependencies: + decompress-response: "npm:^6.0.0" + once: "npm:^1.3.1" + simple-concat: "npm:^1.0.0" + checksum: 10/93f1b32319782f78f2f2234e9ce34891b7ab6b990d19d8afefaa44423f5235ce2676aae42d6743fecac6c8dfff4b808d4c24fe5265be813d04769917a9a44f36 + languageName: node + linkType: hard + "simple-git-hooks@npm:^2.11.1": version: 2.11.1 resolution: "simple-git-hooks@npm:2.11.1" @@ -10466,6 +10868,15 @@ __metadata: languageName: node linkType: hard +"ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10/7024c1a6e39b3f18aa8f1c8290e884fe91b0f9ca5a6c6d410544daad54de0ba664db879afe16412e187c6c292fd60b937f047ee44292e5c2af2dcc6d8e1a9b48 + languageName: node + linkType: hard + "stable-hash@npm:^0.0.4": version: 0.0.4 resolution: "stable-hash@npm:0.0.4" @@ -10709,6 +11120,13 @@ __metadata: languageName: node linkType: hard +"strip-json-comments@npm:~2.0.1": + version: 2.0.1 + resolution: "strip-json-comments@npm:2.0.1" + checksum: 10/1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 + languageName: node + linkType: hard + "strnum@npm:^1.0.5": version: 1.0.5 resolution: "strnum@npm:1.0.5" @@ -10793,6 +11211,31 @@ __metadata: languageName: node linkType: hard +"tar-fs@npm:^2.0.0": + version: 2.1.1 + resolution: "tar-fs@npm:2.1.1" + dependencies: + chownr: "npm:^1.1.1" + mkdirp-classic: "npm:^0.5.2" + pump: "npm:^3.0.0" + tar-stream: "npm:^2.1.4" + checksum: 10/526deae025453e825f87650808969662fbb12eb0461d033e9b447de60ec951c6c4607d0afe7ce057defe9d4e45cf80399dd74bc15f9d9e0773d5e990a78ce4ac + languageName: node + linkType: hard + +"tar-stream@npm:^2.1.4": + version: 2.2.0 + resolution: "tar-stream@npm:2.2.0" + dependencies: + bl: "npm:^4.0.3" + end-of-stream: "npm:^1.4.1" + fs-constants: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^3.1.1" + checksum: 10/1a52a51d240c118cbcd30f7368ea5e5baef1eac3e6b793fb1a41e6cd7319296c79c0264ccc5859f5294aa80f8f00b9239d519e627b9aade80038de6f966fec6a + languageName: node + linkType: hard + "tar@npm:^6.1.11, tar@npm:^6.2.1": version: 6.2.1 resolution: "tar@npm:6.2.1" @@ -10807,6 +11250,20 @@ __metadata: languageName: node linkType: hard +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf + languageName: node + linkType: hard + "temp-dir@npm:^3.0.0": version: 3.0.0 resolution: "temp-dir@npm:3.0.0" @@ -11028,6 +11485,15 @@ __metadata: languageName: node linkType: hard +"tunnel-agent@npm:^0.6.0": + version: 0.6.0 + resolution: "tunnel-agent@npm:0.6.0" + dependencies: + safe-buffer: "npm:^5.0.1" + checksum: 10/7f0d9ed5c22404072b2ae8edc45c071772affd2ed14a74f03b4e71b4dd1a14c3714d85aed64abcaaee5fec2efc79002ba81155c708f4df65821b444abb0cfade + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -11291,6 +11757,15 @@ __metadata: languageName: node linkType: hard +"unique-filename@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-filename@npm:4.0.0" + dependencies: + unique-slug: "npm:^5.0.0" + checksum: 10/6a62094fcac286b9ec39edbd1f8f64ff92383baa430af303dfed1ffda5e47a08a6b316408554abfddd9730c78b6106bef4ca4d02c1231a735ddd56ced77573df + languageName: node + linkType: hard + "unique-slug@npm:^4.0.0": version: 4.0.0 resolution: "unique-slug@npm:4.0.0" @@ -11300,6 +11775,15 @@ __metadata: languageName: node linkType: hard +"unique-slug@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-slug@npm:5.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10/beafdf3d6f44990e0a5ce560f8f881b4ee811be70b6ba0db25298c31c8cf525ed963572b48cd03be1c1349084f9e339be4241666d7cf1ebdad20598d3c652b27 + languageName: node + linkType: hard + "unist-util-is@npm:^6.0.0": version: 6.0.0 resolution: "unist-util-is@npm:6.0.0" @@ -11880,6 +12364,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10/6ec99e89ba32c7e748b8a3144e64bfc74aa63e2b2eacbb61a0060ad0b961eb1a632b08fb1de067ed59b002cec3e21de18299216ebf2325ef0f78e0f121e14e90 + languageName: node + linkType: hard + "why-is-node-running@npm:^2.3.0": version: 2.3.0 resolution: "why-is-node-running@npm:2.3.0" @@ -12036,6 +12531,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10/1884d272d485845ad04759a255c71775db0fac56308764b4c77ea56a20d56679fad340213054c8c9c9c26fcfd4c4b2a90df993b7e0aaf3cdb73c618d1d1a802a + languageName: node + linkType: hard + "yaml@npm:^1.10.0, yaml@npm:^1.10.2": version: 1.10.2 resolution: "yaml@npm:1.10.2"