From b0bb281f977da7164f4d18df0ad788cf9a6ba887 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 9 Jul 2026 10:26:44 +0000 Subject: [PATCH 1/6] feat!: convert SDK to TypeScript with a dual ESM/CJS build Rewrite the SDK source (lib/*.js -> lib/*.ts) in strict TypeScript, preserving runtime behaviour and the on-the-wire encryption formats exactly. Only module syntax and type annotations changed; the public API is identical. Build & packaging: - Add tsconfig.json (strict) and build with tsup to dist/ as dual ESM (index.mjs) + CommonJS (index.js) with bundled .d.ts. - Point package "main"/"module"/"types"/"exports" at dist and ship only dist; drop the tsc-based generate-types step. - keepNames so error `type`/constructor names are preserved. - require('@evervault/sdk') still returns the EvervaultClient class; `import Evervault from '@evervault/sdk'` works for ESM consumers. Types & internals: - Fold the hand-written types.d.ts / domainTargets.d.ts into source types; monkey-patched Node core modules use default imports so the mutable module.exports is patched (works in both CJS and ESM). Tests & CI: - Run the existing mocha suite against the TS source via tsx and replace rewire (incompatible with compiled TS) with proxyquire / shared-singleton config mutation. 204 passing, unchanged from the JS baseline (the 5 proxy.test.js failures are pre-existing and environmental). - Add typecheck + build steps to CI; bump CodeQL to v3 with the javascript-typescript language. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_011HwoTRLdV2YMub47j88mv5 --- .changeset/typescript-rewrite.md | 7 + .github/workflows/codeql.yml | 8 +- .github/workflows/test.yml | 2 + .mocharc.json | 5 + .prettierignore | 4 + .prettierrc | 1 - lib/{config.js => config.ts} | 8 +- .../{attestationDoc.js => attestationDoc.ts} | 31 +- lib/core/{crypto.js => crypto.ts} | 181 +- lib/core/{http.js => http.ts} | 85 +- lib/core/index.js | 7 - lib/core/index.ts | 5 + lib/core/{pcrManager.js => pcrManager.ts} | 36 +- ...tboundConfig.js => relayOutboundConfig.ts} | 15 +- .../{repeatedTimer.js => repeatedTimer.ts} | 21 +- lib/curves/{base.js => base.ts} | 38 +- lib/curves/{constants.js => constants.ts} | 2 +- lib/curves/index.js | 3 - lib/curves/index.ts | 1 + lib/{index.js => index.ts} | 232 ++- lib/{types.d.ts => types.ts} | 10 +- lib/utils/{attest.js => attest.ts} | 109 +- lib/utils/{certHelper.js => certHelper.ts} | 13 +- lib/utils/{crc32.js => crc32.ts} | 4 +- lib/utils/datatypes.js | 74 - lib/utils/datatypes.ts | 59 + lib/utils/domainTargets.d.ts | 14 - .../{domainTargets.js => domainTargets.ts} | 57 +- lib/utils/errors.js | 102 -- lib/utils/errors.ts | 113 ++ lib/utils/{httpsHelper.js => httpsHelper.ts} | 83 +- lib/utils/index.js | 9 - lib/utils/index.ts | 7 + lib/utils/{proxyAgent.js => proxyAgent.ts} | 61 +- ...alidationHelper.js => validationHelper.ts} | 23 +- package.json | 36 +- pnpm-lock.yaml | 1571 +++++++++++++---- pnpm-workspace.yaml | 1 + tests/client.test.js | 14 +- tests/config.test.js | 14 +- tests/core/crypto.test.js | 2 +- tests/core/http.test.js | 9 +- tests/core/repeatedTimer.test.js | 2 +- tests/proxy.test.js | 2 +- tests/sdk.test.js | 16 +- tsconfig.json | 19 + tsup.config.ts | 12 + 47 files changed, 2014 insertions(+), 1114 deletions(-) create mode 100644 .changeset/typescript-rewrite.md create mode 100644 .mocharc.json create mode 100644 .prettierignore rename lib/{config.js => config.ts} (93%) rename lib/core/{attestationDoc.js => attestationDoc.ts} (65%) rename lib/core/{crypto.js => crypto.ts} (76%) rename lib/core/{http.js => http.ts} (78%) delete mode 100644 lib/core/index.js create mode 100644 lib/core/index.ts rename lib/core/{pcrManager.js => pcrManager.ts} (80%) rename lib/core/{relayOutboundConfig.js => relayOutboundConfig.ts} (73%) rename lib/core/{repeatedTimer.js => repeatedTimer.ts} (64%) rename lib/curves/{base.js => base.ts} (81%) rename lib/curves/{constants.js => constants.ts} (98%) delete mode 100644 lib/curves/index.js create mode 100644 lib/curves/index.ts rename lib/{index.js => index.ts} (69%) rename lib/{types.d.ts => types.ts} (87%) rename lib/utils/{attest.js => attest.ts} (66%) rename lib/utils/{certHelper.js => certHelper.ts} (65%) rename lib/utils/{crc32.js => crc32.ts} (89%) delete mode 100644 lib/utils/datatypes.js create mode 100644 lib/utils/datatypes.ts delete mode 100644 lib/utils/domainTargets.d.ts rename lib/utils/{domainTargets.js => domainTargets.ts} (71%) delete mode 100644 lib/utils/errors.js create mode 100644 lib/utils/errors.ts rename lib/utils/{httpsHelper.js => httpsHelper.ts} (62%) delete mode 100644 lib/utils/index.js create mode 100644 lib/utils/index.ts rename lib/utils/{proxyAgent.js => proxyAgent.ts} (81%) rename lib/utils/{validationHelper.js => validationHelper.ts} (75%) create mode 100644 tsconfig.json create mode 100644 tsup.config.ts diff --git a/.changeset/typescript-rewrite.md b/.changeset/typescript-rewrite.md new file mode 100644 index 00000000..d413e1c1 --- /dev/null +++ b/.changeset/typescript-rewrite.md @@ -0,0 +1,7 @@ +--- +"@evervault/sdk": major +--- + +Rewrite the SDK in TypeScript. The package now ships a compiled `dist/` bundle with dual ESM and CommonJS entry points plus bundled type declarations (built with `tsup`), replacing the previously shipped JavaScript source and the `tsc`-generated `types/` directory. + +The public API is unchanged: `require('@evervault/sdk')` still returns the `EvervaultClient` class, `import Evervault from '@evervault/sdk'` works for ESM consumers, and every client method keeps the same signature and runtime behaviour (including the on-the-wire encryption formats). This is released as a major version only because the package's internal file layout and `exports` map changed, which can affect consumers that imported internal file paths directly. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 948b757a..3fa2bf4d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - language: ['javascript'] + language: ['javascript-typescript'] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support @@ -42,7 +42,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -55,7 +55,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -68,6 +68,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: '/language:${{matrix.language}}' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 71e9dbcb..53cfd6ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,8 @@ jobs: cache: 'pnpm' - run: pnpm install --frozen-lockfile - run: pnpm run lint + - run: pnpm run typecheck + - run: pnpm run build - run: pnpm run test:coverage - run: | sudo apt-get update ; sudo apt-get install -y libfaketime diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 00000000..8d8675b3 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,5 @@ +{ + "require": "tsx/cjs", + "spec": "tests/**/*.test.js", + "timeout": 30000 +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..b2d1f452 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +dist +node_modules +coverage +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc index 7b5de068..c07e9c1e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,6 +3,5 @@ tabWidth: 2 semi: true singleQuote: true bracketSpacing: true -jsxBracketSameLine: false arrowParens: 'always' insertPragma: false diff --git a/lib/config.js b/lib/config.ts similarity index 93% rename from lib/config.js rename to lib/config.ts index 1ec72378..5b9c2933 100644 --- a/lib/config.js +++ b/lib/config.ts @@ -1,4 +1,5 @@ -const { version } = require('../package.json'); +import { version } from '../package.json'; +import type { MasterConfig } from './types'; const DEFAULT_API_URL = 'https://api.evervault.com'; const DEFAULT_TUNNEL_HOSTNAME = 'https://relay.evervault.com:443'; @@ -9,8 +10,7 @@ const DEFAULT_MAX_FILE_SIZE_IN_MB = 25; const DEFAULT_ATTEST_POLL_INTERVAL = 120; const DEFAULT_PCR_PROVIDER_POLL_INTERVAL = 60; -/** @type {import('./types').MasterConfig} */ -module.exports = { +const config: MasterConfig = { http: { baseUrl: process.env.EV_API_URL || DEFAULT_API_URL, userAgent: `evervault-node/${version}`, @@ -61,3 +61,5 @@ module.exports = { }, }, }; + +export = config; diff --git a/lib/core/attestationDoc.js b/lib/core/attestationDoc.ts similarity index 65% rename from lib/core/attestationDoc.js rename to lib/core/attestationDoc.ts index 76c25b80..dbfe5f12 100644 --- a/lib/core/attestationDoc.js +++ b/lib/core/attestationDoc.ts @@ -1,7 +1,22 @@ -const RepeatedTimer = require('./repeatedTimer'); +import RepeatedTimer from './repeatedTimer'; +import type { MasterConfig } from '../types'; class AttestationDoc { - constructor(config, http, enclaves, appUuid, hostname) { + appUuid: string; + http: any; + enclaves: string[]; + config: MasterConfig; + polling: ReturnType | null; + attestationDocCache: Record | null; + hostname: string; + + constructor( + config: MasterConfig, + http: any, + enclaves: string[], + appUuid: string, + hostname: string + ) { this.appUuid = appUuid.replace(/_/g, '-'); this.http = http; this.enclaves = enclaves; @@ -25,21 +40,21 @@ class AttestationDoc { return null; }; - loadAttestationDoc = async (name) => { + loadAttestationDoc = async (name: string) => { try { const response = await this.http.getAttestationDoc( name, this.appUuid, this.hostname ); - this.attestationDocCache[name] = response.attestation_doc; + this.attestationDocCache![name] = response.attestation_doc; } catch (e) { console.warn(`Couldn't load attestation doc for ${name} ${e}`); } }; - get = (name) => { - const doc = this.attestationDocCache[name]; + get = (name: string) => { + const doc = this.attestationDocCache![name]; if (!doc) { console.warn(`No attestation doc found for ${name}`); } @@ -65,10 +80,10 @@ class AttestationDoc { _getAttestationDocs = async () => { await Promise.all( this.enclaves.map(async (name) => { - await this.loadAttestationDoc(name, this.appUuid); + await this.loadAttestationDoc(name); }) ); }; } -module.exports = AttestationDoc; +export default AttestationDoc; diff --git a/lib/core/crypto.js b/lib/core/crypto.ts similarity index 76% rename from lib/core/crypto.js rename to lib/core/crypto.ts index abcbc833..a70e3caa 100644 --- a/lib/core/crypto.js +++ b/lib/core/crypto.ts @@ -1,13 +1,14 @@ -const crypto = require('crypto'); -const { Encoding } = require('../curves'); -const Datatypes = require('../utils/datatypes'); -const { errors } = require('../utils'); -const CRC32 = require('../utils/crc32'); +import * as crypto from 'crypto'; +import { Encoding } from '../curves'; +import * as Datatypes from '../utils/datatypes'; +import { errors } from '../utils'; +import CRC32 from '../utils/crc32'; +import type { CurveConfig } from '../types'; const PRIME256V1 = 'prime256v1'; const SECP256K1 = 'secp256k1'; -const generateBytes = (byteLength) => { +const generateBytes = (byteLength: number): Promise => { return new Promise((resolve, reject) => crypto.randomBytes(byteLength, (err, buf) => { return err ? reject(err) : resolve(buf); @@ -17,22 +18,22 @@ const generateBytes = (byteLength) => { const DEFAULT_ENCRYPT_OPTIONS = { preserveObjectShape: true, - fieldsToEncrypt: undefined, + fieldsToEncrypt: undefined as string[] | undefined, }; -/** - * @param {import('../types').CurveConfig} config - */ -module.exports = (config) => { - let MAX_FILE_SIZE_IN_BYTES = config.maxFileSizeInMB * 1024 * 1024; +type EncryptOptions = typeof DEFAULT_ENCRYPT_OPTIONS; + +const Crypto = (config: CurveConfig) => { + let MAX_FILE_SIZE_IN_BYTES = Number(config.maxFileSizeInMB) * 1024 * 1024; const _encryptObject = async ( - curve, - ecdhTeamKey, - ecdhPublicKey, - derivedSecret, - data, - role - ) => { + curve: string, + ecdhTeamKey: any, + ecdhPublicKey: any, + derivedSecret: Buffer, + data: any, + role?: string | null, + _options?: EncryptOptions + ): Promise => { return await _traverseObject( curve, ecdhTeamKey, @@ -43,13 +44,13 @@ module.exports = (config) => { ); }; const _traverseObject = async ( - curve, - ecdhTeamKey, - ecdhPublicKey, - derivedSecret, - data, - role - ) => { + curve: string, + ecdhTeamKey: any, + ecdhPublicKey: any, + derivedSecret: Buffer, + data: any, + role?: string | null + ): Promise => { if (Datatypes.isEncryptable(data)) { return await _encryptString( curve, @@ -74,9 +75,9 @@ module.exports = (config) => { } return encryptedObject; } else if (Datatypes.isArray(data)) { - const encryptedArray = [...data]; + const encryptedArray: any[] = [...data]; for (let [key, value] of Object.entries(encryptedArray)) { - encryptedArray[key] = await _traverseObject( + encryptedArray[key as any] = await _traverseObject( curve, ecdhTeamKey, ecdhPublicKey, @@ -91,11 +92,16 @@ module.exports = (config) => { } }; - const base64RemovePadding = (str) => { + const base64RemovePadding = (str: string): string => { return str.replace(/={1,2}$/, ''); }; - const getSharedSecret = (ecdh, publicKey, ephemeralPublicKey, curveName) => { + const getSharedSecret = ( + ecdh: crypto.ECDH, + publicKey: any, + ephemeralPublicKey: any, + curveName: string + ): Buffer => { const secret = ecdh.computeSecret(Buffer.from(publicKey, 'base64')); const uncompressedKey = crypto.ECDH.convertKey( ephemeralPublicKey, @@ -103,7 +109,7 @@ module.exports = (config) => { 'base64', 'base64', 'uncompressed' - ); + ) as string; const concatSecret = Buffer.concat([ secret, Buffer.from([0x00, 0x00, 0x00, 0x01]), @@ -116,11 +122,11 @@ module.exports = (config) => { }; function createV2Aad( - dataType, - hasDataPolicy, - ephemeralPublicKeyBytes, - appPublicKeyBytes - ) { + dataType: string | undefined, + hasDataPolicy: boolean, + ephemeralPublicKeyBytes: Buffer, + appPublicKeyBytes: Buffer + ): Buffer { let dataTypeNumber = 0; // Default to String if (dataType === 'number') { @@ -163,23 +169,23 @@ module.exports = (config) => { } const _encryptString = async ( - curve, - ecdhTeamKey, - ecdhPublicKey, - derivedSecret, - str, - datatype, - role - ) => { + curve: string, + ecdhTeamKey: any, + ecdhPublicKey: any, + derivedSecret: Buffer, + str: any, + datatype: string | undefined, + role?: string | null + ): Promise => { const keyIv = await generateBytes(config.ivLength); const cipher = crypto.createCipheriv( - config.cipherAlgorithm, + config.cipherAlgorithm as crypto.CipherGCMTypes, derivedSecret, keyIv, { authTagLength: config.authTagLength, } - ); + ) as crypto.CipherGCM; if (role && (curve === PRIME256V1 || curve === SECP256K1)) { const aad = createV2Aad( datatype, @@ -209,8 +215,11 @@ module.exports = (config) => { ); }; - const buildEncodedMetadata = (role, encryptionTimestamp) => { - let buffer = []; + const buildEncodedMetadata = ( + role: string | null | undefined, + encryptionTimestamp: number + ): Buffer => { + let buffer: number[] = []; // Binary representation of a fixed map with 2 or 3 items, followed by the key-value pairs. buffer.push(0x80 | (!role ? 2 : 3)); @@ -249,8 +258,8 @@ module.exports = (config) => { return Buffer.from(buffer); }; - const buildCipherBuffer = (data, role) => { - let result; + const buildCipherBuffer = (data: any, role?: string | null): Buffer => { + let result: Buffer; if (role) { const metadataBytes = buildEncodedMetadata( role, @@ -265,10 +274,10 @@ module.exports = (config) => { return result; }; - const _evVersionPrefix = (role) => + const _evVersionPrefix = (role?: string | null | boolean): string => role ? config.evVersionWithMetadata : config.evVersion; - const _evEncryptedFileVersion = () => { + const _evEncryptedFileVersion = (): Buffer => { if (config.ecdhCurve == 'secp256k1') { return Buffer.from([0x02]); } else if (config.ecdhCurve === 'prime256v1') { @@ -279,12 +288,12 @@ module.exports = (config) => { }; const _format = ( - datatype = 'string', - keyIv, - ecdhPublicKey, - encryptedData, - role - ) => { + datatype: string | undefined = 'string', + keyIv: string, + ecdhPublicKey: any, + encryptedData: string, + role?: string | null + ): string => { return `ev:${_evVersionPrefix(role)}${ datatype !== 'string' ? ':' + datatype : '' }:${base64RemovePadding(keyIv)}:${base64RemovePadding( @@ -293,20 +302,20 @@ module.exports = (config) => { }; const _encryptBytes = ( - data, - setAuthData, - derivedSecret, - ecdhTeamKey, - keyIv - ) => { + data: Buffer, + setAuthData: boolean, + derivedSecret: Buffer, + ecdhTeamKey: any, + keyIv: Buffer + ): Buffer => { const cipher = crypto.createCipheriv( - config.cipherAlgorithm, + config.cipherAlgorithm as crypto.CipherGCMTypes, derivedSecret, keyIv, { authTagLength: config.authTagLength, } - ); + ) as crypto.CipherGCM; if (setAuthData) { cipher.setAAD(Buffer.from(ecdhTeamKey, 'base64')); @@ -320,13 +329,13 @@ module.exports = (config) => { }; const _encryptFile = async ( - curve, - ecdhTeamKey, - ecdhPublicKey, - derivedSecret, - data, - role - ) => { + curve: string, + ecdhTeamKey: any, + ecdhPublicKey: any, + derivedSecret: Buffer, + data: Buffer, + role?: string | null + ): Promise => { const fileSizeInBytes = data.length; if (role) { throw new errors.DataRolesNotSupportedError( @@ -353,11 +362,15 @@ module.exports = (config) => { return _formatFile(keyIv, ecdhPublicKey, encryptedBuffer); }; - const _calculateOffsetToData = () => { + const _calculateOffsetToData = (): Buffer => { return Buffer.from([0x37, 0x00]); // 55 bytes to starting byte of data if no metadtata }; - const _formatFile = async (keyIv, ecdhPublicKey, encryptedData) => { + const _formatFile = async ( + keyIv: Buffer, + ecdhPublicKey: any, + encryptedData: Buffer + ): Promise => { const evEncryptedFileIdentifier = Buffer.from([ 0x25, 0x45, 0x56, 0x45, 0x4e, 0x43, ]); @@ -386,14 +399,14 @@ module.exports = (config) => { }; const encrypt = async ( - curve, - ecdhTeamKey, - ecdhPublicKey, - derivedSecret, - data, - role = undefined, - options = DEFAULT_ENCRYPT_OPTIONS - ) => { + curve: string, + ecdhTeamKey: any, + ecdhPublicKey: any, + derivedSecret: Buffer, + data: any, + role: string | null | undefined = undefined, + options: EncryptOptions = DEFAULT_ENCRYPT_OPTIONS + ): Promise => { if (!Datatypes.isDefined(data)) { throw new Error('Data must not be undefined'); } @@ -449,3 +462,5 @@ module.exports = (config) => { buildEncodedMetadata, }; }; + +export default Crypto; diff --git a/lib/core/http.js b/lib/core/http.ts similarity index 78% rename from lib/core/http.js rename to lib/core/http.ts index 1910aeea..a15bd2ae 100644 --- a/lib/core/http.js +++ b/lib/core/http.ts @@ -1,23 +1,35 @@ -const { errors, Datatypes } = require('../utils'); +import { errors, Datatypes } from '../utils'; +import axios from 'axios'; +import type { + AxiosRequestConfig, + AxiosResponse, + Method, + ResponseType, +} from 'axios'; +import type { HttpConfig } from '../types'; +import type { Agent as HttpAgent } from 'http'; +import type { Agent as HttpsAgent } from 'https'; -const axios = require('axios'); +interface HttpAgents { + httpAgent?: HttpAgent; + httpsAgent?: HttpsAgent; +} -/** - * @param {string} appUuid - * @param {string} apiKey - * @param {import('../types').HttpConfig} config - * @param {{ httpAgent?: import('http').Agent, httpsAgent?: import('https').Agent }} [agents] - */ -module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { +export default ( + appUuid: string, + apiKey: string, + config: HttpConfig, + { httpAgent, httpsAgent }: HttpAgents = {} +) => { const request = ( - method, - path, - additionalHeaders = {}, - data = undefined, + method: Method, + path: string, + additionalHeaders: Record = {}, + data: any = undefined, basicAuth = false, - responseType = 'json' - ) => { - const headers = { + responseType: ResponseType = 'json' + ): Promise => { + const headers: Record = { 'user-agent': config.userAgent, ...additionalHeaders, }; @@ -29,7 +41,7 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { headers['api-key'] = apiKey; } - const requestConfig = { + const requestConfig: AxiosRequestConfig = { url: path.startsWith('https://') || path.startsWith('http://') ? path @@ -37,7 +49,7 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { method, headers, data, - validateStatus: (_) => true, + validateStatus: (_status: number) => true, responseType, }; @@ -47,19 +59,20 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { return axios(requestConfig); }; - const get = (path, headers) => request('GET', path, headers); + const get = (path: string, headers?: Record) => + request('GET', path, headers); const post = ( - path, - data, - headers = { 'Content-Type': 'application/json' }, + path: string, + data: any, + headers: Record = { 'Content-Type': 'application/json' }, basicAuth = false, - responseType = 'json' + responseType: ResponseType = 'json' ) => request('POST', path, headers, data, basicAuth, responseType); const getCageKey = async () => { const getCagesKeyCallback = async () => { - return await get('cages/key', {}, true).catch((_e) => { + return await get('cages/key', {}).catch((_e) => { throw new errors.EvervaultError( "An error occurred while retrieving the cage's key" ); @@ -99,7 +112,11 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { return response.data; }; - const getAttestationDoc = async (enclaveName, appUuid, hostname) => { + const getAttestationDoc = async ( + enclaveName: string, + appUuid: string, + hostname?: string + ) => { let url = `https://${enclaveName}.${appUuid}.${ hostname ? hostname : config.enclavesHostname }/.well-known/attestation`; @@ -120,7 +137,7 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { ); }); if (response.status >= 200 && response.status < 300) { - const pollIntervalHeaderValue = response.headers['x-poll-interval']; + const pollIntervalHeaderValue: any = response.headers['x-poll-interval']; return { pollInterval: isNaN(pollIntervalHeaderValue) ? null @@ -131,7 +148,7 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { throw errors.mapResponseCodeToError(response); }; - const runFunction = async (functionName, payload) => { + const runFunction = async (functionName: string, payload: any) => { const response = await post( `${config.baseUrl}/functions/${functionName}/runs`, { @@ -155,7 +172,7 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { throw errors.mapApiResponseToError(responseBody); }; - const createRunToken = (functionName, payload) => { + const createRunToken = (functionName: string, payload: any) => { return post( `v2/functions/${functionName}/run-token`, { @@ -168,13 +185,13 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { }; async function makeGetRequestWithRetry( - requestCallback, + requestCallback: () => Promise, maxRetries = 3, retryDelay = 250 - ) { + ): Promise { let retryCount = 0; let retryDelayMs = retryDelay; - let error = null; + let error: unknown = null; while (retryCount < maxRetries) { try { return await requestCallback().then((response) => { @@ -195,10 +212,10 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { throw error; } - const decrypt = async (encryptedData) => { + const decrypt = async (encryptedData: any) => { let contentType; let data; - let responseType; + let responseType: ResponseType; if (Buffer.isBuffer(encryptedData)) { contentType = 'application/octet-stream'; data = encryptedData; @@ -232,7 +249,7 @@ module.exports = (appUuid, apiKey, config, { httpAgent, httpsAgent } = {}) => { throw errors.mapApiResponseToError(resBody); }; - const createToken = async (action, payload, expiry) => { + const createToken = async (action: string, payload: any, expiry?: any) => { let wellFormedExpiry; if (expiry) { if (expiry && expiry instanceof Date) { diff --git a/lib/core/index.js b/lib/core/index.js deleted file mode 100644 index 5f41868d..00000000 --- a/lib/core/index.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - Crypto: require('./crypto'), - Http: require('./http'), - RelayOutboundConfig: require('./relayOutboundConfig'), - AttestationDoc: require('./attestationDoc'), - PcrManager: require('./pcrManager'), -}; diff --git a/lib/core/index.ts b/lib/core/index.ts new file mode 100644 index 00000000..081234c1 --- /dev/null +++ b/lib/core/index.ts @@ -0,0 +1,5 @@ +export { default as Crypto } from './crypto'; +export { default as Http } from './http'; +export * as RelayOutboundConfig from './relayOutboundConfig'; +export { default as AttestationDoc } from './attestationDoc'; +export { default as PcrManager } from './pcrManager'; diff --git a/lib/core/pcrManager.js b/lib/core/pcrManager.ts similarity index 80% rename from lib/core/pcrManager.js rename to lib/core/pcrManager.ts index 4bb49e0b..ec9de26b 100644 --- a/lib/core/pcrManager.js +++ b/lib/core/pcrManager.ts @@ -1,8 +1,14 @@ -const RepeatedTimer = require('./repeatedTimer'); - -const staticPcrsToProvider = (pcrs) => { +import RepeatedTimer from './repeatedTimer'; +import type { + MasterConfig, + PCRs, + AttestationData, + AttestationCallback, +} from '../types'; + +const staticPcrsToProvider = (pcrs: PCRs[]) => { const provider = async () => { - return new Promise((resolve) => { + return new Promise((resolve) => { resolve(pcrs); }); }; @@ -10,8 +16,11 @@ const staticPcrsToProvider = (pcrs) => { return { pcrs, provider }; }; -const loadPcrStore = (attestationData) => { - const providers = {}; +const loadPcrStore = ( + attestationData: Record +) => { + const providers: Record Promise }> = + {}; for (const [enclaveName, value] of Object.entries(attestationData)) { if (Array.isArray(value)) { providers[enclaveName] = staticPcrsToProvider(value); @@ -28,7 +37,14 @@ const loadPcrStore = (attestationData) => { }; class PcrManager { - constructor(config, attestationData) { + store: Record; + config: MasterConfig; + polling: ReturnType | null; + + constructor( + config: MasterConfig, + attestationData: Record + ) { this.store = loadPcrStore(attestationData); this.config = config; this.polling = null; @@ -48,7 +64,7 @@ class PcrManager { return null; }; - fetchPcrs = async (enclaveName) => { + fetchPcrs = async (enclaveName: string) => { const enclave = this.store[enclaveName]; if (!enclave || !enclave.provider) { @@ -92,7 +108,7 @@ class PcrManager { } }; - get = (enclaveName) => { + get = (enclaveName: string) => { const storedAttestationData = this.store[enclaveName]; const pcrs = storedAttestationData ? storedAttestationData.pcrs : undefined; @@ -137,4 +153,4 @@ class PcrManager { }; } -module.exports = PcrManager; +export default PcrManager; diff --git a/lib/core/relayOutboundConfig.js b/lib/core/relayOutboundConfig.ts similarity index 73% rename from lib/core/relayOutboundConfig.js rename to lib/core/relayOutboundConfig.ts index 7b124865..2f10ec73 100644 --- a/lib/core/relayOutboundConfig.js +++ b/lib/core/relayOutboundConfig.ts @@ -1,7 +1,8 @@ -const RepeatedTimer = require('./repeatedTimer'); +import RepeatedTimer from './repeatedTimer'; +import type { MasterConfig } from '../types'; -let polling = null; -let decryptionDomainsCache = null; +let polling: ReturnType | null = null; +let decryptionDomainsCache: string[] | null = null; const disablePolling = () => { if (polling) { @@ -21,11 +22,11 @@ const clearCache = () => { decryptionDomainsCache = null; }; -const getDecryptionDomains = () => { +const getDecryptionDomains = (): string[] | null => { return decryptionDomainsCache; }; -const init = async (config, http) => { +const init = async (config: MasterConfig, http: any) => { let pollingInterval = config.http.pollInterval; const getRelayOutboundConfigFromApi = async () => { @@ -38,7 +39,7 @@ const init = async (config, http) => { } decryptionDomainsCache = Object.values( configResponse.data.outboundDestinations - ).map((config) => config.destinationDomain); + ).map((config: any) => config.destinationDomain); }; /* Initialization */ @@ -52,7 +53,7 @@ const init = async (config, http) => { return polling; }; -module.exports = { +export { init, getDecryptionDomains, disablePolling, diff --git a/lib/core/repeatedTimer.js b/lib/core/repeatedTimer.ts similarity index 64% rename from lib/core/repeatedTimer.js rename to lib/core/repeatedTimer.ts index 8f2de5d1..ec7ca031 100644 --- a/lib/core/repeatedTimer.js +++ b/lib/core/repeatedTimer.ts @@ -1,18 +1,21 @@ -const { InvalidInterval } = require('../utils/errors'); +import { InvalidInterval } from '../utils/errors'; -module.exports = (defaultInterval, cb) => { - const parsedInterval = parseFloat(defaultInterval); +export default ( + defaultInterval: number | string, + cb: () => Promise | void +) => { + const parsedInterval = parseFloat(defaultInterval as any); if (Number.isNaN(parsedInterval)) { throw new InvalidInterval(`Expected number, received ${parsedInterval}`); } - const createInterval = () => { + const createInterval = (): NodeJS.Timeout => { const initializedInterval = setInterval(async () => { try { await cb(); } catch (e) { console.error(`EVERVAULT :: An error occurred while polling (${e})`); } - }, interval * 1000); + }, (interval as number) * 1000); initializedInterval.unref(); return initializedInterval; }; @@ -23,7 +26,7 @@ module.exports = (defaultInterval, cb) => { } }; - const updateInterval = (newInterval) => { + const updateInterval = (newInterval: number) => { if (interval !== newInterval) { interval = newInterval; stop(); @@ -34,15 +37,15 @@ module.exports = (defaultInterval, cb) => { const getInterval = () => interval; const stop = () => { - clearInterval(currentIntervalId); + if (currentIntervalId) clearInterval(currentIntervalId); currentIntervalId = null; }; const isRunning = () => currentIntervalId !== null; /* Initialization */ - let interval = defaultInterval; - let currentIntervalId = null; + let interval: number | string = defaultInterval; + let currentIntervalId: NodeJS.Timeout | null = null; start(); return { diff --git a/lib/curves/base.js b/lib/curves/base.ts similarity index 81% rename from lib/curves/base.js rename to lib/curves/base.ts index 19778233..30c1a236 100644 --- a/lib/curves/base.js +++ b/lib/curves/base.ts @@ -1,6 +1,10 @@ -const crypto = require('crypto'); -const ASN1 = require('asn1js'); -const curveConstants = require('./constants'); +import * as crypto from 'crypto'; +import * as ASN1ns from 'asn1js'; +import curveConstants from './constants'; + +// asn1js's constructor param typings are awkward for this low-level DER +// encoder; treat the namespace as untyped here and rely on runtime behavior. +const ASN1: any = ASN1ns; /** * Given an EC curve name and its constants, generate a DER encoder for its compressed public keys @@ -9,7 +13,7 @@ const curveConstants = require('./constants'); * @returns Function(compressedPubKey): base64EncodedString */ const createCurve = () => { - return (curveName, compressedPubKey) => { + return (curveName: string, compressedPubKey: string): Buffer => { const asn1Encoder = buildEncoder(curveName); const decompressed = crypto.ECDH.convertKey( compressedPubKey, @@ -17,13 +21,13 @@ const createCurve = () => { 'base64', 'hex', 'uncompressed' - ); + ) as string; return asn1Encoder(decompressed); }; }; -const hexStringToUint8Array = (hexString) => { - return hexString.match(/../g).map((h) => parseInt(h, 16)); +const hexStringToUint8Array = (hexString: string): number[] => { + return hexString.match(/../g)!.map((h) => parseInt(h, 16)); }; const PUBLIC_KEY_TYPE = '1.2.840.10045.2.1'; @@ -35,7 +39,7 @@ const VERSION = '01'; // https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03111/BSI-TR-03111_V-2-0_pdf.pdf?__blob=publicationFile&v=1 // // The seed parameter is optional. -const FieldId = (curveParams) => { +const FieldId = (curveParams: any) => { return new ASN1.Sequence({ name: 'fieldID', value: [ @@ -55,7 +59,7 @@ const FieldId = (curveParams) => { }); }; -const Curve = (curveParams) => { +const Curve = (curveParams: any) => { return new ASN1.Sequence({ name: 'curve', value: curveParams.seed @@ -93,7 +97,7 @@ const Curve = (curveParams) => { }); }; -const ECParameters = (curveParams) => { +const ECParameters = (curveParams: any) => { return new ASN1.Sequence({ name: 'ecParameters', value: [ @@ -125,7 +129,7 @@ const ECParameters = (curveParams) => { }); }; -const AlgorithmIdentifier = (curveParams) => { +const AlgorithmIdentifier = (curveParams: any) => { return new ASN1.Sequence({ name: 'algorithm', value: [ @@ -138,7 +142,7 @@ const AlgorithmIdentifier = (curveParams) => { }); }; -const SubjectPublicKeyInfo = (curveParams, decompressedKey) => { +const SubjectPublicKeyInfo = (curveParams: any, decompressedKey: string) => { return new ASN1.Sequence({ name: 'SubjectPublicKeyInfo', value: [ @@ -151,14 +155,12 @@ const SubjectPublicKeyInfo = (curveParams, decompressedKey) => { }); }; -const buildEncoder = (curveName) => { - const curveParams = curveConstants[curveName]; - return (decompressedKey) => { +const buildEncoder = (curveName: string) => { + const curveParams = curveConstants[curveName as keyof typeof curveConstants]; + return (decompressedKey: string): Buffer => { const spki = SubjectPublicKeyInfo(curveParams, decompressedKey); return Buffer.from(spki.toString('hex'), 'hex'); }; }; -module.exports = { - encodePublicKey: createCurve(), -}; +export const encodePublicKey = createCurve(); diff --git a/lib/curves/constants.js b/lib/curves/constants.ts similarity index 98% rename from lib/curves/constants.js rename to lib/curves/constants.ts index e3aa1bad..11850bce 100644 --- a/lib/curves/constants.js +++ b/lib/curves/constants.ts @@ -1,5 +1,5 @@ // https://neuromancer.sk/std/x962/prime256v1 -module.exports = { +export default { prime256v1: { p: 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', a: 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC', diff --git a/lib/curves/index.js b/lib/curves/index.js deleted file mode 100644 index 91e964c5..00000000 --- a/lib/curves/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - Encoding: require('./base'), -}; diff --git a/lib/curves/index.ts b/lib/curves/index.ts new file mode 100644 index 00000000..cdf5239b --- /dev/null +++ b/lib/curves/index.ts @@ -0,0 +1 @@ +export * as Encoding from './base'; diff --git a/lib/index.js b/lib/index.ts similarity index 69% rename from lib/index.js rename to lib/index.ts index 07b18d6d..80342563 100644 --- a/lib/index.js +++ b/lib/index.ts @@ -1,55 +1,78 @@ -const crypto = require('crypto'); -const http = require('http'); -const https = require('https'); -const retry = require('async-retry'); -const { Buffer } = require('buffer'); - -const { +import * as crypto from 'crypto'; +import * as http from 'http'; +import https from 'https'; +import type { AgentOptions } from 'https'; +import retry from 'async-retry'; +import { Buffer } from 'buffer'; + +import { Datatypes, errors, validationHelper, httpsHelper, attest, -} = require('./utils'); -const config = require('./config'); -const { +} from './utils'; +import config from './config'; +import { Crypto, Http, RelayOutboundConfig, AttestationDoc, PcrManager, -} = require('./core'); -const { TokenCreationError } = require('./utils/errors'); -const HttpsProxyAgent = require('./utils/proxyAgent'); -const { importTarget, matchTarget } = require('./utils/domainTargets'); +} from './core'; +import { TokenCreationError } from './utils/errors'; +import HttpsProxyAgent from './utils/proxyAgent'; +import { importTarget, matchTarget } from './utils/domainTargets'; +import type { Target } from './utils/domainTargets'; +import type { + MasterConfig, + SdkOptions, + OutboundRelayOptions, + SupportedCurve, + AttestationData, + AttestationCallback, + AttestationBindings, +} from './types'; const originalRequest = https.request; +type Timer = ReturnType; + class EvervaultClient { - /** @type {{ [curveName: string]: import('./types').SupportedCurve }} */ - static CURVES = { + static CURVES: { + readonly SECP256K1: SupportedCurve; + readonly PRIME256V1: SupportedCurve; + } = { SECP256K1: 'secp256k1', PRIME256V1: 'prime256v1', }; - /** @typedef {ReturnType} Timer */ - /** @private @type {{ enclaves: Timer[] | null, relayOutbound: Timer | null}} */ _backgroundJobs; - - /** @private @type {string} */ apiKey; - /** @private @type {string} */ appId; - /** @private @type {import('./types')} */ config; - /** @private @type {import('./types').SupportedCurve} */ curve; - /** @private @type {ReturnType} */ http; - /** @private @type {import('./utils/httpsHelper')} */ httpsHelper; - /** @private @type {boolean | undefined} */ retry; - /** @private @type {ReturnType} */ crypto; - - /** - * @param {string} appId - * @param {string} apiKey - * @param {Partial} options - */ - constructor(appId, apiKey = undefined, options = {}) { + private _backgroundJobs: { + enclaves: Timer[] | null; + relayOutbound: Timer | null; + }; + private apiKey?: string; + private appId: string; + private config: MasterConfig; + private curve: SupportedCurve; + private http: ReturnType; + private httpsHelper: typeof httpsHelper; + private retry?: boolean; + private crypto: ReturnType; + private encryptionMode?: boolean; + + // Hidden properties defined via defineHiddenProperty (Object.defineProperty). + private _ecdhTeamKey?: any; + private _ecdh?: any; + private _ecdhPublicKey?: any; + private _derivedAesKey?: any; + private _refreshInterval?: any; + + constructor( + appId: string, + apiKey: string | undefined = undefined, + options: Partial = {} + ) { if ( appId === '' || !Datatypes.isString(appId) || @@ -69,7 +92,7 @@ class EvervaultClient { ); } this.config = config; - let curve; + let curve: SupportedCurve; if (!options.curve || !this.config.encryption[options.curve]) { curve = EvervaultClient.CURVES.SECP256K1; //default to old curve } else { @@ -96,7 +119,7 @@ class EvervaultClient { this.curve = curve; this.retry = options.retry; - this.http = Http(appId, apiKey, this.config.http, { + this.http = Http(appId, apiKey as string, this.config.http, { httpAgent: options.httpAgent, httpsAgent: options.httpsAgent, }); @@ -118,12 +141,10 @@ class EvervaultClient { this._shouldOverloadHttpModule(options, apiKey); } - /** - * @param {Record} attestationData - * @param {import('./types').AttestationBindings} attestationBindings - * @throws {import('./utils/errors').MalformedAttestationData} - */ - async enableEnclaves(attestationData, attestationBindings) { + async enableEnclaves( + attestationData: Record, + attestationBindings: AttestationBindings + ) { validationHelper.validateApiKey(this.appId, this.apiKey); attest.validateAttestationData(attestationData); // Store attestation documents in cache @@ -160,13 +181,11 @@ class EvervaultClient { } } - /** - * @param {import('./types') AttestationData} attestationData - * @param {import('./types').AttestationBindings} attestationBindings - * @param {import('https').AgentOptions} option - * @throws {import('./utils/errors').MalformedAttestationData} - **/ - async createEnclaveHttpsAgent(attestationData, attestationBindings, options) { + async createEnclaveHttpsAgent( + attestationData: Record, + attestationBindings: AttestationBindings, + options?: AgentOptions + ) { attest.validateAttestationData(attestationData); const attestationCache = new AttestationDoc( @@ -192,19 +211,15 @@ class EvervaultClient { ); } - /** @returns {Promise} */ - async generateNonce() { + async generateNonce(): Promise { const nonce = await this.crypto.generateBytes(16); return nonce.toString('base64').replaceAll(/=|\//g, ''); } - /** - * @private - * @param {Partial} options - * @param {string} apiKey - * @returns {Promise} - */ - async _shouldOverloadHttpModule(options, apiKey) { + private async _shouldOverloadHttpModule( + options: Partial, + apiKey?: string + ): Promise { if (options.decryptionDomains && options.decryptionDomains.length > 0) { const decryptionDomainsFilter = this._decryptionDomainsFilter( options.decryptionDomains @@ -227,31 +242,26 @@ class EvervaultClient { originalRequest ); } else { - https.request = originalRequest; + (https as any).request = originalRequest; } } - /** - * @private - * @returns {string[]} - */ - _alwaysIgnoreDomains() { + private _alwaysIgnoreDomains(): string[] { const caHost = new URL(this.config.http.certHostname).host; const apiHost = new URL(this.config.http.baseUrl).host; return [caHost, apiHost, this.config.http.enclavesHostname]; } - /** - * @private - * @param {string[]} decryptionDomains - * @returns {(domain: string, path: string) => boolean} - */ - _decryptionDomainsFilter(decryptionDomains) { + private _decryptionDomainsFilter( + decryptionDomains: string[] + ): (domain: string, path: string) => boolean { const parsedDomains = decryptionDomains .map((decryptionDomain) => importTarget(decryptionDomain)) - .filter((importedTarget) => importedTarget != null); - return (domain, path) => + .filter( + (importedTarget): importedTarget is Target => importedTarget != null + ); + return (domain: string, path: string) => this._isDecryptionDomain( domain, path, @@ -260,32 +270,28 @@ class EvervaultClient { ); } - /** - * @private - * @param {string} domain - * @param {string} path - * @param {import('./utils/domainTargets').Target[]} decryptionDomains - * @param {string[]} alwaysIgnore - */ - _isDecryptionDomain(domain, path, decryptionDomains, alwaysIgnore) { + private _isDecryptionDomain( + domain: string, + path: string, + decryptionDomains: Target[], + alwaysIgnore: string[] + ): boolean { if (alwaysIgnore.includes(domain)) return false; return decryptionDomains.some((decryptionDomain) => matchTarget(domain, path, decryptionDomain) ); } - /** @private @returns {(domain: string, path: string) => boolean} */ - _relayOutboundConfigDomainFilter() { + private _relayOutboundConfigDomainFilter(): ( + domain: string, + path: string + ) => boolean { return this._decryptionDomainsFilter( - RelayOutboundConfig.getDecryptionDomains() + RelayOutboundConfig.getDecryptionDomains() as string[] ).bind(this); } - /** - * @private - * @param {string | undefined} role - */ - _refreshKeys(role) { + private _refreshKeys(role?: string | null) { this._ecdh.generateKeys(); this.defineHiddenProperty( '_ecdhPublicKey', @@ -312,12 +318,7 @@ class EvervaultClient { } } - /** - * @param {Object || String} data - * @param {String || undefined} role - * @returns {Promise} - */ - async encrypt(data, role = null) { + async encrypt(data: any, role: string | null = null): Promise { const dataRoleRegex = /^[a-z0-9-]{1,20}$/; if (role !== null && !dataRoleRegex.test(role)) { throw new Error( @@ -344,7 +345,7 @@ class EvervaultClient { this.defineHiddenProperty( '_refreshInterval', setInterval( - (ref) => { + (ref: EvervaultClient) => { ref._refreshKeys(role); }, this.config.encryption[this.curve].keyCycleMinutes * 60 * 1000, @@ -362,21 +363,12 @@ class EvervaultClient { ); } - /** - * @param {any} encryptedData - * @returns {Promise} - */ - async decrypt(encryptedData) { + async decrypt(encryptedData: any): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); return this.http.decrypt(encryptedData); } - /** - * @param {string} functionName - * @param {object} payload - * @returns {Promise<*>} - */ - async run(functionName, payload) { + async run(functionName: string, payload: any): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); validationHelper.validateFunctionName(functionName); validationHelper.validatePayload(payload); @@ -395,12 +387,7 @@ class EvervaultClient { } } - /** - * @param {string} functionName - * @param {object} payload - * @returns {Promise<*>} - */ - async createRunToken(functionName, payload) { + async createRunToken(functionName: string, payload: any): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); validationHelper.validatePayload(payload); validationHelper.validateFunctionName(functionName); @@ -409,10 +396,7 @@ class EvervaultClient { return response.data; } - /** - * @param {import('./types').OutboundRelayOptions} options - */ - async enableOutboundRelay(options = {}) { + async enableOutboundRelay(options: OutboundRelayOptions = {}): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); validationHelper.validateRelayOutboundOptions(options); if (!options || !options.decryptionDomains) { @@ -456,10 +440,7 @@ class EvervaultClient { } } - /** - * @returns {HttpsProxyAgent} - */ - createRelayHttpsAgent() { + createRelayHttpsAgent(): HttpsProxyAgent { validationHelper.validateApiKey(this.appId, this.apiKey); return this.httpsHelper.httpsRelayAgent( { @@ -470,12 +451,7 @@ class EvervaultClient { ); } - /** - * @private - * @param {string | number | symbol} property - * @param {*} value - */ - defineHiddenProperty(property, value) { + private defineHiddenProperty(property: string | number | symbol, value: any) { Object.defineProperty(this, property, { enumerable: false, configurable: true, @@ -484,7 +460,7 @@ class EvervaultClient { }); } - async createClientSideDecryptToken(payload, expiry = null) { + async createClientSideDecryptToken(payload: any, expiry: any = null) { validationHelper.validateApiKey(this.appId, this.apiKey); if (!payload) { throw new TokenCreationError( @@ -495,4 +471,4 @@ class EvervaultClient { } } -module.exports = EvervaultClient; +export = EvervaultClient; diff --git a/lib/types.d.ts b/lib/types.ts similarity index 87% rename from lib/types.d.ts rename to lib/types.ts index 240a07e4..bfeb52ad 100644 --- a/lib/types.d.ts +++ b/lib/types.ts @@ -1,3 +1,6 @@ +import type { Agent as HttpAgent } from 'http'; +import type { Agent as HttpsAgent } from 'https'; + export interface HttpConfig { baseUrl: string; userAgent: string; @@ -7,7 +10,7 @@ export interface HttpConfig { pollInterval: string | number; attestationDocPollInterval: string | number; pcrProviderPollInterval: string | number; - proxiedMarker: Symbol; + proxiedMarker: symbol; } export interface CurveConfig { @@ -44,8 +47,9 @@ export interface SdkOptions { curve?: SupportedCurve; retry?: boolean; enableOutboundRelay?: boolean; - httpAgent?: import('http').Agent; - httpsAgent?: import('https').Agent; + encryptionMode?: boolean; + httpAgent?: HttpAgent; + httpsAgent?: HttpsAgent; } export interface PCRs { diff --git a/lib/utils/attest.js b/lib/utils/attest.ts similarity index 66% rename from lib/utils/attest.js rename to lib/utils/attest.ts index 0004c50d..15c1eb6c 100644 --- a/lib/utils/attest.js +++ b/lib/utils/attest.ts @@ -1,10 +1,14 @@ -const { AttestationError, MalformedAttestationData } = require('./errors'); -const tls = require('tls'); -const https = require('https'); -const { hostname } = require('os'); +import { AttestationError, MalformedAttestationData } from './errors'; +import tls from 'tls'; +import * as https from 'https'; +import type { HttpConfig } from '../types'; + const origCheckServerIdentity = tls.checkServerIdentity; -function parseNameAndAppFromHost(hostname) { +function parseNameAndAppFromHost(hostname: string): { + name: string; + appUuid: string; +} { const hostnameTokens = hostname.split('.'); // Check if nonce prefix is present if (hostnameTokens[1] === 'attest') { @@ -14,21 +18,13 @@ function parseNameAndAppFromHost(hostname) { } } -/** - * @param {string} hostname - * @param {Buffer} cert - * @param {import('../core/pcrManager')} pcrManager - * @param {import('../core/attestationDoc')} attestationCache - * @param {import('../types').AttestationBindings} attestationBindings - * @returns {Error | undefined} - */ function attestConnection( - hostname, - cert, - cagePcrManager, - attestationCache, - attestationBindings -) { + hostname: string, + cert: any, + cagePcrManager: any, + attestationCache: any, + attestationBindings: any +): Error | undefined { try { if (!attestationBindings == null) { throw new AttestationError( @@ -69,7 +65,7 @@ function attestConnection( cert ); } - } catch (err) { + } catch (err: any) { console.error( `EVERVAULT ERROR :: An unexpected error occurred while attempting to attest a connection to your Enclave`, err.message @@ -83,18 +79,17 @@ function attestConnection( * Pass this to a https request to ensure that the connection is attested. */ class EnclaveAgent extends https.Agent { - /** - * @param {import('https').AgentOptions} option - * @param {import('../core/attestationDoc')} attestationCache - * @param {import('../core/pcrManager')} pcrManager - * @param {import('../types').AttestationBindings} attestationBindings - * */ + config: HttpConfig; + attestationCache: any; + pcrManager: any; + attestationBindings: any; + constructor( - option, - config, - attestationCache, - pcrManager, - attestationBindings + option: https.AgentOptions | undefined, + config: HttpConfig, + attestationCache: any, + pcrManager: any, + attestationBindings: any ) { super(option); this.config = config; @@ -103,7 +98,10 @@ class EnclaveAgent extends https.Agent { this.attestationBindings = attestationBindings; } - #checkEnclaveServerIdentity = (hostname, cert) => { + #checkEnclaveServerIdentity = ( + hostname: string, + cert: any + ): Error | undefined => { if (hostname.endsWith(this.config.enclavesHostname)) { const attestationResult = attestConnection( hostname, @@ -120,31 +118,22 @@ class EnclaveAgent extends https.Agent { return origCheckServerIdentity(hostname, cert); }; - createConnection(options, callback) { + createConnection(options: any, callback: any): any { options.checkServerIdentity = this.#checkEnclaveServerIdentity; return tls.connect(options, callback); } } -/** - * - * @param {import('../types').HttpConfig} config - * @param {import('../core/attestationDoc')} attestationCache - * @param {import('../core/pcrManager')} pcrManager - * @param {import('../types').AttestationBindings} attestationBindings - */ function addAttestationListener( - config, - attestationCache, - pcrManager, - attestationBindings -) { - /** - * @param {string} hostname - * @param {import('node:tls').PeerCertificate} cert - * @returns {Error | undefined} - */ - tls.checkServerIdentity = function (hostname, cert) { + config: HttpConfig, + attestationCache: any, + pcrManager: any, + attestationBindings: any +): void { + (tls as any).checkServerIdentity = function ( + hostname: string, + cert: any + ): Error | undefined { // only attempt attestation if the host is a cage if (hostname.endsWith(config.enclavesHostname)) { // we expect undefined when attestation is successful, else an error @@ -167,23 +156,25 @@ function addAttestationListener( /** * Ensure that the provided attestation data is correctly structured - * @param {unknown} providedAttestationData - * @throws {MalformedAttestationData} */ -function validateAttestationData(providedAttestationData) { - const isObject = (val) => +function validateAttestationData(providedAttestationData: unknown): void { + const isObject = (val: unknown) => val != null && typeof val === 'object' && !Array.isArray(val); - const isFunction = (val) => typeof val === 'function'; + const isFunction = (val: unknown) => typeof val === 'function'; if (!isObject(providedAttestationData)) { throw new MalformedAttestationData( `Expected an object to be provided as attestation data, received ${ - Array.isArray(providedAttestationData) ? 'Array' : typeof val + Array.isArray(providedAttestationData) + ? 'Array' + : typeof providedAttestationData }` ); } - const containsOnlyObjects = Object.values(providedAttestationData).every( + const containsOnlyObjects = Object.values( + providedAttestationData as Record + ).every( (pcrs) => isObject(pcrs) || (Array.isArray(pcrs) && pcrs.every(isObject)) || @@ -196,7 +187,7 @@ function validateAttestationData(providedAttestationData) { } } -module.exports = { +export { attestConnection, addAttestationListener, parseNameAndAppFromHost, diff --git a/lib/utils/certHelper.js b/lib/utils/certHelper.ts similarity index 65% rename from lib/utils/certHelper.js rename to lib/utils/certHelper.ts index 45a4d47a..3c7fd32b 100644 --- a/lib/utils/certHelper.js +++ b/lib/utils/certHelper.ts @@ -1,12 +1,11 @@ -const { X509Certificate } = require('crypto'); +import { X509Certificate } from 'crypto'; +import * as tls from 'tls'; +import * as net from 'net'; -const parseX509 = (cert) => { +const parseX509 = (cert: any) => { if (X509Certificate) { return new X509Certificate(cert); } else { - const tls = require('tls'); - const net = require('net'); - const secureContext = tls.createSecureContext({ cert, }); @@ -17,6 +16,4 @@ const parseX509 = (cert) => { } }; -module.exports = { - parseX509, -}; +export { parseX509 }; diff --git a/lib/utils/crc32.js b/lib/utils/crc32.ts similarity index 89% rename from lib/utils/crc32.js rename to lib/utils/crc32.ts index fda5a54a..bbb895f5 100644 --- a/lib/utils/crc32.js +++ b/lib/utils/crc32.ts @@ -15,7 +15,7 @@ for (let i = 0; i < 256; i++) { // // @param {ArrayBuffer} buffer // @return {Number} -function crc32(buffer) { +function crc32(buffer: Buffer): number { let crc = 0xffffffff; const len = buffer.byteLength; @@ -26,4 +26,4 @@ function crc32(buffer) { return crc ^ 0xffffffff; } -module.exports = crc32; +export default crc32; diff --git a/lib/utils/datatypes.js b/lib/utils/datatypes.js deleted file mode 100644 index 0404af46..00000000 --- a/lib/utils/datatypes.js +++ /dev/null @@ -1,74 +0,0 @@ -const isArray = (data) => isDefined(data) && data.constructor.name === 'Array'; -const isBuffer = (data) => data.constructor.name.toLowerCase() === 'buffer'; -const isObject = (data) => typeof data === 'object'; -const isObjectStrict = (data) => - isDefined(data) && isObject(data) && !isArray(data) && !isBuffer(data); -const isString = (data) => typeof data === 'string'; -const isNumber = (data) => typeof data === 'number'; -const isDefined = (data) => typeof data !== 'undefined' && data !== null; -const isUndefined = (data) => typeof data === 'undefined'; -const isBoolean = (data) => typeof data === 'boolean'; -const isFunction = (data) => typeof data === 'function'; - -const isEncryptable = (data) => - isDefined(data) && (isString(data) || isNumber(data) || isBoolean(data)); - -const getHeaderType = (data) => { - if (!isDefined(data)) return; - if (isArray(data)) return 'array'; - else { - return typeof data; - } -}; - -const ensureString = (data) => { - if (isUndefined(data)) return; - - if (!isDefined(data)) return JSON.stringify(data); - if (isString(data)) return data.trim(); - if (['bigint', 'function'].includes(typeof data)) { - return data.toString(); - } - if (isBuffer(data)) { - return data.toString('utf8'); - } - return JSON.stringify(data); -}; - -const base64ToBase64Url = (base64String) => { - return base64String.replace('+', '-').replace('/', '_'); -}; - -const base64ToBuffer = (data) => Buffer.from(data, 'base64'); -const utf8ToBase64Url = (data) => { - const base64 = Buffer.from(data, 'utf8').toString('base64'); - return base64ToBase64Url(base64); -}; - -const KEY_HEADER = '-----BEGIN PUBLIC KEY-----\n'; -const KEY_FOOTER = '-----END PUBLIC KEY-----'; -const formatKey = (key) => { - if (key.includes(KEY_HEADER) && key.includes(KEY_FOOTER)) { - return key; - } - return `${KEY_HEADER}${key.match(/.{0,64}/g).join('\n')}${KEY_FOOTER}`; -}; - -module.exports = { - isArray, - isObject, - isObjectStrict, - isBuffer, - isString, - isFunction, - isEncryptable, - isNumber, - isBoolean, - getHeaderType, - isDefined, - isUndefined, - ensureString, - base64ToBuffer, - utf8ToBase64Url, - formatKey, -}; diff --git a/lib/utils/datatypes.ts b/lib/utils/datatypes.ts new file mode 100644 index 00000000..2817ab3b --- /dev/null +++ b/lib/utils/datatypes.ts @@ -0,0 +1,59 @@ +export const isArray = (data: any): boolean => + isDefined(data) && data.constructor.name === 'Array'; +export const isBuffer = (data: any): boolean => + data.constructor.name.toLowerCase() === 'buffer'; +export const isObject = (data: any): boolean => typeof data === 'object'; +export const isObjectStrict = (data: any): boolean => + isDefined(data) && isObject(data) && !isArray(data) && !isBuffer(data); +export const isString = (data: any): data is string => typeof data === 'string'; +export const isNumber = (data: any): boolean => typeof data === 'number'; +export const isDefined = (data: any): boolean => + typeof data !== 'undefined' && data !== null; +export const isUndefined = (data: any): boolean => typeof data === 'undefined'; +export const isBoolean = (data: any): boolean => typeof data === 'boolean'; +export const isFunction = (data: any): boolean => typeof data === 'function'; + +export const isEncryptable = (data: any): boolean => + isDefined(data) && (isString(data) || isNumber(data) || isBoolean(data)); + +export const getHeaderType = (data: any): string | undefined => { + if (!isDefined(data)) return; + if (isArray(data)) return 'array'; + else { + return typeof data; + } +}; + +export const ensureString = (data: any): string | undefined => { + if (isUndefined(data)) return; + + if (!isDefined(data)) return JSON.stringify(data); + if (isString(data)) return data.trim(); + if (['bigint', 'function'].includes(typeof data)) { + return data.toString(); + } + if (isBuffer(data)) { + return data.toString('utf8'); + } + return JSON.stringify(data); +}; + +const base64ToBase64Url = (base64String: string): string => { + return base64String.replace('+', '-').replace('/', '_'); +}; + +export const base64ToBuffer = (data: string): Buffer => + Buffer.from(data, 'base64'); +export const utf8ToBase64Url = (data: string): string => { + const base64 = Buffer.from(data, 'utf8').toString('base64'); + return base64ToBase64Url(base64); +}; + +const KEY_HEADER = '-----BEGIN PUBLIC KEY-----\n'; +const KEY_FOOTER = '-----END PUBLIC KEY-----'; +export const formatKey = (key: string): string => { + if (key.includes(KEY_HEADER) && key.includes(KEY_FOOTER)) { + return key; + } + return `${KEY_HEADER}${key.match(/.{0,64}/g)!.join('\n')}${KEY_FOOTER}`; +}; diff --git a/lib/utils/domainTargets.d.ts b/lib/utils/domainTargets.d.ts deleted file mode 100644 index 7c90faf1..00000000 --- a/lib/utils/domainTargets.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type MatcherSpecificity = "wildcard" | "absolute"; -export type MatcherType = "host" | "path"; - -export interface Target { - rawValue: string; - host: Matcher; - path?: Matcher; -} - -export interface Matcher { - specificity: MatcherSpecificity; - type: MatcherType; - value: string; -} \ No newline at end of file diff --git a/lib/utils/domainTargets.js b/lib/utils/domainTargets.ts similarity index 71% rename from lib/utils/domainTargets.js rename to lib/utils/domainTargets.ts index 6f3d00f6..41544fda 100644 --- a/lib/utils/domainTargets.js +++ b/lib/utils/domainTargets.ts @@ -2,12 +2,25 @@ * Grouping of helpers and types to aid reasoning about destinations when intercepting outbound traffic. */ +export type MatcherSpecificity = 'wildcard' | 'absolute'; +export type MatcherType = 'host' | 'path'; + +export interface Matcher { + type: MatcherType; + specificity: MatcherSpecificity; + value: string; +} + +export interface Target { + rawValue: string; + host: Matcher; + path?: Matcher; +} + /** * Apply the matching logic based on the matcher type and specificity. - * @param {string} givenValue - * @param {import("./domainTargets").Matcher} matcher */ -function applyMatch(givenValue, matcher) { +function applyMatch(givenValue: string, matcher: Matcher): boolean { if (matcher.specificity === 'absolute') { return givenValue === matcher.value; } @@ -22,11 +35,12 @@ function applyMatch(givenValue, matcher) { /** * Apply a target matcher against the given host and path combination. If a path matcher is defined on the target, it will only match if *both* the host and path match. - * @param {string} requestedHost - * @param {string} requestedPath - * @param {import('./domainTargets').Target} target */ -function matchTarget(requestedHost, requestedPath, target) { +function matchTarget( + requestedHost: string, + requestedPath: string, + target: Target +): boolean { if (target.path != null) { return ( applyMatch(requestedHost, target.host) && @@ -38,20 +52,18 @@ function matchTarget(requestedHost, requestedPath, target) { /** * Check if the given hostname includes a protocol prefix. - * @param {string} val - * @returns {boolean} */ -function startsWithProto(val) { +function startsWithProto(val: string): boolean { return val.startsWith('https://') || val.startsWith('http://'); } /** * Create a matcher object from a hostname string. If the hostname begins with an asterisk, it will be treated as a wildcard matcher. - * @param {string} host - * @return {import('./domainTargets').Matcher} */ -function buildHostMatcher(host) { - const specificity = host.startsWith('*') ? 'wildcard' : 'absolute'; +function buildHostMatcher(host: string): Matcher { + const specificity: MatcherSpecificity = host.startsWith('*') + ? 'wildcard' + : 'absolute'; const value = specificity === 'wildcard' ? host.slice(1) : host; return { type: 'host', @@ -62,11 +74,11 @@ function buildHostMatcher(host) { /** * Create a matcher object from a path string. If the string ends with an asterisk, it will be treated as a wildcard matcher. - * @param {string} path - * @return {import('./domainTargets').Matcher} */ -function buildPathMatcher(path) { - const specificity = path.endsWith('*') ? 'wildcard' : 'absolute'; +function buildPathMatcher(path: string): Matcher { + const specificity: MatcherSpecificity = path.endsWith('*') + ? 'wildcard' + : 'absolute'; const value = specificity === 'wildcard' ? path.slice(0, -1) : path; return { type: 'path', @@ -77,10 +89,8 @@ function buildPathMatcher(path) { /** * Convert a user provided input into a target matcher, lightly validating the input in the process. - * @param {unknown} rawInputValue - * @returns {import("./domainTargets").Target | null} */ -function importTarget(rawInputValue) { +function importTarget(rawInputValue: unknown): Target | null { if (typeof rawInputValue !== 'string' || rawInputValue.length === 0) { return null; } @@ -108,7 +118,4 @@ function importTarget(rawInputValue) { }; } -module.exports = { - importTarget, - matchTarget, -}; +export { importTarget, matchTarget }; diff --git a/lib/utils/errors.js b/lib/utils/errors.js deleted file mode 100644 index 1bed9ad7..00000000 --- a/lib/utils/errors.js +++ /dev/null @@ -1,102 +0,0 @@ -class EvervaultError extends Error { - constructor(message) { - super(message); - this.type = this.constructor.name; - } -} - -class FunctionTimeoutError extends EvervaultError {} - -class FunctionNotReadyError extends EvervaultError {} - -class FunctionRuntimeError extends EvervaultError { - constructor(message, stack, id) { - super(message); - this.stack = stack; - this.id = id; - } -} - -class AttestationError extends EvervaultError { - constructor(reason, host, cert) { - super(reason); - this.host = host; - this.cert = cert; - } -} - -class MalformedAttestationData extends EvervaultError { - constructor(message) { - super(`Malformed attestation data provided - ${message}`); - } -} - -class InvalidInterval extends EvervaultError { - constructor(reason) { - super(`Invalid interval provided to repeated timer. ${reason}`); - } -} - -class ExceededMaxFileSizeError extends EvervaultError {} - -class DataRolesNotSupportedError extends EvervaultError {} - -class TokenCreationError extends EvervaultError {} - -const mapFunctionFailureResponseToError = ({ error, id }) => { - if (error) { - throw new FunctionRuntimeError(error.message, error.stack, id); - } - throw new EvervaultError('An unknown error occurred.'); -}; - -const mapApiResponseToError = ({ code, detail }) => { - if (code === 'functions/request-timeout') { - throw new FunctionTimeoutError(detail); - } - if (code === 'functions/function-not-ready') { - throw new FunctionNotReadyError(detail); - } - throw new EvervaultError(detail); -}; - -const mapResponseCodeToError = ({ status, data, headers }) => { - if (status === 401) - return new EvervaultError('Invalid authorization provided.'); - if ( - status === 403 && - headers['x-evervault-error-code'] === 'forbidden-ip-error' - ) { - return new EvervaultError( - data.message || "IP is not present on the invoked Enclave's whitelist." - ); - } - if (status === 403) { - return new EvervaultError( - 'The API key provided does not have the required permissions.' - ); - } - if (status === 422) { - return new EvervaultError(data.message || 'Unable to decrypt data.'); - } - if (data.message) { - return new EvervaultError(data.message); - } - return new EvervaultError(`Request returned with status [${status}]`); -}; - -module.exports = { - EvervaultError, - mapApiResponseToError, - mapResponseCodeToError, - mapFunctionFailureResponseToError, - AttestationError, - ExceededMaxFileSizeError, - TokenCreationError, - FunctionTimeoutError, - FunctionNotReadyError, - FunctionRuntimeError, - MalformedAttestationData, - InvalidInterval, - DataRolesNotSupportedError, -}; diff --git a/lib/utils/errors.ts b/lib/utils/errors.ts new file mode 100644 index 00000000..19361e5b --- /dev/null +++ b/lib/utils/errors.ts @@ -0,0 +1,113 @@ +export class EvervaultError extends Error { + type: string; + + constructor(message: string) { + super(message); + this.type = this.constructor.name; + } +} + +export class FunctionTimeoutError extends EvervaultError {} + +export class FunctionNotReadyError extends EvervaultError {} + +export class FunctionRuntimeError extends EvervaultError { + id: string; + + constructor(message: string, stack: string | undefined, id: string) { + super(message); + this.stack = stack; + this.id = id; + } +} + +export class AttestationError extends EvervaultError { + host: string; + cert: any; + + constructor(reason: string, host: string, cert: any) { + super(reason); + this.host = host; + this.cert = cert; + } +} + +export class MalformedAttestationData extends EvervaultError { + constructor(message: string) { + super(`Malformed attestation data provided - ${message}`); + } +} + +export class InvalidInterval extends EvervaultError { + constructor(reason: string) { + super(`Invalid interval provided to repeated timer. ${reason}`); + } +} + +export class ExceededMaxFileSizeError extends EvervaultError {} + +export class DataRolesNotSupportedError extends EvervaultError {} + +export class TokenCreationError extends EvervaultError {} + +export const mapFunctionFailureResponseToError = ({ + error, + id, +}: { + error?: { message: string; stack?: string }; + id?: string; +}): never => { + if (error) { + throw new FunctionRuntimeError(error.message, error.stack, id as string); + } + throw new EvervaultError('An unknown error occurred.'); +}; + +export const mapApiResponseToError = ({ + code, + detail, +}: { + code?: string; + detail?: string; +}): never => { + if (code === 'functions/request-timeout') { + throw new FunctionTimeoutError(detail as string); + } + if (code === 'functions/function-not-ready') { + throw new FunctionNotReadyError(detail as string); + } + throw new EvervaultError(detail as string); +}; + +export const mapResponseCodeToError = ({ + status, + data, + headers, +}: { + status: number; + data: any; + headers: any; +}): EvervaultError => { + if (status === 401) + return new EvervaultError('Invalid authorization provided.'); + if ( + status === 403 && + headers['x-evervault-error-code'] === 'forbidden-ip-error' + ) { + return new EvervaultError( + data.message || "IP is not present on the invoked Enclave's whitelist." + ); + } + if (status === 403) { + return new EvervaultError( + 'The API key provided does not have the required permissions.' + ); + } + if (status === 422) { + return new EvervaultError(data.message || 'Unable to decrypt data.'); + } + if (data.message) { + return new EvervaultError(data.message); + } + return new EvervaultError(`Request returned with status [${status}]`); +}; diff --git a/lib/utils/httpsHelper.js b/lib/utils/httpsHelper.ts similarity index 62% rename from lib/utils/httpsHelper.js rename to lib/utils/httpsHelper.ts index f29439ee..58348ce5 100644 --- a/lib/utils/httpsHelper.js +++ b/lib/utils/httpsHelper.ts @@ -1,22 +1,22 @@ -const https = require('https'); -const tls = require('tls'); -const Datatypes = require('./datatypes'); -const certHelper = require('./certHelper'); -const HttpsProxyAgent = require('./proxyAgent'); -const { - http: { proxiedMarker }, -} = require('../config'); +import https from 'https'; +import tls from 'tls'; +import * as Datatypes from './datatypes'; +import * as certHelper from './certHelper'; +import HttpsProxyAgent from './proxyAgent'; +import config from '../config'; + +const proxiedMarker = config.http.proxiedMarker; const origCreateSecureContext = tls.createSecureContext; const EVERVAULT_DOMAINS = ['evervault.com', 'evervault.io', 'evervault.dev']; -const certificateUtil = (evClient) => { - let x509 = null; +const certificateUtil = (evClient: any) => { + let x509: any = null; async function updateCertificate() { const pem = await evClient.getCert(); let cert = pem.toString(); x509 = certHelper.parseX509(cert); - tls.createSecureContext = (options) => { - const context = origCreateSecureContext(options); + (tls as any).createSecureContext = (options: any) => { + const context: any = origCreateSecureContext(options); context.context.addCACert(pem); return context; }; @@ -39,12 +39,10 @@ const certificateUtil = (evClient) => { }; }; -/** - * - * @param {Parameters} args - * @returns {{ domain: string, path: string }} - */ -function getDomainAndPathFromArgs(args) { +function getDomainAndPathFromArgs(args: any[]): { + domain: string; + path: string; +} { if (typeof args[0] === 'string') { const parsedUrl = new URL(args[0]); return { domain: parsedUrl.host, path: parsedUrl.pathname }; @@ -54,7 +52,7 @@ function getDomainAndPathFromArgs(args) { return { domain: args[0].host, path: args[0].pathname }; } - let domain, path; + let domain: any, path: any; for (const arg of args) { if (arg instanceof Object) { domain = domain ?? arg.hostname ?? arg.host; @@ -67,28 +65,15 @@ function getDomainAndPathFromArgs(args) { }; } -/** - * @param {string} apiKey - * @param {string} tunnelHostname - * @param {(domain: string, path: string) => boolean} domainFilter - * @param {boolean} debugRequests - * @param {ReturnType} evClient - * @param {typeof import('node:https').request} originalRequest - * @returns {void} - */ const overloadHttpsModule = ( - apiKey, - tunnelHostname, - domainFilter, + apiKey: string | undefined, + tunnelHostname: string, + domainFilter: (domain: string, path: string) => boolean, debugRequests = false, - evClient, - originalRequest -) => { - /** - * @param {Parameters} args - * @returns {ReturnType} - */ - function wrapMethodRequest(...args) { + evClient: any, + originalRequest: typeof https.request +): void => { + function wrapMethodRequest(this: any, ...args: any[]) { const { domain, path } = getDomainAndPathFromArgs(args); const shouldProxy = !!domain && domainFilter(domain, path); if ( @@ -101,7 +86,7 @@ const overloadHttpsModule = ( `EVERVAULT DEBUG :: Request to domain: ${domain}${path}, Outbound Proxy enabled: ${shouldProxy}` ); } - args = args.map((arg) => { + args = args.map((arg: any) => { if (shouldProxy && arg instanceof Object) { const { updateCertificate, isCertificateInvalid } = certificateUtil(evClient); @@ -114,19 +99,19 @@ const overloadHttpsModule = ( } return arg; }); - const request = originalRequest.apply(this, args); + const request: any = (originalRequest as any).apply(this, args); request[proxiedMarker] = shouldProxy; return request; } - https.request = wrapMethodRequest; + (https as any).request = wrapMethodRequest; }; const httpsRelayAgent = ( - agentConfig = { port: 443, rejectUnauthorized: true, secureProxy: true }, - evClient, - apiKey -) => { + agentConfig: any = { port: 443, rejectUnauthorized: true, secureProxy: true }, + evClient: any, + apiKey?: string +): HttpsProxyAgent => { const { updateCertificate, isCertificateInvalid } = certificateUtil(evClient); const parsedUrl = new URL(agentConfig.hostname); const agent = new HttpsProxyAgent( @@ -144,8 +129,4 @@ const httpsRelayAgent = ( return agent; }; -module.exports = { - overloadHttpsModule, - httpsRelayAgent, - getDomainAndPathFromArgs, -}; +export { overloadHttpsModule, httpsRelayAgent, getDomainAndPathFromArgs }; diff --git a/lib/utils/index.js b/lib/utils/index.js deleted file mode 100644 index 6d90add2..00000000 --- a/lib/utils/index.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - Datatypes: require('./datatypes'), - domainTargets: require('./domainTargets'), - errors: require('./errors'), - certHelper: require('./certHelper'), - validationHelper: require('./validationHelper'), - httpsHelper: require('./httpsHelper'), - attest: require('./attest'), -}; diff --git a/lib/utils/index.ts b/lib/utils/index.ts new file mode 100644 index 00000000..13550023 --- /dev/null +++ b/lib/utils/index.ts @@ -0,0 +1,7 @@ +export * as Datatypes from './datatypes'; +export * as domainTargets from './domainTargets'; +export * as errors from './errors'; +export * as certHelper from './certHelper'; +export * as validationHelper from './validationHelper'; +export * as httpsHelper from './httpsHelper'; +export * as attest from './attest'; diff --git a/lib/utils/proxyAgent.js b/lib/utils/proxyAgent.ts similarity index 81% rename from lib/utils/proxyAgent.js rename to lib/utils/proxyAgent.ts index 13d0b106..fde7ce31 100644 --- a/lib/utils/proxyAgent.js +++ b/lib/utils/proxyAgent.ts @@ -1,8 +1,12 @@ -const net = require('net'); -const tls = require('tls'); -const url = require('url'); -const assert = require('assert'); -const { Agent } = require('agent-base'); +import * as net from 'net'; +import * as tls from 'tls'; +import * as url from 'url'; +import assert from 'assert'; +import agentBase from 'agent-base'; + +// agent-base is a CommonJS module; import the default and pull `Agent` off it so +// the ESM build doesn't attempt an unsupported named import from CJS. +const { Agent } = agentBase as any; /** * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to @@ -18,8 +22,19 @@ const { Agent } = require('agent-base'); * * @api public */ -class HttpsProxyAgent extends Agent { - constructor(_opts, updateCertificateCallback, isCertificateInvalidCallback) { +// agent-base's Agent typings (abstract callback shape, constructor overloads) +// fight this vendored subclass; extend it untyped and rely on runtime behavior. +class HttpsProxyAgent extends (Agent as any) { + secureProxy: boolean; + proxy: any; + private _updateCertificateCallback: any; + private _isCertificateInvalidCallback: any; + + constructor( + _opts: any, + updateCertificateCallback?: any, + isCertificateInvalidCallback?: any + ) { let opts; if (typeof _opts === 'string') { opts = url.parse(_opts); @@ -75,7 +90,7 @@ class HttpsProxyAgent extends Agent { * * @api protected */ - async callback(req, opts) { + async callback(req: any, opts: any): Promise { const { proxy, secureProxy } = this; // Wait until the proxy is ready to initialize @@ -88,14 +103,14 @@ class HttpsProxyAgent extends Agent { } // Create a socket connection to the proxy server. - let socket; + let socket: any; if (secureProxy) { socket = tls.connect(proxy); } else { socket = net.connect(proxy); } - const headers = { ...proxy.headers }; + const headers: Record = { ...proxy.headers }; const hostname = `${opts.host}:${opts.port}`; let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; @@ -157,7 +172,7 @@ class HttpsProxyAgent extends Agent { fakeSocket.readable = true; // Need to wait for the "socket" event to re-play the "data" events. - req.once('socket', (s) => { + req.once('socket', (s: any) => { assert(s.listenerCount('data') > 0); // Replay the "buffered" Buffer onto the fake `socket`, since at @@ -171,24 +186,24 @@ class HttpsProxyAgent extends Agent { } } -function isFunction(value) { +function isFunction(value: any): boolean { return typeof value === 'function'; } -function resume(socket) { +function resume(socket: any): void { socket.resume(); } -function isDefaultPort(port, secure) { +function isDefaultPort(port: any, secure: any): boolean { return Boolean((!secure && port === 80) || (secure && port === 443)); } -function isHTTPS(protocol) { +function isHTTPS(protocol: any): boolean { return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; } -function omit(obj, ...keys) { - const ret = {}; +function omit(obj: any, ...keys: string[]): any { + const ret: any = {}; for (let key in obj) { if (!keys.includes(key)) { @@ -198,14 +213,16 @@ function omit(obj, ...keys) { return ret; } -function parseProxyResponse(socket) { +function parseProxyResponse( + socket: any +): Promise<{ statusCode: number; buffered: Buffer }> { return new Promise((resolve, reject) => { // we need to buffer any HTTP traffic that happens with the proxy before we get // the CONNECT response, so that if the response is anything other than an "200" // response code, then we can re-play the "data" events on the socket once the // HTTP parser is hooked up... let buffersLength = 0; - const buffers = []; + const buffers: Buffer[] = []; function read() { const b = socket.read(); @@ -218,12 +235,12 @@ function parseProxyResponse(socket) { socket.removeListener('readable', read); } - function onerror(err) { + function onerror(err: any) { cleanup(); reject(err); } - function ondata(b) { + function ondata(b: Buffer) { buffers.push(b); buffersLength += b.length; @@ -250,4 +267,4 @@ function parseProxyResponse(socket) { }); } -module.exports = HttpsProxyAgent; +export default HttpsProxyAgent; diff --git a/lib/utils/validationHelper.js b/lib/utils/validationHelper.ts similarity index 75% rename from lib/utils/validationHelper.js rename to lib/utils/validationHelper.ts index aa94159a..948942ef 100644 --- a/lib/utils/validationHelper.js +++ b/lib/utils/validationHelper.ts @@ -1,8 +1,13 @@ -const crypto = require('crypto'); -const errors = require('./errors'); -const Datatypes = require('./datatypes'); +import * as crypto from 'crypto'; +import * as errors from './errors'; +import * as Datatypes from './datatypes'; +import type { OutboundRelayOptions, SdkOptions } from '../types'; -const validateApiKey = (appUuid, apiKey, options = {}) => { +const validateApiKey = ( + appUuid: string, + apiKey?: string, + options: Partial = {} +): void => { if (options.encryptionMode === true) { return; } @@ -27,7 +32,7 @@ const validateApiKey = (appUuid, apiKey, options = {}) => { } }; -const validatePayload = (payload) => { +const validatePayload = (payload: any): void => { if ( !Datatypes.isObjectStrict(payload) && (payload != null || payload != undefined) @@ -36,12 +41,14 @@ const validatePayload = (payload) => { } }; -const validateFunctionName = (functionName) => { +const validateFunctionName = (functionName: string): void => { if (!Datatypes.isString(functionName)) throw new errors.EvervaultError('Function name invalid'); }; -const validateRelayOutboundOptions = (options = {}) => { +const validateRelayOutboundOptions = ( + options: OutboundRelayOptions = {} +): void => { if ( (Datatypes.isDefined(options) && !Datatypes.isObjectStrict(options)) || (Datatypes.isDefined(options) && @@ -55,7 +62,7 @@ const validateRelayOutboundOptions = (options = {}) => { } }; -module.exports = { +export { validateApiKey, validatePayload, validateFunctionName, diff --git a/package.json b/package.json index b658f20a..552a965a 100644 --- a/package.json +++ b/package.json @@ -3,18 +3,27 @@ "version": "6.4.0", "description": "Node.js SDK for Evervault", "packageManager": "pnpm@11.9.0", - "main": "lib/index.js", - "typings": "types/index.d.ts", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js" + } + }, "scripts": { "prepare": "husky install", - "lint": "prettier --check \"./**/*.js\"", - "test": "mocha 'tests/**/*.test.js' --timeout 30000", + "build": "tsup", + "lint": "prettier --check \"./**/*.{ts,js}\"", + "typecheck": "tsc --noEmit", + "test": "mocha", "test:e2e": "mocha 'e2e/**/*.test.js' --timeout 5000 --exit", - "test:filter": "mocha 'tests/**/*.test.js' --grep", + "test:filter": "mocha --grep", "test:e2e:filter": "mocha 'e2e/**/*.test.js' --timeout 5000 --grep", "test:coverage": "nyc --reporter=text pnpm run test", - "prepublishOnly": "pnpm run generate-types", - "generate-types": "tsc lib/*.js lib/**/*.js --declaration --allowJs --emitDeclarationOnly --allowSyntheticDefaultImports --outDir types" + "prepublishOnly": "pnpm run build" }, "repository": { "type": "git", @@ -33,8 +42,7 @@ "url": "https://github.com/evervault/evervault-node/issues" }, "files": [ - "lib", - "types" + "dist" ], "engines": { "node": ">=22" @@ -48,6 +56,8 @@ }, "devDependencies": { "@changesets/cli": "^2.29.2", + "@types/async-retry": "^1.4.9", + "@types/node": "^22.10.2", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "crc-32": "^1.2.2", @@ -59,10 +69,12 @@ "nyc": "^17.0.0", "prettier": "^2.3.2", "proxy": "^1.0.2", - "rewire": "^7.0.0", + "proxyquire": "^2.1.3", "sinon": "^9.0.2", "sinon-chai": "^3.5.0", - "typescript": "^5.3.3", + "tsup": "^8.3.5", + "tsx": "^4.19.2", + "typescript": "^5.9.3", "uuid": "^8.1.0" }, "release": { @@ -71,6 +83,6 @@ ] }, "lint-staged": { - "**/*.js": "prettier --write --ignore-unknown \"./**/*.js\"" + "**/*.{ts,js}": "prettier --write --ignore-unknown" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d40c8716..bf680ab7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,7 +30,13 @@ importers: devDependencies: '@changesets/cli': specifier: ^2.29.2 - version: 2.31.0 + version: 2.31.0(@types/node@22.20.1) + '@types/async-retry': + specifier: ^1.4.9 + version: 1.4.9 + '@types/node': + specifier: ^22.10.2 + version: 22.20.1 chai: specifier: ^4.2.0 version: 4.5.0 @@ -64,17 +70,23 @@ importers: proxy: specifier: ^1.0.2 version: 1.0.2(supports-color@8.1.1) - rewire: - specifier: ^7.0.0 - version: 7.0.0(supports-color@8.1.1) + proxyquire: + specifier: ^2.1.3 + version: 2.1.3 sinon: specifier: ^9.0.2 version: 9.2.4 sinon-chai: specifier: ^3.5.0 version: 3.7.0(chai@4.5.0)(sinon@9.2.4) + tsup: + specifier: ^8.3.5 + version: 8.5.1(tsx@4.23.0)(typescript@5.9.3) + tsx: + specifier: ^4.19.2 + version: 4.23.0 typescript: - specifier: ^5.3.3 + specifier: ^5.9.3 version: 5.9.3 uuid: specifier: ^11.1.1 @@ -208,36 +220,317 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] - '@eslint/js@8.57.1': - resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] - '@humanwhocodes/config-array@0.13.0': - resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} @@ -320,6 +613,144 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + cpu: [x64] + os: [win32] + '@sinonjs/commons@1.8.6': resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} @@ -335,19 +766,23 @@ packages: Deprecated: no longer maintained and no longer used by Sinon packages. See https://github.com/sinonjs/nise/issues/243 for replacement details. + '@types/async-retry@1.4.9': + resolution: {integrity: sha512-s1ciZQJzRh3708X/m3vPExr5KJlzlZJvXsKpbtE2luqNcbROr64qU+3KpJsYHqWMeaxI839OvXf9PrUSw1Xtyg==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@22.20.1': + resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} + '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@ungap/structured-clone@1.3.2': - resolution: {integrity: sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@types/retry@0.12.5': + resolution: {integrity: sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==} acorn@8.17.0: resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} @@ -362,9 +797,6 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ajv@6.15.0: - resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} - ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -385,6 +817,9 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -464,6 +899,16 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + caching-transform@4.0.0: resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==} engines: {node: '>=8'} @@ -518,6 +963,10 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -559,6 +1008,10 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} @@ -569,6 +1022,13 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -609,9 +1069,6 @@ packages: resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} engines: {node: '>=6'} - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - default-require-extensions@3.0.1: resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==} engines: {node: '>=8'} @@ -640,10 +1097,6 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -680,6 +1133,16 @@ packages: es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -692,40 +1155,6 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint@8.57.1: - resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true - - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -733,25 +1162,25 @@ packages: extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-keys@1.0.2: + resolution: {integrity: sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==} + engines: {node: '>=0.10.0'} fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} @@ -769,17 +1198,13 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true - flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} - follow-redirects@1.16.0: resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} engines: {node: '>=4.0'} @@ -857,10 +1282,6 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -870,10 +1291,6 @@ packages: engines: {node: '>=12'} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -885,9 +1302,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -970,6 +1384,10 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -990,9 +1408,8 @@ packages: resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} engines: {node: '>=0.10.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} + is-object@1.0.2: + resolution: {integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==} is-plain-obj@2.1.0: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} @@ -1055,6 +1472,10 @@ packages: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1067,18 +1488,9 @@ packages: engines: {node: '>=6'} hasBin: true - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} @@ -1093,16 +1505,13 @@ packages: just-extend@4.2.1: resolution: {integrity: sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==} - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - leven@2.1.0: resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==} engines: {node: '>=0.10.0'} - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -1120,6 +1529,10 @@ packages: enquirer: optional: true + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -1135,9 +1548,6 @@ packages: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -1158,6 +1568,9 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -1170,6 +1583,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1200,11 +1616,17 @@ packages: resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + mocha@10.8.2: resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} engines: {node: '>= 14.0.0'} hasBin: true + module-not-found-error@1.0.1: + resolution: {integrity: sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==} + mri@1.1.4: resolution: {integrity: sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==} engines: {node: '>=4'} @@ -1223,8 +1645,8 @@ packages: msgpackr@1.12.1: resolution: {integrity: sha512-4EUH9tQHnMmEgzW/MdAP0KIfa1T9AF+htl0ffe2n5vb2EKn9y2co8ccpgWko6S52Jy1PQZKwRnx5/KkYjtd9MQ==} - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} nise@4.1.0: resolution: {integrity: sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==} @@ -1258,6 +1680,10 @@ packages: engines: {node: '>=18'} hasBin: true + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -1265,10 +1691,6 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -1335,6 +1757,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-to-regexp@1.9.0: resolution: {integrity: sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==} @@ -1342,6 +1767,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} @@ -1352,20 +1780,45 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + please-upgrade-node@3.2.0: resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} @@ -1388,9 +1841,8 @@ packages: resolution: {integrity: sha512-KNac2ueWRpjbUh77OAFPZuNdfEqNynm9DD4xHT14CccGpW8wKZwEkN0yjlb7X9G9Z9F55N0Q+1z+WfgAhwYdzQ==} hasBin: true - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + proxyquire@2.1.3: + resolution: {integrity: sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==} pvtsutils@1.3.6: resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} @@ -1413,6 +1865,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + release-zalgo@1.0.0: resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} engines: {node: '>=4'} @@ -1432,6 +1888,11 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -1444,9 +1905,6 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rewire@7.0.0: - resolution: {integrity: sha512-DyyNyzwMtGYgu0Zl/ya0PR/oaunM+VuCuBxCuhYJHHaV0V+YvYa3bBGxb5OZ71vndgmp1pYY8F4YOwQo1siRGw==} - rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} @@ -1455,6 +1913,11 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1524,6 +1987,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + spawn-wrap@2.0.0: resolution: {integrity: sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==} engines: {node: '>=8'} @@ -1563,6 +2030,11 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -1575,6 +2047,10 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -1583,22 +2059,60 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + tsx@4.23.0: + resolution: {integrity: sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==} + engines: {node: '>=18.0.0'} + hasBin: true type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} @@ -1608,10 +2122,6 @@ packages: resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -1628,6 +2138,12 @@ packages: engines: {node: '>=14.17'} hasBin: true + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -1638,9 +2154,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - uuid@11.1.1: resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} hasBin: true @@ -1653,10 +2166,6 @@ packages: engines: {node: '>= 8'} hasBin: true - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - workerpool@6.5.1: resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} @@ -1845,7 +2354,7 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/cli@2.31.0': + '@changesets/cli@2.31.0(@types/node@22.20.1)': dependencies: '@changesets/apply-release-plan': 7.1.1 '@changesets/assemble-release-plan': 6.0.10 @@ -1861,7 +2370,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3 + '@inquirer/external-editor': 1.0.3(@types/node@22.20.1) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 enquirer: 2.4.1 @@ -1921,83 +2430,206 @@ snapshots: dependencies: picocolors: 1.1.1 - '@changesets/parse@0.4.3': - dependencies: - '@changesets/types': 6.1.0 - js-yaml: 4.2.0 + '@changesets/parse@0.4.3': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.2.0 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.7': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.3 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.2.0 + prettier: 2.8.8 + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/aix-ppc64@0.28.1': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.28.1': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-arm@0.28.1': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/android-x64@0.28.1': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.28.1': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.28.1': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.28.1': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.28.1': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.28.1': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-arm@0.28.1': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.28.1': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.28.1': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.28.1': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.28.1': + optional: true + + '@esbuild/linux-riscv64@0.27.7': + optional: true + + '@esbuild/linux-riscv64@0.28.1': + optional: true + + '@esbuild/linux-s390x@0.27.7': + optional: true + + '@esbuild/linux-s390x@0.28.1': + optional: true + + '@esbuild/linux-x64@0.27.7': + optional: true + + '@esbuild/linux-x64@0.28.1': + optional: true + + '@esbuild/netbsd-arm64@0.27.7': + optional: true + + '@esbuild/netbsd-arm64@0.28.1': + optional: true + + '@esbuild/netbsd-x64@0.27.7': + optional: true + + '@esbuild/netbsd-x64@0.28.1': + optional: true - '@changesets/pre@2.0.2': - dependencies: - '@changesets/errors': 0.2.0 - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 + '@esbuild/openbsd-arm64@0.27.7': + optional: true - '@changesets/read@0.6.7': - dependencies: - '@changesets/git': 3.0.4 - '@changesets/logger': 0.1.1 - '@changesets/parse': 0.4.3 - '@changesets/types': 6.1.0 - fs-extra: 7.0.1 - p-filter: 2.1.0 - picocolors: 1.1.1 + '@esbuild/openbsd-arm64@0.28.1': + optional: true - '@changesets/should-skip-package@0.1.2': - dependencies: - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 + '@esbuild/openbsd-x64@0.27.7': + optional: true - '@changesets/types@4.1.0': {} + '@esbuild/openbsd-x64@0.28.1': + optional: true - '@changesets/types@6.1.0': {} + '@esbuild/openharmony-arm64@0.27.7': + optional: true - '@changesets/write@0.4.0': - dependencies: - '@changesets/types': 6.1.0 - fs-extra: 7.0.1 - human-id: 4.2.0 - prettier: 2.8.8 + '@esbuild/openharmony-arm64@0.28.1': + optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1(supports-color@8.1.1))': - dependencies: - eslint: 8.57.1(supports-color@8.1.1) - eslint-visitor-keys: 3.4.3 + '@esbuild/sunos-x64@0.27.7': + optional: true - '@eslint-community/regexpp@4.12.2': {} + '@esbuild/sunos-x64@0.28.1': + optional: true - '@eslint/eslintrc@2.1.4(supports-color@8.1.1)': - dependencies: - ajv: 6.15.0 - debug: 4.4.3(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.2.0 - minimatch: 3.1.5 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color + '@esbuild/win32-arm64@0.27.7': + optional: true - '@eslint/js@8.57.1': {} + '@esbuild/win32-arm64@0.28.1': + optional: true - '@humanwhocodes/config-array@0.13.0(supports-color@8.1.1)': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.3(supports-color@8.1.1) - minimatch: 3.1.5 - transitivePeerDependencies: - - supports-color + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-ia32@0.28.1': + optional: true - '@humanwhocodes/module-importer@1.0.1': {} + '@esbuild/win32-x64@0.27.7': + optional: true - '@humanwhocodes/object-schema@2.0.3': {} + '@esbuild/win32-x64@0.28.1': + optional: true - '@inquirer/external-editor@1.0.3': + '@inquirer/external-editor@1.0.3(@types/node@22.20.1)': dependencies: chardet: 2.2.0 iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 22.20.1 '@istanbuljs/load-nyc-config@1.1.0': dependencies: @@ -2074,6 +2706,81 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@rollup/rollup-android-arm-eabi@4.62.2': + optional: true + + '@rollup/rollup-android-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-x64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.2': + optional: true + '@sinonjs/commons@1.8.6': dependencies: type-detect: 4.0.8 @@ -2090,15 +2797,21 @@ snapshots: '@sinonjs/text-encoding@0.7.3': {} - '@types/node@12.20.55': {} + '@types/async-retry@1.4.9': + dependencies: + '@types/retry': 0.12.5 - '@types/parse-json@4.0.2': {} + '@types/estree@1.0.9': {} - '@ungap/structured-clone@1.3.2': {} + '@types/node@12.20.55': {} - acorn-jsx@5.3.2(acorn@8.17.0): + '@types/node@22.20.1': dependencies: - acorn: 8.17.0 + undici-types: 6.21.0 + + '@types/parse-json@4.0.2': {} + + '@types/retry@0.12.5': {} acorn@8.17.0: {} @@ -2113,13 +2826,6 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv@6.15.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - ansi-colors@4.1.3: {} ansi-escapes@4.3.2: @@ -2136,6 +2842,8 @@ snapshots: dependencies: color-convert: 2.0.1 + any-promise@1.3.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -2219,6 +2927,13 @@ snapshots: node-releases: 2.0.50 update-browserslist-db: 1.2.3(browserslist@4.28.4) + bundle-require@5.1.0(esbuild@0.27.7): + dependencies: + esbuild: 0.27.7 + load-tsconfig: 0.2.5 + + cac@6.7.14: {} + caching-transform@4.0.0: dependencies: hasha: 5.2.2 @@ -2285,6 +3000,10 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + clean-stack@2.2.0: {} cli-cursor@3.1.0: @@ -2328,12 +3047,18 @@ snapshots: dependencies: delayed-stream: 1.0.0 + commander@4.1.1: {} + commander@8.3.0: {} commondir@1.0.1: {} concat-map@0.0.1: {} + confbox@0.1.8: {} + + consola@3.4.2: {} + convert-source-map@1.9.0: {} convert-source-map@2.0.0: {} @@ -2368,8 +3093,6 @@ snapshots: dependencies: type-detect: 4.1.0 - deep-is@0.1.4: {} - default-require-extensions@3.0.1: dependencies: strip-bom: 4.0.0 @@ -2389,10 +3112,6 @@ snapshots: dependencies: path-type: 4.0.0 - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -2429,80 +3148,70 @@ snapshots: es6-error@4.1.1: {} + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + esbuild@0.28.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 + escalade@3.2.0: {} escape-string-regexp@1.0.5: {} escape-string-regexp@4.0.0: {} - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint@8.57.1(supports-color@8.1.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1(supports-color@8.1.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/eslintrc': 2.1.4(supports-color@8.1.1) - '@eslint/js': 8.57.1 - '@humanwhocodes/config-array': 0.13.0(supports-color@8.1.1) - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.3.2 - ajv: 6.15.0 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.2.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.5 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - espree@9.6.1: - dependencies: - acorn: 8.17.0 - acorn-jsx: 5.3.2(acorn@8.17.0) - eslint-visitor-keys: 3.4.3 - - esquery@1.7.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -2517,8 +3226,6 @@ snapshots: extendable-error@0.1.7: {} - fast-deep-equal@3.1.3: {} - fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2527,17 +3234,18 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - fastq@1.20.1: dependencies: reusify: 1.1.0 - file-entry-cache@6.0.1: + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + fill-keys@1.0.2: dependencies: - flat-cache: 3.2.0 + is-object: 1.0.2 + merge-descriptors: 1.0.3 fill-range@7.1.1: dependencies: @@ -2559,16 +3267,14 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@3.2.0: + fix-dts-default-cjs-exports@1.0.1: dependencies: - flatted: 3.4.2 - keyv: 4.5.4 - rimraf: 3.0.2 + magic-string: 0.30.21 + mlly: 1.8.2 + rollup: 4.62.2 flat@5.0.2: {} - flatted@3.4.2: {} - follow-redirects@1.16.0: {} foreground-child@2.0.0: @@ -2644,10 +3350,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -2665,10 +3367,6 @@ snapshots: minimatch: 5.1.9 once: 1.4.0 - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - globby@11.1.0: dependencies: array-union: 2.1.0 @@ -2682,8 +3380,6 @@ snapshots: graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - has-flag@3.0.0: {} has-flag@4.0.0: {} @@ -2748,6 +3444,10 @@ snapshots: dependencies: binary-extensions: 2.3.0 + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -2760,7 +3460,7 @@ snapshots: is-obj@1.0.1: {} - is-path-inside@3.0.3: {} + is-object@1.0.2: {} is-plain-obj@2.1.0: {} @@ -2826,6 +3526,8 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + joycon@3.1.1: {} + js-tokens@4.0.0: {} js-yaml@4.2.0: @@ -2834,14 +3536,8 @@ snapshots: jsesc@3.1.0: {} - json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - json-stringify-safe@5.0.1: {} json5@2.2.3: {} @@ -2852,16 +3548,9 @@ snapshots: just-extend@4.2.1: {} - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - leven@2.1.0: {} - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -2895,6 +3584,8 @@ snapshots: optionalDependencies: enquirer: 2.4.1 + load-tsconfig@0.2.5: {} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -2907,8 +3598,6 @@ snapshots: lodash.get@4.4.2: {} - lodash.merge@4.6.2: {} - lodash.startcase@4.4.0: {} lodash@4.18.1: {} @@ -2933,6 +3622,10 @@ snapshots: dependencies: yallist: 3.1.1 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + make-dir@3.1.0: dependencies: semver: 6.3.1 @@ -2943,6 +3636,8 @@ snapshots: math-intrinsics@1.1.0: {} + merge-descriptors@1.0.3: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -2968,6 +3663,13 @@ snapshots: dependencies: brace-expansion: 2.1.1 + mlly@1.8.2: + dependencies: + acorn: 8.17.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + mocha@10.8.2: dependencies: ansi-colors: 4.1.3 @@ -2991,6 +3693,8 @@ snapshots: yargs-parser: 20.2.9 yargs-unparser: 2.0.0 + module-not-found-error@1.0.1: {} + mri@1.1.4: {} mri@1.2.0: {} @@ -3013,7 +3717,11 @@ snapshots: optionalDependencies: msgpackr-extract: 3.0.4 - natural-compare@1.4.0: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 nise@4.1.0: dependencies: @@ -3081,6 +3789,8 @@ snapshots: transitivePeerDependencies: - supports-color + object-assign@4.1.1: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -3089,15 +3799,6 @@ snapshots: dependencies: mimic-fn: 2.1.0 - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - outdent@0.5.0: {} p-filter@2.1.0: @@ -3160,29 +3861,47 @@ snapshots: path-key@3.1.1: {} + path-parse@1.0.7: {} + path-to-regexp@1.9.0: dependencies: isarray: 0.0.1 path-type@4.0.0: {} + pathe@2.0.3: {} + pathval@1.1.1: {} picocolors@1.1.1: {} picomatch@2.3.2: {} + picomatch@4.0.5: {} + pify@4.0.1: {} + pirates@4.0.7: {} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + please-upgrade-node@3.2.0: dependencies: semver-compare: 1.0.0 - prelude-ls@1.2.1: {} + postcss-load-config@6.0.1(tsx@4.23.0): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + tsx: 4.23.0 prettier@2.8.8: {} @@ -3202,7 +3921,11 @@ snapshots: transitivePeerDependencies: - supports-color - punycode@2.3.1: {} + proxyquire@2.1.3: + dependencies: + fill-keys: 1.0.2 + module-not-found-error: 1.0.1 + resolve: 1.22.12 pvtsutils@1.3.6: dependencies: @@ -3225,6 +3948,8 @@ snapshots: dependencies: picomatch: 2.3.2 + readdirp@4.1.2: {} + release-zalgo@1.0.0: dependencies: es6-error: 4.1.1 @@ -3237,6 +3962,13 @@ snapshots: resolve-from@5.0.0: {} + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@3.1.0: dependencies: onetime: 5.1.2 @@ -3246,18 +3978,43 @@ snapshots: reusify@1.1.0: {} - rewire@7.0.0(supports-color@8.1.1): - dependencies: - eslint: 8.57.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - rfdc@1.4.1: {} rimraf@3.0.2: dependencies: glob: 7.2.3 + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -3318,6 +4075,8 @@ snapshots: source-map@0.6.1: {} + source-map@0.7.6: {} + spawn-wrap@2.0.0: dependencies: foreground-child: 2.0.0 @@ -3358,6 +4117,16 @@ snapshots: strip-json-comments@3.1.1: {} + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.17 + ts-interface-checker: 0.1.13 + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -3370,6 +4139,8 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + term-size@2.2.1: {} test-exclude@6.0.0: @@ -3378,26 +4149,70 @@ snapshots: glob: 7.2.3 minimatch: 3.1.5 - text-table@0.2.0: {} + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 through@2.3.8: {} + tinyexec@0.3.2: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + tree-kill@1.2.2: {} + + ts-interface-checker@0.1.13: {} + tslib@2.8.1: {} - type-check@0.4.0: + tsup@8.5.1(tsx@4.23.0)(typescript@5.9.3): dependencies: - prelude-ls: 1.2.1 + bundle-require: 5.1.0(esbuild@0.27.7) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3(supports-color@8.1.1) + esbuild: 0.27.7 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(tsx@4.23.0) + resolve-from: 5.0.0 + rollup: 4.62.2 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.17 + tree-kill: 1.2.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + + tsx@4.23.0: + dependencies: + esbuild: 0.28.1 + optionalDependencies: + fsevents: 2.3.3 type-detect@4.0.8: {} type-detect@4.1.0: {} - type-fest@0.20.2: {} - type-fest@0.21.3: {} type-fest@0.8.1: {} @@ -3408,6 +4223,10 @@ snapshots: typescript@5.9.3: {} + ufo@1.6.4: {} + + undici-types@6.21.0: {} + universalify@0.1.2: {} update-browserslist-db@1.2.3(browserslist@4.28.4): @@ -3416,10 +4235,6 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - uuid@11.1.1: {} which-module@2.0.1: {} @@ -3428,8 +4243,6 @@ snapshots: dependencies: isexe: 2.0.0 - word-wrap@1.2.5: {} - workerpool@6.5.1: {} wrap-ansi@6.2.0: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 77dc0ac3..328483e4 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ allowBuilds: + esbuild: true msgpackr-extract: false minimumReleaseAgeExclude: - serialize-javascript@7.0.3 || 7.0.5 diff --git a/tests/client.test.js b/tests/client.test.js index db7b3364..f70118bb 100644 --- a/tests/client.test.js +++ b/tests/client.test.js @@ -5,7 +5,7 @@ const nock = require('nock'); const sinon = require('sinon'); const axios = require('axios'); const https = require('https'); -const rewire = require('rewire'); +const proxyquire = require('proxyquire'); const { RelayOutboundConfig } = require('../lib/core'); const { errors } = require('../lib/utils'); const fixtures = require('./utilities/fixtures'); @@ -22,11 +22,13 @@ let EvervaultClient; const encryptStub = sinon.stub(); describe('Testing the Evervault SDK', () => { beforeEach(() => { - EvervaultClient = rewire('../lib'); - EvervaultClient.__set__({ - Crypto: () => ({ - encrypt: encryptStub, - }), + EvervaultClient = proxyquire('../lib', { + './core': { + ...require('../lib/core'), + Crypto: () => ({ + encrypt: encryptStub, + }), + }, }); }); diff --git a/tests/config.test.js b/tests/config.test.js index ae3175f4..2c5dbac1 100644 --- a/tests/config.test.js +++ b/tests/config.test.js @@ -3,7 +3,7 @@ chai.use(require('sinon-chai')); const { expect } = chai; const sinon = require('sinon'); -const rewire = require('rewire'); +const proxyquire = require('proxyquire'); const { errors } = require('../lib/utils'); const testApiKey = @@ -14,11 +14,13 @@ let EvervaultClient; const encryptStub = sinon.stub(); describe('Testing the Evervault SDK Config', () => { beforeEach(() => { - EvervaultClient = rewire('../lib'); - EvervaultClient.__set__({ - Crypto: () => ({ - encrypt: encryptStub, - }), + EvervaultClient = proxyquire('../lib', { + './core': { + ...require('../lib/core'), + Crypto: () => ({ + encrypt: encryptStub, + }), + }, }); }); diff --git a/tests/core/crypto.test.js b/tests/core/crypto.test.js index 8c7a0efb..640cc9ec 100644 --- a/tests/core/crypto.test.js +++ b/tests/core/crypto.test.js @@ -1,7 +1,7 @@ const { expect } = require('chai'); const crypto = require('crypto'); const { unpack } = require('msgpackr'); -const Crypto = require('../../lib/core/crypto'); +const Crypto = require('../../lib/core/crypto').default; const { errors } = require('../../lib/utils'); const crc32 = require('crc-32'); diff --git a/tests/core/http.test.js b/tests/core/http.test.js index 2329a7d4..d67aa680 100644 --- a/tests/core/http.test.js +++ b/tests/core/http.test.js @@ -9,7 +9,7 @@ describe('Http Module', () => { 'ev:key:1:3bOqOkKrVFrk2Ps9yM1tHEi90CvZCjsGIihoyZncM9SdLoXQxknPPjwxiMLyDVYyX:cRhR9o:tCZFZV'; const testAppId = 'app_8022cc5a3073'; const testValidConfig = require('../../lib/config').http; - const testHttpClient = require('../../lib/core/http')( + const testHttpClient = require('../../lib/core/http').default( testAppId, testApiKey, testValidConfig @@ -596,14 +596,13 @@ describe('Http Module', () => { }); describe('agent forwarding', () => { - const rewire = require('rewire'); + const proxyquire = require('proxyquire'); /** * Creates a rewired http module with a stub axios and optional agents, * returning both the client and a getter for the last captured axios config. */ const buildClientWithAxiosStub = (agents = {}) => { - const httpModule = rewire('../../lib/core/http'); let capturedConfig; const axiosStub = (cfg) => { capturedConfig = cfg; @@ -613,7 +612,9 @@ describe('Http Module', () => { headers: { 'x-poll-interval': '5' }, }); }; - httpModule.__set__('axios', axiosStub); + const httpModule = proxyquire('../../lib/core/http', { + axios: axiosStub, + }).default; const client = httpModule(testAppId, testApiKey, testValidConfig, agents); return { client, diff --git a/tests/core/repeatedTimer.test.js b/tests/core/repeatedTimer.test.js index 5cd86cb3..fd528743 100644 --- a/tests/core/repeatedTimer.test.js +++ b/tests/core/repeatedTimer.test.js @@ -2,7 +2,7 @@ const { expect } = require('chai'); const Sinon = require('sinon'); const { InvalidInterval } = require('../../lib/utils/errors'); -const RepeatedTimer = require('../../lib/core/repeatedTimer'); +const RepeatedTimer = require('../../lib/core/repeatedTimer').default; describe('RepeatedTimer Module', () => { it('Rejects when given a non-numeric value', () => { diff --git a/tests/proxy.test.js b/tests/proxy.test.js index e064a854..84290b00 100644 --- a/tests/proxy.test.js +++ b/tests/proxy.test.js @@ -4,7 +4,7 @@ const http = require('http'); const https = require('https'); const assert = require('assert'); const Proxy = require('proxy'); -const HttpsProxyAgent = require('../lib/utils/proxyAgent'); +const HttpsProxyAgent = require('../lib/utils/proxyAgent').default; const { httpsRelayAgent } = require('../lib/utils/httpsHelper'); const { Http } = require('../lib/core'); diff --git a/tests/sdk.test.js b/tests/sdk.test.js index 25196558..0d2d3393 100644 --- a/tests/sdk.test.js +++ b/tests/sdk.test.js @@ -5,7 +5,6 @@ chai.use(require('sinon-chai')); const { expect } = chai; const axios = require('axios'); const { errors } = require('../lib/utils'); -const rewire = require('rewire'); const { createProxyServer, createServer } = require('./utilities/mockServer'); const testApiKey = @@ -199,10 +198,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = rewire('../lib'); + EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; - EvervaultClient.__set__('config', config); Evervault = EvervaultClient; }); @@ -274,10 +272,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = rewire('../lib'); + EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; - EvervaultClient.__set__('config', config); Evervault = EvervaultClient; }); @@ -329,10 +326,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = rewire('../lib'); + EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; - EvervaultClient.__set__('config', config); Evervault = EvervaultClient; }); @@ -384,10 +380,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = rewire('../lib'); + EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; - EvervaultClient.__set__('config', config); Evervault = EvervaultClient; }); @@ -466,13 +461,12 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = rewire('../lib'); + EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${apiServer.address().port}`; config.http.tunnelHostname = `http://localhost:${ proxyServer.address().port }`; - EvervaultClient.__set__('config', config); Evervault = EvervaultClient; }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..aeafba54 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "moduleResolution": "node", + "lib": ["ES2022"], + "types": ["node"], + "strict": true, + "declaration": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["lib/**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 00000000..6e10cf74 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['lib/index.ts'], + format: ['cjs', 'esm'], + dts: true, + sourcemap: true, + clean: true, + target: 'node22', + outDir: 'dist', + keepNames: true, +}); From 29834b9aff1106df6322c32845907f2eb22ea3ff Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 9 Jul 2026 11:16:22 +0000 Subject: [PATCH 2/6] fix: don't clobber global https.request from non-relay clients; inject config in sdk tests CI ran the suite against the real network and surfaced two test-infra regressions from the TS migration that the local sandbox hid: - EvervaultClient's constructor called `_shouldOverloadHttpModule`, whose else-branch unconditionally ran `https.request = originalRequest`. On every non-relay client this reset the global `https.request`, removing nock's interception (nock doesn't re-patch once "active"), which cascaded failures across client/http test files. Guard the restore so it only runs when this process actually overloaded `https.request` for Relay. This is also more correct: a plain client no longer disables another client's outbound Relay. - sdk.test.js pointed the client at its mock server by mutating the config singleton. Under tsx the module-cache timing made that unreliable, so the client hit the real API. Inject the mutated config into the client with proxyquire (`{ './config': config }`), mirroring the old rewire `__set__`. Local suite unchanged (204 passing; the 5 proxy.test.js failures are environmental to this sandbox). Verified the guard preserves nock's patch and that config injection reaches the client. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_011HwoTRLdV2YMub47j88mv5 --- lib/index.ts | 11 ++++++++++- tests/sdk.test.js | 9 +++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 80342563..39683777 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -35,6 +35,10 @@ import type { } from './types'; const originalRequest = https.request; +// Tracks whether this process has overloaded `https.request` for Relay. We only +// restore the original request when we were the ones who replaced it, so that a +// plain client never clobbers an unrelated `https.request` (e.g. a test's nock). +let httpsRequestOverloaded = false; type Timer = ReturnType; @@ -232,6 +236,7 @@ class EvervaultClient { this.http, originalRequest ); + httpsRequestOverloaded = true; } else if (options.enableOutboundRelay) { await this.httpsHelper.overloadHttpsModule( apiKey, @@ -241,8 +246,10 @@ class EvervaultClient { this.http, originalRequest ); - } else { + httpsRequestOverloaded = true; + } else if (httpsRequestOverloaded) { (https as any).request = originalRequest; + httpsRequestOverloaded = false; } } @@ -419,6 +426,7 @@ class EvervaultClient { this.http, originalRequest ); + httpsRequestOverloaded = true; } else { const decryptionDomainsFilter = this._decryptionDomainsFilter( options.decryptionDomains @@ -431,6 +439,7 @@ class EvervaultClient { this.http, originalRequest ); + httpsRequestOverloaded = true; } } diff --git a/tests/sdk.test.js b/tests/sdk.test.js index 0d2d3393..20fc7337 100644 --- a/tests/sdk.test.js +++ b/tests/sdk.test.js @@ -5,6 +5,7 @@ chai.use(require('sinon-chai')); const { expect } = chai; const axios = require('axios'); const { errors } = require('../lib/utils'); +const proxyquire = require('proxyquire'); const { createProxyServer, createServer } = require('./utilities/mockServer'); const testApiKey = @@ -198,9 +199,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; + EvervaultClient = proxyquire('../lib', { './config': config }); Evervault = EvervaultClient; }); @@ -272,9 +273,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; + EvervaultClient = proxyquire('../lib', { './config': config }); Evervault = EvervaultClient; }); @@ -326,9 +327,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; + EvervaultClient = proxyquire('../lib', { './config': config }); Evervault = EvervaultClient; }); @@ -380,9 +381,9 @@ describe('evervault client', () => { // rewiring is needed to set the config environment variables // there isn't a clean way to do this at runtime because of Node.js // module caching system. - EvervaultClient = require('../lib'); const config = require('../lib/config'); config.http.baseUrl = `http://localhost:${server.address().port}`; + EvervaultClient = proxyquire('../lib', { './config': config }); Evervault = EvervaultClient; }); From c4ec86e2125b256f279f41626541c3d6ed0d2b05 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 9 Jul 2026 11:44:30 +0000 Subject: [PATCH 3/6] test: run the suite against compiled CJS under plain Node instead of tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nock-based tests passed locally but failed in CI only. Running the suite through tsx (on-the-fly TS transpilation with a custom module loader) interacted with nock/axios HTTP interception differently on the CI runners, so requests bypassed nock and hit the network. Compile lib/*.ts to CJS with `tsc -p tsconfig.build.json` and run mocha against the emitted JS under plain Node — the same execution model the JavaScript suite used before the TypeScript migration. The compiled lib/*.js are build artifacts (git- and prettier-ignored); tsup still builds the published dual-format bundle from the .ts sources, and `tsc --noEmit` still type-checks. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_011HwoTRLdV2YMub47j88mv5 --- .gitignore | 4 ++++ .mocharc.json | 1 - .prettierignore | 2 ++ package.json | 9 +++++---- tsconfig.build.json | 11 +++++++++++ 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 tsconfig.build.json diff --git a/.gitignore b/.gitignore index 6671f03b..a1e27329 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ types .direnv +# Compiled JS emitted from lib/*.ts for running the test suite under plain Node +lib/**/*.js +lib/**/*.js.map + # Logs logs *.log diff --git a/.mocharc.json b/.mocharc.json index 8d8675b3..d0b38579 100644 --- a/.mocharc.json +++ b/.mocharc.json @@ -1,5 +1,4 @@ { - "require": "tsx/cjs", "spec": "tests/**/*.test.js", "timeout": 30000 } diff --git a/.prettierignore b/.prettierignore index b2d1f452..75a52e40 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,3 +2,5 @@ dist node_modules coverage pnpm-lock.yaml +lib/**/*.js +lib/**/*.js.map diff --git a/package.json b/package.json index 552a965a..2e2907bc 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,13 @@ "scripts": { "prepare": "husky install", "build": "tsup", + "build:test": "tsc -p tsconfig.build.json", "lint": "prettier --check \"./**/*.{ts,js}\"", "typecheck": "tsc --noEmit", - "test": "mocha", - "test:e2e": "mocha 'e2e/**/*.test.js' --timeout 5000 --exit", - "test:filter": "mocha --grep", - "test:e2e:filter": "mocha 'e2e/**/*.test.js' --timeout 5000 --grep", + "test": "pnpm run build:test && mocha", + "test:e2e": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 5000 --exit", + "test:filter": "pnpm run build:test && mocha --grep", + "test:e2e:filter": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 5000 --grep", "test:coverage": "nyc --reporter=text pnpm run test", "prepublishOnly": "pnpm run build" }, diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..eea57e63 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "declaration": false, + "sourceMap": true, + "rootDir": ".", + "outDir": "." + }, + "include": ["lib/**/*.ts"] +} From bbe490d961d7e1fcfc29de1fc9a9eaf3a4cc9db0 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 9 Jul 2026 12:08:21 +0000 Subject: [PATCH 4/6] fix: stop mocharc spec from pulling the unit suite into the e2e run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mocha concatenates the `spec` from `.mocharc.json` with any CLI positional file arguments rather than letting the CLI override it. The `test:e2e` script (run by the `e2e.yml` workflow) invokes `mocha 'e2e/**/*.test.js'`, so once `.mocharc.json` declared `spec: tests/**`, that job silently ran the entire unit suite alongside the e2e tests. The e2e tests run first, call `enableOutboundRelay()` which monkey-patches the global `https.request`, and that leaves nock unable to intercept the unit tests — producing the CI-only failures. Keep only `timeout` in `.mocharc.json` and pass the unit spec explicitly on the CLI in `test` / `test:filter`, so each mocha invocation resolves exactly one suite (matching the pre-TypeScript setup). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_011HwoTRLdV2YMub47j88mv5 --- .mocharc.json | 1 - package.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.mocharc.json b/.mocharc.json index d0b38579..d84a0c2c 100644 --- a/.mocharc.json +++ b/.mocharc.json @@ -1,4 +1,3 @@ { - "spec": "tests/**/*.test.js", "timeout": 30000 } diff --git a/package.json b/package.json index 2e2907bc..5cb3327d 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,9 @@ "build:test": "tsc -p tsconfig.build.json", "lint": "prettier --check \"./**/*.{ts,js}\"", "typecheck": "tsc --noEmit", - "test": "pnpm run build:test && mocha", + "test": "pnpm run build:test && mocha 'tests/**/*.test.js'", "test:e2e": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 5000 --exit", - "test:filter": "pnpm run build:test && mocha --grep", + "test:filter": "pnpm run build:test && mocha 'tests/**/*.test.js' --grep", "test:e2e:filter": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 5000 --grep", "test:coverage": "nyc --reporter=text pnpm run test", "prepublishOnly": "pnpm run build" From 8daa8d1c018441c1cb81cbd895ed942076666c69 Mon Sep 17 00:00:00 2001 From: Matt Paletta Date: Thu, 9 Jul 2026 14:16:40 +0100 Subject: [PATCH 5/6] feat: infer real types across the SDK, replacing any at the public API Give consumers precise types instead of `any` on the client surface: - encrypt returns EncryptedData, preserving input shape (objects keep their keys with encrypted string leaves, Buffers stay Buffers, primitives become strings) and rejecting non-encryptable inputs - decrypt, run (-> FunctionRunResult), createRunToken (-> RunToken) and createClientSideDecryptToken (-> ClientSideToken) now carry real types - hidden ECDH fields typed as Buffer / crypto.ECDH / NodeJS.Timeout Internally, export a reusable HttpClient type and thread it through attestationDoc/relayOutboundConfig/httpsHelper; type the PCR store, the attestation helpers, and the key/token/relay response shapes. Also make Http.getAppKey throw mapResponseCodeToError on non-2xx (mirroring getCageKey) instead of returning undefined and crashing downstream. Genuinely dynamic/vendored surfaces (crypto key material that is Buffer|string, the agent-base subclass, the asn1js DER encoder, the https.request/tls monkeypatch paths) are left untyped with rationale comments. Co-Authored-By: Claude Opus 4.8 --- lib/core/attestationDoc.ts | 7 +-- lib/core/http.ts | 54 ++++++++++++++++------- lib/core/pcrManager.ts | 12 ++++-- lib/core/relayOutboundConfig.ts | 5 ++- lib/core/repeatedTimer.ts | 2 +- lib/index.ts | 45 ++++++++++++++----- lib/types.ts | 76 +++++++++++++++++++++++++++++++++ lib/utils/attest.ts | 44 ++++++++++--------- lib/utils/certHelper.ts | 2 +- lib/utils/errors.ts | 8 ++-- lib/utils/httpsHelper.ts | 16 +++++-- 11 files changed, 207 insertions(+), 64 deletions(-) diff --git a/lib/core/attestationDoc.ts b/lib/core/attestationDoc.ts index dbfe5f12..0783035d 100644 --- a/lib/core/attestationDoc.ts +++ b/lib/core/attestationDoc.ts @@ -1,18 +1,19 @@ import RepeatedTimer from './repeatedTimer'; +import type { HttpClient } from './http'; import type { MasterConfig } from '../types'; class AttestationDoc { appUuid: string; - http: any; + http: HttpClient; enclaves: string[]; config: MasterConfig; polling: ReturnType | null; - attestationDocCache: Record | null; + attestationDocCache: Record | null; hostname: string; constructor( config: MasterConfig, - http: any, + http: HttpClient, enclaves: string[], appUuid: string, hostname: string diff --git a/lib/core/http.ts b/lib/core/http.ts index a15bd2ae..ef8942ea 100644 --- a/lib/core/http.ts +++ b/lib/core/http.ts @@ -6,7 +6,13 @@ import type { Method, ResponseType, } from 'axios'; -import type { HttpConfig } from '../types'; +import type { + HttpConfig, + TeamKeyResponse, + ClientSideToken, + RelayOutboundConfigResponse, + DecryptableData, +} from '../types'; import type { Agent as HttpAgent } from 'http'; import type { Agent as HttpsAgent } from 'https'; @@ -15,7 +21,7 @@ interface HttpAgents { httpsAgent?: HttpsAgent; } -export default ( +const Http = ( appUuid: string, apiKey: string, config: HttpConfig, @@ -25,7 +31,7 @@ export default ( method: Method, path: string, additionalHeaders: Record = {}, - data: any = undefined, + data: unknown = undefined, basicAuth = false, responseType: ResponseType = 'json' ): Promise => { @@ -64,13 +70,13 @@ export default ( const post = ( path: string, - data: any, + data: unknown, headers: Record = { 'Content-Type': 'application/json' }, basicAuth = false, responseType: ResponseType = 'json' ) => request('POST', path, headers, data, basicAuth, responseType); - const getCageKey = async () => { + const getCageKey = async (): Promise => { const getCagesKeyCallback = async () => { return await get('cages/key', {}).catch((_e) => { throw new errors.EvervaultError( @@ -85,7 +91,7 @@ export default ( throw errors.mapResponseCodeToError(response); }; - const getAppKey = async () => { + const getAppKey = async (): Promise => { const getAppKeyCallback = async () => { return await get('keys', { 'x-evervault-app-id': appUuid, @@ -99,6 +105,7 @@ export default ( if (response.status >= 200 && response.status < 300) { return response.data; } + throw errors.mapResponseCodeToError(response); }; const getCert = async () => { @@ -130,25 +137,30 @@ export default ( return response.data; }; - const getRelayOutboundConfig = async () => { + const getRelayOutboundConfig = async (): Promise<{ + pollInterval: number | null; + data: RelayOutboundConfigResponse; + }> => { const response = await get('v2/relay-outbound').catch((e) => { throw new errors.EvervaultError( `An error occoured while retrieving the Relay Outbound configuration: ${e}` ); }); if (response.status >= 200 && response.status < 300) { - const pollIntervalHeaderValue: any = response.headers['x-poll-interval']; + const pollIntervalHeaderValue = response.headers['x-poll-interval']; + const pollInterval = parseFloat(String(pollIntervalHeaderValue)); return { - pollInterval: isNaN(pollIntervalHeaderValue) - ? null - : parseFloat(pollIntervalHeaderValue), + pollInterval: Number.isNaN(pollInterval) ? null : pollInterval, data: response.data, }; } throw errors.mapResponseCodeToError(response); }; - const runFunction = async (functionName: string, payload: any) => { + const runFunction = async ( + functionName: string, + payload: Record + ) => { const response = await post( `${config.baseUrl}/functions/${functionName}/runs`, { @@ -172,7 +184,10 @@ export default ( throw errors.mapApiResponseToError(responseBody); }; - const createRunToken = (functionName: string, payload: any) => { + const createRunToken = ( + functionName: string, + payload: Record + ) => { return post( `v2/functions/${functionName}/run-token`, { @@ -212,7 +227,7 @@ export default ( throw error; } - const decrypt = async (encryptedData: any) => { + const decrypt = async (encryptedData: DecryptableData): Promise => { let contentType; let data; let responseType: ResponseType; @@ -249,7 +264,11 @@ export default ( throw errors.mapApiResponseToError(resBody); }; - const createToken = async (action: string, payload: any, expiry?: any) => { + const createToken = async ( + action: string, + payload: unknown, + expiry?: Date | number | null + ): Promise => { let wellFormedExpiry; if (expiry) { if (expiry && expiry instanceof Date) { @@ -305,3 +324,8 @@ export default ( getAttestationDoc, }; }; + +export default Http; + +/** The HTTP client returned by {@link Http}. */ +export type HttpClient = ReturnType; diff --git a/lib/core/pcrManager.ts b/lib/core/pcrManager.ts index ec9de26b..6ac4f033 100644 --- a/lib/core/pcrManager.ts +++ b/lib/core/pcrManager.ts @@ -6,7 +6,12 @@ import type { AttestationCallback, } from '../types'; -const staticPcrsToProvider = (pcrs: PCRs[]) => { +interface PcrStoreEntry { + pcrs: AttestationData | null; + provider: () => Promise; +} + +const staticPcrsToProvider = (pcrs: PCRs[]): PcrStoreEntry => { const provider = async () => { return new Promise((resolve) => { resolve(pcrs); @@ -19,8 +24,7 @@ const staticPcrsToProvider = (pcrs: PCRs[]) => { const loadPcrStore = ( attestationData: Record ) => { - const providers: Record Promise }> = - {}; + const providers: Record = {}; for (const [enclaveName, value] of Object.entries(attestationData)) { if (Array.isArray(value)) { providers[enclaveName] = staticPcrsToProvider(value); @@ -37,7 +41,7 @@ const loadPcrStore = ( }; class PcrManager { - store: Record; + store: Record; config: MasterConfig; polling: ReturnType | null; diff --git a/lib/core/relayOutboundConfig.ts b/lib/core/relayOutboundConfig.ts index 2f10ec73..86b4434f 100644 --- a/lib/core/relayOutboundConfig.ts +++ b/lib/core/relayOutboundConfig.ts @@ -1,4 +1,5 @@ import RepeatedTimer from './repeatedTimer'; +import type { HttpClient } from './http'; import type { MasterConfig } from '../types'; let polling: ReturnType | null = null; @@ -26,7 +27,7 @@ const getDecryptionDomains = (): string[] | null => { return decryptionDomainsCache; }; -const init = async (config: MasterConfig, http: any) => { +const init = async (config: MasterConfig, http: HttpClient) => { let pollingInterval = config.http.pollInterval; const getRelayOutboundConfigFromApi = async () => { @@ -39,7 +40,7 @@ const init = async (config: MasterConfig, http: any) => { } decryptionDomainsCache = Object.values( configResponse.data.outboundDestinations - ).map((config: any) => config.destinationDomain); + ).map((destination) => destination.destinationDomain); }; /* Initialization */ diff --git a/lib/core/repeatedTimer.ts b/lib/core/repeatedTimer.ts index ec7ca031..44fe0300 100644 --- a/lib/core/repeatedTimer.ts +++ b/lib/core/repeatedTimer.ts @@ -4,7 +4,7 @@ export default ( defaultInterval: number | string, cb: () => Promise | void ) => { - const parsedInterval = parseFloat(defaultInterval as any); + const parsedInterval = parseFloat(String(defaultInterval)); if (Number.isNaN(parsedInterval)) { throw new InvalidInterval(`Expected number, received ${parsedInterval}`); } diff --git a/lib/index.ts b/lib/index.ts index 39683777..719559dd 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -32,6 +32,12 @@ import type { AttestationData, AttestationCallback, AttestationBindings, + EncryptableData, + EncryptedData, + DecryptableData, + FunctionRunResult, + RunToken, + ClientSideToken, } from './types'; const originalRequest = https.request; @@ -66,11 +72,13 @@ class EvervaultClient { private encryptionMode?: boolean; // Hidden properties defined via defineHiddenProperty (Object.defineProperty). - private _ecdhTeamKey?: any; - private _ecdh?: any; - private _ecdhPublicKey?: any; - private _derivedAesKey?: any; - private _refreshInterval?: any; + // These are populated imperatively (and invisibly to the type checker) by + // `defineHiddenProperty`, so they use definite assignment assertions. + private _ecdhTeamKey!: Buffer; + private _ecdh!: crypto.ECDH; + private _ecdhPublicKey!: Buffer; + private _derivedAesKey!: Buffer; + private _refreshInterval!: NodeJS.Timeout; constructor( appId: string, @@ -325,7 +333,10 @@ class EvervaultClient { } } - async encrypt(data: any, role: string | null = null): Promise { + async encrypt( + data: T, + role: string | null = null + ): Promise> { const dataRoleRegex = /^[a-z0-9-]{1,20}$/; if (role !== null && !dataRoleRegex.test(role)) { throw new Error( @@ -370,12 +381,15 @@ class EvervaultClient { ); } - async decrypt(encryptedData: any): Promise { + async decrypt(encryptedData: DecryptableData): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); return this.http.decrypt(encryptedData); } - async run(functionName: string, payload: any): Promise { + async run( + functionName: string, + payload: Record + ): Promise> { validationHelper.validateApiKey(this.appId, this.apiKey); validationHelper.validateFunctionName(functionName); validationHelper.validatePayload(payload); @@ -394,7 +408,10 @@ class EvervaultClient { } } - async createRunToken(functionName: string, payload: any): Promise { + async createRunToken( + functionName: string, + payload: Record + ): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); validationHelper.validatePayload(payload); validationHelper.validateFunctionName(functionName); @@ -460,7 +477,10 @@ class EvervaultClient { ); } - private defineHiddenProperty(property: string | number | symbol, value: any) { + private defineHiddenProperty( + property: string | number | symbol, + value: unknown + ) { Object.defineProperty(this, property, { enumerable: false, configurable: true, @@ -469,7 +489,10 @@ class EvervaultClient { }); } - async createClientSideDecryptToken(payload: any, expiry: any = null) { + async createClientSideDecryptToken( + payload: unknown, + expiry: Date | number | null = null + ): Promise { validationHelper.validateApiKey(this.appId, this.apiKey); if (!payload) { throw new TokenCreationError( diff --git a/lib/types.ts b/lib/types.ts index bfeb52ad..c7b2ff73 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -69,3 +69,79 @@ export interface AttestationBindings { attestationDoc: Buffer ) => boolean; } + +/** + * A value that can be passed to `encrypt`. Primitives, Buffers, and any nested + * combination of objects and arrays of those are all supported. + */ +export type EncryptableData = + | string + | number + | boolean + | null + | Buffer + | EncryptableData[] + | { [key: string]: EncryptableData }; + +/** + * The result of encrypting a value of type `T`. The shape of the input is + * preserved: Buffers stay Buffers, primitives become encrypted strings, and + * objects/arrays are traversed with each leaf value encrypted. + */ +export type EncryptedData = T extends Buffer + ? Buffer + : T extends string | number | boolean + ? string + : T extends null | undefined + ? T + : T extends Array + ? EncryptedData[] + : T extends object + ? { [K in keyof T]: EncryptedData } + : string; + +/** + * A value that can be passed to `decrypt`. Mirrors the shape produced by + * `encrypt`: encrypted strings, Buffers, and nested objects/arrays of those. + */ +export type DecryptableData = + | string + | Buffer + | DecryptableData[] + | { [key: string]: DecryptableData }; + +/** The response returned by a successful Function run. */ +export interface FunctionRunResult { + id: string; + result: T; + status: 'success'; +} + +/** A short-lived token used to invoke a Function from an untrusted client. */ +export interface RunToken { + token: string; +} + +/** A short-lived token created via `createClientSideDecryptToken`. */ +export interface ClientSideToken { + token: string; + createdAt: Date; + expiry: Date; +} + +/** The team/app key material returned by the keys endpoints. */ +export interface TeamKeyResponse { + key?: string; + ecdhKey: string; + ecdhP256Key: string; +} + +/** A single outbound Relay destination entry. */ +export interface RelayOutboundDestination { + destinationDomain: string; +} + +/** The body returned by the Relay Outbound configuration endpoint. */ +export interface RelayOutboundConfigResponse { + outboundDestinations: Record; +} diff --git a/lib/utils/attest.ts b/lib/utils/attest.ts index 15c1eb6c..12408709 100644 --- a/lib/utils/attest.ts +++ b/lib/utils/attest.ts @@ -1,7 +1,9 @@ import { AttestationError, MalformedAttestationData } from './errors'; import tls from 'tls'; import * as https from 'https'; -import type { HttpConfig } from '../types'; +import type { HttpConfig, AttestationBindings, PCRs } from '../types'; +import type PcrManager from '../core/pcrManager'; +import type AttestationDoc from '../core/attestationDoc'; const origCheckServerIdentity = tls.checkServerIdentity; @@ -20,10 +22,10 @@ function parseNameAndAppFromHost(hostname: string): { function attestConnection( hostname: string, - cert: any, - cagePcrManager: any, - attestationCache: any, - attestationBindings: any + cert: Buffer, + cagePcrManager: PcrManager, + attestationCache: AttestationDoc, + attestationBindings: AttestationBindings ): Error | undefined { try { if (!attestationBindings == null) { @@ -38,11 +40,11 @@ function attestConnection( // check if PCRs for this cage have been given const pcrs = cagePcrManager.get(name); - var pcrsList = []; + let pcrsList: PCRs[] = []; if (Array.isArray(pcrs)) { pcrsList = pcrs; } else if (typeof pcrs === 'object') { - pcrsList = [pcrs]; + pcrsList = [pcrs as PCRs]; } let attestationDoc = attestationCache.get(name); @@ -80,16 +82,16 @@ function attestConnection( */ class EnclaveAgent extends https.Agent { config: HttpConfig; - attestationCache: any; - pcrManager: any; - attestationBindings: any; + attestationCache: AttestationDoc; + pcrManager: PcrManager; + attestationBindings: AttestationBindings; constructor( option: https.AgentOptions | undefined, config: HttpConfig, - attestationCache: any, - pcrManager: any, - attestationBindings: any + attestationCache: AttestationDoc, + pcrManager: PcrManager, + attestationBindings: AttestationBindings ) { super(option); this.config = config; @@ -100,7 +102,7 @@ class EnclaveAgent extends https.Agent { #checkEnclaveServerIdentity = ( hostname: string, - cert: any + cert: tls.PeerCertificate ): Error | undefined => { if (hostname.endsWith(this.config.enclavesHostname)) { const attestationResult = attestConnection( @@ -118,7 +120,11 @@ class EnclaveAgent extends https.Agent { return origCheckServerIdentity(hostname, cert); }; - createConnection(options: any, callback: any): any { + // Overrides https.Agent#createConnection to force TLS attestation. Node's + // Agent typings model this as returning a generic Duplex over RequestOptions, + // which doesn't match the tls.connect signature used here, so the params stay + // untyped. + createConnection(options: any, callback: any): tls.TLSSocket { options.checkServerIdentity = this.#checkEnclaveServerIdentity; return tls.connect(options, callback); } @@ -126,13 +132,13 @@ class EnclaveAgent extends https.Agent { function addAttestationListener( config: HttpConfig, - attestationCache: any, - pcrManager: any, - attestationBindings: any + attestationCache: AttestationDoc, + pcrManager: PcrManager, + attestationBindings: AttestationBindings ): void { (tls as any).checkServerIdentity = function ( hostname: string, - cert: any + cert: tls.PeerCertificate ): Error | undefined { // only attempt attestation if the host is a cage if (hostname.endsWith(config.enclavesHostname)) { diff --git a/lib/utils/certHelper.ts b/lib/utils/certHelper.ts index 3c7fd32b..c80f9c0c 100644 --- a/lib/utils/certHelper.ts +++ b/lib/utils/certHelper.ts @@ -2,7 +2,7 @@ import { X509Certificate } from 'crypto'; import * as tls from 'tls'; import * as net from 'net'; -const parseX509 = (cert: any) => { +const parseX509 = (cert: string | Buffer) => { if (X509Certificate) { return new X509Certificate(cert); } else { diff --git a/lib/utils/errors.ts b/lib/utils/errors.ts index 19361e5b..39ea1b38 100644 --- a/lib/utils/errors.ts +++ b/lib/utils/errors.ts @@ -23,9 +23,9 @@ export class FunctionRuntimeError extends EvervaultError { export class AttestationError extends EvervaultError { host: string; - cert: any; + cert: Buffer; - constructor(reason: string, host: string, cert: any) { + constructor(reason: string, host: string, cert: Buffer) { super(reason); this.host = host; this.cert = cert; @@ -85,8 +85,8 @@ export const mapResponseCodeToError = ({ headers, }: { status: number; - data: any; - headers: any; + data: { message?: string }; + headers: Record; }): EvervaultError => { if (status === 401) return new EvervaultError('Invalid authorization provided.'); diff --git a/lib/utils/httpsHelper.ts b/lib/utils/httpsHelper.ts index 58348ce5..b1e0989f 100644 --- a/lib/utils/httpsHelper.ts +++ b/lib/utils/httpsHelper.ts @@ -4,12 +4,13 @@ import * as Datatypes from './datatypes'; import * as certHelper from './certHelper'; import HttpsProxyAgent from './proxyAgent'; import config from '../config'; +import type { HttpClient } from '../core/http'; const proxiedMarker = config.http.proxiedMarker; const origCreateSecureContext = tls.createSecureContext; const EVERVAULT_DOMAINS = ['evervault.com', 'evervault.io', 'evervault.dev']; -const certificateUtil = (evClient: any) => { +const certificateUtil = (evClient: HttpClient) => { let x509: any = null; async function updateCertificate() { const pem = await evClient.getCert(); @@ -70,7 +71,7 @@ const overloadHttpsModule = ( tunnelHostname: string, domainFilter: (domain: string, path: string) => boolean, debugRequests = false, - evClient: any, + evClient: HttpClient, originalRequest: typeof https.request ): void => { function wrapMethodRequest(this: any, ...args: any[]) { @@ -107,9 +108,16 @@ const overloadHttpsModule = ( (https as any).request = wrapMethodRequest; }; +interface RelayAgentConfig { + hostname: string; + port?: number; + rejectUnauthorized?: boolean; + secureProxy?: boolean; +} + const httpsRelayAgent = ( - agentConfig: any = { port: 443, rejectUnauthorized: true, secureProxy: true }, - evClient: any, + agentConfig: RelayAgentConfig, + evClient: HttpClient, apiKey?: string ): HttpsProxyAgent => { const { updateCertificate, isCertificateInvalid } = certificateUtil(evClient); From 169f0ed698b5fe26af300bbc43d5156c331b93b1 Mon Sep 17 00:00:00 2001 From: Matt Paletta Date: Thu, 16 Jul 2026 11:30:50 +0100 Subject: [PATCH 6/6] fix: raise e2e mocha timeout to 30s to absorb httpbin latency The two path-filtering outbound-relay tests each make two httpbin.org requests; the 5s timeout was too tight for slow-but-reachable httpbin, causing intermittent timeouts. Align with the .mocharc.json default (30s). Co-Authored-By: Claude Opus 4.8 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5cb3327d..ecfd576f 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,9 @@ "lint": "prettier --check \"./**/*.{ts,js}\"", "typecheck": "tsc --noEmit", "test": "pnpm run build:test && mocha 'tests/**/*.test.js'", - "test:e2e": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 5000 --exit", + "test:e2e": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 30000 --exit", "test:filter": "pnpm run build:test && mocha 'tests/**/*.test.js' --grep", - "test:e2e:filter": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 5000 --grep", + "test:e2e:filter": "pnpm run build:test && mocha 'e2e/**/*.test.js' --timeout 30000 --grep", "test:coverage": "nyc --reporter=text pnpm run test", "prepublishOnly": "pnpm run build" },