diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e61f52874..5057f65d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [16, 18, 20, 22] + node: [20, 22, 24] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/fix-latest.yml b/.github/workflows/fix-latest.yml index 48369c28a..db1043619 100644 --- a/.github/workflows/fix-latest.yml +++ b/.github/workflows/fix-latest.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 registry-url: 'https://registry.npmjs.org' - name: Install Dependencies diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8f2f4a101..038685eaa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,6 +29,10 @@ jobs: run: | npm install + - name: Build Project + run: | + npm run build + - name: Run Tests run: | npm run test diff --git a/.github/workflows/runtime-tests.yml b/.github/workflows/runtime-tests.yml new file mode 100644 index 000000000..8dafadd38 --- /dev/null +++ b/.github/workflows/runtime-tests.yml @@ -0,0 +1,24 @@ +name: Runtime Compatibility Tests + +on: [push, pull_request] + +jobs: + runtime-compatibility: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - uses: denoland/setup-deno@v2 + with: + deno-version: v1.x + - uses: oven-sh/setup-bun@v2 + + - name: Install and build + run: | + npm install + npm run build + + - name: Runtime compatibility check + run: npm run check:runtimes diff --git a/.gitignore b/.gitignore index 5b689e202..c4bc04b6e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ yarn-error.log lib/ .DS_Store yarn.lock -.idea/ \ No newline at end of file +.idea/ diff --git a/README.md b/README.md index 9b4328621..438868c20 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ See the [API Reference](https://workos.com/docs/reference/client-libraries) for ## Requirements -Node 16 or higher. +Node 20 or higher. ## Installation Install the package with: ``` -npm i @workos-inc/node +npm install @workos-inc/node ``` ## Configuration @@ -37,6 +37,60 @@ import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS('sk_1234'); ``` +## Public Client Mode (Browser/Mobile/CLI) + +For apps that can't securely store secrets, initialize with just a client ID: + +```ts +import { WorkOS } from '@workos-inc/node'; + +const workos = new WorkOS({ clientId: 'client_...' }); // No API key needed + +// Generate auth URL with automatic PKCE +const { url, codeVerifier } = + await workos.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + redirectUri: 'myapp://callback', + clientId: 'client_...', + }); + +// After user authenticates, exchange code for tokens +const { accessToken, refreshToken } = + await workos.userManagement.authenticateWithCode({ + code: authorizationCode, + codeVerifier, + clientId: 'client_...', + }); +``` + +> [!IMPORTANT] +> Store `codeVerifier` securely on-device between generating the auth URL and handling the callback. For mobile apps, use platform secure storage (iOS Keychain, Android Keystore). For CLI apps, consider OS credential storage. The verifier must survive app restarts during the auth flow. + +See the [AuthKit documentation](https://workos.com/docs/authkit) for details on PKCE authentication. + +### PKCE with Confidential Clients + +Server-side apps can also use PKCE alongside the client secret for defense in depth (recommended by OAuth 2.1): + +```ts +const workos = new WorkOS('sk_...'); // With API key + +// Use PKCE even with API key for additional security +const { url, codeVerifier } = + await workos.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + redirectUri: 'https://example.com/callback', + clientId: 'client_...', + }); + +// Both client_secret AND code_verifier will be sent +const { accessToken } = await workos.userManagement.authenticateWithCode({ + code: authorizationCode, + codeVerifier, + clientId: 'client_...', +}); +``` + ## SDK Versioning For our SDKs WorkOS follows a Semantic Versioning ([SemVer](https://semver.org/)) process where all releases will have a version X.Y.Z (like 1.0.0) pattern wherein Z would be a bug fix (e.g., 1.0.1), Y would be a minor release (1.1.0) and X would be a major release (2.0.0). We permit any breaking changes to only be released in major versions and strongly recommend reading changelogs before making any major version upgrades. diff --git a/docs/V8_MIGRATION_GUIDE.md b/docs/V8_MIGRATION_GUIDE.md new file mode 100644 index 000000000..5dff6a876 --- /dev/null +++ b/docs/V8_MIGRATION_GUIDE.md @@ -0,0 +1,590 @@ +# WorkOS Node SDK v8 Migration Guide + +This guide will help you migrate from v7 to v8 of the WorkOS Node SDK. + +## Table of Contents + +- [Quick Start](#quick-start) +- [Node.js Version Requirement](#nodejs-version-requirement) +- [Package Type Changes](#package-type-changes) +- [New Features](#new-features) + - [PKCE Authentication](#pkce-authentication) + - [Type-Safe Client Factory](#type-safe-client-factory) +- [Breaking Changes by Module](#breaking-changes-by-module) + - [Directory Sync](#directory-sync) + - [User Management](#user-management) + - [SSO](#sso) + - [MFA](#mfa) + - [Organizations](#organizations) + - [Vault](#vault) + - [Events](#events) + +--- + +## Quick Start + +1. **Update Node.js**: Ensure you're running Node.js 20 or higher +2. **Update the package**: `npm install @workos-inc/node@8` +3. **Run tests**: Check for TypeScript errors and runtime issues +4. **Review breaking changes**: See sections below for specific migrations + +--- + +## Node.js Version Requirement + +**Minimum Node.js version is now 20+** (previously 16+) + +Node.js 18 reached end-of-life in April 2025. If you're still on Node 18 or earlier, upgrade before migrating to v8. + +```bash +# Check your Node version +node --version + +# If below v20, upgrade Node.js first +# https://nodejs.org/ +``` + +--- + +## Package Type Changes + +The package is now **ESM-first** with dual CJS/ESM exports. + +### What this means: + +- If you use `import` (ESM), nothing changes +- If you use `require` (CommonJS), it still works via conditional exports +- TypeScript types are properly exported for both module systems + +### Most projects won't need changes + +The SDK uses conditional exports, so your bundler/runtime will automatically use the right build: + +```typescript +// ESM - works +import { WorkOS } from '@workos-inc/node'; + +// CommonJS - still works +const { WorkOS } = require('@workos-inc/node'); + +// Cloudflare Workers - use /worker +import { WorkOS } from '@workos-inc/node/worker'; +``` + +### If you have custom build configurations + +If you're doing deep imports or have custom bundler configs, you may need adjustments. The internal file structure has changed to support dual builds. + +**Before (v7):** +```typescript +// ❌ Deep imports no longer work +import { NodeHttpClient } from '@workos-inc/node/lib/common/net/node-client'; +``` + +**After (v8):** +```typescript +// ✅ Use the public API +import { WorkOS } from '@workos-inc/node'; +const workos = new WorkOS({ apiKey: 'sk_...' }); +``` + +--- + +## New Features + +### PKCE Authentication + +v8 adds full PKCE (Proof Key for Code Exchange) support for public clients. + +#### What is PKCE? + +PKCE enables secure authentication in mobile apps, desktop apps, and SPAs without exposing your API key. Previously, you needed a backend proxy to handle auth. Not anymore. + +#### Using PKCE + +**Option 1: Automatic PKCE (Recommended)** + +```typescript +import { WorkOS } from '@workos-inc/node'; + +// Initialize with just clientId (no API key for public clients) +const workos = new WorkOS({ clientId: 'client_123' }); + +// Generate authorization URL with PKCE +const { url, state, codeVerifier } = await workos.userManagement.getAuthorizationUrlWithPKCE({ + redirectUri: 'myapp://callback', + provider: 'authkit', +}); + +// Store codeVerifier securely (in-memory, secure storage, etc.) +// Redirect user to url... + +// After user authenticates and you receive the code: +const { accessToken, refreshToken, user } = await workos.userManagement.authenticateWithCode({ + code: authCode, + codeVerifier, // Use the codeVerifier from earlier +}); +``` + +**Option 2: Manual PKCE** + +```typescript +// Generate PKCE manually +const { codeVerifier, codeChallenge } = workos.pkce.generate(); + +// Use in authorization URL +const url = workos.userManagement.getAuthorizationUrl({ + redirectUri: 'myapp://callback', + provider: 'authkit', + codeChallenge, + codeChallengeMethod: 'S256', +}); +``` + +**Option 3: Server-side (no changes needed)** + +If you're using the SDK server-side with an API key, nothing changes: + +```typescript +// Still works exactly the same +const workos = new WorkOS({ apiKey: 'sk_...', clientId: 'client_123' }); + +const { accessToken, user } = await workos.userManagement.authenticateWithCode({ + code: authCode, +}); +``` + +### Type-Safe Client Factory + +v8 introduces `createWorkOS()` for compile-time type safety. + +#### Problem it solves + +In v7, you could accidentally call server-only methods on a public client: + +```typescript +// v7 - Runtime error, but TypeScript allows it +const workos = new WorkOS({ clientId: 'client_123' }); // No API key +await workos.userManagement.listUsers(); // ❌ Fails at runtime +``` + +#### Solution: createWorkOS() + +```typescript +import { createWorkOS } from '@workos-inc/node'; + +// Public client - TypeScript knows what's available +const publicClient = createWorkOS({ clientId: 'client_123' }); +publicClient.userManagement.getAuthorizationUrlWithPKCE({ ... }); // ✅ Works +publicClient.userManagement.listUsers(); // ❌ TypeScript error - method doesn't exist + +// Confidential client - full API access +const serverClient = createWorkOS({ apiKey: 'sk_...', clientId: 'client_123' }); +serverClient.userManagement.listUsers(); // ✅ Works +``` + +**When to use:** +- Use `createWorkOS()` for type safety when building public vs server apps +- Use `new WorkOS()` if you don't need compile-time enforcement + +--- + +## Breaking Changes by Module + +### Directory Sync + +#### DirectoryUser fields moved to customAttributes + +User fields are now in `customAttributes` to better match the API structure. + +**Before (v7):** +```typescript +const user = await workos.directorySync.getUser({ user: 'directory_user_123' }); + +console.log(user.emails); // Primary email +console.log(user.username); // Username +console.log(user.jobTitle); // Job title +``` + +**After (v8):** +```typescript +const user = await workos.directorySync.getUser({ user: 'directory_user_123' }); + +console.log(user.customAttributes?.emails); // Array of emails +console.log(user.customAttributes?.username); // Username +console.log(user.customAttributes?.jobTitle); // Job title +``` + +#### getPrimaryEmail() utility removed + +The `getPrimaryEmail()` helper function has been removed. + +**Before (v7):** +```typescript +import { getPrimaryEmail } from '@workos-inc/node'; + +const email = getPrimaryEmail(user); +``` + +**After (v8):** +```typescript +// Option 1: Access directly +const primaryEmail = user.customAttributes?.emails?.[0]; + +// Option 2: Create your own helper +function getPrimaryEmail(user: DirectoryUser): string | undefined { + return user.customAttributes?.emails?.[0]; +} +``` + +### User Management + +#### Removed deprecated methods + +Several methods have been removed. They were deprecated in v6 and v7. + +**sendMagicAuthCode() removed** + +**Before (v7):** +```typescript +await workos.sendMagicAuthCode({ email: 'user@example.com' }); +``` + +**After (v8):** +```typescript +await workos.userManagement.sendMagicCode({ email: 'user@example.com' }); +``` + +**sendPasswordResetEmail() removed** + +**Before (v7):** +```typescript +await workos.sendPasswordResetEmail({ email: 'user@example.com' }); +``` + +**After (v8):** +```typescript +await workos.userManagement.sendPasswordResetEmail({ email: 'user@example.com' }); +``` + +**refreshAndSealSessionData() removed** + +**Before (v7):** +```typescript +const session = await workos.userManagement.refreshAndSealSessionData({ + sessionData: encryptedSession, + cookiePassword: 'secret', +}); +``` + +**After (v8):** +```typescript +// Use the new session helper methods +import { refreshSession, sealSession } from '@workos-inc/node'; + +const refreshedSession = await refreshSession({ + sessionData: session, + organizationId: 'org_123', +}); + +const sealed = await sealSession({ + sessionData: refreshedSession, + cookiePassword: 'secret', +}); +``` + +#### AuthorizationURLOptions: context field removed + +The `context` field is no longer supported. + +**Before (v7):** +```typescript +const url = workos.userManagement.getAuthorizationUrl({ + provider: 'authkit', + redirectUri: 'https://example.com/callback', + context: { foo: 'bar' }, // ❌ No longer supported +}); +``` + +**After (v8):** +```typescript +const url = workos.userManagement.getAuthorizationUrl({ + provider: 'authkit', + redirectUri: 'https://example.com/callback', + // Use state parameter for client-side data + state: 'your-state-data', +}); +``` + +#### listOrganizationMemberships now requires userId or organizationId + +You can no longer call `listOrganizationMemberships()` without parameters. + +**Before (v7):** +```typescript +// ❌ No longer works +const memberships = await workos.userManagement.listOrganizationMemberships(); +``` + +**After (v8):** +```typescript +// ✅ Specify userId OR organizationId +const memberships = await workos.userManagement.listOrganizationMemberships({ + userId: 'user_123', +}); + +// OR +const memberships = await workos.userManagement.listOrganizationMemberships({ + organizationId: 'org_456', +}); +``` + +### SSO + +#### SSOAuthorizationURLOptions type changes + +Options are now a **discriminated union**. You must specify exactly one of: `connection`, `organization`, or `provider`. + +**Before (v7):** +```typescript +// TypeScript allowed this, but it was ambiguous +const url = workos.sso.getAuthorizationUrl({ + connection: 'conn_123', + organization: 'org_456', // Both allowed + redirectUri: 'https://example.com/callback', +}); +``` + +**After (v8):** +```typescript +// ✅ Specify exactly one +const url = workos.sso.getAuthorizationUrl({ + connection: 'conn_123', // OR organization OR provider (not multiple) + redirectUri: 'https://example.com/callback', +}); + +// TypeScript will error if you try to specify multiple: +const url = workos.sso.getAuthorizationUrl({ + connection: 'conn_123', + organization: 'org_456', // ❌ TypeScript error + redirectUri: 'https://example.com/callback', +}); +``` + +#### domain field removed + +The deprecated `domain` field has been removed. + +**Before (v7):** +```typescript +const url = workos.sso.getAuthorizationUrl({ + domain: 'example.com', // ❌ Removed + redirectUri: 'https://example.com/callback', +}); +``` + +**After (v8):** +```typescript +const url = workos.sso.getAuthorizationUrl({ + organization: 'org_123', // Use organization instead + redirectUri: 'https://example.com/callback', +}); +``` + +### MFA + +#### verifyFactor() removed + +Use `verifyChallenge()` instead (same functionality). + +**Before (v7):** +```typescript +const result = await workos.mfa.verifyFactor({ + authenticationFactorId: 'auth_factor_123', + code: '123456', +}); +``` + +**After (v8):** +```typescript +const result = await workos.mfa.verifyChallenge({ + authenticationFactorId: 'auth_factor_123', + code: '123456', +}); +``` + +### Organizations + +#### Removed fields from CreateOrganizationOptions and UpdateOrganizationOptions + +**allowProfilesOutsideOrganization removed** + +**Before (v7):** +```typescript +await workos.organizations.createOrganization({ + name: 'Acme Corp', + allowProfilesOutsideOrganization: true, // ❌ Removed +}); +``` + +**After (v8):** +```typescript +await workos.organizations.createOrganization({ + name: 'Acme Corp', + // Field removed - use API settings instead +}); +``` + +**domains field removed (use domainData instead)** + +**Before (v7):** +```typescript +await workos.organizations.createOrganization({ + name: 'Acme Corp', + domains: ['example.com'], // ❌ Removed +}); +``` + +**After (v8):** +```typescript +await workos.organizations.createOrganization({ + name: 'Acme Corp', + domainData: [{ domain: 'example.com', state: 'verified' }], // ✅ Use domainData +}); +``` + +#### OrganizationDomainState enum change + +`LegacyVerified` removed from enum. + +**Before (v7):** +```typescript +if (domain.state === 'legacy_verified') { // ❌ No longer exists + // ... +} +``` + +**After (v8):** +```typescript +if (domain.state === 'verified') { // ✅ Use 'verified' + // ... +} +``` + +### Vault + +#### Removed deprecated method aliases + +All `*Secret` methods removed. Use `*Object` methods instead. + +| Removed (v7) | Use Instead (v8) | +|------------------------|------------------------| +| `createSecret()` | `createObject()` | +| `listSecrets()` | `listObjects()` | +| `listSecretVersions()` | `listObjectVersions()` | +| `readSecret()` | `readObject()` | +| `describeSecret()` | `describeObject()` | +| `updateSecret()` | `updateObject()` | +| `deleteSecret()` | `deleteObject()` | + +**Before (v7):** +```typescript +const secret = await workos.vault.createSecret({ + name: 'api-key', + value: 'sk_test_123', +}); +``` + +**After (v8):** +```typescript +const object = await workos.vault.createObject({ + name: 'api-key', + value: 'sk_test_123', +}); +``` + +### Events + +#### Event type changes + +**dsync.deactivated removed** + +**Before (v7):** +```typescript +if (event.event === 'dsync.deactivated') { + // Handle deactivated event +} +``` + +**After (v8):** +```typescript +if (event.event === 'dsync.deleted') { // ✅ Use dsync.deleted + // Handle deleted event +} +``` + +**Organization membership events removed** + +- `OrganizationMembershipAdded` - Not applicable in v8 +- `OrganizationMembershipRemoved` - Not applicable in v8 + +If you were using these events, contact WorkOS support for migration guidance. + +--- + +## Internal Changes (Non-Breaking) + +These changes shouldn't affect your code, but are worth knowing: + +### HTTP and Crypto Providers Removed + +Internal classes like `NodeHttpClient`, `NodeCryptoProvider`, and iron-session providers have been removed. If you were importing these directly (not recommended), use the main `WorkOS` class instead. + +### Build System Migration + +We migrated from `tsc` to `tsdown` for faster builds and better runtime compatibility. This doesn't affect usage but results in: +- Smaller bundle sizes +- Better tree-shaking +- Improved compatibility with edge runtimes + +### Dependency Updates + +- Using `iron-webcrypto` v2 instead of `iron-session` +- Removed external `leb` and `qs` packages (internal implementations) +- Migrated from TSLint to ESLint + +--- + +## Testing Your Migration + +After migrating, run these checks: + +1. **TypeScript compilation**: `npx tsc --noEmit` +2. **Unit tests**: Ensure all tests pass +3. **Runtime testing**: Test auth flows end-to-end +4. **Check deprecation warnings**: Look for any warnings in your logs + +--- + +## Getting Help + +- **Issues**: [GitHub Issues](https://github.com/workos/workos-node/issues) +- **Slack**: WorkOS Community Slack +- **Docs**: [WorkOS Documentation](https://workos.com/docs) + +--- + +## Summary Checklist + +- [ ] Upgraded to Node.js 20+ +- [ ] Installed v8: `npm install @workos-inc/node@8` +- [ ] Updated Directory Sync to use `customAttributes` +- [ ] Replaced `getPrimaryEmail()` if used +- [ ] Migrated deprecated User Management methods +- [ ] Updated SSO authorization options to discriminated union +- [ ] Changed `verifyFactor()` to `verifyChallenge()` +- [ ] Removed `allowProfilesOutsideOrganization` from Organizations +- [ ] Updated Vault methods from `*Secret` to `*Object` +- [ ] Updated event types (`dsync.deactivated` → `dsync.deleted`) +- [ ] Tested PKCE flows if building public clients +- [ ] Ran tests and verified everything works diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..f71490fb1 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,62 @@ +// @ts-check + +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import jestPlugin from 'eslint-plugin-jest'; +import n from 'eslint-plugin-n'; + +const ignores = [ + '**/*.snap', + 'coverage', + 'node_modules', + 'dist', + 'build', + 'lib', +]; + +const tests = ['**/*.spec.{js,ts}']; + +export default tseslint.config( + { + ignores, + }, + { linterOptions: { reportUnusedDisableDirectives: 'error' } }, + eslint.configs.recommended, + tseslint.configs.recommended, + n.configs['flat/recommended'], + { + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-require-imports': 'off', + 'n/no-missing-import': 'off', + 'n/no-unsupported-features/node-builtins': 'off', + }, + }, + { + files: ['**/*.cjs'], + languageOptions: { + globals: { + require: 'readonly', + module: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + exports: 'readonly', + process: 'readonly', + }, + }, + }, + { + files: tests, + extends: [jestPlugin.configs['flat/recommended']], + rules: { + 'no-undef': 'off', + 'jest/no-alias-methods': 'off', + 'jest/no-identical-title': 'off', + 'jest/no-disabled-tests': 'off', + 'jest/no-conditional-expect': 'off', + 'jest/valid-expect': 'off', + 'jest/expect-expect': 'off', + }, + }, +); diff --git a/jest-transform-esm.cjs b/jest-transform-esm.cjs new file mode 100644 index 000000000..474caca57 --- /dev/null +++ b/jest-transform-esm.cjs @@ -0,0 +1,9 @@ +const babelJest = require('babel-jest'); + +module.exports = babelJest.createTransformer({ + presets: [ + ['@babel/preset-env', { targets: { node: 'current' } }], + '@babel/preset-typescript', + ], + plugins: ['@babel/plugin-transform-modules-commonjs'], +}); diff --git a/jest.config.js b/jest.config.cjs similarity index 64% rename from jest.config.js rename to jest.config.cjs index 455d61ef5..1ed790d07 100644 --- a/jest.config.js +++ b/jest.config.cjs @@ -9,8 +9,9 @@ module.exports = { setupFilesAfterEnv: ['./setup-jest.ts'], transform: { '^.+\\.ts?$': 'ts-jest', + '^.+\\.m?js$': '/jest-transform-esm.cjs', }, - moduleNameMapper: { - '^jose': require.resolve('jose'), - }, + transformIgnorePatterns: [ + 'node_modules/(?!(iron-webcrypto|uint8array-extras|@noble|@scure|jose)/)', + ], }; diff --git a/package-lock.json b/package-lock.json index 12ce0779c..0d71ba395 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,48 +1,105 @@ { "name": "@workos-inc/node", - "version": "7.82.0", + "version": "8.0.0-rc.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@workos-inc/node", - "version": "7.82.0", + "version": "8.0.0-rc.10", "license": "MIT", "dependencies": { - "iron-session": "~6.3.1", - "jose": "~5.6.3", - "leb": "^1.0.0", - "qs": "6.14.1" + "iron-webcrypto": "^2.0.0", + "jose": "~6.1.0" }, "devDependencies": { - "@peculiar/webcrypto": "^1.4.5", - "@types/jest": "29.5.14", - "@types/node": "14.18.54", - "jest": "29.7.0", + "@arethetypeswrong/cli": "^0.18.2", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/preset-env": "^7.26.9", + "@babel/preset-typescript": "^7.27.0", + "@eslint/js": "^9.37.0", + "@types/jest": "^30.0.0", + "@types/node": "~20", + "@typescript-eslint/parser": "^8.46.0", + "babel-jest": "^30.2.0", + "eslint": "^9.37.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-n": "^17.23.1", + "jest": "30.2.0", "jest-environment-miniflare": "^2.14.2", "jest-fetch-mock": "^3.0.3", - "nock": "^13.5.5", - "prettier": "2.8.8", - "supertest": "6.3.3", - "ts-jest": "29.1.3", - "tslint": "6.1.3", - "typescript": "5.1.6" + "miniflare": "^4.20251004.0", + "prettier": "^3.5.3", + "ts-jest": "29.4.4", + "tsdown": "^0.17.0", + "tsx": "^4.20.6", + "typescript": "5.9.3", + "typescript-eslint": "^8.46.0" }, "engines": { - "node": ">=16" + "node": ">=20.15.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "node_modules/@andrewbranch/untar.js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz", + "integrity": "sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==", + "dev": true + }, + "node_modules/@arethetypeswrong/cli": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.18.2.tgz", + "integrity": "sha512-PcFM20JNlevEDKBg4Re29Rtv2xvjvQZzg7ENnrWFSS0PHgdP2njibVFw+dRUhNkPgNfac9iUqO0ohAXqQL4hbw==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "@arethetypeswrong/core": "0.18.2", + "chalk": "^4.1.2", + "cli-table3": "^0.6.3", + "commander": "^10.0.1", + "marked": "^9.1.2", + "marked-terminal": "^7.1.0", + "semver": "^7.5.4" + }, + "bin": { + "attw": "dist/index.js" }, "engines": { - "node": ">=6.0.0" + "node": ">=20" + } + }, + "node_modules/@arethetypeswrong/core": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.18.2.tgz", + "integrity": "sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@andrewbranch/untar.js": "^1.0.3", + "@loaderkit/resolve": "^1.0.2", + "cjs-module-lexer": "^1.2.3", + "fflate": "^0.8.2", + "lru-cache": "^11.0.1", + "semver": "^7.5.4", + "typescript": "5.6.1-rc", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@arethetypeswrong/core/node_modules/typescript": { + "version": "5.6.1-rc", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.1-rc.tgz", + "integrity": "sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, "node_modules/@babel/code-frame": { @@ -50,6 +107,7 @@ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", @@ -60,30 +118,33 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", - "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.3", - "@babel/parser": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -98,14 +159,25 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -114,11 +186,25 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", @@ -130,11 +216,123 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, "engines": { "node": ">=6.9.0" } @@ -144,6 +342,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" @@ -157,6 +356,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", @@ -169,11 +369,75 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, "engines": { "node": ">=6.9.0" } @@ -183,15 +447,17 @@ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -201,30 +467,48 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helpers": { + "node_modules/@babel/helper-wrap-function": { "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", - "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/parser": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -233,79 +517,198 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -316,6 +719,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -328,6 +732,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -343,6 +748,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -355,6 +761,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -367,6 +774,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -379,6 +787,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -391,6 +800,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -403,6 +813,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -415,6 +826,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -430,6 +842,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -445,6 +858,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -455,1394 +869,6192 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", - "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.3", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2", - "debug": "^4.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20250813.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250813.0.tgz", - "integrity": "sha512-RFFjomDndGR+p7ug1HWDlW21qOJyRZbmI99dUtuR9tmwJbSZhUUnSFmzok9lBYVfkMMrO1O5vmB+IlgiecgLEA==", - "dev": true - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", "dev": true, + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", + "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", "dev": true, + "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", "dev": true, + "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dev": true, + "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", "dev": true, + "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", + "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/cache": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.14.4.tgz", - "integrity": "sha512-ayzdjhcj+4mjydbNK7ZGDpIXNliDbQY4GPcY2KrYw0v1OSUdj5kZUkygD09fqoGRfAks0d91VelkyRsAXX8FQA==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/core": "2.14.4", - "@miniflare/shared": "2.14.4", - "http-cache-semantics": "^4.1.0", - "undici": "5.28.4" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/core": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.14.4.tgz", - "integrity": "sha512-FMmZcC1f54YpF4pDWPtdQPIO8NXfgUxCoR9uyrhxKJdZu7M6n8QKopPVNuaxR40jcsdxb7yKoQoFWnHfzJD9GQ==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", + "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", "dev": true, + "license": "MIT", "dependencies": { - "@iarna/toml": "^2.2.5", - "@miniflare/queues": "2.14.4", - "@miniflare/shared": "2.14.4", - "@miniflare/watcher": "2.14.4", - "busboy": "^1.6.0", - "dotenv": "^10.0.0", - "kleur": "^4.1.4", - "set-cookie-parser": "^2.4.8", - "undici": "5.28.4", - "urlpattern-polyfill": "^4.0.3" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/d1": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.14.4.tgz", - "integrity": "sha512-pMBVq9XWxTDdm+RRCkfXZP+bREjPg1JC8s8C0JTovA9OGmLQXqGTnFxIaS9vf1d8k3uSUGhDzPTzHr0/AUW1gA==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/core": "2.14.4", - "@miniflare/shared": "2.14.4" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.7" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/durable-objects": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.14.4.tgz", - "integrity": "sha512-+JrmHP6gHHrjxV8S3axVw5lGHLgqmAGdcO/1HJUPswAyJEd3Ah2YnKhpo+bNmV4RKJCtEq9A2hbtVjBTD2YzwA==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/core": "2.14.4", - "@miniflare/shared": "2.14.4", - "@miniflare/storage-memory": "2.14.4", - "undici": "5.28.4" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/html-rewriter": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.14.4.tgz", - "integrity": "sha512-GB/vZn7oLbnhw+815SGF+HU5EZqSxbhIa3mu2L5MzZ2q5VOD5NHC833qG8c2GzDPhIaZ99ITY+ZJmbR4d+4aNQ==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/core": "2.14.4", - "@miniflare/shared": "2.14.4", - "html-rewriter-wasm": "^0.4.1", - "undici": "5.28.4" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/kv": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.14.4.tgz", - "integrity": "sha512-QlERH0Z+klwLg0xw+/gm2yC34Nnr/I0GcQ+ASYqXeIXBwjqOtMBa3YVQnocaD+BPy/6TUtSpOAShHsEj76R2uw==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", + "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/shared": "2.14.4" + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.5" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/queues": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.14.4.tgz", - "integrity": "sha512-aXQ5Ik8Iq1KGMBzGenmd6Js/jJgqyYvjom95/N9GptCGpiVWE5F0XqC1SL5rCwURbHN+aWY191o8XOFyY2nCUA==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/shared": "2.14.4" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.7" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/r2": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.14.4.tgz", - "integrity": "sha512-4ctiZWh7Ty7LB3brUjmbRiGMqwyDZgABYaczDtUidblo2DxX4JZPnJ/ZAyxMPNJif32kOJhcg6arC2hEthR9Sw==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/core": "2.14.4", - "@miniflare/shared": "2.14.4", - "undici": "5.28.4" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@miniflare/runner-vm": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.14.4.tgz", - "integrity": "sha512-Nog0bB9SVhPbZAkTWfO4lpLAUsBXKEjlb4y+y66FJw77mPlmPlVdpjElCvmf8T3VN/pqh83kvELGM+/fucMf4g==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/shared": "2.14.4" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/shared": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.14.4.tgz", - "integrity": "sha512-upl4RSB3hyCnITOFmRZjJj4A72GmkVrtfZTilkdq5Qe5TTlzsjVeDJp7AuNUM9bM8vswRo+N5jOiot6O4PVwwQ==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/better-sqlite3": "^7.6.0", - "kleur": "^4.1.4", - "npx-import": "^1.1.4", - "picomatch": "^2.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/shared-test-environment": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/shared-test-environment/-/shared-test-environment-2.14.4.tgz", - "integrity": "sha512-FdU2/8wEd00vIu+MfofLiHcfZWz+uCbE2VTL85KpyYfBsNGAbgRtzFMpOXdoXLqQfRu6MBiRwWpb2FbMrBzi7g==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", "dev": true, + "license": "MIT", "dependencies": { - "@cloudflare/workers-types": "^4.20221111.1", - "@miniflare/cache": "2.14.4", - "@miniflare/core": "2.14.4", - "@miniflare/d1": "2.14.4", - "@miniflare/durable-objects": "2.14.4", - "@miniflare/html-rewriter": "2.14.4", - "@miniflare/kv": "2.14.4", - "@miniflare/queues": "2.14.4", - "@miniflare/r2": "2.14.4", - "@miniflare/shared": "2.14.4", - "@miniflare/sites": "2.14.4", - "@miniflare/storage-memory": "2.14.4", - "@miniflare/web-sockets": "2.14.4" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/sites": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.14.4.tgz", - "integrity": "sha512-O5npWopi+fw9W9Ki0gy99nuBbgDva/iXy8PDC4dAXDB/pz45nISDqldabk0rL2t4W2+lY6LXKzdOw+qJO1GQTA==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/kv": "2.14.4", - "@miniflare/shared": "2.14.4", - "@miniflare/storage-file": "2.14.4" + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/storage-file": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.14.4.tgz", - "integrity": "sha512-JxcmX0hXf4cB0cC9+s6ZsgYCq+rpyUKRPCGzaFwymWWplrO3EjPVxKCcMxG44jsdgsII6EZihYUN2J14wwCT7A==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/shared": "2.14.4", - "@miniflare/storage-memory": "2.14.4" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/storage-memory": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.14.4.tgz", - "integrity": "sha512-9jB5BqNkMZ3SFjbPFeiVkLi1BuSahMhc/W1Y9H0W89qFDrrD+z7EgRgDtHTG1ZRyi9gIlNtt9qhkO1B6W2qb2A==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/shared": "2.14.4" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/watcher": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.14.4.tgz", - "integrity": "sha512-PYn05ET2USfBAeXF6NZfWl0O32KVyE8ncQ/ngysrh3hoIV7l3qGGH7ubeFx+D8VWQ682qYhwGygUzQv2j1tGGg==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", + "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/shared": "2.14.4" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@miniflare/web-sockets": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.14.4.tgz", - "integrity": "sha512-stTxvLdJ2IcGOs76AnvGYAzGvx8JvQPRxC5DW0P5zdAAnhL33noqb5LKdPt3P37BKp9FzBKZHuihQI9oVqwm0g==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "dev": true, + "license": "MIT", "dependencies": { - "@miniflare/core": "2.14.4", - "@miniflare/shared": "2.14.4", - "undici": "5.28.4", - "ws": "^8.2.2" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=16.13" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">=6.9.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", - "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", "dev": true, + "license": "MIT", "dependencies": { - "@noble/hashes": "^1.1.5" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.4.0.tgz", - "integrity": "sha512-umbembjIWOrPSOzEGG5vxFLkeM8kzIhLkgigtsOrfLKnuzxWxejAcUX+q/SoZCdemlODOcr5WiYa7+dIEzBXZQ==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dev": true, + "license": "MIT", "dependencies": { - "asn1js": "^3.0.6", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@peculiar/json-schema": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", - "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@peculiar/webcrypto": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", - "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dev": true, + "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.8.0" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=10.12.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dev": true, + "license": "MIT", "dependencies": { - "type-detect": "4.0.8" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "dev": true, + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/better-sqlite3": { - "version": "7.6.13", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", - "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/content-disposition": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.9.tgz", - "integrity": "sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ==" - }, - "node_modules/@types/cookie": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.4.tgz", - "integrity": "sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==" - }, - "node_modules/@types/cookies": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.9.1.tgz", - "integrity": "sha512-E/DPgzifH4sM1UMadJMWd6mO2jOd4g1Ejwzx8/uRCDpJis1IrlyQEcGAYEomtAqRYmD5ORbNXMeI9U0RiVGZbg==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@types/express": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "node_modules/@babel/preset-env": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz", + "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "@babel/compat-data": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.5", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.4", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.28.5", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.28.5", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.4", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.4", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@types/http-assert": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.6.tgz", - "integrity": "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/@babel/preset-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "dev": true, + "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "*" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/istanbul-lib-report": "*" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/keygrip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", - "integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==" - }, - "node_modules/@types/koa": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.15.0.tgz", - "integrity": "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==", - "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/koa-compose": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.8.tgz", - "integrity": "sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==", + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/koa": "*" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" }, - "node_modules/@types/node": { - "version": "14.18.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", - "integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==" - }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" - }, - "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } + "node_modules/@braidai/lang": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@braidai/lang/-/lang-1.1.2.tgz", + "integrity": "sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA==", + "dev": true, + "license": "ISC" }, - "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260107.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260107.1.tgz", + "integrity": "sha512-Srwe/IukVppkMU2qTndkFaKCmZBI7CnZoq4Y0U0gD/8158VGzMREHTqCii4IcCeHifwrtDqTWu8EcA1VBKI4mg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260107.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260107.1.tgz", + "integrity": "sha512-aAYwU7zXW+UZFh/a4vHP5cs1ulTOcDRLzwU9547yKad06RlZ6ioRm7ovjdYvdqdmbI8mPd99v4LN9gMmecazQw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@types/yargs-parser": "*" + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260107.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260107.1.tgz", + "integrity": "sha512-Wh7xWtFOkk6WY3CXe3lSqZ1anMkFcwy+qOGIjtmvQ/3nCOaG34vKNwPIE9iwryPupqkSuDmEqkosI1UUnSTh1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260107.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260107.1.tgz", + "integrity": "sha512-NI0/5rdssdZZKYHxNG4umTmMzODByq86vSCEk8u4HQbGhRCQo7rV1eXn84ntSBdyWBzWdYGISCbeZMsgfIjSTg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260107.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260107.1.tgz", + "integrity": "sha512-gmBMqs606Gd/IhBEBPSL/hJAqy2L8IyPUjKtoqd/Ccy7GQxbSc0rYlRkxbQ9YzmqnuhrTVYvXuLscyWrpmAJkw==", + "cpu": [ + "x64" + ], "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@cloudflare/workers-types": { + "version": "4.20260108.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260108.0.tgz", + "integrity": "sha512-0SuzZ7SeMB35X0wL2rhsEQG1dmfAGY8N8z7UwrkFb6hxerxwXP4QuIzcF8HtCJTRTjChmarxV+HQC+ADB4UK1A==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "license": "MIT OR Apache-2.0" + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.1.90" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/asn1js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz", - "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==", + "node_modules/@emnapi/core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "pvtsutils": "^1.3.6", - "pvutils": "^1.1.3", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=12.0.0" + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true, + "license": "ISC" + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@loaderkit/resolve": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@loaderkit/resolve/-/resolve-1.0.4.tgz", + "integrity": "sha512-rJzYKVcV4dxJv+vW6jlvagF8zvGxHJ2+HTr1e2qOejfmGhAApgJHl8Aog4mMszxceTRiKTTbnpgmTO1bEZHV/A==", + "dev": true, + "license": "ISC", + "dependencies": { + "@braidai/lang": "^1.0.0" + } + }, + "node_modules/@miniflare/cache": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.14.4.tgz", + "integrity": "sha512-ayzdjhcj+4mjydbNK7ZGDpIXNliDbQY4GPcY2KrYw0v1OSUdj5kZUkygD09fqoGRfAks0d91VelkyRsAXX8FQA==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/core": "2.14.4", + "@miniflare/shared": "2.14.4", + "http-cache-semantics": "^4.1.0", + "undici": "5.28.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/core": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.14.4.tgz", + "integrity": "sha512-FMmZcC1f54YpF4pDWPtdQPIO8NXfgUxCoR9uyrhxKJdZu7M6n8QKopPVNuaxR40jcsdxb7yKoQoFWnHfzJD9GQ==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@iarna/toml": "^2.2.5", + "@miniflare/queues": "2.14.4", + "@miniflare/shared": "2.14.4", + "@miniflare/watcher": "2.14.4", + "busboy": "^1.6.0", + "dotenv": "^10.0.0", + "kleur": "^4.1.4", + "set-cookie-parser": "^2.4.8", + "undici": "5.28.4", + "urlpattern-polyfill": "^4.0.3" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/d1": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.14.4.tgz", + "integrity": "sha512-pMBVq9XWxTDdm+RRCkfXZP+bREjPg1JC8s8C0JTovA9OGmLQXqGTnFxIaS9vf1d8k3uSUGhDzPTzHr0/AUW1gA==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/core": "2.14.4", + "@miniflare/shared": "2.14.4" + }, + "engines": { + "node": ">=16.7" + } + }, + "node_modules/@miniflare/durable-objects": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.14.4.tgz", + "integrity": "sha512-+JrmHP6gHHrjxV8S3axVw5lGHLgqmAGdcO/1HJUPswAyJEd3Ah2YnKhpo+bNmV4RKJCtEq9A2hbtVjBTD2YzwA==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/core": "2.14.4", + "@miniflare/shared": "2.14.4", + "@miniflare/storage-memory": "2.14.4", + "undici": "5.28.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/html-rewriter": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.14.4.tgz", + "integrity": "sha512-GB/vZn7oLbnhw+815SGF+HU5EZqSxbhIa3mu2L5MzZ2q5VOD5NHC833qG8c2GzDPhIaZ99ITY+ZJmbR4d+4aNQ==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/core": "2.14.4", + "@miniflare/shared": "2.14.4", + "html-rewriter-wasm": "^0.4.1", + "undici": "5.28.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/kv": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.14.4.tgz", + "integrity": "sha512-QlERH0Z+klwLg0xw+/gm2yC34Nnr/I0GcQ+ASYqXeIXBwjqOtMBa3YVQnocaD+BPy/6TUtSpOAShHsEj76R2uw==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/shared": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/queues": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.14.4.tgz", + "integrity": "sha512-aXQ5Ik8Iq1KGMBzGenmd6Js/jJgqyYvjom95/N9GptCGpiVWE5F0XqC1SL5rCwURbHN+aWY191o8XOFyY2nCUA==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/shared": "2.14.4" + }, + "engines": { + "node": ">=16.7" + } + }, + "node_modules/@miniflare/r2": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.14.4.tgz", + "integrity": "sha512-4ctiZWh7Ty7LB3brUjmbRiGMqwyDZgABYaczDtUidblo2DxX4JZPnJ/ZAyxMPNJif32kOJhcg6arC2hEthR9Sw==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/core": "2.14.4", + "@miniflare/shared": "2.14.4", + "undici": "5.28.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/runner-vm": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.14.4.tgz", + "integrity": "sha512-Nog0bB9SVhPbZAkTWfO4lpLAUsBXKEjlb4y+y66FJw77mPlmPlVdpjElCvmf8T3VN/pqh83kvELGM+/fucMf4g==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/shared": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/shared": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.14.4.tgz", + "integrity": "sha512-upl4RSB3hyCnITOFmRZjJj4A72GmkVrtfZTilkdq5Qe5TTlzsjVeDJp7AuNUM9bM8vswRo+N5jOiot6O4PVwwQ==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/better-sqlite3": "^7.6.0", + "kleur": "^4.1.4", + "npx-import": "^1.1.4", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/shared-test-environment": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/shared-test-environment/-/shared-test-environment-2.14.4.tgz", + "integrity": "sha512-FdU2/8wEd00vIu+MfofLiHcfZWz+uCbE2VTL85KpyYfBsNGAbgRtzFMpOXdoXLqQfRu6MBiRwWpb2FbMrBzi7g==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@cloudflare/workers-types": "^4.20221111.1", + "@miniflare/cache": "2.14.4", + "@miniflare/core": "2.14.4", + "@miniflare/d1": "2.14.4", + "@miniflare/durable-objects": "2.14.4", + "@miniflare/html-rewriter": "2.14.4", + "@miniflare/kv": "2.14.4", + "@miniflare/queues": "2.14.4", + "@miniflare/r2": "2.14.4", + "@miniflare/shared": "2.14.4", + "@miniflare/sites": "2.14.4", + "@miniflare/storage-memory": "2.14.4", + "@miniflare/web-sockets": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/sites": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.14.4.tgz", + "integrity": "sha512-O5npWopi+fw9W9Ki0gy99nuBbgDva/iXy8PDC4dAXDB/pz45nISDqldabk0rL2t4W2+lY6LXKzdOw+qJO1GQTA==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/kv": "2.14.4", + "@miniflare/shared": "2.14.4", + "@miniflare/storage-file": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/storage-file": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.14.4.tgz", + "integrity": "sha512-JxcmX0hXf4cB0cC9+s6ZsgYCq+rpyUKRPCGzaFwymWWplrO3EjPVxKCcMxG44jsdgsII6EZihYUN2J14wwCT7A==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/shared": "2.14.4", + "@miniflare/storage-memory": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/storage-memory": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.14.4.tgz", + "integrity": "sha512-9jB5BqNkMZ3SFjbPFeiVkLi1BuSahMhc/W1Y9H0W89qFDrrD+z7EgRgDtHTG1ZRyi9gIlNtt9qhkO1B6W2qb2A==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/shared": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/watcher": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.14.4.tgz", + "integrity": "sha512-PYn05ET2USfBAeXF6NZfWl0O32KVyE8ncQ/ngysrh3hoIV7l3qGGH7ubeFx+D8VWQ682qYhwGygUzQv2j1tGGg==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/shared": "2.14.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/web-sockets": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.14.4.tgz", + "integrity": "sha512-stTxvLdJ2IcGOs76AnvGYAzGvx8JvQPRxC5DW0P5zdAAnhL33noqb5LKdPt3P37BKp9FzBKZHuihQI9oVqwm0g==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "dev": true, + "license": "MIT", + "dependencies": { + "@miniflare/core": "2.14.4", + "@miniflare/shared": "2.14.4", + "undici": "5.28.4", + "ws": "^8.2.2" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.101.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.101.0.tgz", + "integrity": "sha512-nuFhqlUzJX+gVIPPfuE6xurd4lST3mdcWOhyK/rZO0B9XWMKm79SuszIQEnSMmmDhq1DC8WWVYGVd+6F93o1gQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/dumper/node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@poppinss/dumper/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.53.tgz", + "integrity": "sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.53.tgz", + "integrity": "sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.53.tgz", + "integrity": "sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.53.tgz", + "integrity": "sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.53.tgz", + "integrity": "sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.53.tgz", + "integrity": "sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.53.tgz", + "integrity": "sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.53.tgz", + "integrity": "sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.53.tgz", + "integrity": "sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.53.tgz", + "integrity": "sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.53.tgz", + "integrity": "sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.53.tgz", + "integrity": "sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.53.tgz", + "integrity": "sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", + "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.47", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.47.tgz", + "integrity": "sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.14.tgz", + "integrity": "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz", + "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz", + "integrity": "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/type-utils": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.52.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.52.0.tgz", + "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.52.0", + "@typescript-eslint/types": "^8.52.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz", + "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz", + "integrity": "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.52.0.tgz", + "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.52.0", + "@typescript-eslint/tsconfig-utils": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.52.0.tgz", + "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.52.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/babel-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", + "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.2.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.13.tgz", + "integrity": "sha512-WhtvB2NG2wjr04+h77sg3klAIwrgOqnjS49GGudnUPGFFgg7G17y7Qecqp+2Dr5kUDxNRBca0SK7cG8JwzkWDQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/birpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builtins": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", + "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001763", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001763.tgz", + "integrity": "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/core-js-compat": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dts-resolver": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.3.tgz", + "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "29.12.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.12.1.tgz", + "integrity": "sha512-Rxo7r4jSANMBkXLICJKS0gjacgyopfNAsoS0e3R9AHnjoKuQOaaPfmsDJPi8UWwygI099OV/K/JhpYRVkxD4AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, + "engines": { + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-n": { + "version": "17.23.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz", + "integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.0", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "globrex": "^0.1.2", + "ignore": "^5.3.2", + "semver": "^7.6.3", + "ts-declaration-location": "^1.0.6" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": ">=8.23.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "node": ">=6.9.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, + "license": "ISC", "engines": { - "node": ">=8" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "resolve-pkg-maps": "^1.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.25.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", - "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001733", - "electron-to-chromium": "^1.5.199", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" + "function-bind": "^1.1.2" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">= 0.4" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">= 6" + "node": "*" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true, - "dependencies": { - "node-int64": "^0.4.0" + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-rewriter-wasm": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/html-rewriter-wasm/-/html-rewriter-wasm-0.4.1.tgz", + "integrity": "sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/builtins": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", + "node_modules/import-without-cache": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/import-without-cache/-/import-without-cache-0.2.5.tgz", + "integrity": "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==", "dev": true, - "dependencies": { - "semver": "^7.0.0" + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/builtins/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.8.19" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/iron-webcrypto": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-2.0.0.tgz", + "integrity": "sha512-rtffZKDUHciZElM8mjFCufBC7nVhCxHYyWHESqs89OioEDz4parOofd8/uhrejh/INhQFfYQfByS22LlezR9sQ==", + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "uint8array-extras": "^1.5.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/sponsors/brc-dd" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -1851,669 +7063,1001 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001735", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", - "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.12.0" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } + "license": "ISC" }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=8" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "color-name": "~1.1.4" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "delayed-stream": "~1.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", - "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" }, "bin": { - "create-jest": "bin/create-jest.js" + "jest": "bin/jest.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "node_modules/jest-changed-files": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", "dev": true, + "license": "MIT", "dependencies": { - "node-fetch": "^2.7.0" + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "node_modules/jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=6.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "node-notifier": { "optional": true } } }, - "node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "node_modules/jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { - "babel-plugin-macros": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { "optional": true } } }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, "engines": { - "node": ">=0.4.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" + }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "node_modules/jest-environment-miniflare": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/jest-environment-miniflare/-/jest-environment-miniflare-2.14.4.tgz", + "integrity": "sha512-r5OtP6seAotjWmB10jNfr6UUf9n55Bsr4DHLkXX+7bq1bguTI3m+eNIY+rPE4/fqUoCSEMKAYhLi+JauGGsboA==", + "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", "dev": true, + "license": "MIT", "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" + "@jest/environment": ">=27", + "@jest/fake-timers": ">=27", + "@jest/types": ">=27", + "@miniflare/queues": "2.14.4", + "@miniflare/runner-vm": "2.14.4", + "@miniflare/shared": "2.14.4", + "@miniflare/shared-test-environment": "2.14.4", + "jest-mock": ">=27", + "jest-util": ">=27" + }, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "jest": ">=27" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + }, "engines": { - "node": ">=0.3.1" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-fetch-mock": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", + "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.0.4", + "promise-polyfill": "^8.1.3" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "node_modules/jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.202", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.202.tgz", - "integrity": "sha512-NxbYjRmiHcHXV1Ws3fWUW+SLb62isauajk45LUJ/HgIOkUA7jLZu/X2Iif+X9FBNK8QkF9Zb4Q2mcwXCcY30mg==", - "dev": true + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + }, "engines": { - "node": ">=12" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", "dev": true, + "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/jest-runtime/node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, "engines": { - "node": ">=6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">=4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + }, "engines": { - "node": ">= 0.8.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "bser": "2.1.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/jose": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", + "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": ">= 6" + "node": ">=6" } }, - "node_modules/formidable": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz", - "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { - "@paralleldrive/cuid2": "^2.2.2", - "dezalgo": "^1.0.4", - "once": "^1.4.0", - "qs": "^6.11.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" + "json-buffer": "3.0.1" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=6" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">= 0.8.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=8.0.0" + "node": "20 || >=22" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, "engines": { "node": ">=10" }, @@ -2521,1559 +8065,1501 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "tmpl": "1.0.5" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" + "node_modules/marked": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", + "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 16" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/marked-terminal": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", + "integrity": "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "ansi-regex": "^6.1.0", + "chalk": "^5.4.1", + "cli-highlight": "^2.1.11", + "cli-table3": "^0.6.5", + "node-emoji": "^2.2.0", + "supports-hyperlinks": "^3.1.0" + }, "engines": { - "node": ">=8" + "node": ">=16.0.0" + }, + "peerDependencies": { + "marked": ">=1 <16" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8.6" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-rewriter-wasm": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/html-rewriter-wasm/-/html-rewriter-wasm-0.4.1.tgz", - "integrity": "sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==", - "dev": true - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true - }, - "node_modules/human-signals": { + "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.17.0" + "node": ">=6" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/miniflare": { + "version": "4.20260107.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260107.0.tgz", + "integrity": "sha512-X93sXczqbBq9ixoM6jnesmdTqp+4baVC/aM/DuPpRS0LK0XtcqaO75qPzNEvDEzBAHxwMAWRIum/9hg32YB8iA==", "dev": true, + "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "sharp": "^0.33.5", + "stoppable": "1.1.0", + "undici": "7.14.0", + "workerd": "1.20260107.1", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "^3.25.76" }, "bin": { - "import-local-fixture": "fixtures/cli.js" + "miniflare": "bootstrap.js" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.0.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/miniflare/node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=0.8.19" + "node": ">=0.4.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/miniflare/node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "license": "MIT", + "engines": { + "node": ">=20.18.1" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/iron-session": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/iron-session/-/iron-session-6.3.1.tgz", - "integrity": "sha512-3UJ7y2vk/WomAtEySmPgM6qtYF1cZ3tXuWX5GsVX4PJXAcs5y/sV9HuSfpjKS6HkTL/OhZcTDWJNLZ7w+Erx3A==", - "dependencies": { - "@peculiar/webcrypto": "^1.4.0", - "@types/cookie": "^0.5.1", - "@types/express": "^4.17.13", - "@types/koa": "^2.13.5", - "@types/node": "^17.0.41", - "cookie": "^0.5.0", - "iron-webcrypto": "^0.2.5" - }, + "node_modules/miniflare/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10.0.0" }, "peerDependencies": { - "express": ">=4", - "koa": ">=2", - "next": ">=10" + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { - "express": { - "optional": true - }, - "koa": { + "bufferutil": { "optional": true }, - "next": { + "utf-8-validate": { "optional": true } } }, - "node_modules/iron-session/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" - }, - "node_modules/iron-webcrypto": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-0.2.8.tgz", - "integrity": "sha512-YPdCvjFMOBjXaYuDj5tiHst5CEk6Xw84Jo8Y2+jzhMceclAnb3+vNPP/CTtb5fO2ZEuXEaO4N+w62Vfko757KA==", - "dependencies": { - "buffer": "^6" - }, - "funding": { - "url": "https://github.com/sponsors/brc-dd" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "hasown": "^2.0.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, - "engines": { - "node": ">=0.12.0" + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/napi-postinstall" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=10" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-source-maps": { + "node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "path-key": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "node_modules/npx-import": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/npx-import/-/npx-import-1.1.4.tgz", + "integrity": "sha512-3ShymTWOgqGyNlh5lMJAejLuIv3W1K3fbI5Ewc6YErZU3Sp0PqsNs8UIU1O8z5+KVl/Du5ag56Gza9vdorGEoA==", "dev": true, + "license": "ISC", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" + "execa": "^6.1.0", + "parse-package-name": "^1.0.0", + "semver": "^7.3.7", + "validate-npm-package-name": "^4.0.0" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/npx-import/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "node_modules/npx-import/node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", "dev": true, - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, + "license": "Apache-2.0", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.20.0" } }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "node_modules/npx-import/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npx-import/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "node_modules/npx-import/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "path-key": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "node_modules/npx-import/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "mimic-fn": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npx-import/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/npx-import/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/npx-import/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npx-import/node_modules/validate-npm-package-name": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", + "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", "dev": true, + "license": "ISC", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "builtins": "^5.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "wrappy": "1" } }, - "node_modules/jest-environment-miniflare": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/jest-environment-miniflare/-/jest-environment-miniflare-2.14.4.tgz", - "integrity": "sha512-r5OtP6seAotjWmB10jNfr6UUf9n55Bsr4DHLkXX+7bq1bguTI3m+eNIY+rPE4/fqUoCSEMKAYhLi+JauGGsboA==", - "deprecated": "Miniflare v2 is no longer supported. Please upgrade to Miniflare v4", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": ">=27", - "@jest/fake-timers": ">=27", - "@jest/types": ">=27", - "@miniflare/queues": "2.14.4", - "@miniflare/runner-vm": "2.14.4", - "@miniflare/shared": "2.14.4", - "@miniflare/shared-test-environment": "2.14.4", - "jest-mock": ">=27", - "jest-util": ">=27" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=16.13" + "node": ">=6" }, - "peerDependencies": { - "jest": ">=27" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8.0" } }, - "node_modules/jest-fetch-mock": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", - "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { - "cross-fetch": "^3.0.4", - "promise-polyfill": "^8.1.3" + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" + "p-try": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "callsites": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "node_modules/parse-package-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-package-name/-/parse-package-name-1.0.0.tgz", + "integrity": "sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "parse5": "^6.0.1" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } + "license": "MIT" }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "node": ">=16 || 14 >=14.18" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/prettier": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jose": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.6.3.tgz", - "integrity": "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==", - "funding": { - "url": "https://github.com/sponsors/panva" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/promise-polyfill": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", + "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } + "license": "MIT" }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/leb": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/leb/-/leb-1.0.0.tgz", - "integrity": "sha512-Y3c3QZfvKWHX60BVOQPhLCvVGmDYWyJEiINE3drOog6KCyN2AOwvuQQzlS3uJg1J85kzpILXIUwRXULWavir+w==" + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "yallist": "^3.0.2" + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, "bin": { - "semver": "bin/semver.js" + "resolve": "bin/resolve" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { - "tmpl": "1.0.5" + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "engines": { - "node": ">= 0.6" + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/rolldown": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.53.tgz", + "integrity": "sha512-Qd9c2p0XKZdgT5AYd+KgAMggJ8ZmCs3JnS9PTMWkyUfteKlfmKtxJbWTHkVakxwXs1Ub7jrRYVeFeF7N0sQxyw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@oxc-project/types": "=0.101.0", + "@rolldown/pluginutils": "1.0.0-beta.53" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.53", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.53", + "@rolldown/binding-darwin-x64": "1.0.0-beta.53", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.53", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.53", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.53", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.53", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.53", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.53", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.53", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.53", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.53", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.53" + } + }, + "node_modules/rolldown-plugin-dts": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.18.4.tgz", + "integrity": "sha512-7UpdiICFd/BhdjKtDPeakCFRk6pbkTGFe0Z6u01egt4c8aoO+JoPGF1Smc+JRuCH2s5j5hBdteBi0e10G0xQdQ==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "@babel/generator": "^7.28.5", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "ast-kit": "^2.2.0", + "birpc": "^4.0.0", + "dts-resolver": "^2.1.3", + "get-tsconfig": "^4.13.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" }, - "engines": { - "node": ">=8.6" + "peerDependencies": { + "@ts-macro/tsc": "^0.3.6", + "@typescript/native-preview": ">=7.0.0-dev.20250601.1", + "rolldown": "^1.0.0-beta.51", + "typescript": "^5.0.0", + "vue-tsc": "~3.1.0" + }, + "peerDependenciesMeta": { + "@ts-macro/tsc": { + "optional": true + }, + "@typescript/native-preview": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } } }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, + "license": "ISC", "bin": { - "mime": "cli.js" + "semver": "bin/semver.js" }, "engines": { - "node": ">=4.0.0" + "node": ">=10" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "dev": true, - "engines": { - "node": ">= 0.6" - } + "license": "MIT" }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "mime-db": "1.52.0" + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" }, "engines": { - "node": ">= 0.6" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", "dev": true, + "license": "MIT", "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "is-arrayish": "^0.3.1" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "dev": true, + "license": "MIT" }, - "node_modules/nock": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", - "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" + "unicode-emoji-modifier-base": "^1.0.0" }, "engines": { - "node": ">= 10.13" + "node": ">=8" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, + "license": "MIT", "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=8" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/npx-import": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/npx-import/-/npx-import-1.1.4.tgz", - "integrity": "sha512-3ShymTWOgqGyNlh5lMJAejLuIv3W1K3fbI5Ewc6YErZU3Sp0PqsNs8UIU1O8z5+KVl/Du5ag56Gza9vdorGEoA==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, - "dependencies": { - "execa": "^6.1.0", - "parse-package-name": "^1.0.0", - "semver": "^7.3.7", - "validate-npm-package-name": "^4.0.0" - } + "license": "BSD-3-Clause" }, - "node_modules/npx-import/node_modules/execa": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=10" } }, - "node_modules/npx-import/node_modules/human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12.20.0" + "node": ">=8" } }, - "node_modules/npx-import/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4", + "npm": ">=6" } }, - "node_modules/npx-import/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10.0.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/npx-import/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/npx-import/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/npx-import/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/npx-import/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/npx-import/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "wrappy": "1" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4081,874 +9567,987 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-package-name": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-package-name/-/parse-package-name-1.0.0.tgz", - "integrity": "sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, "engines": { - "node": ">=8.6" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://opencollective.com/synckit" } }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { - "find-up": "^4.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=10.13.0" + "node": "*" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" } }, - "node_modules/promise-polyfill": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", - "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", - "dev": true - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dev": true, + "license": "MIT", "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "thenify": ">= 3.1.0 < 4" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/prompts/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" + "node": ">=0.8" } }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/pvtsutils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", - "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", - "dependencies": { - "tslib": "^2.8.1" - } - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "side-channel": "^1.1.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=0.6" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, + "license": "MIT", + "peer": true, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=8.0" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, - "engines": { - "node": ">=10" + "license": "MIT", + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/ts-declaration-location": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz", + "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==", "dev": true, + "funding": [ + { + "type": "ko-fi", + "url": "https://ko-fi.com/rebeccastevens" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/ts-declaration-location" + } + ], + "license": "BSD-3-Clause", "dependencies": { - "shebang-regex": "^3.0.0" + "picomatch": "^4.0.2" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "typescript": ">=4.0.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/ts-declaration-location/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/ts-jest": { + "version": "29.4.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.4.tgz", + "integrity": "sha512-ccVcRABct5ZELCT5U0+DZwkXMCcOCLi2doHRrKy1nK/s7J7bch6TzJMsrY09WxgUUIP/ITfmcDS8D2yl63rnXw==", + "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.2", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">= 0.4" + "node": ">=16" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/tsdown": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.17.2.tgz", + "integrity": "sha512-SuU+0CWm/95KfXqojHTVuwcouIsdn7HpYcwDyOdKktJi285NxKwysjFUaxYLxpCNqqPvcFvokXLO4dZThRwzkw==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "ansis": "^4.2.0", + "cac": "^6.7.14", + "empathic": "^2.0.0", + "hookable": "^5.5.3", + "import-without-cache": "^0.2.2", + "obug": "^2.1.1", + "rolldown": "1.0.0-beta.53", + "rolldown-plugin-dts": "^0.18.3", + "semver": "^7.7.3", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tree-kill": "^1.2.2", + "unconfig-core": "^7.4.2", + "unrun": "^0.2.19" }, - "engines": { - "node": ">= 0.4" + "bin": { + "tsdown": "dist/run.mjs" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "engines": { - "node": ">=8" + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@arethetypeswrong/core": "^0.18.1", + "@vitejs/devtools": "^0.0.0-alpha.19", + "publint": "^0.3.0", + "typescript": "^5.0.0", + "unplugin-lightningcss": "^0.4.0", + "unplugin-unused": "^0.5.0" + }, + "peerDependenciesMeta": { + "@arethetypeswrong/core": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "publint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "unplugin-lightningcss": { + "optional": true + }, + "unplugin-unused": { + "optional": true + } } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "0BSD", + "optional": true }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, + "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=4" } }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=8" + "node": ">=14.17" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/typescript-eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.52.0.tgz", + "integrity": "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "@typescript-eslint/eslint-plugin": "8.52.0", + "@typescript-eslint/parser": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/unconfig-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.2.tgz", + "integrity": "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/superagent": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", - "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", - "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dev": true, + "license": "MIT", "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" + "@fastify/busboy": "^2.0.0" }, "engines": { - "node": ">=6.4.0 <13 || >=14" + "node": ">=14.0" } }, - "node_modules/superagent/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/supertest": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", - "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", - "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net", + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^8.0.5" - }, + "license": "MIT", "engines": { - "node": ">=6.4.0" + "node": ">=4" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "dev": true, + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "napi-postinstall": "^0.3.0" }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/ts-jest": { - "version": "29.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.3.tgz", - "integrity": "sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==", + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/unrun": { + "version": "0.2.24", + "resolved": "https://registry.npmjs.org/unrun/-/unrun-0.2.24.tgz", + "integrity": "sha512-xa4/O5q2jmI6EqxweJ+sOy5cyORZWcsgmi8pmABVSUyg24Fh44qJrneUHavZEMsbJbghHYWKSraFy5hDCb/m4w==", "dev": true, + "license": "MIT", "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "rolldown": "1.0.0-beta.59" }, "bin": { - "ts-jest": "cli.js" + "unrun": "dist/cli.mjs" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/Gugustinette" }, "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" + "synckit": "^0.11.11" }, "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { + "synckit": { "optional": true } } }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/unrun/node_modules/@oxc-project/types": { + "version": "0.107.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.107.0.tgz", + "integrity": "sha512-QFDRbYfV2LVx8tyqtyiah3jQPUj1mK2+RYwxyFWyGoys6XJnwTdlzO6rdNNHOPorHAu5Uo34oWRKcvNpbJarmQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.59.tgz", + "integrity": "sha512-6yLLgyswYwiCfls9+hoNFY9F8TQdwo15hpXDHzlAR0X/GojeKF+AuNcXjYNbOJ4zjl/5D6lliE8CbpB5t1OWIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.59.tgz", + "integrity": "sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "node_modules/unrun/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.59.tgz", + "integrity": "sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/unrun/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.59.tgz", + "integrity": "sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=4" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/unrun/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.59.tgz", + "integrity": "sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/unrun/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.59.tgz", + "integrity": "sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "color-name": "1.1.3" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/tslint/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/unrun/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.59.tgz", + "integrity": "sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.8.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/unrun/node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.59.tgz", + "integrity": "sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/unrun/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.59.tgz", + "integrity": "sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==", + "cpu": [ + "x64" + ], "dev": true, - "bin": { - "semver": "bin/semver" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/unrun/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.59.tgz", + "integrity": "sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=4" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/tslint/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/unrun/node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.59.tgz", + "integrity": "sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==", + "cpu": [ + "wasm32" + ], "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "tslib": "^1.8.1" + "@napi-rs/wasm-runtime": "^1.1.1" }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/unrun/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.59.tgz", + "integrity": "sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/unrun/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.59.tgz", + "integrity": "sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "node_modules/unrun/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.59.tgz", + "integrity": "sha512-aoh6LAJRyhtazs98ydgpNOYstxUlsOV1KJXcpf/0c0vFcUA8uyd/hwKRhqE/AAPNqAho9RliGsvitCoOzREoVA==", "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } + "license": "MIT" }, - "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "node_modules/unrun/node_modules/rolldown": { + "version": "1.0.0-beta.59", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.59.tgz", + "integrity": "sha512-Slm000Gd8/AO9z4Kxl4r8mp/iakrbAuJ1L+7ddpkNxgQ+Vf37WPvY63l3oeyZcfuPD1DRrUYBsRPIXSOhvOsmw==", "dev": true, + "license": "MIT", "dependencies": { - "@fastify/busboy": "^2.0.0" + "@oxc-project/types": "=0.107.0", + "@rolldown/pluginutils": "1.0.0-beta.59" + }, + "bin": { + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=14.0" + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.59", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.59", + "@rolldown/binding-darwin-x64": "1.0.0-beta.59", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.59", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.59", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.59", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.59", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.59", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.59", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.59", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.59", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.59", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.59" } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -4964,6 +10563,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -4975,17 +10575,29 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/urlpattern-polyfill": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-4.0.3.tgz", "integrity": "sha512-DOE84vZT2fEcl9gqCUTcnAw5ZY5Id55ikUcziSUntuEFL3pRvavg5kwDmTEUJkeCHInTlV/HexFomgYnzO5kdQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -4996,15 +10608,13 @@ } }, "node_modules/validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, - "dependencies": { - "builtins": "^5.0.0" - }, + "license": "ISC", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/walker": { @@ -5012,33 +10622,24 @@ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } }, - "node_modules/webcrypto-core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz", - "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.13", - "@peculiar/json-schema": "^1.1.12", - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.5", - "tslib": "^2.7.0" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -5049,6 +10650,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -5059,11 +10661,69 @@ "node": ">= 8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/workerd": { + "version": "1.20260107.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260107.1.tgz", + "integrity": "sha512-4ylAQJDdJZdMAUl2SbJgTa77YHpa88l6qmhiuCLNactP933+rifs7I0w1DslhUIFgydArUX5dNLAZnZhT7Bh7g==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260107.1", + "@cloudflare/workerd-darwin-arm64": "1.20260107.1", + "@cloudflare/workerd-linux-64": "1.20260107.1", + "@cloudflare/workerd-linux-arm64": "1.20260107.1", + "@cloudflare/workerd-windows-64": "1.20260107.1" + } + }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5076,30 +10736,94 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -5121,6 +10845,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -5129,13 +10854,15 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -5154,6 +10881,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -5163,12 +10891,48 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 57500f6eb..29b0387fd 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "7.82.0", + "version": "8.0.0-rc.10", "name": "@workos-inc/node", "author": "WorkOS", "description": "A Node wrapper for the WorkOS API", @@ -9,11 +9,15 @@ "workos" ], "engines": { - "node": ">=16" + "node": ">=20.15.0" }, - "typings": "lib/index.d.ts", + "type": "module", + "main": "./lib/index.cjs", + "module": "./lib/index.js", + "types": "./lib/index.d.ts", "files": [ - "lib/" + "lib/", + "package.json" ], "repository": { "type": "git", @@ -24,52 +28,93 @@ }, "scripts": { "clean": "rm -rf lib", - "build": "tsc -p .", - "lint": "tslint -p tsconfig.json -c tslint.json", + "build": "tsdown", + "build:watch": "tsdown --watch", + "lint": "eslint", "test": "jest", "test:watch": "jest --watch", - "test:worker": "jest src/worker.spec.ts", + "check:runtimes": "tsx scripts/ecosystem-check.ts", + "check:types": "attw --pack . --ignore-rules no-resolution", "prettier": "prettier \"src/**/*.{js,ts,tsx}\" --check", "format": "prettier \"src/**/*.{js,ts,tsx}\" --write", - "prepublishOnly": "npm run build" + "prepublishOnly": "npm run build", + "typecheck": "tsc --noEmit" }, "dependencies": { - "iron-session": "~6.3.1", - "jose": "~5.6.3", - "leb": "^1.0.0", - "qs": "6.14.1" + "iron-webcrypto": "^2.0.0", + "jose": "~6.1.0" }, "devDependencies": { - "@peculiar/webcrypto": "^1.4.5", - "@types/jest": "29.5.14", - "@types/node": "14.18.54", - "jest": "29.7.0", + "@arethetypeswrong/cli": "^0.18.2", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/preset-env": "^7.26.9", + "@babel/preset-typescript": "^7.27.0", + "@eslint/js": "^9.37.0", + "@types/jest": "^30.0.0", + "@types/node": "~20", + "@typescript-eslint/parser": "^8.46.0", + "babel-jest": "^30.2.0", + "eslint": "^9.37.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-n": "^17.23.1", + "jest": "30.2.0", "jest-environment-miniflare": "^2.14.2", "jest-fetch-mock": "^3.0.3", - "nock": "^13.5.5", - "prettier": "2.8.8", - "supertest": "6.3.3", - "ts-jest": "29.1.3", - "tslint": "6.1.3", - "typescript": "5.1.6" + "miniflare": "^4.20251004.0", + "prettier": "^3.5.3", + "ts-jest": "29.4.4", + "tsdown": "^0.17.0", + "tsx": "^4.20.6", + "typescript": "5.9.3", + "typescript-eslint": "^8.46.0" }, "exports": { - "types": "./lib/index.d.ts", - "workerd": { - "import": "./lib/index.worker.js", - "default": "./lib/index.worker.js" - }, - "edge-light": { - "import": "./lib/index.worker.js", - "default": "./lib/index.worker.js" + ".": { + "workerd": { + "types": "./lib/index.worker.d.ts", + "import": "./lib/index.worker.js", + "require": "./lib/index.worker.cjs" + }, + "edge-light": { + "types": "./lib/index.worker.d.ts", + "import": "./lib/index.worker.js", + "require": "./lib/index.worker.cjs" + }, + "deno": { + "types": "./lib/index.d.ts", + "default": "./lib/index.js" + }, + "bun": { + "types": "./lib/index.d.ts", + "import": "./lib/index.js", + "require": "./lib/index.cjs" + }, + "convex": { + "types": "./lib/index.worker.d.ts", + "import": "./lib/index.worker.js", + "default": "./lib/index.worker.cjs" + }, + "import": { + "types": "./lib/index.d.ts", + "default": "./lib/index.js" + }, + "require": { + "types": "./lib/index.d.cts", + "default": "./lib/index.cjs" + }, + "default": "./lib/index.js" }, - "convex": { - "import": "./lib/index.worker.js", + "./worker": { + "import": { + "types": "./lib/index.worker.d.ts", + "default": "./lib/index.worker.js" + }, + "require": { + "types": "./lib/index.worker.d.cts", + "default": "./lib/index.worker.cjs" + }, "default": "./lib/index.worker.js" }, - "default": { - "import": "./lib/index.js", - "default": "./lib/index.js" - } + "./package.json": "./package.json" } } diff --git a/scripts/ecosystem-check.ts b/scripts/ecosystem-check.ts new file mode 100644 index 000000000..32991007d --- /dev/null +++ b/scripts/ecosystem-check.ts @@ -0,0 +1,141 @@ +// scripts/ecosystem-check.ts +import { spawnSync } from 'node:child_process'; +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import os from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const root = join(__dirname, '..'); +const lib = join(root, 'lib'); +const tmp = mkdtempSync(join(os.tmpdir(), 'workos-test-')); + +// Map of "runtime label" → { cmd, args } +const tests: Record = { + 'node-cjs': { + cmd: 'node', + args: [ + '-e', + `console.log('✅ Node CJS:', require("${lib}/index.cjs").WorkOS.name)`, + ], + }, + 'node-esm': { + cmd: 'node', + args: [ + '-e', + `import("${lib}/index.js").then(m => console.log('✅ Node ESM:', m.WorkOS.name))`, + ], + }, + deno: { + cmd: 'deno', + args: [ + 'eval', + `import("${lib}/index.js").then(m => console.log('✅ Deno:', m.WorkOS.name))`, + ], + }, + 'bun-cjs': { + cmd: 'bun', + args: [ + '-e', + `console.log('✅ Bun CJS:', require("${lib}/index.cjs").WorkOS.name)`, + ], + }, + 'bun-esm': { + cmd: 'bun', + args: [ + '-e', + `import("${lib}/index.js").then(m => console.log('✅ Bun ESM:', m.WorkOS.name))`, + ], + }, +}; + +let allOK = true; +let ranTests = 0; + +console.log('🚀 Running WorkOS SDK ecosystem compatibility checks...\n'); + +// Run basic runtime tests +for (const [name, { cmd, args }] of Object.entries(tests)) { + process.stdout.write(`Testing ${name.padEnd(12)}... `); + + const { status, stderr } = spawnSync(cmd, args, { + stdio: ['inherit', 'pipe', 'pipe'], + encoding: 'utf8', + }); + + if (status !== 0) { + allOK = false; + console.error(`❌ Failed`); + if (stderr) { + console.error(` Error: ${stderr.trim()}`); + } + } else { + ranTests++; + console.log(`✅ Passed`); + } +} + +// Test Cloudflare Worker environment using miniflare +process.stdout.write(`Testing worker ... `); + +// 1. Check if miniflare is available +const miniflareCheck = spawnSync('npx', ['miniflare', '--version'], { + stdio: 'ignore', // We don't need to see the version output + encoding: 'utf8', +}); + +if (miniflareCheck.status !== 0) { + console.log(`⚠️ Skipped (miniflare not found or failed to execute)`); +} else { + // 2. Create the temporary worker script + const workerScriptPath = join(tmp, 'worker-test.js'); + const safeLibPath = lib.replace(/\\/g, '\\\\'); // For Windows compatibility + + const workerScriptContent = ` +import { WorkOS } from '${safeLibPath}/index.worker.js'; + +if (WorkOS && WorkOS.name === 'WorkOS') { + console.log('✅ Worker (miniflare): SDK imported successfully.'); +} else { + console.error('❌ Worker (miniflare): SDK import failed or WorkOS class is incorrect.'); + process.exit(1); +} +`; + + writeFileSync(workerScriptPath, workerScriptContent); + + // 3. Execute the worker script with miniflare + const { status, stderr } = spawnSync( + 'npx', + ['miniflare', '--modules', workerScriptPath], + { + stdio: ['inherit', 'pipe', 'pipe'], + encoding: 'utf8', + }, + ); + + // 4. Process the result + if (status !== 0) { + allOK = false; + console.error(`❌ Failed`); + if (stderr) { + console.error(` Error: ${stderr.trim()}`); + } + } else { + ranTests++; + console.log(`✅ Passed`); + } +} + +// Cleanup +rmSync(tmp, { recursive: true, force: true }); + +console.log(`\n📊 Results: ${ranTests} runtime tests completed`); + +if (allOK) { + console.log('🎉 All core runtime compatibility checks passed!'); +} else { + console.log('💥 Some runtime tests failed. Check the output above.'); + throw new Error('Ecosystem compatibility checks failed'); +} diff --git a/setup-jest.ts b/setup-jest.ts index eeebd42ef..019680cb6 100644 --- a/setup-jest.ts +++ b/setup-jest.ts @@ -1,16 +1,9 @@ import { enableFetchMocks } from 'jest-fetch-mock'; -import { Crypto } from '@peculiar/webcrypto'; -import { WorkOS } from './src/workos'; -import { WebIronSessionProvider } from './src/common/iron-session/web-iron-session-provider'; +import { webcrypto } from 'crypto'; enableFetchMocks(); -// Assign Node's Crypto to global.crypto if it is not already present +// Make Node's crypto.webcrypto available as global.crypto for tests if (!global.crypto) { - global.crypto = new Crypto(); + global.crypto = webcrypto as unknown as Crypto; } - -// For tests, we can use the WebIronSessionProvider -WorkOS.prototype.createIronSessionProvider = jest - .fn() - .mockReturnValue(new WebIronSessionProvider()); diff --git a/src/actions/actions.spec.ts b/src/actions/actions.spec.ts index 3035d580b..79abde396 100644 --- a/src/actions/actions.spec.ts +++ b/src/actions/actions.spec.ts @@ -2,7 +2,7 @@ import crypto from 'crypto'; import { WorkOS } from '../workos'; import mockAuthActionContext from './fixtures/authentication-action-context.json'; import mockUserRegistrationActionContext from './fixtures/user-registration-action-context.json'; -import { NodeCryptoProvider } from '../common/crypto/node-crypto-provider'; +import { SubtleCryptoProvider } from '../common/crypto/subtle-crypto-provider'; const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); @@ -27,7 +27,7 @@ describe('Actions', () => { describe('signResponse', () => { describe('type: authentication', () => { it('returns a signed response', async () => { - const nodeCryptoProvider = new NodeCryptoProvider(); + const nodeCryptoProvider = new SubtleCryptoProvider(); const response = await workos.actions.signResponse( { @@ -55,7 +55,7 @@ describe('Actions', () => { describe('type: user_registration', () => { it('returns a signed response', async () => { - const nodeCryptoProvider = new NodeCryptoProvider(); + const nodeCryptoProvider = new SubtleCryptoProvider(); const response = await workos.actions.signResponse( { diff --git a/src/api-keys/interfaces/create-organization-api-key-options.interface.ts b/src/api-keys/interfaces/create-organization-api-key-options.interface.ts index f2164c0a7..2482fb735 100644 --- a/src/api-keys/interfaces/create-organization-api-key-options.interface.ts +++ b/src/api-keys/interfaces/create-organization-api-key-options.interface.ts @@ -11,5 +11,8 @@ export interface SerializedCreateOrganizationApiKeyOptions { permissions?: string[]; } -export interface CreateOrganizationApiKeyRequestOptions - extends Pick {} +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface CreateOrganizationApiKeyRequestOptions extends Pick< + PostOptions, + 'idempotencyKey' +> {} diff --git a/src/audit-logs/audit-logs.spec.ts b/src/audit-logs/audit-logs.spec.ts index 9d2303884..d34aab05e 100644 --- a/src/audit-logs/audit-logs.spec.ts +++ b/src/audit-logs/audit-logs.spec.ts @@ -17,7 +17,6 @@ import { serializeCreateAuditLogEventOptions, serializeCreateAuditLogSchemaOptions, } from './serializers'; -import { FetchError } from '../common/utils/fetch-error'; const event: CreateAuditLogEventOptions = { action: 'document.updated', @@ -174,18 +173,14 @@ describe('AuditLogs', () => { const workosSpy = jest.spyOn(WorkOS.prototype, 'post'); workosSpy.mockImplementationOnce(() => { - throw new FetchError({ - message: - 'Could not authorize the request. Maybe your API key is invalid?', - response: { status: 401, headers: new Headers(), data: {} }, - }); + throw new UnauthorizedException('a-request-id'); }); const workos = new WorkOS('invalid apikey'); await expect( workos.auditLogs.createEvent('org_123', event), - ).rejects.toThrowError(new UnauthorizedException('a-request-id')); + ).rejects.toThrow(UnauthorizedException); }); }); @@ -222,6 +217,11 @@ describe('AuditLogs', () => { beforeEach(() => { fetch.resetMocks(); jest.clearAllMocks(); + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); }); it('retries on 500 status code and eventually succeeds', async () => { @@ -233,9 +233,9 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await expect( - workos.auditLogs.createEvent('org_123', event), - ).resolves.toBeUndefined(); + const promise = workos.auditLogs.createEvent('org_123', event); + await jest.runAllTimersAsync(); + await expect(promise).resolves.toBeUndefined(); expect(fetch).toHaveBeenCalledTimes(3); }); @@ -249,9 +249,9 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await expect( - workos.auditLogs.createEvent('org_123', event), - ).resolves.toBeUndefined(); + const promise = workos.auditLogs.createEvent('org_123', event); + await jest.runAllTimersAsync(); + await expect(promise).resolves.toBeUndefined(); expect(fetch).toHaveBeenCalledTimes(3); }); @@ -265,9 +265,9 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await expect( - workos.auditLogs.createEvent('org_123', event), - ).resolves.toBeUndefined(); + const promise = workos.auditLogs.createEvent('org_123', event); + await jest.runAllTimersAsync(); + await expect(promise).resolves.toBeUndefined(); expect(fetch).toHaveBeenCalledTimes(3); }); @@ -281,9 +281,9 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await expect( - workos.auditLogs.createEvent('org_123', event), - ).resolves.toBeUndefined(); + const promise = workos.auditLogs.createEvent('org_123', event); + await jest.runAllTimersAsync(); + await expect(promise).resolves.toBeUndefined(); expect(fetch).toHaveBeenCalledTimes(3); }); @@ -298,12 +298,12 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await expect( - workos.auditLogs.createEvent('org_123', event), - ).resolves.toBeUndefined(); + const promise = workos.auditLogs.createEvent('org_123', event); + await jest.runAllTimersAsync(); + await expect(promise).resolves.toBeUndefined(); expect(fetch).toHaveBeenCalledTimes(4); - }, 10000); + }); it('retries a maximum of 3 times (4 total attempts)', async () => { fetch.mockResponse(JSON.stringify({ error: 'Internal Server Error' }), { @@ -312,13 +312,17 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await expect( - workos.auditLogs.createEvent('org_123', event), - ).rejects.toThrow(); + const promise = workos.auditLogs + .createEvent('org_123', event) + .catch((e) => e); + await jest.runAllTimersAsync(); + const result = await promise; + + expect(result).toBeInstanceOf(Error); // 1 initial attempt + 3 retries = 4 total attempts expect(fetch).toHaveBeenCalledTimes(4); - }, 10000); + }); it('uses the same idempotency key across all retry attempts', async () => { fetch.mockResponses( @@ -329,9 +333,11 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await workos.auditLogs.createEvent('org_123', event, { + const promise = workos.auditLogs.createEvent('org_123', event, { idempotencyKey: 'test-idempotency-key', }); + await jest.runAllTimersAsync(); + await promise; expect(fetch).toHaveBeenCalledTimes(3); @@ -341,7 +347,7 @@ describe('AuditLogs', () => { const headers = call[1]?.headers as Record; expect(headers['Idempotency-Key']).toBe('test-idempotency-key'); } - }, 10000); + }); it('maintains auto-generated idempotency key across retry attempts', async () => { fetch.mockResponses( @@ -352,7 +358,9 @@ describe('AuditLogs', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - await workos.auditLogs.createEvent('org_123', event); + const promise = workos.auditLogs.createEvent('org_123', event); + await jest.runAllTimersAsync(); + await promise; expect(fetch).toHaveBeenCalledTimes(3); @@ -373,7 +381,7 @@ describe('AuditLogs', () => { // All keys should be the same expect(idempotencyKeys[0]).toBe(idempotencyKeys[1]); expect(idempotencyKeys[1]).toBe(idempotencyKeys[2]); - }, 10000); + }); }); }); @@ -431,7 +439,6 @@ describe('AuditLogs', () => { const options: AuditLogExportOptions = { actions: ['foo', 'bar'], - actors: ['Jon', 'Smith'], actorNames: ['Jon', 'Smith'], actorIds: ['user_foo', 'user_bar'], organizationId: 'org_123', @@ -488,18 +495,14 @@ describe('AuditLogs', () => { }; workosSpy.mockImplementationOnce(() => { - throw new FetchError({ - message: - 'Could not authorize the request. Maybe your API key is invalid?', - response: { status: 401, headers: new Headers(), data: {} }, - }); + throw new UnauthorizedException('a-request-id'); }); const workos = new WorkOS('invalid apikey'); - await expect( - workos.auditLogs.createExport(options), - ).rejects.toThrowError(new UnauthorizedException('a-request-id')); + await expect(workos.auditLogs.createExport(options)).rejects.toThrow( + UnauthorizedException, + ); }); }); }); @@ -550,18 +553,14 @@ describe('AuditLogs', () => { const workosSpy = jest.spyOn(WorkOS.prototype, 'get'); workosSpy.mockImplementationOnce(() => { - throw new FetchError({ - message: - 'Could not authorize the request. Maybe your API key is invalid?', - response: { status: 401, headers: new Headers(), data: {} }, - }); + throw new UnauthorizedException('a-request-id'); }); const workos = new WorkOS('invalid apikey'); await expect( workos.auditLogs.getExport('audit_log_export_1234'), - ).rejects.toThrowError(new UnauthorizedException('a-request-id')); + ).rejects.toThrow(UnauthorizedException); expect(workosSpy).toHaveBeenCalledWith( `/audit_logs/exports/audit_log_export_1234`, diff --git a/src/audit-logs/audit-logs.ts b/src/audit-logs/audit-logs.ts index 5b8acee4e..105d72e4d 100644 --- a/src/audit-logs/audit-logs.ts +++ b/src/audit-logs/audit-logs.ts @@ -35,7 +35,7 @@ export class AuditLogs { ...options, idempotencyKey: options.idempotencyKey || - `workos-node-${this.workos.getCryptoProvider().randomUUID()}`, + `workos-node-${globalThis.crypto.randomUUID()}`, }; await this.workos.post( diff --git a/src/audit-logs/interfaces/audit-log-export-options.interface.ts b/src/audit-logs/interfaces/audit-log-export-options.interface.ts index db5985a76..7c7f22e96 100644 --- a/src/audit-logs/interfaces/audit-log-export-options.interface.ts +++ b/src/audit-logs/interfaces/audit-log-export-options.interface.ts @@ -1,9 +1,5 @@ export interface AuditLogExportOptions { actions?: string[]; - /** - * @deprecated Please use `actorNames` instead. - */ - actors?: string[]; actorNames?: string[]; actorIds?: string[]; organizationId: string; @@ -14,7 +10,6 @@ export interface AuditLogExportOptions { export interface SerializedAuditLogExportOptions { actions?: string[]; - actors?: string[]; actor_names?: string[]; actor_ids?: string[]; organization_id: string; diff --git a/src/audit-logs/serializers/audit-log-export-options.serializer.ts b/src/audit-logs/serializers/audit-log-export-options.serializer.ts index 51f8e6c67..72b011771 100644 --- a/src/audit-logs/serializers/audit-log-export-options.serializer.ts +++ b/src/audit-logs/serializers/audit-log-export-options.serializer.ts @@ -7,7 +7,6 @@ export const serializeAuditLogExportOptions = ( options: AuditLogExportOptions, ): SerializedAuditLogExportOptions => ({ actions: options.actions, - actors: options.actors, actor_names: options.actorNames, actor_ids: options.actorIds, organization_id: options.organizationId, diff --git a/src/common/crypto/crypto-provider.spec.ts b/src/common/crypto/crypto-provider.spec.ts deleted file mode 100644 index c1f36e27c..000000000 --- a/src/common/crypto/crypto-provider.spec.ts +++ /dev/null @@ -1,116 +0,0 @@ -import crypto from 'crypto'; -import { NodeCryptoProvider } from './node-crypto-provider'; -import { SubtleCryptoProvider } from './subtle-crypto-provider'; -import mockWebhook from '../../webhooks/fixtures/webhook.json'; -import { SignatureProvider } from './signature-provider'; - -describe('CryptoProvider', () => { - let payload: any; - let secret: string; - let timestamp: number; - let signatureHash: string; - - beforeEach(() => { - payload = mockWebhook; - secret = 'secret'; - timestamp = Date.now() * 1000; - const unhashedString = `${timestamp}.${JSON.stringify(payload)}`; - signatureHash = crypto - .createHmac('sha256', secret) - .update(unhashedString) - .digest() - .toString('hex'); - }); - - describe('when computing HMAC signature', () => { - it('returns the same for the Node crypto and Web Crypto versions', async () => { - const nodeCryptoProvider = new NodeCryptoProvider(); - const subtleCryptoProvider = new SubtleCryptoProvider(); - - const stringifiedPayload = JSON.stringify(payload); - const payloadHMAC = `${timestamp}.${stringifiedPayload}`; - - const nodeCompare = await nodeCryptoProvider.computeHMACSignatureAsync( - payloadHMAC, - secret, - ); - const subtleCompare = - await subtleCryptoProvider.computeHMACSignatureAsync( - payloadHMAC, - secret, - ); - - expect(nodeCompare).toEqual(subtleCompare); - }); - }); - - describe('when securely comparing', () => { - it('returns the same for the Node crypto and Web Crypto versions', async () => { - const nodeCryptoProvider = new NodeCryptoProvider(); - const subtleCryptoProvider = new SubtleCryptoProvider(); - const signatureProvider = new SignatureProvider(subtleCryptoProvider); - - const signature = await signatureProvider.computeSignature( - timestamp, - payload, - secret, - ); - - expect( - nodeCryptoProvider.secureCompare(signature, signatureHash), - ).toEqual(subtleCryptoProvider.secureCompare(signature, signatureHash)); - - expect(nodeCryptoProvider.secureCompare(signature, 'foo')).toEqual( - subtleCryptoProvider.secureCompare(signature, 'foo'), - ); - }); - }); - - describe('when generating UUIDs', () => { - const UUID_V4_REGEX = - /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; - - it('generates valid UUID v4 format for NodeCryptoProvider', () => { - const nodeCryptoProvider = new NodeCryptoProvider(); - const uuid = nodeCryptoProvider.randomUUID(); - - expect(uuid).toMatch(UUID_V4_REGEX); - }); - - it('generates valid UUID v4 format for SubtleCryptoProvider', () => { - const subtleCryptoProvider = new SubtleCryptoProvider(); - const uuid = subtleCryptoProvider.randomUUID(); - - expect(uuid).toMatch(UUID_V4_REGEX); - }); - - it('generates unique UUIDs', () => { - const nodeCryptoProvider = new NodeCryptoProvider(); - const subtleCryptoProvider = new SubtleCryptoProvider(); - - const uuids = new Set([ - nodeCryptoProvider.randomUUID(), - nodeCryptoProvider.randomUUID(), - subtleCryptoProvider.randomUUID(), - subtleCryptoProvider.randomUUID(), - ]); - - expect(uuids.size).toBe(4); - }); - - it('SubtleCryptoProvider falls back when crypto.randomUUID is unavailable', () => { - const originalRandomUUID = globalThis.crypto.randomUUID; - // @ts-ignore - intentionally removing for test - delete globalThis.crypto.randomUUID; - - try { - const subtleCryptoProvider = new SubtleCryptoProvider(); - const uuid = subtleCryptoProvider.randomUUID(); - - expect(uuid).toMatch(UUID_V4_REGEX); - } finally { - globalThis.crypto.randomUUID = originalRandomUUID; - } - }); - }); -}); diff --git a/src/common/crypto/node-crypto-provider.ts b/src/common/crypto/node-crypto-provider.ts deleted file mode 100644 index 8d639b170..000000000 --- a/src/common/crypto/node-crypto-provider.ts +++ /dev/null @@ -1,103 +0,0 @@ -import * as crypto from 'crypto'; -import { CryptoProvider } from './crypto-provider'; - -/** - * `CryptoProvider which uses the Node `crypto` package for its computations. - */ -export class NodeCryptoProvider extends CryptoProvider { - /** @override */ - computeHMACSignature(payload: string, secret: string): string { - return crypto - .createHmac('sha256', secret) - .update(payload, 'utf8') - .digest('hex'); - } - - /** @override */ - async computeHMACSignatureAsync( - payload: string, - secret: string, - ): Promise { - const signature = this.computeHMACSignature(payload, secret); - return signature; - } - - /** @override */ - async secureCompare(stringA: string, stringB: string): Promise { - const bufferA = this.encoder.encode(stringA); - const bufferB = this.encoder.encode(stringB); - - if (bufferA.length !== bufferB.length) { - return false; - } - - // Generate a random key for HMAC - const key = crypto.randomBytes(32); // Generates a 256-bit key - const hmacA = crypto.createHmac('sha256', key).update(bufferA).digest(); - const hmacB = crypto.createHmac('sha256', key).update(bufferB).digest(); - - // Perform a constant time comparison - return crypto.timingSafeEqual(hmacA, hmacB); - } - - async encrypt( - plaintext: Uint8Array, - key: Uint8Array, - iv?: Uint8Array, - aad?: Uint8Array, - ): Promise<{ - ciphertext: Uint8Array; - iv: Uint8Array; - tag: Uint8Array; - }> { - const actualIv = iv || crypto.randomBytes(32); - const cipher = crypto.createCipheriv('aes-256-gcm', key, actualIv); - - if (aad) { - cipher.setAAD(Buffer.from(aad)); - } - - const ciphertext = Buffer.concat([ - cipher.update(Buffer.from(plaintext)), - cipher.final(), - ]); - - const tag = cipher.getAuthTag(); - - return { - ciphertext: new Uint8Array(ciphertext), - iv: new Uint8Array(actualIv), - tag: new Uint8Array(tag), - }; - } - - async decrypt( - ciphertext: Uint8Array, - key: Uint8Array, - iv: Uint8Array, - tag: Uint8Array, - aad?: Uint8Array, - ): Promise { - const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv); - decipher.setAuthTag(Buffer.from(tag)); - - if (aad) { - decipher.setAAD(Buffer.from(aad)); - } - - const decrypted = Buffer.concat([ - decipher.update(Buffer.from(ciphertext)), - decipher.final(), - ]); - - return new Uint8Array(decrypted); - } - - randomBytes(length: number): Uint8Array { - return new Uint8Array(crypto.randomBytes(length)); - } - - randomUUID(): string { - return crypto.randomUUID(); - } -} diff --git a/src/common/crypto/seal.spec.ts b/src/common/crypto/seal.spec.ts new file mode 100644 index 000000000..eaa4bb3e5 --- /dev/null +++ b/src/common/crypto/seal.spec.ts @@ -0,0 +1,117 @@ +import { sealData, unsealData } from './seal'; + +describe('seal', () => { + const password = 'test-password-at-least-32-characters-long'; + + describe('sealData', () => { + it('seals data and appends version delimiter', async () => { + const data = { foo: 'bar' }; + const sealed = await sealData(data, { password }); + + expect(sealed).toContain('~2'); + expect(sealed.startsWith('Fe26.2*')).toBe(true); + }); + }); + + describe('unsealData', () => { + it('round-trips seal/unseal', async () => { + const data = { userId: '123', email: 'test@example.com' }; + const sealed = await sealData(data, { password }); + const unsealed = await unsealData(sealed, { password }); + + expect(unsealed).toEqual(data); + }); + + it('round-trips complex nested data', async () => { + const data = { + user: { id: '123', name: 'Test' }, + roles: ['admin', 'user'], + metadata: { nested: { deep: true } }, + }; + const sealed = await sealData(data, { password }); + const unsealed = await unsealData(sealed, { password }); + + expect(unsealed).toEqual(data); + }); + + it('returns empty object for bad password', async () => { + const data = { foo: 'bar' }; + const sealed = await sealData(data, { password }); + const unsealed = await unsealData(sealed, { + password: 'wrong-password-at-least-32-characters', + }); + + expect(unsealed).toEqual({}); + }); + + it('returns empty object for tampered seal', async () => { + const data = { foo: 'bar' }; + const sealed = await sealData(data, { password }); + // Tamper with the sealed data + const tampered = sealed.replace('Fe26.2', 'Fe26.2tampered'); + const unsealed = await unsealData(tampered, { password }); + + expect(unsealed).toEqual({}); + }); + + it('handles legacy tokens with persistent field (version 1)', async () => { + // Manually construct a v1-style token that would have persistent wrapper + const data = { persistent: { userId: '123' } }; + const sealed = await sealData(data, { password }); + // Replace ~2 with ~1 to simulate v1 token + const v1Sealed = sealed.replace('~2', '~1'); + + const unsealed = await unsealData<{ userId: string }>(v1Sealed, { + password, + }); + expect(unsealed).toEqual({ userId: '123' }); + }); + + it('handles tokens without version delimiter', async () => { + const data = { foo: 'bar' }; + const sealed = await sealData(data, { password }); + // Remove version delimiter to simulate pre-versioned token + const noVersion = sealed.split('~')[0]; + + const unsealed = await unsealData(noVersion, { password }); + expect(unsealed).toEqual(data); + }); + }); + + describe('iron-session compatibility', () => { + // This test verifies that tokens sealed with this implementation + // produce the same format as iron-session (Fe26.2 prefix with ~2 suffix) + it('produces iron-session compatible format', async () => { + const data = { userId: '123' }; + const sealed = await sealData(data, { password }); + + // Verify format: Fe26.2*...*~2 + const parts = sealed.split('~'); + expect(parts).toHaveLength(2); + expect(parts[1]).toBe('2'); + + const ironPart = parts[0]; + expect(ironPart.startsWith('Fe26.2*')).toBe(true); + + // Iron format has 8 asterisk-delimited components + const components = ironPart.split('*'); + expect(components).toHaveLength(8); + expect(components[0]).toBe('Fe26.2'); + }); + + // Verify that tokens can be round-tripped and maintain the expected format + // This ensures compatibility with iron-session which uses the same Fe26.2 format + it('can unseal self-generated tokens (simulates iron-session compatibility)', async () => { + const data = { userId: '123', email: 'test@example.com' }; + const sealed = await sealData(data, { password }); + + // Verify the format matches iron-session's expected output + expect(sealed).toMatch( + /^Fe26\.2\*1\*[^*]+\*[^*]+\*[^*]+\*\*[^*]+\*[^*]+~2$/, + ); + + const unsealed = await unsealData(sealed, { password }); + expect(unsealed).toEqual(data); + }); + }); +}); diff --git a/src/common/crypto/seal.ts b/src/common/crypto/seal.ts new file mode 100644 index 000000000..235103582 --- /dev/null +++ b/src/common/crypto/seal.ts @@ -0,0 +1,82 @@ +import { + seal as ironSeal, + unseal as ironUnseal, + defaults, +} from 'iron-webcrypto'; + +const VERSION_DELIMITER = '~'; +const CURRENT_MAJOR_VERSION = 2; + +interface SealOptions { + password: string; +} + +interface UnsealOptions { + password: string; +} + +function parseSeal(seal: string): { + sealWithoutVersion: string; + tokenVersion: number | null; +} { + const [sealWithoutVersion = '', tokenVersionAsString] = + seal.split(VERSION_DELIMITER); + const tokenVersion = + tokenVersionAsString == null ? null : parseInt(tokenVersionAsString, 10); + return { sealWithoutVersion, tokenVersion }; +} + +export async function sealData( + data: unknown, + { password }: SealOptions, +): Promise { + const passwordObj = { + id: '1', + secret: password, + }; + + const seal = await ironSeal(data, passwordObj, { + ...defaults, + ttl: 0, + encode: JSON.stringify, + }); + + return `${seal}${VERSION_DELIMITER}${CURRENT_MAJOR_VERSION}`; +} + +export async function unsealData( + encryptedData: string, + { password }: UnsealOptions, +): Promise { + const { sealWithoutVersion, tokenVersion } = parseSeal(encryptedData); + + const passwordMap = { 1: password }; + + let data: unknown; + try { + data = + (await ironUnseal(sealWithoutVersion, passwordMap, { + ...defaults, + ttl: 0, + })) ?? {}; + } catch (error) { + if ( + error instanceof Error && + /^(Expired seal|Bad hmac value|Cannot find password|Incorrect number of sealed components|Wrong mac prefix)/.test( + error.message, + ) + ) { + return {} as T; + } + throw error; + } + + if (tokenVersion === 2) { + return data as T; + } else if (tokenVersion !== null) { + const record = data as Record; + return (record.persistent ?? data) as T; + } + + return data as T; +} diff --git a/src/common/crypto/subtle-crypto-provider.ts b/src/common/crypto/subtle-crypto-provider.ts index 056fe15c1..e9a557b51 100644 --- a/src/common/crypto/subtle-crypto-provider.ts +++ b/src/common/crypto/subtle-crypto-provider.ts @@ -94,7 +94,7 @@ export class SubtleCryptoProvider extends CryptoProvider { const cryptoKey = await this.subtleCrypto.importKey( 'raw', - key, + key as BufferSource, { name: 'AES-GCM' }, false, ['encrypt'], @@ -102,17 +102,17 @@ export class SubtleCryptoProvider extends CryptoProvider { const encryptParams: AesGcmParams = { name: 'AES-GCM', - iv: actualIv, + iv: actualIv as BufferSource, }; if (aad) { - encryptParams.additionalData = aad; + encryptParams.additionalData = aad as BufferSource; } const encryptedData = await this.subtleCrypto.encrypt( encryptParams, cryptoKey, - plaintext, + plaintext as BufferSource, ); const encryptedBytes = new Uint8Array(encryptedData); @@ -144,7 +144,7 @@ export class SubtleCryptoProvider extends CryptoProvider { const cryptoKey = await this.subtleCrypto.importKey( 'raw', - key, + key as BufferSource, { name: 'AES-GCM' }, false, ['decrypt'], @@ -152,11 +152,11 @@ export class SubtleCryptoProvider extends CryptoProvider { const decryptParams: AesGcmParams = { name: 'AES-GCM', - iv, + iv: iv as BufferSource, }; if (aad) { - decryptParams.additionalData = aad; + decryptParams.additionalData = aad as BufferSource; } const decryptedData = await this.subtleCrypto.decrypt( diff --git a/src/common/exceptions/api-key-required.exception.ts b/src/common/exceptions/api-key-required.exception.ts new file mode 100644 index 000000000..b2b6a7f1a --- /dev/null +++ b/src/common/exceptions/api-key-required.exception.ts @@ -0,0 +1,14 @@ +export class ApiKeyRequiredException extends Error { + readonly status = 403; + readonly name = 'ApiKeyRequiredException'; + readonly path: string; + + constructor(path: string) { + super( + `API key required for "${path}". ` + + `For server-side apps, initialize with: new WorkOS("sk_..."). ` + + `For browser/mobile/CLI apps, use authenticateWithCodeAndVerifier() and authenticateWithRefreshToken() which work without an API key.`, + ); + this.path = path; + } +} diff --git a/src/common/exceptions/index.ts b/src/common/exceptions/index.ts index 845f0d6ed..a3bdc7575 100644 --- a/src/common/exceptions/index.ts +++ b/src/common/exceptions/index.ts @@ -1,3 +1,4 @@ +export * from './api-key-required.exception'; export * from './generic-server.exception'; export * from './bad-request.exception'; export * from './no-api-key-provided.exception'; diff --git a/src/common/interfaces/event.interface.ts b/src/common/interfaces/event.interface.ts index d57fa5207..b401949ce 100644 --- a/src/common/interfaces/event.interface.ts +++ b/src/common/interfaces/event.interface.ts @@ -57,14 +57,12 @@ interface EventResponseBase { context?: Record; } -export interface AuthenticationEmailVerificationSucceededEvent - extends EventBase { +export interface AuthenticationEmailVerificationSucceededEvent extends EventBase { event: 'authentication.email_verification_succeeded'; data: AuthenticationEvent; } -export interface AuthenticationEmailVerificationSucceededEventResponse - extends EventResponseBase { +export interface AuthenticationEmailVerificationSucceededEventResponse extends EventResponseBase { event: 'authentication.email_verification_succeeded'; data: AuthenticationEventResponse; } @@ -74,8 +72,7 @@ export interface AuthenticationMagicAuthFailedEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationMagicAuthFailedEventResponse - extends EventResponseBase { +export interface AuthenticationMagicAuthFailedEventResponse extends EventResponseBase { event: 'authentication.magic_auth_failed'; data: AuthenticationEventResponse; } @@ -85,8 +82,7 @@ export interface AuthenticationMagicAuthSucceededEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationMagicAuthSucceededEventResponse - extends EventResponseBase { +export interface AuthenticationMagicAuthSucceededEventResponse extends EventResponseBase { event: 'authentication.magic_auth_succeeded'; data: AuthenticationEventResponse; } @@ -96,8 +92,7 @@ export interface AuthenticationMfaSucceededEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationMfaSucceededEventResponse - extends EventResponseBase { +export interface AuthenticationMfaSucceededEventResponse extends EventResponseBase { event: 'authentication.mfa_succeeded'; data: AuthenticationEventResponse; } @@ -107,8 +102,7 @@ export interface AuthenticationOAuthFailedEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationOAuthFailedEventResponse - extends EventResponseBase { +export interface AuthenticationOAuthFailedEventResponse extends EventResponseBase { event: 'authentication.oauth_failed'; data: AuthenticationEventResponse; } @@ -118,8 +112,7 @@ export interface AuthenticationOAuthSucceededEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationOAuthSucceededEventResponse - extends EventResponseBase { +export interface AuthenticationOAuthSucceededEventResponse extends EventResponseBase { event: 'authentication.oauth_succeeded'; data: AuthenticationEventResponse; } @@ -129,8 +122,7 @@ export interface AuthenticationPasskeyFailedEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationPasskeyFailedEventResponse - extends EventResponseBase { +export interface AuthenticationPasskeyFailedEventResponse extends EventResponseBase { event: 'authentication.passkey_failed'; data: AuthenticationEventResponse; } @@ -140,8 +132,7 @@ export interface AuthenticationPasskeySucceededEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationPasskeySucceededEventResponse - extends EventResponseBase { +export interface AuthenticationPasskeySucceededEventResponse extends EventResponseBase { event: 'authentication.passkey_succeeded'; data: AuthenticationEventResponse; } @@ -151,8 +142,7 @@ export interface AuthenticationPasswordFailedEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationPasswordFailedEventResponse - extends EventResponseBase { +export interface AuthenticationPasswordFailedEventResponse extends EventResponseBase { event: 'authentication.password_failed'; data: AuthenticationEventResponse; } @@ -162,8 +152,7 @@ export interface AuthenticationPasswordSucceededEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationPasswordSucceededEventResponse - extends EventResponseBase { +export interface AuthenticationPasswordSucceededEventResponse extends EventResponseBase { event: 'authentication.password_succeeded'; data: AuthenticationEventResponse; } @@ -173,8 +162,7 @@ export interface AuthenticationRadarRiskDetectedEvent extends EventBase { data: AuthenticationRadarRiskDetectedEventData; } -export interface AuthenticationRadarRiskDetectedEventResponse - extends EventResponseBase { +export interface AuthenticationRadarRiskDetectedEventResponse extends EventResponseBase { event: 'authentication.radar_risk_detected'; data: AuthenticationRadarRiskDetectedEventResponseData; } @@ -184,8 +172,7 @@ export interface AuthenticationSSOFailedEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationSSOFailedEventResponse - extends EventResponseBase { +export interface AuthenticationSSOFailedEventResponse extends EventResponseBase { event: 'authentication.sso_failed'; data: AuthenticationEventResponse; } @@ -195,8 +182,7 @@ export interface AuthenticationSSOSucceededEvent extends EventBase { data: AuthenticationEvent; } -export interface AuthenticationSSOSucceededEventResponse - extends EventResponseBase { +export interface AuthenticationSSOSucceededEventResponse extends EventResponseBase { event: 'authentication.sso_succeeded'; data: AuthenticationEventResponse; } @@ -241,16 +227,6 @@ export interface DsyncActivatedEventResponse extends EventResponseBase { data: EventDirectoryResponse; } -export interface DsyncDeactivatedEvent extends EventBase { - event: 'dsync.deactivated'; - data: EventDirectory; -} - -export interface DsyncDeactivatedEventResponse extends EventResponseBase { - event: 'dsync.deactivated'; - data: EventDirectoryResponse; -} - export interface DsyncDeletedEvent extends EventBase { event: 'dsync.deleted'; data: Omit; @@ -362,8 +338,7 @@ export interface EmailVerificationCreatedEvent extends EventBase { data: EmailVerificationEvent; } -export interface EmailVerificationCreatedEventResponse - extends EventResponseBase { +export interface EmailVerificationCreatedEventResponse extends EventResponseBase { event: 'email_verification.created'; data: EmailVerificationEventResponse; } @@ -467,29 +442,12 @@ export interface UserDeletedEventResponse extends EventResponseBase { data: UserResponse; } -/** - * @deprecated Use OrganizationMembershipCreated instead. Will be removed in a future major version. - */ -export interface OrganizationMembershipAdded extends EventBase { - event: 'organization_membership.added'; - data: OrganizationMembership; -} - -/** - * @deprecated Use OrganizationMembershipCreatedResponse instead. Will be removed in a future major version. - */ -export interface OrganizationMembershipAddedResponse extends EventResponseBase { - event: 'organization_membership.added'; - data: OrganizationMembershipResponse; -} - export interface OrganizationMembershipCreated extends EventBase { event: 'organization_membership.created'; data: OrganizationMembership; } -export interface OrganizationMembershipCreatedResponse - extends EventResponseBase { +export interface OrganizationMembershipCreatedResponse extends EventResponseBase { event: 'organization_membership.created'; data: OrganizationMembershipResponse; } @@ -499,8 +457,7 @@ export interface OrganizationMembershipDeleted extends EventBase { data: OrganizationMembership; } -export interface OrganizationMembershipDeletedResponse - extends EventResponseBase { +export interface OrganizationMembershipDeletedResponse extends EventResponseBase { event: 'organization_membership.deleted'; data: OrganizationMembershipResponse; } @@ -510,29 +467,11 @@ export interface OrganizationMembershipUpdated extends EventBase { data: OrganizationMembership; } -export interface OrganizationMembershipUpdatedResponse - extends EventResponseBase { +export interface OrganizationMembershipUpdatedResponse extends EventResponseBase { event: 'organization_membership.updated'; data: OrganizationMembershipResponse; } -/** - * @deprecated Use OrganizationMembershipDeleted instead. Will be removed in a future major version. - */ -export interface OrganizationMembershipRemoved extends EventBase { - event: 'organization_membership.removed'; - data: OrganizationMembership; -} - -/** - * @deprecated Use OrganizationMembershipDeletedResponse instead. Will be removed in a future major version. - */ -export interface OrganizationMembershipRemovedResponse - extends EventResponseBase { - event: 'organization_membership.removed'; - data: OrganizationMembershipResponse; -} - export interface OrganizationCreatedEvent extends EventBase { event: 'organization.created'; data: Organization; @@ -618,8 +557,7 @@ export interface OrganizationDomainVerifiedEvent extends EventBase { data: OrganizationDomain; } -export interface OrganizationDomainVerifiedEventResponse - extends EventResponseBase { +export interface OrganizationDomainVerifiedEventResponse extends EventResponseBase { event: 'organization_domain.verified'; data: OrganizationDomainResponse; } @@ -629,8 +567,7 @@ export interface OrganizationDomainVerificationFailedEvent extends EventBase { data: OrganizationDomain; } -export interface OrganizationDomainVerificationFailedEventResponse - extends EventResponseBase { +export interface OrganizationDomainVerificationFailedEventResponse extends EventResponseBase { event: 'organization_domain.verification_failed'; data: OrganizationDomainResponse; } @@ -640,8 +577,7 @@ export interface OrganizationDomainCreatedEvent extends EventBase { data: OrganizationDomain; } -export interface OrganizationDomainCreatedEventResponse - extends EventResponseBase { +export interface OrganizationDomainCreatedEventResponse extends EventResponseBase { event: 'organization_domain.created'; data: OrganizationDomainResponse; } @@ -651,8 +587,7 @@ export interface OrganizationDomainUpdatedEvent extends EventBase { data: OrganizationDomain; } -export interface OrganizationDomainUpdatedEventResponse - extends EventResponseBase { +export interface OrganizationDomainUpdatedEventResponse extends EventResponseBase { event: 'organization_domain.updated'; data: OrganizationDomainResponse; } @@ -662,8 +597,7 @@ export interface OrganizationDomainDeletedEvent extends EventBase { data: OrganizationDomain; } -export interface OrganizationDomainDeletedEventResponse - extends EventResponseBase { +export interface OrganizationDomainDeletedEventResponse extends EventResponseBase { event: 'organization_domain.deleted'; data: OrganizationDomainResponse; } @@ -706,7 +640,6 @@ export type Event = | ConnectionDeactivatedEvent | ConnectionDeletedEvent | DsyncActivatedEvent - | DsyncDeactivatedEvent | DsyncDeletedEvent | DsyncGroupCreatedEvent | DsyncGroupUpdatedEvent @@ -727,11 +660,9 @@ export type Event = | UserCreatedEvent | UserUpdatedEvent | UserDeletedEvent - | OrganizationMembershipAdded | OrganizationMembershipCreated | OrganizationMembershipDeleted | OrganizationMembershipUpdated - | OrganizationMembershipRemoved | RoleCreatedEvent | RoleDeletedEvent | RoleUpdatedEvent @@ -766,7 +697,6 @@ export type EventResponse = | ConnectionDeactivatedEventResponse | ConnectionDeletedEventResponse | DsyncActivatedEventResponse - | DsyncDeactivatedEventResponse | DsyncDeletedEventResponse | DsyncGroupCreatedEventResponse | DsyncGroupUpdatedEventResponse @@ -787,11 +717,9 @@ export type EventResponse = | UserCreatedEventResponse | UserUpdatedEventResponse | UserDeletedEventResponse - | OrganizationMembershipAddedResponse | OrganizationMembershipCreatedResponse | OrganizationMembershipDeletedResponse | OrganizationMembershipUpdatedResponse - | OrganizationMembershipRemovedResponse | RoleCreatedEventResponse | RoleDeletedEventResponse | RoleUpdatedEventResponse diff --git a/src/common/interfaces/get-options.interface.ts b/src/common/interfaces/get-options.interface.ts index 2acc74765..93c7fd1d5 100644 --- a/src/common/interfaces/get-options.interface.ts +++ b/src/common/interfaces/get-options.interface.ts @@ -2,4 +2,6 @@ export interface GetOptions { query?: Record; accessToken?: string; warrantToken?: string; + /** Skip API key requirement check (for PKCE-safe methods) */ + skipApiKeyCheck?: boolean; } diff --git a/src/common/interfaces/post-options.interface.ts b/src/common/interfaces/post-options.interface.ts index 6b4920a98..7c9120c86 100644 --- a/src/common/interfaces/post-options.interface.ts +++ b/src/common/interfaces/post-options.interface.ts @@ -2,4 +2,6 @@ export interface PostOptions { query?: { [key: string]: any }; idempotencyKey?: string; warrantToken?: string; + /** Skip API key requirement check (for PKCE-safe methods) */ + skipApiKeyCheck?: boolean; } diff --git a/src/common/interfaces/put-options.interface.ts b/src/common/interfaces/put-options.interface.ts index 9063235be..1ac3c5863 100644 --- a/src/common/interfaces/put-options.interface.ts +++ b/src/common/interfaces/put-options.interface.ts @@ -1,4 +1,6 @@ export interface PutOptions { query?: { [key: string]: any }; idempotencyKey?: string; + /** Skip API key requirement check (for PKCE-safe methods) */ + skipApiKeyCheck?: boolean; } diff --git a/src/common/interfaces/workos-options.interface.ts b/src/common/interfaces/workos-options.interface.ts index f750942b3..1bc8ad035 100644 --- a/src/common/interfaces/workos-options.interface.ts +++ b/src/common/interfaces/workos-options.interface.ts @@ -1,6 +1,7 @@ import { AppInfo } from './app-info.interface'; export interface WorkOSOptions { + apiKey?: string; apiHostname?: string; https?: boolean; port?: number; diff --git a/src/common/iron-session/edge-iron-session-provider.ts b/src/common/iron-session/edge-iron-session-provider.ts deleted file mode 100644 index 90f7cd60c..000000000 --- a/src/common/iron-session/edge-iron-session-provider.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { sealData, unsealData } from 'iron-session/edge'; -import { - IronSessionProvider, - SealDataOptions, - UnsealedDataType, -} from './iron-session-provider'; - -/** - * EdgeIronSessionProvider which uses the base iron-session seal/unseal methods. - */ -export class EdgeIronSessionProvider extends IronSessionProvider { - /** @override */ - async sealData(data: unknown, options: SealDataOptions): Promise { - // The iron-session default ttl is 14 days, which can be problematic if the WorkOS session is configured to be > 14 days. - // In that case the session expires and can't be refreshed, so we set the ttl to 0 to set it to the max possible value. - const sealOptions = { - ...options, - ttl: 0, - }; - return sealData(data, sealOptions); - } - - /** @override */ - async unsealData( - seal: string, - options: SealDataOptions, - ): Promise { - return unsealData(seal, options); - } -} diff --git a/src/common/iron-session/iron-session-provider.ts b/src/common/iron-session/iron-session-provider.ts deleted file mode 100644 index efe85e533..000000000 --- a/src/common/iron-session/iron-session-provider.ts +++ /dev/null @@ -1,27 +0,0 @@ -export type SealDataOptions = { - password: - | string - | { - [id: string]: string; - }; - ttl?: number | undefined; -}; - -export type UnsealedDataType = Record; - -/** - * Interface encapsulating the sealData/unsealData methods for separate iron-session implementations. - * - * This allows for different implementations of the iron-session library to be used in - * worker/edge vs. regular web environments, which is required because of the different crypto APIs available. - * Once we drop support for Node 16 and upgrade to iron-session 8+, we can remove this abstraction as iron-session 8+ - * handles this on its own. - */ -export abstract class IronSessionProvider { - abstract sealData(data: unknown, options: SealDataOptions): Promise; - - abstract unsealData( - seal: string, - options: SealDataOptions, - ): Promise; -} diff --git a/src/common/iron-session/web-iron-session-provider.ts b/src/common/iron-session/web-iron-session-provider.ts deleted file mode 100644 index bacad11cb..000000000 --- a/src/common/iron-session/web-iron-session-provider.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { sealData, unsealData } from 'iron-session'; -import { - IronSessionProvider, - SealDataOptions, - UnsealedDataType, -} from './iron-session-provider'; - -/** - * WebIronSessionProvider which uses the base iron-session seal/unseal methods. - */ -export class WebIronSessionProvider extends IronSessionProvider { - /** @override */ - async sealData(data: unknown, options: SealDataOptions): Promise { - // The iron-session default ttl is 14 days, which can be problematic if the WorkOS session is configured to be > 14 days. - // In that case the session expires and can't be refreshed, so we set the ttl to 0 to set it to the max possible value. - const sealOptions = { - ...options, - ttl: 0, - }; - return sealData(data, sealOptions); - } - - /** @override */ - async unsealData( - seal: string, - options: SealDataOptions, - ): Promise { - return unsealData(seal, options); - } -} diff --git a/src/common/net/fetch-client.spec.ts b/src/common/net/fetch-client.spec.ts index 340c04d98..74bea0f2e 100644 --- a/src/common/net/fetch-client.spec.ts +++ b/src/common/net/fetch-client.spec.ts @@ -236,9 +236,9 @@ describe('Fetch client', () => { const mockSleep = jest.spyOn(fetchClient, 'sleep'); mockSleep.mockImplementation(() => Promise.resolve()); - await expect( - fetchClient.get('/fga/v1/resources', {}), - ).rejects.toThrowError('Gateway Timeout'); + await expect(fetchClient.get('/fga/v1/resources', {})).rejects.toThrow( + 'Gateway Timeout', + ); expect(mockShouldRetryRequest).toHaveBeenCalledTimes(4); expect(mockSleep).toHaveBeenCalledTimes(3); @@ -256,9 +256,9 @@ describe('Fetch client', () => { 'shouldRetryRequest', ); - await expect( - fetchClient.get('/fga/v1/resources', {}), - ).rejects.toThrowError('Bad Request'); + await expect(fetchClient.get('/fga/v1/resources', {})).rejects.toThrow( + 'Bad Request', + ); expect(mockShouldRetryRequest).toHaveBeenCalledTimes(1); }); diff --git a/src/common/net/fetch-client.ts b/src/common/net/fetch-client.ts index 57959fb31..4b5cf808a 100644 --- a/src/common/net/fetch-client.ts +++ b/src/common/net/fetch-client.ts @@ -175,14 +175,10 @@ export class FetchHttpClient extends HttpClient implements HttpClientInterface { const { 'User-Agent': userAgent } = (this.options?.headers || {}) as RequestHeaders; - // Create AbortController for timeout if configured - let abortController: AbortController | undefined; - let timeoutId: ReturnType | undefined; - // Access timeout from the options with default of 60 seconds const timeout = this.options?.timeout ?? DEFAULT_FETCH_TIMEOUT; // Default 60 seconds - abortController = new AbortController(); - timeoutId = setTimeout(() => { + const abortController = new AbortController(); + const timeoutId = setTimeout(() => { abortController?.abort(); }, timeout); diff --git a/src/common/net/http-client.ts b/src/common/net/http-client.ts index 2e9593b46..b3ac1a92a 100644 --- a/src/common/net/http-client.ts +++ b/src/common/net/http-client.ts @@ -12,7 +12,10 @@ export abstract class HttpClient implements HttpClientInterface { readonly MINIMUM_SLEEP_TIME_IN_MILLISECONDS = 500; readonly RETRY_STATUS_CODES = [408, 500, 502, 504]; - constructor(readonly baseURL: string, readonly options?: RequestInit) {} + constructor( + readonly baseURL: string, + readonly options?: RequestInit, + ) {} /** The HTTP client name used for diagnostics */ getClientName(): string { @@ -111,9 +114,7 @@ export abstract class HttpClient implements HttpClientInterface { } // tslint:disable-next-line -export abstract class HttpClientResponse - implements HttpClientResponseInterface -{ +export abstract class HttpClientResponse implements HttpClientResponseInterface { _statusCode: number; _headers: ResponseHeaders; diff --git a/src/common/net/index.ts b/src/common/net/index.ts deleted file mode 100644 index db39b5fea..000000000 --- a/src/common/net/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { FetchHttpClient } from './fetch-client'; -import { HttpClient } from './http-client'; -import { NodeHttpClient } from './node-client'; - -export function createHttpClient( - baseURL: string, - options: RequestInit, - fetchFn?: typeof fetch, -): HttpClient { - if (typeof fetch !== 'undefined' || typeof fetchFn !== 'undefined') { - return new FetchHttpClient(baseURL, options, fetchFn); - } else { - return new NodeHttpClient(baseURL, options); - } -} - -export * from './fetch-client'; -export * from './node-client'; -export * from './http-client'; diff --git a/src/common/net/node-client.spec.ts b/src/common/net/node-client.spec.ts deleted file mode 100644 index 0b0b6a9cf..000000000 --- a/src/common/net/node-client.spec.ts +++ /dev/null @@ -1,259 +0,0 @@ -import nock from 'nock'; -import { NodeHttpClient } from './node-client'; - -const nodeClient = new NodeHttpClient('https://test.workos.com', { - headers: { - Authorization: `Bearer sk_test`, - 'User-Agent': 'test-node-client', - }, -}); - -describe('Node client', () => { - beforeEach(() => nock.cleanAll()); - - it('get for FGA path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .get('/fga/v1/resources') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.get('/fga/v1/resources', {}); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('post for FGA path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .post('/fga/v1/resources') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.post('/fga/v1/resources', {}, {}); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('put for FGA path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .put('/fga/v1/resources/user/user-1') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.put( - '/fga/v1/resources/user/user-1', - {}, - {}, - ); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('delete for FGA path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .delete('/fga/v1/resources/user/user-1') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.delete( - '/fga/v1/resources/user/user-1', - {}, - ); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('get for Vault path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .get('/vault/v1/kv') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.get('/vault/v1/kv', {}); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('post for Vault path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .post('/vault/v1/kv') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.post('/vault/v1/kv', {}, {}); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('put for Vault path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .put('/vault/v1/kv/secret') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.put('/vault/v1/kv/secret', {}, {}); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('delete for Vault path should call nodeRequestWithRetry and return response', async () => { - nock('https://test.workos.com') - .delete('/vault/v1/kv/secret') - .reply(200, { data: 'response' }); - const mockNodeRequestWithRetry = jest.spyOn( - NodeHttpClient.prototype as any, - 'nodeRequestWithRetry', - ); - - const response = await nodeClient.delete('/vault/v1/kv/secret', {}); - - expect(mockNodeRequestWithRetry).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('should retry request on 500 status code', async () => { - nock('https://test.workos.com') - .get('/fga/v1/resources') - .reply(500) - .get('/fga/v1/resources') - .reply(200, { data: 'response' }); - const mockShouldRetryRequest = jest.spyOn( - NodeHttpClient.prototype as any, - 'shouldRetryRequest', - ); - const mockSleep = jest.spyOn(nodeClient, 'sleep'); - mockSleep.mockImplementation(() => Promise.resolve()); - - const response = await nodeClient.get('/fga/v1/resources', {}); - - expect(mockShouldRetryRequest).toHaveBeenCalledTimes(2); - expect(mockSleep).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('should retry request on 502 status code', async () => { - nock('https://test.workos.com') - .get('/fga/v1/resources') - .reply(502) - .get('/fga/v1/resources') - .reply(200, { data: 'response' }); - const mockShouldRetryRequest = jest.spyOn( - NodeHttpClient.prototype as any, - 'shouldRetryRequest', - ); - const mockSleep = jest.spyOn(nodeClient, 'sleep'); - mockSleep.mockImplementation(() => Promise.resolve()); - - const response = await nodeClient.get('/fga/v1/resources', {}); - - expect(mockShouldRetryRequest).toHaveBeenCalledTimes(2); - expect(mockSleep).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('should retry request on 504 status code', async () => { - nock('https://test.workos.com') - .get('/fga/v1/resources') - .reply(504) - .get('/fga/v1/resources') - .reply(200, { data: 'response' }); - const mockShouldRetryRequest = jest.spyOn( - NodeHttpClient.prototype as any, - 'shouldRetryRequest', - ); - const mockSleep = jest.spyOn(nodeClient, 'sleep'); - mockSleep.mockImplementation(() => Promise.resolve()); - - const response = await nodeClient.get('/fga/v1/resources', {}); - - expect(mockShouldRetryRequest).toHaveBeenCalledTimes(2); - expect(mockSleep).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); - - it('should retry request up to 3 times on retryable status code', async () => { - nock('https://test.workos.com') - .get('/fga/v1/resources') - .reply(504) - .get('/fga/v1/resources') - .reply(502) - .get('/fga/v1/resources') - .reply(500) - .get('/fga/v1/resources') - .reply(500); - const mockShouldRetryRequest = jest.spyOn( - NodeHttpClient.prototype as any, - 'shouldRetryRequest', - ); - const mockSleep = jest.spyOn(nodeClient, 'sleep'); - mockSleep.mockImplementation(() => Promise.resolve()); - - await expect( - nodeClient.get('/fga/v1/resources', {}), - ).rejects.toThrowError(); - - expect(mockShouldRetryRequest).toHaveBeenCalledTimes(4); - expect(mockSleep).toHaveBeenCalledTimes(3); - }); - - it('should not retry request on non-retryable status code', async () => { - nock('https://test.workos.com').get('/fga/v1/resources').reply(400); - const mockShouldRetryRequest = jest.spyOn( - NodeHttpClient.prototype as any, - 'shouldRetryRequest', - ); - - await expect( - nodeClient.get('/fga/v1/resources', {}), - ).rejects.toThrowError(); - - expect(mockShouldRetryRequest).toHaveBeenCalledTimes(1); - }); - - it('should retry request on TypeError', async () => { - nock('https://test.workos.com') - .get('/fga/v1/resources') - .replyWithError(new TypeError('Network request failed')) - .get('/fga/v1/resources') - .reply(200, { data: 'response' }); - const mockShouldRetryRequest = jest.spyOn( - NodeHttpClient.prototype as any, - 'shouldRetryRequest', - ); - const mockSleep = jest.spyOn(nodeClient, 'sleep'); - mockSleep.mockImplementation(() => Promise.resolve()); - - const response = await nodeClient.get('/fga/v1/resources', {}); - - expect(mockShouldRetryRequest).toHaveBeenCalledTimes(1); - expect(mockSleep).toHaveBeenCalledTimes(1); - expect(await response.toJSON()).toEqual({ data: 'response' }); - }); -}); diff --git a/src/common/net/node-client.ts b/src/common/net/node-client.ts deleted file mode 100644 index 71009aaa1..000000000 --- a/src/common/net/node-client.ts +++ /dev/null @@ -1,364 +0,0 @@ -import { HttpClient, HttpClientError, HttpClientResponse } from './http-client'; -import { - HttpClientInterface, - HttpClientResponseInterface, - RequestHeaders, - RequestOptions, -} from '../interfaces/http-client.interface'; - -import { - RequestOptions as HttpRequestOptions, - Agent as HttpAgent, -} from 'node:http'; -import { Agent as HttpsAgent } from 'node:https'; - -import * as http_ from 'node:http'; -import * as https_ from 'node:https'; - -// `import * as http_ from 'http'` creates a "Module Namespace Exotic Object" -// which is immune to monkey-patching, whereas http_.default (in an ES Module context) -// will resolve to the same thing as require('http'), which is -// monkey-patchable. We care about this because users in their test -// suites might be using a library like "nock" which relies on the ability -// to monkey-patch and intercept calls to http.request. -const http = (http_ as unknown as { default: typeof http_ }).default || http_; -const https = - (https_ as unknown as { default: typeof https_ }).default || https_; - -export class NodeHttpClient extends HttpClient implements HttpClientInterface { - private httpAgent: HttpAgent; - private httpsAgent: HttpsAgent; - - constructor(readonly baseURL: string, readonly options?: RequestInit) { - super(baseURL, options); - - this.httpAgent = new http.Agent({ keepAlive: true }); - this.httpsAgent = new https.Agent({ keepAlive: true }); - } - - getClientName(): string { - return 'node'; - } - - static override getBody(entity: unknown): string | null { - if (entity === null || entity === undefined) { - return null; - } - - if (entity instanceof URLSearchParams) { - return entity.toString(); - } - - return JSON.stringify(entity); - } - - async get( - path: string, - options: RequestOptions, - ): Promise { - const resourceURL = HttpClient.getResourceURL( - this.baseURL, - path, - options.params, - ); - - if (HttpClient.isPathRetryable(path)) { - return await this.nodeRequestWithRetry( - resourceURL, - 'GET', - null, - options.headers, - ); - } else { - return await this.nodeRequest(resourceURL, 'GET', null, options.headers); - } - } - - async post( - path: string, - entity: Entity, - options: RequestOptions, - ): Promise { - const resourceURL = HttpClient.getResourceURL( - this.baseURL, - path, - options.params, - ); - - if (HttpClient.isPathRetryable(path)) { - return await this.nodeRequestWithRetry( - resourceURL, - 'POST', - NodeHttpClient.getBody(entity), - { - ...HttpClient.getContentTypeHeader(entity), - ...options.headers, - }, - ); - } else { - return await this.nodeRequest( - resourceURL, - 'POST', - NodeHttpClient.getBody(entity), - { - ...HttpClient.getContentTypeHeader(entity), - ...options.headers, - }, - ); - } - } - - async put( - path: string, - entity: Entity, - options: RequestOptions, - ): Promise { - const resourceURL = HttpClient.getResourceURL( - this.baseURL, - path, - options.params, - ); - - if (HttpClient.isPathRetryable(path)) { - return await this.nodeRequestWithRetry( - resourceURL, - 'PUT', - NodeHttpClient.getBody(entity), - { - ...HttpClient.getContentTypeHeader(entity), - ...options.headers, - }, - ); - } else { - return await this.nodeRequest( - resourceURL, - 'PUT', - NodeHttpClient.getBody(entity), - { - ...HttpClient.getContentTypeHeader(entity), - ...options.headers, - }, - ); - } - } - - async delete( - path: string, - options: RequestOptions, - ): Promise { - const resourceURL = HttpClient.getResourceURL( - this.baseURL, - path, - options.params, - ); - - if (HttpClient.isPathRetryable(path)) { - return await this.nodeRequestWithRetry( - resourceURL, - 'DELETE', - null, - options.headers, - ); - } else { - return await this.nodeRequest( - resourceURL, - 'DELETE', - null, - options.headers, - ); - } - } - - private async nodeRequest( - url: string, - method: string, - body: string | null, - headers?: RequestHeaders, - ): Promise { - return new Promise((resolve, reject) => { - const isSecureConnection = url.startsWith('https'); - const agent = isSecureConnection ? this.httpsAgent : this.httpAgent; - const lib = isSecureConnection ? https : http; - - const { 'User-Agent': userAgent } = this.options - ?.headers as RequestHeaders; - - const options: HttpRequestOptions = { - method, - headers: { - Accept: 'application/json, text/plain, */*', - 'Content-Type': 'application/json', - ...(this.options?.headers as http_.OutgoingHttpHeaders), - ...headers, - 'User-Agent': this.addClientToUserAgent(userAgent.toString()), - }, - agent, - }; - - const req = lib.request(url, options, async (res) => { - const clientResponse = new NodeHttpClientResponse(res); - - if (res.statusCode && (res.statusCode < 200 || res.statusCode > 299)) { - reject( - new HttpClientError({ - message: res.statusMessage as string, - response: { - status: res.statusCode, - headers: res.headers, - data: await clientResponse.toJSON(), - }, - }), - ); - } - - resolve(clientResponse); - }); - - req.on('error', (err) => { - reject(new Error(err.message)); - }); - - if (body) { - req.setHeader('Content-Length', Buffer.byteLength(body)); - req.write(body); - } - req.end(); - }); - } - - private async nodeRequestWithRetry( - url: string, - method: string, - body: string | null, - headers?: RequestHeaders, - ): Promise { - const isSecureConnection = url.startsWith('https'); - const agent = isSecureConnection ? this.httpsAgent : this.httpAgent; - const lib = isSecureConnection ? https : http; - - const { 'User-Agent': userAgent } = this.options?.headers as RequestHeaders; - - const options: HttpRequestOptions = { - method, - headers: { - Accept: 'application/json, text/plain, */*', - 'Content-Type': 'application/json', - ...(this.options?.headers as http_.OutgoingHttpHeaders), - ...headers, - 'User-Agent': this.addClientToUserAgent(userAgent.toString()), - }, - agent, - }; - - let retryAttempts = 1; - - const makeRequest = async (): Promise => - new Promise((resolve, reject) => { - const req = lib.request(url, options, async (res) => { - const clientResponse = new NodeHttpClientResponse(res); - - if (this.shouldRetryRequest(res, retryAttempts)) { - retryAttempts++; - - await this.sleep(retryAttempts); - - return makeRequest().then(resolve).catch(reject); - } - - if ( - res.statusCode && - (res.statusCode < 200 || res.statusCode > 299) - ) { - reject( - new HttpClientError({ - message: res.statusMessage as string, - response: { - status: res.statusCode, - headers: res.headers, - data: await clientResponse.toJSON(), - }, - }), - ); - } - - resolve(new NodeHttpClientResponse(res)); - }); - - req.on('error', async (err) => { - if (err != null && err instanceof TypeError) { - retryAttempts++; - await this.sleep(retryAttempts); - return makeRequest().then(resolve).catch(reject); - } - - reject(new Error(err.message)); - }); - - if (body) { - req.setHeader('Content-Length', Buffer.byteLength(body)); - req.write(body); - } - req.end(); - }); - - return makeRequest(); - } - - private shouldRetryRequest(response: any, retryAttempt: number): boolean { - if (retryAttempt > this.MAX_RETRY_ATTEMPTS) { - return false; - } - - if ( - response != null && - this.RETRY_STATUS_CODES.includes(response.statusCode) - ) { - return true; - } - - return false; - } -} - -// tslint:disable-next-line -export class NodeHttpClientResponse - extends HttpClientResponse - implements HttpClientResponseInterface -{ - _res: http_.IncomingMessage; - - constructor(res: http_.IncomingMessage) { - // @ts-ignore - super(res.statusCode, res.headers || {}); - this._res = res; - } - - getRawResponse(): http_.IncomingMessage { - return this._res; - } - - toJSON(): Promise | any { - return new Promise((resolve, reject) => { - const contentType = this._res.headers['content-type']; - const isJsonResponse = contentType?.includes('application/json'); - - if (!isJsonResponse) { - resolve(null); - } - - let response = ''; - - this._res.setEncoding('utf8'); - this._res.on('data', (chunk) => { - response += chunk; - }); - this._res.once('end', () => { - try { - resolve(JSON.parse(response)); - } catch (e) { - reject(e); - } - }); - }); - } -} diff --git a/src/common/serializers/event.serializer.ts b/src/common/serializers/event.serializer.ts index c0de787e5..26f778dce 100644 --- a/src/common/serializers/event.serializer.ts +++ b/src/common/serializers/event.serializer.ts @@ -64,7 +64,6 @@ export const deserializeEvent = (event: EventResponse): Event => { data: deserializeConnection(event.data), }; case 'dsync.activated': - case 'dsync.deactivated': return { ...eventBase, event: event.event, @@ -149,11 +148,9 @@ export const deserializeEvent = (event: EventResponse): Event => { event: event.event, data: deserializeUser(event.data), }; - case 'organization_membership.added': case 'organization_membership.created': case 'organization_membership.deleted': case 'organization_membership.updated': - case 'organization_membership.removed': return { ...eventBase, event: event.event, diff --git a/src/common/utils/env.ts b/src/common/utils/env.ts new file mode 100644 index 000000000..8740d15ea --- /dev/null +++ b/src/common/utils/env.ts @@ -0,0 +1,93 @@ +/** + * Cross-runtime environment variable helper + */ + +type Runtime = + | 'node' + | 'deno' + | 'bun' + | 'cloudflare' + | 'fastly' + | 'edge-light' + | 'other'; + +let detectedRuntime: Runtime | null = null; + +/** + * Detect the current runtime environment. + * This function checks for various runtime environments such as Node.js, Deno, Bun, Cloudflare Workers, Fastly, and Edge Light. + * It returns a string representing the detected runtime and caches the result for future calls. + * @returns The detected runtime environment as a string. + */ +export function detectRuntime(): Runtime { + if (detectedRuntime) { + return detectedRuntime; + } + + const global = globalThis as any; + + if (typeof process !== 'undefined' && process.release?.name === 'node') { + detectedRuntime = 'node'; + } else if (typeof global.Deno !== 'undefined') { + detectedRuntime = 'deno'; + } else if ( + typeof navigator !== 'undefined' && + navigator.userAgent?.includes('Bun') + ) { + detectedRuntime = 'bun'; + } else if ( + typeof navigator !== 'undefined' && + navigator.userAgent?.includes('Cloudflare') + ) { + detectedRuntime = 'cloudflare'; + } else if (typeof global !== 'undefined' && 'fastly' in global) { + detectedRuntime = 'fastly'; + } else if (typeof global !== 'undefined' && 'EdgeRuntime' in global) { + detectedRuntime = 'edge-light'; + } else { + detectedRuntime = 'other'; + } + + return detectedRuntime; +} + +function getEnvironmentVariable(key: string): string | undefined { + const runtime = detectRuntime(); + const global = globalThis as any; + + try { + switch (runtime) { + case 'node': + case 'bun': + case 'edge-light': + return process.env[key]; + + case 'deno': + return global.Deno.env.get(key); + + case 'cloudflare': + return global.env?.[key] ?? global[key]; + + case 'fastly': + return global[key]; + + default: + return process?.env?.[key] ?? global.env?.[key] ?? global[key]; + } + } catch { + return undefined; + } +} + +/** + * Get an environment variable value, trying to access it in different runtimes. + * @param key - The name of the environment variable. + * @param defaultValue - The default value to return if the variable is not found. + * @return The value of the environment variable or the default value. + */ +export function getEnv( + key: string, + defaultValue?: T, +): string | T | undefined { + return getEnvironmentVariable(key) ?? defaultValue; +} diff --git a/src/common/utils/leb128.spec.ts b/src/common/utils/leb128.spec.ts new file mode 100644 index 000000000..869e59e9c --- /dev/null +++ b/src/common/utils/leb128.spec.ts @@ -0,0 +1,288 @@ +import { encodeUInt32, decodeUInt32 } from './leb128'; + +describe('leb128', () => { + describe('encodeUInt32', () => { + describe('boundary values', () => { + test('encodes 0 (1 byte: 0x00)', () => { + const result = encodeUInt32(0); + expect(result).toEqual(new Uint8Array([0x00])); + }); + + test('encodes 127 (1 byte: 0x7F) - largest 1-byte value', () => { + const result = encodeUInt32(127); + expect(result).toEqual(new Uint8Array([0x7f])); + }); + + test('encodes 128 (2 bytes: 0x80 0x01) - smallest 2-byte value', () => { + const result = encodeUInt32(128); + expect(result).toEqual(new Uint8Array([0x80, 0x01])); + }); + + test('encodes 16383 (2 bytes: 0xFF 0x7F) - largest 2-byte value', () => { + const result = encodeUInt32(16383); + expect(result).toEqual(new Uint8Array([0xff, 0x7f])); + }); + + test('encodes 16384 (3 bytes: 0x80 0x80 0x01)', () => { + const result = encodeUInt32(16384); + expect(result).toEqual(new Uint8Array([0x80, 0x80, 0x01])); + }); + + test('encodes 2097151 (3 bytes: 0xFF 0xFF 0x7F)', () => { + const result = encodeUInt32(2097151); + expect(result).toEqual(new Uint8Array([0xff, 0xff, 0x7f])); + }); + + test('encodes 2097152 (4 bytes: 0x80 0x80 0x80 0x01)', () => { + const result = encodeUInt32(2097152); + expect(result).toEqual(new Uint8Array([0x80, 0x80, 0x80, 0x01])); + }); + + test('encodes 268435455 (4 bytes: 0xFF 0xFF 0xFF 0x7F)', () => { + const result = encodeUInt32(268435455); + expect(result).toEqual(new Uint8Array([0xff, 0xff, 0xff, 0x7f])); + }); + + test('encodes 268435456 (5 bytes: 0x80 0x80 0x80 0x80 0x01)', () => { + const result = encodeUInt32(268435456); + expect(result).toEqual(new Uint8Array([0x80, 0x80, 0x80, 0x80, 0x01])); + }); + + test('encodes 4294967295 (5 bytes: 0xFF 0xFF 0xFF 0xFF 0x0F) - MAX_UINT32', () => { + const result = encodeUInt32(4294967295); + expect(result).toEqual(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0x0f])); + }); + }); + + describe('common values', () => { + test('encodes 42', () => { + const result = encodeUInt32(42); + expect(result).toEqual(new Uint8Array([0x2a])); + }); + + test('encodes 300', () => { + const result = encodeUInt32(300); + expect(result).toEqual(new Uint8Array([0xac, 0x02])); + }); + + test('encodes 1000000', () => { + const result = encodeUInt32(1000000); + expect(result).toEqual(new Uint8Array([0xc0, 0x84, 0x3d])); + }); + }); + + describe('invalid inputs', () => { + test('throws for negative numbers', () => { + expect(() => encodeUInt32(-1)).toThrow('Value must be non-negative'); + }); + + test('throws for numbers > MAX_UINT32', () => { + expect(() => encodeUInt32(4294967296)).toThrow( + 'Value must not exceed 4294967295', + ); + }); + + test('throws for non-integers', () => { + expect(() => encodeUInt32(3.14)).toThrow('Value must be an integer'); + }); + + test('throws for NaN', () => { + expect(() => encodeUInt32(NaN)).toThrow( + 'Value must be a finite number', + ); + }); + + test('throws for Infinity', () => { + expect(() => encodeUInt32(Infinity)).toThrow( + 'Value must be a finite number', + ); + }); + }); + }); + + describe('decodeUInt32', () => { + describe('round-trip verification', () => { + test('round-trips encode/decode for 0', () => { + const encoded = encodeUInt32(0); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(0); + expect(nextIndex).toBe(1); + }); + + test('round-trips encode/decode for 127', () => { + const encoded = encodeUInt32(127); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(127); + expect(nextIndex).toBe(1); + }); + + test('round-trips encode/decode for 128', () => { + const encoded = encodeUInt32(128); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(128); + expect(nextIndex).toBe(2); + }); + + test('round-trips encode/decode for 16383', () => { + const encoded = encodeUInt32(16383); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(16383); + expect(nextIndex).toBe(2); + }); + + test('round-trips encode/decode for 300', () => { + const encoded = encodeUInt32(300); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(300); + expect(nextIndex).toBe(2); + }); + + test('round-trips encode/decode for 1000000', () => { + const encoded = encodeUInt32(1000000); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(1000000); + expect(nextIndex).toBe(3); + }); + + test('round-trips encode/decode for MAX_UINT32', () => { + const encoded = encodeUInt32(4294967295); + const { value, nextIndex } = decodeUInt32(encoded); + expect(value).toBe(4294967295); + expect(nextIndex).toBe(5); + }); + + test('round-trips 1000 random values between 0 and 1000000', () => { + for (let i = 0; i < 1000; i++) { + const original = Math.floor(Math.random() * 1000000); + const encoded = encodeUInt32(original); + const { value } = decodeUInt32(encoded); + expect(value).toBe(original); + } + }); + }); + + describe('offset handling', () => { + test('decodes from offset 0 by default', () => { + const data = new Uint8Array([0x2a]); // 42 + const { value, nextIndex } = decodeUInt32(data); + expect(value).toBe(42); + expect(nextIndex).toBe(1); + }); + + test('decodes from specified offset', () => { + const data = new Uint8Array([0xff, 0xff, 0xac, 0x02]); // garbage, then 300 + const { value, nextIndex } = decodeUInt32(data, 2); + expect(value).toBe(300); + expect(nextIndex).toBe(4); + }); + + test('returns correct nextIndex after decoding', () => { + const data = encodeUInt32(128); + const { nextIndex } = decodeUInt32(data); + expect(nextIndex).toBe(2); + }); + + test('decodes multiple values in sequence using nextIndex', () => { + // Encode three values: 42, 300, 1000000 + const encoded1 = encodeUInt32(42); + const encoded2 = encodeUInt32(300); + const encoded3 = encodeUInt32(1000000); + + // Concatenate into single buffer + const buffer = new Uint8Array( + encoded1.length + encoded2.length + encoded3.length, + ); + buffer.set(encoded1, 0); + buffer.set(encoded2, encoded1.length); + buffer.set(encoded3, encoded1.length + encoded2.length); + + // Decode sequentially + const result1 = decodeUInt32(buffer, 0); + expect(result1.value).toBe(42); + + const result2 = decodeUInt32(buffer, result1.nextIndex); + expect(result2.value).toBe(300); + + const result3 = decodeUInt32(buffer, result2.nextIndex); + expect(result3.value).toBe(1000000); + }); + }); + + describe('invalid inputs', () => { + test('throws for offset beyond buffer bounds', () => { + const data = new Uint8Array([0x2a]); + expect(() => decodeUInt32(data, 5)).toThrow( + 'Offset 5 is out of bounds', + ); + }); + + test('throws for negative offset', () => { + const data = new Uint8Array([0x2a]); + expect(() => decodeUInt32(data, -1)).toThrow( + 'Offset -1 is out of bounds', + ); + }); + + test('throws for truncated encoding (incomplete byte sequence)', () => { + // Create a truncated encoding: 0x80 indicates more bytes follow, but none present + const data = new Uint8Array([0x80]); + expect(() => decodeUInt32(data)).toThrow('Truncated LEB128 encoding'); + }); + + test('throws for truncated multi-byte encoding', () => { + // 0x80 0x80 indicates at least 3 bytes needed, but only 2 present + const data = new Uint8Array([0x80, 0x80]); + expect(() => decodeUInt32(data)).toThrow('Truncated LEB128 encoding'); + }); + + test('throws for encoding that exceeds uint32 range', () => { + // 6 bytes with continuation bits (should never happen for uint32) + const data = new Uint8Array([0x80, 0x80, 0x80, 0x80, 0x80, 0x01]); + expect(() => decodeUInt32(data)).toThrow( + 'LEB128 sequence exceeds maximum length for uint32', + ); + }); + }); + }); + + describe('compatibility with leb package', () => { + // These tests ensure wire-format compatibility with the original leb package + // If these tests pass, existing encrypted data can be decrypted after the migration + + test('produces identical output to leb.encodeUInt32 for value 42', () => { + const result = encodeUInt32(42); + // Known output from leb package + expect(result).toEqual(new Uint8Array([0x2a])); + }); + + test('produces identical output to leb.encodeUInt32 for value 300', () => { + const result = encodeUInt32(300); + // Known output from leb package + expect(result).toEqual(new Uint8Array([0xac, 0x02])); + }); + + test('produces identical output to leb.encodeUInt32 for value 1000000', () => { + const result = encodeUInt32(1000000); + // Known output from leb package + expect(result).toEqual(new Uint8Array([0xc0, 0x84, 0x3d])); + }); + + test('decodes leb.encodeUInt32 output correctly', () => { + // These are known outputs from the leb package + const knownEncodings: Array<[number, number[]]> = [ + [0, [0x00]], + [42, [0x2a]], + [127, [0x7f]], + [128, [0x80, 0x01]], + [300, [0xac, 0x02]], + [1000000, [0xc0, 0x84, 0x3d]], + [4294967295, [0xff, 0xff, 0xff, 0xff, 0x0f]], + ]; + + for (const [expectedValue, bytes] of knownEncodings) { + const { value } = decodeUInt32(new Uint8Array(bytes)); + expect(value).toBe(expectedValue); + } + }); + }); +}); diff --git a/src/common/utils/leb128.ts b/src/common/utils/leb128.ts new file mode 100644 index 000000000..26f81cb46 --- /dev/null +++ b/src/common/utils/leb128.ts @@ -0,0 +1,104 @@ +/** + * LEB128 (Little Endian Base 128) encoding for unsigned 32-bit integers. + * Variable-length encoding: each byte stores 7 bits of data, bit 7 is continuation flag. + */ + +const MAX_UINT32 = 0xffffffff; +const CONTINUATION_BIT = 0x80; +const DATA_BITS_MASK = 0x7f; +const DATA_BITS_PER_BYTE = 7; +const MAX_BYTES_FOR_UINT32 = 5; + +/** + * Encodes an unsigned 32-bit integer into LEB128 format. + * + * @param value - Unsigned 32-bit integer (0 to 4,294,967,295) + * @returns Encoded bytes (1-5 bytes depending on value) + */ +export function encodeUInt32(value: number): Uint8Array { + validateUInt32(value); + + if (value === 0) { + return new Uint8Array([0]); + } + + const bytes: number[] = []; + + do { + let byte = value & DATA_BITS_MASK; + value >>>= DATA_BITS_PER_BYTE; + + if (value !== 0) { + byte |= CONTINUATION_BIT; + } + + bytes.push(byte); + } while (value !== 0); + + return new Uint8Array(bytes); +} + +/** + * Decodes an unsigned 32-bit integer from LEB128 format. + * + * @param data - Buffer containing LEB128 encoded data + * @param offset - Starting position in buffer (default: 0) + * @returns Decoded value and index after last byte read + */ +export function decodeUInt32( + data: Uint8Array, + offset = 0, +): { value: number; nextIndex: number } { + validateOffset(data, offset); + + let result = 0; + let shift = 0; + let index = offset; + let bytesRead = 0; + + while (index < data.length) { + const byte = data[index++]; + bytesRead++; + + if (bytesRead > MAX_BYTES_FOR_UINT32) { + throw new Error('LEB128 sequence exceeds maximum length for uint32'); + } + + result |= (byte & DATA_BITS_MASK) << shift; + + if (!hasContinuationBit(byte)) { + return { value: result >>> 0, nextIndex: index }; + } + + shift += DATA_BITS_PER_BYTE; + } + + throw new Error('Truncated LEB128 encoding'); +} + +function validateUInt32(value: number): void { + if (!Number.isFinite(value)) { + throw new Error('Value must be a finite number'); + } + if (!Number.isInteger(value)) { + throw new Error('Value must be an integer'); + } + if (value < 0) { + throw new Error('Value must be non-negative'); + } + if (value > MAX_UINT32) { + throw new Error(`Value must not exceed ${MAX_UINT32} (MAX_UINT32)`); + } +} + +function validateOffset(data: Uint8Array, offset: number): void { + if (offset < 0 || offset >= data.length) { + throw new Error( + `Offset ${offset} is out of bounds (buffer length: ${data.length})`, + ); + } +} + +function hasContinuationBit(byte: number): boolean { + return (byte & CONTINUATION_BIT) !== 0; +} diff --git a/src/common/utils/pagination.spec.ts b/src/common/utils/pagination.spec.ts new file mode 100644 index 000000000..b7899b12f --- /dev/null +++ b/src/common/utils/pagination.spec.ts @@ -0,0 +1,162 @@ +import { List, PaginationOptions } from '../interfaces'; +import { AutoPaginatable } from './pagination'; + +type TestObject = { + id: string; +}; + +describe('AutoPaginatable', () => { + let mockApiCall: jest.Mock; + + beforeEach(() => { + jest.useFakeTimers(); + mockApiCall = jest.fn(); + }); + + afterEach(() => { + jest.useRealTimers(); + jest.clearAllMocks(); + }); + + it('returns initial data when limit is specified', async () => { + const initialData: List = { + object: 'list', + data: [{ id: '1' }, { id: '2' }], + listMetadata: { after: 'cursor1' }, + }; + + const paginatable = new AutoPaginatable( + initialData, + mockApiCall, + { limit: 2 }, + ); + + const result = await paginatable.autoPagination(); + + expect(result).toEqual(initialData.data); + expect(mockApiCall).not.toHaveBeenCalled(); + }); + + it('paginates through all pages', async () => { + const initialData: List = { + object: 'list', + data: [{ id: '1' }, { id: '2' }], + listMetadata: { after: 'cursor1' }, + }; + + mockApiCall + .mockResolvedValueOnce({ + object: 'list', + data: [{ id: '3' }, { id: '4' }], + listMetadata: { after: 'cursor2' }, + }) + .mockResolvedValueOnce({ + object: 'list', + data: [{ id: '5' }, { id: '6' }], + listMetadata: { after: null }, + }); + + const paginatable = new AutoPaginatable( + initialData, + mockApiCall, + ); + + const resultPromise = paginatable.autoPagination(); + + // Fast-forward through setTimeout calls + await jest.advanceTimersByTimeAsync(350); + + const result = await resultPromise; + + expect(result).toEqual([ + { id: '3' }, + { id: '4' }, + { id: '5' }, + { id: '6' }, + ]); + + expect(mockApiCall).toHaveBeenCalledTimes(2); + expect(mockApiCall).toHaveBeenNthCalledWith(1, { + limit: 100, + after: undefined, + }); + expect(mockApiCall).toHaveBeenNthCalledWith(2, { + limit: 100, + after: 'cursor2', + }); + }); + + it('respects rate limiting between requests', async () => { + const initialData: List = { + object: 'list', + data: [{ id: '1' }], + listMetadata: { after: 'cursor1' }, + }; + + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); + + mockApiCall + .mockResolvedValueOnce({ + object: 'list', + data: [{ id: '2' }], + listMetadata: { after: 'cursor2' }, + }) + .mockResolvedValueOnce({ + object: 'list', + data: [{ id: '3' }], + listMetadata: { after: null }, + }); + + const paginatable = new AutoPaginatable( + initialData, + mockApiCall, + ); + + const resultPromise = paginatable.autoPagination(); + + await jest.advanceTimersByTimeAsync(700); // 350ms * 2 for two pages + await resultPromise; + + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 350); + }); + + it('passes through additional options to API calls', async () => { + const initialData: List = { + object: 'list', + data: [{ id: '1' }], + listMetadata: { after: 'cursor1' }, + }; + + mockApiCall + .mockResolvedValueOnce({ + object: 'list', + data: [{ id: '2' }], + listMetadata: { after: 'cursor2' }, + }) + .mockResolvedValueOnce({ + object: 'list', + data: [{ id: '3' }], + listMetadata: { after: null }, + }); + + const paginatable = new AutoPaginatable< + TestObject, + PaginationOptions & { status: 'active' } + >(initialData, mockApiCall, { status: 'active' }); + + const resultPromise = paginatable.autoPagination(); + jest.advanceTimersByTimeAsync(1000); + await resultPromise; + + expect(mockApiCall).toHaveBeenNthCalledWith(1, { + after: undefined, + status: 'active', + limit: 100, + }); + expect(mockApiCall).toHaveBeenNthCalledWith(2, { + after: 'cursor2', + status: 'active', + limit: 100, + }); + }); +}); diff --git a/src/common/utils/pagination.ts b/src/common/utils/pagination.ts index 4a5d8bf86..bd349365b 100644 --- a/src/common/utils/pagination.ts +++ b/src/common/utils/pagination.ts @@ -1,20 +1,21 @@ import { List, PaginationOptions } from '../interfaces'; -export class AutoPaginatable { - readonly object: 'list' = 'list'; - readonly options: PaginationOptions; +export class AutoPaginatable< + ResourceType, + ParametersType extends PaginationOptions = PaginationOptions, +> { + readonly object = 'list' as const; + readonly options: ParametersType; constructor( - protected list: List, - private apiCall: (params: PaginationOptions) => Promise>, - options?: PaginationOptions, + protected list: List, + private apiCall: (params: PaginationOptions) => Promise>, + options?: ParametersType, ) { - this.options = { - ...options, - }; + this.options = options ?? ({} as ParametersType); } - get data(): T[] { + get data(): ResourceType[] { return this.list.data; } @@ -22,7 +23,9 @@ export class AutoPaginatable { return this.list.listMetadata; } - private async *generatePages(params: PaginationOptions): AsyncGenerator { + private async *generatePages( + params: PaginationOptions, + ): AsyncGenerator { const result = await this.apiCall({ ...this.options, limit: 100, @@ -42,12 +45,12 @@ export class AutoPaginatable { * Automatically paginates over the list of results, returning the complete data set. * Returns the first result if `options.limit` is passed to the first request. */ - async autoPagination(): Promise { + async autoPagination(): Promise { if (this.options.limit) { return this.data; } - const results: T[] = []; + const results: ResourceType[] = []; for await (const page of this.generatePages({ after: this.options.after, diff --git a/src/common/utils/query-string.ts b/src/common/utils/query-string.ts new file mode 100644 index 000000000..428b28c1f --- /dev/null +++ b/src/common/utils/query-string.ts @@ -0,0 +1,57 @@ +type QueryValue = + | string + | string[] + | Record + | undefined; + +/** + * Converts options to a query string. + * - Arrays: scope=read&scope=write (repeat format) + * - Objects: params[key]=value (bracket notation) + * - Encoding: RFC1738 (space as +) + * - Keys sorted alphabetically + */ +export function toQueryString(options: Record): string { + const params: Array<[string, string]> = []; + const sortedKeys = Object.keys(options).sort((a, b) => a.localeCompare(b)); + + for (const key of sortedKeys) { + const value = options[key]; + + if (value === undefined) { + continue; + } + + if (Array.isArray(value)) { + for (const item of value) { + params.push([key, String(item)]); + } + } else if (typeof value === 'object' && value !== null) { + const sortedSubKeys = Object.keys(value).sort((a, b) => + a.localeCompare(b), + ); + for (const subKey of sortedSubKeys) { + const subValue = value[subKey]; + if (subValue !== undefined) { + params.push([`${key}[${subKey}]`, String(subValue)]); + } + } + } else { + params.push([key, String(value)]); + } + } + + return params + .map(([key, value]) => { + const encodedKey = encodeRFC1738(key); + const encodedValue = encodeRFC1738(value); + return `${encodedKey}=${encodedValue}`; + }) + .join('&'); +} + +function encodeRFC1738(str: string): string { + return encodeURIComponent(str) + .replace(/%20/g, '+') + .replace(/[!'*]/g, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase()); +} diff --git a/src/common/utils/runtime-info.spec.ts b/src/common/utils/runtime-info.spec.ts new file mode 100644 index 000000000..a901081ae --- /dev/null +++ b/src/common/utils/runtime-info.spec.ts @@ -0,0 +1,235 @@ +import { getRuntimeInfo } from './runtime-info'; +import { detectRuntime } from './env'; + +// Mock the env module +jest.mock('./env'); +const mockDetectRuntime = detectRuntime as jest.MockedFunction< + typeof detectRuntime +>; + +describe('RuntimeInfo', () => { + let originalProcess: any; + let originalGlobalThis: any; + let originalNavigator: any; + + beforeEach(() => { + // Store original globals + originalProcess = global.process; + originalGlobalThis = globalThis; + originalNavigator = global.navigator; + + // Reset mocks + mockDetectRuntime.mockReset(); + }); + + afterEach(() => { + // Restore original globals + global.process = originalProcess; + Object.assign(globalThis, originalGlobalThis); + global.navigator = originalNavigator; + }); + + describe('Node.js runtime', () => { + it('returns node runtime with version', () => { + mockDetectRuntime.mockReturnValue('node'); + global.process = { version: 'v20.5.0' } as any; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'node', + version: 'v20.5.0', + }); + }); + + it('handles missing process.version gracefully', () => { + mockDetectRuntime.mockReturnValue('node'); + global.process = {} as any; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'node', + version: undefined, + }); + }); + + it('handles missing process object gracefully', () => { + mockDetectRuntime.mockReturnValue('node'); + delete (global as any).process; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'node', + version: undefined, + }); + }); + }); + + describe('Deno runtime', () => { + it('returns deno runtime with version', () => { + mockDetectRuntime.mockReturnValue('deno'); + (globalThis as any).Deno = { + version: { deno: '1.36.4' }, + }; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'deno', + version: '1.36.4', + }); + }); + + it('handles missing Deno.version gracefully', () => { + mockDetectRuntime.mockReturnValue('deno'); + (globalThis as any).Deno = {}; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'deno', + version: undefined, + }); + }); + + it('handles missing Deno object gracefully', () => { + mockDetectRuntime.mockReturnValue('deno'); + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'deno', + version: undefined, + }); + }); + }); + + describe('Bun runtime', () => { + it('returns bun runtime with version from Bun.version', () => { + mockDetectRuntime.mockReturnValue('bun'); + (globalThis as any).Bun = { version: '1.0.0' }; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'bun', + version: '1.0.0', + }); + }); + + it('falls back to navigator.userAgent for Bun version', () => { + mockDetectRuntime.mockReturnValue('bun'); + // Clear any existing Bun global + delete (globalThis as any).Bun; + global.navigator = { + userAgent: 'Bun/1.0.25', + } as any; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'bun', + version: '1.0.25', + }); + }); + + it('handles missing version sources gracefully', () => { + mockDetectRuntime.mockReturnValue('bun'); + // Clear any existing Bun global and navigator + delete (globalThis as any).Bun; + delete (global as any).navigator; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'bun', + version: undefined, + }); + }); + + it('handles malformed navigator.userAgent gracefully', () => { + mockDetectRuntime.mockReturnValue('bun'); + // Clear any existing Bun global + delete (globalThis as any).Bun; + global.navigator = { + userAgent: 'SomeOtherRuntime/1.0.0', + } as any; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'bun', + version: undefined, + }); + }); + }); + + describe('Edge runtimes', () => { + it.each(['cloudflare', 'fastly', 'edge-light', 'other'] as const)( + 'returns %s runtime without version', + (runtime) => { + mockDetectRuntime.mockReturnValue(runtime); + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: runtime, + version: undefined, + }); + }, + ); + }); + + describe('Error handling', () => { + it('handles exceptions during version detection gracefully', () => { + mockDetectRuntime.mockReturnValue('node'); + + // Create a process object that throws when accessing version + global.process = { + get version() { + throw new Error('Access denied'); + }, + } as any; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'node', + version: undefined, + }); + }); + + it('handles exceptions during Deno version detection gracefully', () => { + mockDetectRuntime.mockReturnValue('deno'); + + // Create a Deno object that throws when accessing version + (globalThis as any).Deno = { + get version() { + throw new Error('Access denied'); + }, + }; + + const result = getRuntimeInfo(); + + expect(result).toEqual({ + name: 'deno', + version: undefined, + }); + }); + }); + + describe('Real-world scenarios', () => { + it('works with actual Node.js environment', () => { + // Test with real Node.js environment + mockDetectRuntime.mockReturnValue('node'); + + const result = getRuntimeInfo(); + + // In test environment, this should be Node.js with real process.version + expect(result.name).toBe('node'); + expect(result.version).toMatch(/^v\d+\.\d+\.\d+/); + }); + }); +}); diff --git a/src/common/utils/runtime-info.ts b/src/common/utils/runtime-info.ts new file mode 100644 index 000000000..70f90e37c --- /dev/null +++ b/src/common/utils/runtime-info.ts @@ -0,0 +1,83 @@ +import { detectRuntime } from './env'; + +// Extend globalThis to include runtime-specific globals +declare global { + var Deno: + | { + version: { + deno: string; + }; + } + | undefined; + + var Bun: + | { + version: string; + } + | undefined; +} + +export interface RuntimeInfo { + name: string; + version?: string; +} + +/** + * Get runtime information including name and version. + * Safely extracts version information for different JavaScript runtimes. + * @returns RuntimeInfo object with name and optional version + */ +export function getRuntimeInfo(): RuntimeInfo { + const name = detectRuntime(); + let version: string | undefined; + + try { + switch (name) { + case 'node': + // process.version includes 'v' prefix (e.g., "v20.5.0") + version = typeof process !== 'undefined' ? process.version : undefined; + break; + + case 'deno': + // Deno.version.deno returns just version number (e.g., "1.36.4") + version = globalThis.Deno?.version?.deno; + break; + + case 'bun': + version = globalThis.Bun?.version || extractBunVersionFromUserAgent(); + break; + + // These environments typically don't expose version info + case 'cloudflare': + case 'fastly': + case 'edge-light': + case 'other': + default: + version = undefined; + break; + } + } catch { + version = undefined; + } + + return { + name, + version, + }; +} + +/** + * Extract Bun version from navigator.userAgent as fallback. + * @returns Bun version string or undefined + */ +function extractBunVersionFromUserAgent(): string | undefined { + try { + if (typeof navigator !== 'undefined' && navigator.userAgent) { + const match = navigator.userAgent.match(/Bun\/(\d+\.\d+\.\d+)/); + return match?.[1]; + } + } catch { + // Ignore errors + } + return undefined; +} diff --git a/src/common/utils/test-utils.ts b/src/common/utils/test-utils.ts index a90b094b8..89269a88c 100644 --- a/src/common/utils/test-utils.ts +++ b/src/common/utils/test-utils.ts @@ -1,7 +1,7 @@ import fetch, { MockParams } from 'jest-fetch-mock'; export function fetchOnce( - response: {} = {}, + response = {}, { status = 200, headers, ...rest }: MockParams = {}, ) { return fetch.once(JSON.stringify(response), { diff --git a/src/common/utils/unreachable.ts b/src/common/utils/unreachable.ts index 027562d9b..75ffae5fb 100644 --- a/src/common/utils/unreachable.ts +++ b/src/common/utils/unreachable.ts @@ -9,7 +9,6 @@ */ export const unreachable = ( condition: never, - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions message = `Entered unreachable code. Received '${condition}'.`, ): never => { throw new TypeError(message); diff --git a/src/directory-sync/directory-sync.spec.ts b/src/directory-sync/directory-sync.spec.ts index 35149e98d..2f2b6cb17 100644 --- a/src/directory-sync/directory-sync.spec.ts +++ b/src/directory-sync/directory-sync.spec.ts @@ -81,21 +81,12 @@ describe('DirectorySync', () => { directoryId: 'dir_123', organizationId: 'org_123', email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], firstName: 'Jon', groups: [group], idpId: 'idp_foo', lastName: 'Snow', - jobTitle: 'Knight of the Watch', rawAttributes: {}, state: 'active', - username: 'jonsnow', createdAt: '2021-10-27 15:21:50.640959', updatedAt: '2021-12-13 12:15:45.531847', }; @@ -109,21 +100,12 @@ describe('DirectorySync', () => { directory_id: 'dir_123', organization_id: 'org_123', email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], first_name: 'Jon', groups: [groupResponse], idp_id: 'idp_foo', last_name: 'Snow', - job_title: 'Knight of the Watch', raw_attributes: {}, state: 'active', - username: 'jonsnow', created_at: '2021-10-27 15:21:50.640959', updated_at: '2021-12-13 12:15:45.531847', }; @@ -137,21 +119,12 @@ describe('DirectorySync', () => { directoryId: 'dir_123', organizationId: 'org_123', email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], firstName: 'Jon', groups: [group], idpId: 'idp_foo', lastName: 'Snow', - jobTitle: 'Knight of the Watch', rawAttributes: {}, state: 'active', - username: 'jonsnow', role: { slug: 'super_admin' }, roles: [{ slug: 'super_admin' }], createdAt: '2021-10-27 15:21:50.640959', @@ -167,21 +140,12 @@ describe('DirectorySync', () => { directory_id: 'dir_123', organization_id: 'org_123', email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], first_name: 'Jon', groups: [groupResponse], idp_id: 'idp_foo', last_name: 'Snow', - job_title: 'Knight of the Watch', raw_attributes: {}, state: 'active', - username: 'jonsnow', role: { slug: 'super_admin' }, roles: [{ slug: 'super_admin' }], created_at: '2021-10-27 15:21:50.640959', @@ -471,9 +435,8 @@ describe('DirectorySync', () => { it(`requests a Directory User`, async () => { fetchOnce(userWithRoleResponse); - const subject = await workos.directorySync.getUser( - 'directory_user_456', - ); + const subject = + await workos.directorySync.getUser('directory_user_456'); expect(subject).toEqual(userWithRoles); }); diff --git a/src/directory-sync/directory-sync.ts b/src/directory-sync/directory-sync.ts index 6f9ff98bd..fe3110fe7 100644 --- a/src/directory-sync/directory-sync.ts +++ b/src/directory-sync/directory-sync.ts @@ -11,6 +11,7 @@ import { ListDirectoriesOptions, ListDirectoryGroupsOptions, ListDirectoryUsersOptions, + SerializedListDirectoriesOptions, } from './interfaces'; import { deserializeDirectory, @@ -25,7 +26,7 @@ export class DirectorySync { async listDirectories( options?: ListDirectoriesOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -58,7 +59,7 @@ export class DirectorySync { async listGroups( options: ListDirectoryGroupsOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -79,7 +80,12 @@ export class DirectorySync { async listUsers( options: ListDirectoryUsersOptions, - ): Promise>> { + ): Promise< + AutoPaginatable< + DirectoryUserWithGroups, + ListDirectoryUsersOptions + > + > { return new AutoPaginatable( await fetchAndDeserialize< DirectoryUserWithGroupsResponse, diff --git a/src/directory-sync/interfaces/directory-user.interface.ts b/src/directory-sync/interfaces/directory-user.interface.ts index c445b012d..6338a6243 100644 --- a/src/directory-sync/interfaces/directory-user.interface.ts +++ b/src/directory-sync/interfaces/directory-user.interface.ts @@ -19,26 +19,7 @@ export interface DirectoryUser< idpId: string; firstName: string | null; email: string | null; - /** @deprecated Will be removed in a future major version. - * Enable the `emails` custom attribute in dashboard and pull from customAttributes instead. - * See https://workos.com/docs/directory-sync/attributes/custom-attributes/auto-mapped-attributes for details. - */ - emails: { - type?: string; - value?: string; - primary?: boolean; - }[]; - /** @deprecated Will be removed in a future major version. - * Enable the `username` custom attribute in dashboard and pull from customAttributes instead. - * See https://workos.com/docs/directory-sync/attributes/custom-attributes/auto-mapped-attributes for details. - */ - username: string | null; lastName: string | null; - /** @deprecated Will be removed in a future major version. - * Enable the `job_title` custom attribute in dashboard and pull from customAttributes instead. - * See https://workos.com/docs/directory-sync/attributes/custom-attributes/auto-mapped-attributes for details. - */ - jobTitle: string | null; state: 'active' | 'inactive'; role?: RoleResponse; roles?: RoleResponse[]; @@ -59,26 +40,7 @@ export interface DirectoryUserResponse< idp_id: string; first_name: string | null; email: string | null; - /** @deprecated Will be removed in a future major version. - * Enable the `emails` custom attribute in dashboard and pull from customAttributes instead. - * See https://workos.com/docs/directory-sync/attributes/custom-attributes/auto-mapped-attributes for details. - */ - emails: { - type?: string; - value?: string; - primary?: boolean; - }[]; - /** @deprecated Will be removed in a future major version. - * Enable the `username` custom attribute in dashboard and pull from customAttributes instead. - * See https://workos.com/docs/directory-sync/attributes/custom-attributes/auto-mapped-attributes for details. - */ - username: string | null; last_name: string | null; - /** @deprecated Will be removed in a future major version. - * Enable the `job_title` custom attribute in dashboard and pull from customAttributes instead. - * See https://workos.com/docs/directory-sync/attributes/custom-attributes/auto-mapped-attributes for details. - */ - job_title: string | null; state: 'active' | 'inactive'; role?: RoleResponse; roles?: RoleResponse[]; diff --git a/src/directory-sync/serializers/directory-user.serializer.ts b/src/directory-sync/serializers/directory-user.serializer.ts index b45509d79..2ab99c3e5 100644 --- a/src/directory-sync/serializers/directory-user.serializer.ts +++ b/src/directory-sync/serializers/directory-user.serializer.ts @@ -23,10 +23,7 @@ export const deserializeDirectoryUser = < idpId: directoryUser.idp_id, firstName: directoryUser.first_name, email: directoryUser.email, - emails: directoryUser.emails, - username: directoryUser.username, lastName: directoryUser.last_name, - jobTitle: directoryUser.job_title, state: directoryUser.state, role: directoryUser.role, roles: directoryUser.roles, @@ -55,10 +52,7 @@ export const deserializeUpdatedEventDirectoryUser = ( idpId: directoryUser.idp_id, firstName: directoryUser.first_name, email: directoryUser.email, - emails: directoryUser.emails, - username: directoryUser.username, lastName: directoryUser.last_name, - jobTitle: directoryUser.job_title, state: directoryUser.state, role: directoryUser.role, roles: directoryUser.roles, diff --git a/src/directory-sync/utils/get-primary-email.spec.ts b/src/directory-sync/utils/get-primary-email.spec.ts deleted file mode 100644 index 3ec704fd9..000000000 --- a/src/directory-sync/utils/get-primary-email.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { getPrimaryEmail } from './get-primary-email'; -import { DirectoryUser } from '../interfaces'; - -describe('getPrimaryEmail', () => { - const user: DirectoryUser = { - object: 'directory_user', - id: 'user_123', - customAttributes: { - custom: true, - }, - directoryId: 'dir_123', - organizationId: 'org_123', - email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], - firstName: 'Jon', - idpId: 'idp_foo', - lastName: 'Snow', - rawAttributes: {}, - state: 'active', - username: 'jonsnow', - jobTitle: 'Knight of the Watch', - createdAt: '2021-10-27 15:21:50.640958', - updatedAt: '2021-12-13 12:15:45.531847', - }; - - it(`returns primary email value`, () => { - const primaryEmail = getPrimaryEmail(user); - - expect(primaryEmail).toEqual('jonsnow@workos.com'); - }); -}); diff --git a/src/directory-sync/utils/get-primary-email.ts b/src/directory-sync/utils/get-primary-email.ts deleted file mode 100644 index dd74f3f24..000000000 --- a/src/directory-sync/utils/get-primary-email.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { DirectoryUser } from '../interfaces/directory-user.interface'; - -export function getPrimaryEmail(user: DirectoryUser): string | undefined { - const primaryEmail = user.emails?.find((email) => email.primary); - return primaryEmail?.value; -} diff --git a/src/events/events.spec.ts b/src/events/events.spec.ts index f7fd6e82f..8a69f2e37 100644 --- a/src/events/events.spec.ts +++ b/src/events/events.spec.ts @@ -28,7 +28,6 @@ describe('Event', () => { organizationId: 'org_1234', name: 'Connection', type: ConnectionType.OktaSAML, - connectionType: ConnectionType.OktaSAML, state: 'active', domains: [], createdAt: '2020-05-06 04:21:48.649164', @@ -137,20 +136,11 @@ describe('Event', () => { directoryId: 'dir_123', organizationId: 'org_123', email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], firstName: 'Jon', idpId: 'idp_foo', lastName: 'Snow', - jobTitle: 'Knight of the Watch', rawAttributes: {}, state: 'active', - username: 'jonsnow', role: { slug: 'super_admin' }, previousAttributes: { role: { slug: 'member' }, @@ -173,20 +163,11 @@ describe('Event', () => { directory_id: 'dir_123', organization_id: 'org_123', email: 'jonsnow@workos.com', - emails: [ - { - primary: true, - type: 'type', - value: 'jonsnow@workos.com', - }, - ], first_name: 'Jon', idp_id: 'idp_foo', last_name: 'Snow', - job_title: 'Knight of the Watch', raw_attributes: {}, state: 'active', - username: 'jonsnow', role: { slug: 'super_admin' }, previous_attributes: { role: { slug: 'member' }, diff --git a/src/factory.spec.ts b/src/factory.spec.ts new file mode 100644 index 000000000..97352eb56 --- /dev/null +++ b/src/factory.spec.ts @@ -0,0 +1,181 @@ +import { + createWorkOS, + type PublicUserManagement, + type PublicSSO, +} from './factory'; + +describe('createWorkOS', () => { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...OLD_ENV }; + delete process.env.WORKOS_API_KEY; + delete process.env.WORKOS_CLIENT_ID; + }); + + afterEach(() => { + process.env = OLD_ENV; + }); + + describe('with only clientId (public client)', () => { + it('returns a WorkOS instance with clientId', () => { + const workos = createWorkOS({ clientId: 'client_123' }); + + expect(workos.clientId).toBe('client_123'); + expect(workos.baseURL).toBeDefined(); + }); + + it('has access to PKCE utilities', () => { + const workos = createWorkOS({ clientId: 'client_123' }); + + expect(workos.pkce).toBeDefined(); + expect(typeof workos.pkce.generate).toBe('function'); + expect(typeof workos.pkce.generateCodeVerifier).toBe('function'); + expect(typeof workos.pkce.generateCodeChallenge).toBe('function'); + }); + + it('has access to public userManagement methods', () => { + const workos = createWorkOS({ clientId: 'client_123' }); + + expect(typeof workos.userManagement.getAuthorizationUrl).toBe('function'); + expect(typeof workos.userManagement.getAuthorizationUrlWithPKCE).toBe( + 'function', + ); + expect(typeof workos.userManagement.authenticateWithCodeAndVerifier).toBe( + 'function', + ); + expect(typeof workos.userManagement.authenticateWithRefreshToken).toBe( + 'function', + ); + expect(typeof workos.userManagement.getLogoutUrl).toBe('function'); + expect(typeof workos.userManagement.getJwksUrl).toBe('function'); + }); + + it('has access to public SSO methods', () => { + const workos = createWorkOS({ clientId: 'client_123' }); + + expect(typeof workos.sso.getAuthorizationUrl).toBe('function'); + expect(typeof workos.sso.getAuthorizationUrlWithPKCE).toBe('function'); + }); + }); + + describe('with apiKey (confidential client)', () => { + it('returns a WorkOS instance with API key', () => { + const workos = createWorkOS({ + apiKey: 'sk_test_123', + clientId: 'client_123', + }); + + expect(workos.key).toBe('sk_test_123'); + expect(workos.clientId).toBe('client_123'); + expect(workos.baseURL).toBeDefined(); + }); + + it('has access to all services', () => { + const workos = createWorkOS({ + apiKey: 'sk_test_123', + clientId: 'client_123', + }); + + expect(workos.userManagement).toBeDefined(); + expect(workos.sso).toBeDefined(); + expect(workos.organizations).toBeDefined(); + expect(workos.directorySync).toBeDefined(); + expect(workos.auditLogs).toBeDefined(); + }); + }); + + /** + * Type-level tests - these verify compile-time behavior. + * If these compile, the types are working correctly. + */ + describe('type safety (compile-time verification)', () => { + it('PublicWorkOS type has narrowed userManagement', () => { + // This test verifies the type structure at compile time + const workos = createWorkOS({ clientId: 'client_123' }); + + // These should be available on PublicUserManagement + const _getAuthUrl: PublicUserManagement['getAuthorizationUrl'] = + workos.userManagement.getAuthorizationUrl; + const _getAuthUrlPKCE: PublicUserManagement['getAuthorizationUrlWithPKCE'] = + workos.userManagement.getAuthorizationUrlWithPKCE; + const _authWithCodeAndVerifier: PublicUserManagement['authenticateWithCodeAndVerifier'] = + workos.userManagement.authenticateWithCodeAndVerifier; + const _authWithRefresh: PublicUserManagement['authenticateWithRefreshToken'] = + workos.userManagement.authenticateWithRefreshToken; + const _logoutUrl: PublicUserManagement['getLogoutUrl'] = + workos.userManagement.getLogoutUrl; + const _jwksUrl: PublicUserManagement['getJwksUrl'] = + workos.userManagement.getJwksUrl; + + // Verify they exist + expect(_getAuthUrl).toBeDefined(); + expect(_getAuthUrlPKCE).toBeDefined(); + expect(_authWithCodeAndVerifier).toBeDefined(); + expect(_authWithRefresh).toBeDefined(); + expect(_logoutUrl).toBeDefined(); + expect(_jwksUrl).toBeDefined(); + }); + + it('PublicWorkOS type has narrowed SSO', () => { + const workos = createWorkOS({ clientId: 'client_123' }); + + const _getAuthUrl: PublicSSO['getAuthorizationUrl'] = + workos.sso.getAuthorizationUrl; + const _getAuthUrlPKCE: PublicSSO['getAuthorizationUrlWithPKCE'] = + workos.sso.getAuthorizationUrlWithPKCE; + + expect(_getAuthUrl).toBeDefined(); + expect(_getAuthUrlPKCE).toBeDefined(); + }); + + it('confidential client has full WorkOS type', () => { + const workos = createWorkOS({ + apiKey: 'sk_test', + clientId: 'client_123', + }); + + // Full WorkOS should have organizations, directorySync, etc. + expect(workos.organizations).toBeDefined(); + expect(workos.directorySync).toBeDefined(); + expect(workos.auditLogs).toBeDefined(); + expect(workos.events).toBeDefined(); + + // And full userManagement with all methods + expect(typeof workos.userManagement.listUsers).toBe('function'); + expect(typeof workos.userManagement.createUser).toBe('function'); + }); + + it('PublicWorkOS does not expose confidential methods', () => { + const workos = createWorkOS({ clientId: 'client_123' }); + + // These should cause TypeScript errors - proving type narrowing works + // @ts-expect-error - listUsers not available on PublicWorkOS + void workos.userManagement.listUsers; + // @ts-expect-error - createUser not available on PublicWorkOS + void workos.userManagement.createUser; + // @ts-expect-error - organizations not available on PublicWorkOS + void workos.organizations; + // @ts-expect-error - directorySync not available on PublicWorkOS + void workos.directorySync; + // @ts-expect-error - auditLogs not available on PublicWorkOS + void workos.auditLogs; + }); + + it('ignores WORKOS_API_KEY env var for type safety', () => { + process.env.WORKOS_API_KEY = 'sk_from_env'; + + // Factory should return PublicWorkOS based on explicit options, not env + const workos = createWorkOS({ clientId: 'client_123' }); + + // Type is PublicWorkOS, so these should error + // @ts-expect-error - organizations not available on PublicWorkOS + void workos.organizations; + + // Runtime: the underlying WorkOS may have picked up the env var, + // but the TYPE is what matters for compile-time safety + expect(workos.clientId).toBe('client_123'); + }); + }); +}); diff --git a/src/factory.ts b/src/factory.ts new file mode 100644 index 000000000..4673156c1 --- /dev/null +++ b/src/factory.ts @@ -0,0 +1,103 @@ +import { WorkOS } from './workos'; +import type { UserManagement } from './user-management/user-management'; +import type { SSO } from './sso/sso'; +import type { PKCE } from './pkce/pkce'; +import type { WorkOSOptions } from './common/interfaces'; + +/** + * Method names available without API key - single source of truth. + * Add new public methods here to expose them on PublicUserManagement. + */ +type PublicUserManagementMethods = + | 'getAuthorizationUrl' + | 'getAuthorizationUrlWithPKCE' + | 'authenticateWithCode' + | 'authenticateWithCodeAndVerifier' + | 'authenticateWithRefreshToken' + | 'getLogoutUrl' + | 'getJwksUrl'; + +/** + * SSO method names available without API key. + */ +type PublicSSOMethods = + | 'getAuthorizationUrl' + | 'getAuthorizationUrlWithPKCE' + | 'getProfileAndToken'; + +/** + * Subset of UserManagement methods available without an API key. + * Used by public clients (browser, mobile, CLI, desktop apps). + */ +export type PublicUserManagement = Pick< + UserManagement, + PublicUserManagementMethods +>; + +/** + * Subset of SSO methods available without an API key. + */ +export type PublicSSO = Pick; + +/** + * WorkOS client for public/PKCE-only usage. + * Returned when initialized with only clientId (no API key). + * + * For browser, mobile, CLI, and desktop applications that cannot + * securely store an API key. + */ +export interface PublicWorkOS { + readonly baseURL: string; + readonly clientId: string; + readonly pkce: PKCE; + readonly userManagement: PublicUserManagement; + readonly sso: PublicSSO; +} + +/** + * Options for creating a public client (PKCE-only, no API key). + */ +export interface PublicClientOptions extends Omit { + clientId: string; + /** Discriminant: ensures TypeScript selects PublicWorkOS overload when apiKey is absent */ + apiKey?: never; +} + +/** + * Options for creating a confidential client (with API key). + */ +export interface ConfidentialClientOptions extends WorkOSOptions { + apiKey: string; +} + +/** + * Create a type-safe WorkOS client. + * + * Returns a narrowed `PublicWorkOS` type when only `clientId` is provided, + * ensuring compile-time safety for public client usage. Returns the full + * `WorkOS` type when an API key is provided. + * + * Unlike the `WorkOS` constructor, this factory does NOT read from + * environment variables. Pass credentials explicitly for predictable types. + * + * @example + * // Public client (browser, mobile, CLI) - returns PublicWorkOS + * const workos = createWorkOS({ clientId: 'client_123' }); + * await workos.userManagement.getAuthorizationUrlWithPKCE({...}); // OK + * workos.userManagement.listUsers(); // TypeScript error! + * + * @example + * // Confidential client (server) - returns full WorkOS + * const workos = createWorkOS({ + * apiKey: process.env.WORKOS_API_KEY!, + * clientId: 'client_123' + * }); + * await workos.userManagement.listUsers(); // OK + */ +export function createWorkOS(options: PublicClientOptions): PublicWorkOS; +export function createWorkOS(options: ConfidentialClientOptions): WorkOS; +export function createWorkOS( + options: PublicClientOptions | ConfidentialClientOptions, +): PublicWorkOS | WorkOS { + return new WorkOS(options); +} diff --git a/src/feature-flags/feature-flags.spec.ts b/src/feature-flags/feature-flags.spec.ts index e4f33dac1..cc2abf080 100644 --- a/src/feature-flags/feature-flags.spec.ts +++ b/src/feature-flags/feature-flags.spec.ts @@ -109,9 +109,8 @@ describe('FeatureFlags', () => { it('requests a feature flag by slug', async () => { fetchOnce(getFeatureFlagFixture); - const subject = await workos.featureFlags.getFeatureFlag( - 'advanced-dashboard', - ); + const subject = + await workos.featureFlags.getFeatureFlag('advanced-dashboard'); expect(fetchURL()).toContain('/feature-flags/advanced-dashboard'); expect(subject).toEqual({ @@ -133,9 +132,8 @@ describe('FeatureFlags', () => { it('enables a feature flag by slug', async () => { fetchOnce(enableFeatureFlagFixture); - const subject = await workos.featureFlags.enableFeatureFlag( - 'advanced-dashboard', - ); + const subject = + await workos.featureFlags.enableFeatureFlag('advanced-dashboard'); expect(fetchURL()).toContain('/feature-flags/advanced-dashboard/enable'); expect(fetchMethod()).toBe('PUT'); @@ -147,9 +145,8 @@ describe('FeatureFlags', () => { it('disables a feature flag by slug', async () => { fetchOnce(disableFeatureFlagFixture); - const subject = await workos.featureFlags.disableFeatureFlag( - 'advanced-dashboard', - ); + const subject = + await workos.featureFlags.disableFeatureFlag('advanced-dashboard'); expect(fetchURL()).toContain('/feature-flags/advanced-dashboard/disable'); expect(fetchMethod()).toBe('PUT'); diff --git a/src/fga/fga.ts b/src/fga/fga.ts index 24e88aa2b..bb2cfadd9 100644 --- a/src/fga/fga.ts +++ b/src/fga/fga.ts @@ -26,6 +26,9 @@ import { WarrantTokenResponse, BatchWriteResourcesOptions, BatchWriteResourcesResponse, + SerializedListWarrantsOptions, + SerializedListResourcesOptions, + SerializedQueryOptions, } from './interfaces'; import { deserializeBatchWriteResourcesResponse, @@ -105,7 +108,7 @@ export class FGA { async listResources( options?: ListResourcesOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -186,7 +189,7 @@ export class FGA { async listWarrants( options?: ListWarrantsOptions, requestOptions?: ListWarrantsRequestOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -210,8 +213,8 @@ export class FGA { async query( options: QueryOptions, requestOptions: QueryRequestOptions = {}, - ): Promise> { - return new FgaPaginatable( + ): Promise> { + return new FgaPaginatable( await fetchAndDeserializeFGAList( this.workos, '/fga/v1/query', diff --git a/src/fga/serializers/check-options.serializer.ts b/src/fga/serializers/check-options.serializer.ts index a64cd5501..77ceb655a 100644 --- a/src/fga/serializers/check-options.serializer.ts +++ b/src/fga/serializers/check-options.serializer.ts @@ -36,8 +36,8 @@ const serializeCheckWarrantOptions = ( resource_id: isResourceInterface(warrant.resource) ? warrant.resource.getResourceId() : warrant.resource.resourceId - ? warrant.resource.resourceId - : '', + ? warrant.resource.resourceId + : '', relation: warrant.relation, subject: isSubject(warrant.subject) ? { diff --git a/src/fga/serializers/create-resource-options.serializer.ts b/src/fga/serializers/create-resource-options.serializer.ts index 9221e07ad..91914cff3 100644 --- a/src/fga/serializers/create-resource-options.serializer.ts +++ b/src/fga/serializers/create-resource-options.serializer.ts @@ -13,7 +13,7 @@ export const serializeCreateResourceOptions = ( resource_id: isResourceInterface(options.resource) ? options.resource.getResourceId() : options.resource.resourceId - ? options.resource.resourceId - : '', + ? options.resource.resourceId + : '', meta: options.meta, }); diff --git a/src/fga/serializers/delete-resource-options.serializer.ts b/src/fga/serializers/delete-resource-options.serializer.ts index 0a3cc2601..481918631 100644 --- a/src/fga/serializers/delete-resource-options.serializer.ts +++ b/src/fga/serializers/delete-resource-options.serializer.ts @@ -13,6 +13,6 @@ export const serializeDeleteResourceOptions = ( resource_id: isResourceInterface(options) ? options.getResourceId() : options.resourceId - ? options.resourceId - : '', + ? options.resourceId + : '', }); diff --git a/src/fga/serializers/query-result.serializer.ts b/src/fga/serializers/query-result.serializer.ts index 20098bcf9..8d175bc0b 100644 --- a/src/fga/serializers/query-result.serializer.ts +++ b/src/fga/serializers/query-result.serializer.ts @@ -2,8 +2,7 @@ import { QueryResult, QueryResultResponse } from '../interfaces'; import { Warning } from '../interfaces/warning.interface'; import { ListResponse } from '../../common/interfaces'; -export interface QueryResultListResponse - extends ListResponse { +export interface QueryResultListResponse extends ListResponse { warnings?: Warning[]; } diff --git a/src/fga/serializers/write-warrant-options.serializer.ts b/src/fga/serializers/write-warrant-options.serializer.ts index 4b4cd919f..23d17f1b8 100644 --- a/src/fga/serializers/write-warrant-options.serializer.ts +++ b/src/fga/serializers/write-warrant-options.serializer.ts @@ -14,8 +14,8 @@ export const serializeWriteWarrantOptions = ( resource_id: isResourceInterface(warrant.resource) ? warrant.resource.getResourceId() : warrant.resource.resourceId - ? warrant.resource.resourceId - : '', + ? warrant.resource.resourceId + : '', relation: warrant.relation, subject: isSubject(warrant.subject) ? { diff --git a/src/fga/utils/fga-paginatable.ts b/src/fga/utils/fga-paginatable.ts index 9cc3bfe98..7b27c26f6 100644 --- a/src/fga/utils/fga-paginatable.ts +++ b/src/fga/utils/fga-paginatable.ts @@ -3,15 +3,19 @@ import { FGAList } from '../interfaces/list.interface'; import { Warning } from '../interfaces/warning.interface'; import { PaginationOptions } from '../../common/interfaces'; -export class FgaPaginatable extends AutoPaginatable { - protected override list!: FGAList; +export class FgaPaginatable< + T, + P extends PaginationOptions = PaginationOptions, +> extends AutoPaginatable { + protected override list: FGAList; constructor( list: FGAList, apiCall: (params: PaginationOptions) => Promise>, - options?: PaginationOptions, + options?: P, ) { super(list, apiCall, options); + this.list = list; } get warnings(): Warning[] | undefined { diff --git a/src/index.ts b/src/index.ts index 81a7d71e0..18a2cf4db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,17 +1,13 @@ -import { NodeCryptoProvider } from './common/crypto/node-crypto-provider'; import { SubtleCryptoProvider } from './common/crypto/subtle-crypto-provider'; import { CryptoProvider } from './common/crypto/crypto-provider'; import { HttpClient } from './common/net/http-client'; import { FetchHttpClient } from './common/net/fetch-client'; -import { NodeHttpClient } from './common/net/node-client'; import { Actions } from './actions/actions'; import { Webhooks } from './webhooks/webhooks'; import { WorkOS } from './workos'; import { WorkOSOptions } from './common/interfaces'; -import { WebIronSessionProvider } from './common/iron-session/web-iron-session-provider'; -import { IronSessionProvider } from './common/iron-session/iron-session-provider'; export * from './actions/interfaces'; export * from './api-keys/interfaces'; @@ -20,7 +16,6 @@ export * from './common/exceptions'; export * from './common/interfaces'; export * from './common/utils/pagination'; export * from './directory-sync/interfaces'; -export * from './directory-sync/utils/get-primary-email'; export * from './events/interfaces'; export * from './feature-flags/interfaces'; export * from './fga/interfaces'; @@ -32,28 +27,45 @@ export * from './roles/interfaces'; export * from './sso/interfaces'; export * from './user-management/interfaces'; export * from './vault/interfaces'; +export * from './pkce/pkce'; +export { + createWorkOS, + type PublicWorkOS, + type PublicUserManagement, + type PublicSSO, + type PublicClientOptions, + type ConfidentialClientOptions, +} from './factory'; class WorkOSNode extends WorkOS { /** @override */ createHttpClient(options: WorkOSOptions, userAgent: string): HttpClient { + const headers: Record = {}; + + const configHeaders = options.config?.headers; + if (configHeaders) { + if (configHeaders instanceof Headers) { + configHeaders.forEach((v, k) => (headers[k] = v)); + } else if (Array.isArray(configHeaders)) { + configHeaders.forEach(([k, v]) => (headers[k] = v)); + } else { + Object.assign(headers, configHeaders); + } + } + + headers['User-Agent'] = userAgent; + + if (this.key) { + headers['Authorization'] = `Bearer ${this.key}`; + } + const opts = { ...options.config, - timeout: options.timeout, // Pass through the timeout option - headers: { - ...options.config?.headers, - Authorization: `Bearer ${this.key}`, - 'User-Agent': userAgent, - }, + timeout: options.timeout, + headers, }; - if ( - typeof fetch !== 'undefined' || - typeof options.fetchFn !== 'undefined' - ) { - return new FetchHttpClient(this.baseURL, opts, options.fetchFn); - } else { - return new NodeHttpClient(this.baseURL, opts); - } + return new FetchHttpClient(this.baseURL, opts, options.fetchFn); } /** @override */ @@ -62,15 +74,7 @@ class WorkOSNode extends WorkOS { } override getCryptoProvider(): CryptoProvider { - let cryptoProvider: CryptoProvider; - - if (typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined') { - cryptoProvider = new SubtleCryptoProvider(); - } else { - cryptoProvider = new NodeCryptoProvider(); - } - - return cryptoProvider; + return new SubtleCryptoProvider(); } /** @override */ @@ -78,11 +82,6 @@ class WorkOSNode extends WorkOS { return new Actions(this.getCryptoProvider()); } - /** @override */ - createIronSessionProvider(): IronSessionProvider { - return new WebIronSessionProvider(); - } - /** @override */ emitWarning(warning: string): void { return process.emitWarning(warning, 'WorkOS'); diff --git a/src/index.worker.ts b/src/index.worker.ts index c8eb8a67a..6edf21855 100644 --- a/src/index.worker.ts +++ b/src/index.worker.ts @@ -1,8 +1,6 @@ import { Actions } from './actions/actions'; import { CryptoProvider } from './common/crypto/crypto-provider'; import { SubtleCryptoProvider } from './common/crypto/subtle-crypto-provider'; -import { EdgeIronSessionProvider } from './common/iron-session/edge-iron-session-provider'; -import { IronSessionProvider } from './common/iron-session/iron-session-provider'; import { FetchHttpClient } from './common/net/fetch-client'; import { HttpClient } from './common/net/http-client'; import { WorkOSOptions } from './index.worker'; @@ -15,7 +13,6 @@ export * from './common/exceptions'; export * from './common/interfaces'; export * from './common/utils/pagination'; export * from './directory-sync/interfaces'; -export * from './directory-sync/utils/get-primary-email'; export * from './events/interfaces'; export * from './fga/interfaces'; export * from './organizations/interfaces'; @@ -25,17 +22,40 @@ export * from './portal/interfaces'; export * from './sso/interfaces'; export * from './user-management/interfaces'; export * from './roles/interfaces'; +export * from './pkce/pkce'; +export { + createWorkOS, + type PublicWorkOS, + type PublicUserManagement, + type PublicSSO, + type PublicClientOptions, + type ConfidentialClientOptions, +} from './factory'; class WorkOSWorker extends WorkOS { /** @override */ createHttpClient(options: WorkOSOptions, userAgent: string): HttpClient { + const headers: Record = { + 'User-Agent': userAgent, + }; + + const configHeaders = options.config?.headers; + if ( + configHeaders && + typeof configHeaders === 'object' && + !Array.isArray(configHeaders) && + !(configHeaders instanceof Headers) + ) { + Object.assign(headers, configHeaders); + } + + if (this.key) { + headers['Authorization'] = `Bearer ${this.key}`; + } + return new FetchHttpClient(this.baseURL, { ...options.config, - headers: { - ...options.config?.headers, - Authorization: `Bearer ${this.key}`, - 'User-Agent': userAgent, - }, + headers, }); } @@ -57,11 +77,6 @@ class WorkOSWorker extends WorkOS { return new Actions(cryptoProvider); } - /** @override */ - createIronSessionProvider(): IronSessionProvider { - return new EdgeIronSessionProvider(); - } - /** @override */ emitWarning(warning: string): void { // tslint:disable-next-line:no-console diff --git a/src/mfa/interfaces/index.ts b/src/mfa/interfaces/index.ts index 916b4c82a..5cb81eca5 100644 --- a/src/mfa/interfaces/index.ts +++ b/src/mfa/interfaces/index.ts @@ -6,4 +6,3 @@ export * from './sms.interface'; export * from './totp.interface'; export * from './verify-challenge-options'; export * from './verify-challenge-response'; -export * from './verify-factor-options'; diff --git a/src/mfa/interfaces/verify-factor-options.ts b/src/mfa/interfaces/verify-factor-options.ts deleted file mode 100644 index e09219d30..000000000 --- a/src/mfa/interfaces/verify-factor-options.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @deprecated Please use `VerifyChallengeOptions` instead. - */ -export type VerifyFactorOptions = { - authenticationChallengeId: string; - code: string; -}; diff --git a/src/mfa/mfa.ts b/src/mfa/mfa.ts index e82ad3cb9..fc574c44d 100644 --- a/src/mfa/mfa.ts +++ b/src/mfa/mfa.ts @@ -1,17 +1,16 @@ import { WorkOS } from '../workos'; import { - ChallengeFactorOptions, Challenge, + ChallengeFactorOptions, + ChallengeResponse, EnrollFactorOptions, Factor, + FactorResponse, + FactorWithSecrets, + FactorWithSecretsResponse, VerifyChallengeOptions, - VerifyFactorOptions, VerifyResponse, - FactorResponse, - ChallengeResponse, VerifyResponseResponse, - FactorWithSecretsResponse, - FactorWithSecrets, } from './interfaces'; import { deserializeChallenge, @@ -73,13 +72,6 @@ export class Mfa { return deserializeChallenge(data); } - /** - * @deprecated Please use `verifyChallenge` instead. - */ - async verifyFactor(options: VerifyFactorOptions): Promise { - return this.verifyChallenge(options); - } - async verifyChallenge( options: VerifyChallengeOptions, ): Promise { diff --git a/src/organization-domains/interfaces/organization-domain.interface.ts b/src/organization-domains/interfaces/organization-domain.interface.ts index 6697fef2d..228de5bdb 100644 --- a/src/organization-domains/interfaces/organization-domain.interface.ts +++ b/src/organization-domains/interfaces/organization-domain.interface.ts @@ -1,8 +1,4 @@ export enum OrganizationDomainState { - /** - * @deprecated - */ - LegacyVerified = 'legacy_verified', Verified = 'verified', Pending = 'pending', Failed = 'failed', diff --git a/src/organizations/interfaces/create-organization-options.interface.ts b/src/organizations/interfaces/create-organization-options.interface.ts index 4560aa2ec..1f32b6821 100644 --- a/src/organizations/interfaces/create-organization-options.interface.ts +++ b/src/organizations/interfaces/create-organization-options.interface.ts @@ -6,15 +6,6 @@ export interface CreateOrganizationOptions { domainData?: DomainData[]; externalId?: string | null; metadata?: Record; - - /** - * @deprecated If you need to allow sign-ins from any email domain, contact support@workos.com. - */ - allowProfilesOutsideOrganization?: boolean; - /** - * @deprecated Use `domain_data` instead. - */ - domains?: string[]; } export interface SerializedCreateOrganizationOptions { @@ -22,16 +13,9 @@ export interface SerializedCreateOrganizationOptions { domain_data?: DomainData[]; external_id?: string | null; metadata?: Record; - - /** - * @deprecated If you need to allow sign-ins from any email domain, contact support@workos.com. - */ - allow_profiles_outside_organization?: boolean; - /** - * @deprecated Use `domain_data` instead. - */ - domains?: string[]; } -export interface CreateOrganizationRequestOptions - extends Pick {} +export type CreateOrganizationRequestOptions = Pick< + PostOptions, + 'idempotencyKey' +>; diff --git a/src/organizations/interfaces/update-organization-options.interface.ts b/src/organizations/interfaces/update-organization-options.interface.ts index 0e758743d..0f21a4749 100644 --- a/src/organizations/interfaces/update-organization-options.interface.ts +++ b/src/organizations/interfaces/update-organization-options.interface.ts @@ -7,15 +7,6 @@ export interface UpdateOrganizationOptions { stripeCustomerId?: string | null; externalId?: string | null; metadata?: Record; - - /** - * @deprecated If you need to allow sign-ins from any email domain, contact support@workos.com. - */ - allowProfilesOutsideOrganization?: boolean; - /** - * @deprecated Use `domain_data` instead. - */ - domains?: string[]; } export interface SerializedUpdateOrganizationOptions { @@ -24,13 +15,4 @@ export interface SerializedUpdateOrganizationOptions { stripe_customer_id?: string | null; external_id?: string | null; metadata?: Record; - - /** - * @deprecated If you need to allow sign-ins from any email domain, contact support@workos.com. - */ - allow_profiles_outside_organization?: boolean; - /** - * @deprecated Use `domain_data` instead. - */ - domains?: string[]; } diff --git a/src/organizations/organizations.spec.ts b/src/organizations/organizations.spec.ts index 3c671695c..48b0b794e 100644 --- a/src/organizations/organizations.spec.ts +++ b/src/organizations/organizations.spec.ts @@ -132,7 +132,9 @@ describe('Organizations', () => { await workos.organizations.createOrganization( { - domains: ['example.com'], + domainData: [ + { domain: 'example.com', state: DomainDataState.Verified }, + ], name: 'Test Organization', }, { @@ -144,32 +146,15 @@ describe('Organizations', () => { 'Idempotency-Key': 'the-idempotency-key', }); expect(fetchBody()).toEqual({ - domains: ['example.com'], + domain_data: [ + { domain: 'example.com', state: DomainDataState.Verified }, + ], name: 'Test Organization', }); }); }); describe('with a valid payload', () => { - describe('with `domains`', () => { - it('creates an organization', async () => { - fetchOnce(createOrganization, { status: 201 }); - - const subject = await workos.organizations.createOrganization({ - domains: ['example.com'], - name: 'Test Organization', - }); - - expect(fetchBody()).toEqual({ - domains: ['example.com'], - name: 'Test Organization', - }); - expect(subject.id).toEqual('org_01EHT88Z8J8795GZNQ4ZP1J81T'); - expect(subject.name).toEqual('Test Organization'); - expect(subject.domains).toHaveLength(1); - }); - }); - describe('with `domain_data`', () => { it('creates an organization', async () => { fetchOnce(createOrganization, { status: 201 }); @@ -214,14 +199,18 @@ describe('Organizations', () => { await expect( workos.organizations.createOrganization({ - domains: ['example.com'], + domainData: [ + { domain: 'example.com', state: DomainDataState.Verified }, + ], name: 'Test Organization', }), - ).rejects.toThrowError( + ).rejects.toThrow( 'An Organization with the domain example.com already exists.', ); expect(fetchBody()).toEqual({ - domains: ['example.com'], + domain_data: [ + { domain: 'example.com', state: DomainDataState.Verified }, + ], name: 'Test Organization', }); }); @@ -293,26 +282,6 @@ describe('Organizations', () => { describe('updateOrganization', () => { describe('with a valid payload', () => { - describe('with `domains', () => { - it('updates an organization', async () => { - fetchOnce(updateOrganization, { status: 201 }); - - const subject = await workos.organizations.updateOrganization({ - organization: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', - domains: ['example.com'], - name: 'Test Organization 2', - }); - - expect(fetchBody()).toEqual({ - domains: ['example.com'], - name: 'Test Organization 2', - }); - expect(subject.id).toEqual('org_01EHT88Z8J8795GZNQ4ZP1J81T'); - expect(subject.name).toEqual('Test Organization 2'); - expect(subject.domains).toHaveLength(1); - }); - }); - describe('with `domain_data`', () => { it('updates an organization', async () => { fetchOnce(updateOrganization, { status: 201 }); @@ -387,7 +356,7 @@ describe('Organizations', () => { organization: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', stripeCustomerId: 'cus_MX8J9nfK4lP2Yw', }), - ).rejects.toThrowError( + ).rejects.toThrow( 'stripe_customer_id is not enabled for this environment', ); diff --git a/src/organizations/organizations.ts b/src/organizations/organizations.ts index c1118f579..85949a975 100644 --- a/src/organizations/organizations.ts +++ b/src/organizations/organizations.ts @@ -44,7 +44,7 @@ export class Organizations { async listOrganizations( options?: ListOrganizationsOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -127,7 +127,9 @@ export class Organizations { async listOrganizationFeatureFlags( options: ListOrganizationFeatureFlagsOptions, - ): Promise> { + ): Promise< + AutoPaginatable + > { const { organizationId, ...paginationOptions } = options; return new AutoPaginatable( @@ -144,7 +146,7 @@ export class Organizations { deserializeFeatureFlag, params, ), - paginationOptions, + options, ); } diff --git a/src/organizations/serializers/create-organization-options.serializer.ts b/src/organizations/serializers/create-organization-options.serializer.ts index 0fffd53e0..f11aa6d46 100644 --- a/src/organizations/serializers/create-organization-options.serializer.ts +++ b/src/organizations/serializers/create-organization-options.serializer.ts @@ -7,9 +7,7 @@ export const serializeCreateOrganizationOptions = ( options: CreateOrganizationOptions, ): SerializedCreateOrganizationOptions => ({ name: options.name, - allow_profiles_outside_organization: options.allowProfilesOutsideOrganization, domain_data: options.domainData, - domains: options.domains, external_id: options.externalId, metadata: options.metadata, }); diff --git a/src/organizations/serializers/update-organization-options.serializer.ts b/src/organizations/serializers/update-organization-options.serializer.ts index 0f9f943fa..08e8c1b06 100644 --- a/src/organizations/serializers/update-organization-options.serializer.ts +++ b/src/organizations/serializers/update-organization-options.serializer.ts @@ -7,9 +7,7 @@ export const serializeUpdateOrganizationOptions = ( options: Omit, ): SerializedUpdateOrganizationOptions => ({ name: options.name, - allow_profiles_outside_organization: options.allowProfilesOutsideOrganization, domain_data: options.domainData, - domains: options.domains, stripe_customer_id: options.stripeCustomerId, external_id: options.externalId, metadata: options.metadata, diff --git a/src/pkce/pkce.spec.ts b/src/pkce/pkce.spec.ts new file mode 100644 index 000000000..2b0531e15 --- /dev/null +++ b/src/pkce/pkce.spec.ts @@ -0,0 +1,157 @@ +import { PKCE, PKCEPair } from './pkce'; + +describe('PKCE', () => { + let pkce: PKCE; + + beforeEach(() => { + pkce = new PKCE(); + }); + + describe('generateCodeVerifier', () => { + it('generates a string of default length (43)', () => { + const verifier = pkce.generateCodeVerifier(); + expect(verifier).toHaveLength(43); + }); + + it('generates a string of custom length', () => { + const verifier = pkce.generateCodeVerifier(128); + expect(verifier).toHaveLength(128); + }); + + it('generates only RFC 7636 compliant characters', () => { + const verifier = pkce.generateCodeVerifier(); + // RFC 7636: unreserved characters are [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" + expect(verifier).toMatch(/^[A-Za-z0-9\-._~]+$/); + }); + + it('generates unique values', () => { + const verifiers = new Set( + Array.from({ length: 100 }, () => pkce.generateCodeVerifier()), + ); + // All 100 should be unique + expect(verifiers.size).toBe(100); + }); + + it('throws RangeError for length < 43', () => { + expect(() => pkce.generateCodeVerifier(42)).toThrow(RangeError); + expect(() => pkce.generateCodeVerifier(42)).toThrow( + 'Code verifier length must be between 43 and 128', + ); + }); + + it('throws RangeError for length > 128', () => { + expect(() => pkce.generateCodeVerifier(129)).toThrow(RangeError); + expect(() => pkce.generateCodeVerifier(129)).toThrow( + 'Code verifier length must be between 43 and 128', + ); + }); + + it('accepts minimum length (43)', () => { + const verifier = pkce.generateCodeVerifier(43); + expect(verifier).toHaveLength(43); + }); + + it('accepts maximum length (128)', () => { + const verifier = pkce.generateCodeVerifier(128); + expect(verifier).toHaveLength(128); + }); + }); + + describe('generateCodeChallenge', () => { + it('generates base64url-encoded SHA-256 hash', async () => { + const verifier = 'test_verifier_with_exactly_43_characters_xx'; + const challenge = await pkce.generateCodeChallenge(verifier); + + // Challenge should be base64url encoded (no +, /, or = padding) + expect(challenge).toMatch(/^[A-Za-z0-9\-_]+$/); + }); + + it('produces consistent output for same input', async () => { + const verifier = 'consistent_test_verifier_exactly_43_chars_'; + const challenge1 = await pkce.generateCodeChallenge(verifier); + const challenge2 = await pkce.generateCodeChallenge(verifier); + + expect(challenge1).toBe(challenge2); + }); + + it('produces different output for different input', async () => { + const verifier1 = 'first_test_verifier_exactly_43_characters_'; + const verifier2 = 'second_test_verifier_exactly_43_character_'; + + const challenge1 = await pkce.generateCodeChallenge(verifier1); + const challenge2 = await pkce.generateCodeChallenge(verifier2); + + expect(challenge1).not.toBe(challenge2); + }); + + it('produces correct SHA-256 hash for known input', async () => { + // Using a well-known test vector + // The verifier "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" should produce + // the challenge "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM" (from RFC 7636 Appendix B) + const verifier = 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'; + const expectedChallenge = 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM'; + + const challenge = await pkce.generateCodeChallenge(verifier); + expect(challenge).toBe(expectedChallenge); + }); + }); + + describe('generate', () => { + it('returns a PKCEPair with all required fields', async () => { + const pair = await pkce.generate(); + + expect(pair).toHaveProperty('codeVerifier'); + expect(pair).toHaveProperty('codeChallenge'); + expect(pair).toHaveProperty('codeChallengeMethod'); + }); + + it('returns S256 as the challenge method', async () => { + const pair = await pkce.generate(); + expect(pair.codeChallengeMethod).toBe('S256'); + }); + + it('generates valid verifier', async () => { + const pair = await pkce.generate(); + + expect(pair.codeVerifier).toHaveLength(43); + expect(pair.codeVerifier).toMatch(/^[A-Za-z0-9\-._~]+$/); + }); + + it('generates matching challenge for verifier', async () => { + const pair = await pkce.generate(); + + // Verify the challenge matches what we'd generate from the verifier + const expectedChallenge = await pkce.generateCodeChallenge( + pair.codeVerifier, + ); + expect(pair.codeChallenge).toBe(expectedChallenge); + }); + + it('generates unique pairs', async () => { + const pairs = await Promise.all( + Array.from({ length: 10 }, () => pkce.generate()), + ); + + const verifiers = new Set(pairs.map((p) => p.codeVerifier)); + const challenges = new Set(pairs.map((p) => p.codeChallenge)); + + expect(verifiers.size).toBe(10); + expect(challenges.size).toBe(10); + }); + }); + + describe('PKCEPair type', () => { + it('has correct shape', async () => { + const pair: PKCEPair = await pkce.generate(); + + // TypeScript compilation would fail if these types are wrong + const _verifier: string = pair.codeVerifier; + const _challenge: string = pair.codeChallenge; + const _method: 'S256' = pair.codeChallengeMethod; + + expect(_verifier).toBeDefined(); + expect(_challenge).toBeDefined(); + expect(_method).toBe('S256'); + }); + }); +}); diff --git a/src/pkce/pkce.ts b/src/pkce/pkce.ts new file mode 100644 index 000000000..f97e67025 --- /dev/null +++ b/src/pkce/pkce.ts @@ -0,0 +1,62 @@ +export interface PKCEPair { + codeVerifier: string; + codeChallenge: string; + codeChallengeMethod: 'S256'; +} + +/** + * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients. + * + * Implements RFC 7636 for secure authorization code exchange without a client secret. + * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients. + */ +export class PKCE { + /** + * Generate a cryptographically random code verifier. + * + * @param length - Length of verifier (43-128, default 43) + * @returns RFC 7636 compliant code verifier + */ + generateCodeVerifier(length: number = 43): string { + if (length < 43 || length > 128) { + throw new RangeError( + `Code verifier length must be between 43 and 128, got ${length}`, + ); + } + + const byteLength = Math.ceil((length * 3) / 4); + const randomBytes = new Uint8Array(byteLength); + crypto.getRandomValues(randomBytes); + + return this.base64UrlEncode(randomBytes).slice(0, length); + } + + /** + * Generate S256 code challenge from a verifier. + * + * @param verifier - The code verifier + * @returns Base64URL-encoded SHA256 hash + */ + async generateCodeChallenge(verifier: string): Promise { + const encoder = new TextEncoder(); + const data = encoder.encode(verifier); + const hash = await crypto.subtle.digest('SHA-256', data); + return this.base64UrlEncode(new Uint8Array(hash)); + } + + /** + * Generate a complete PKCE pair (verifier + challenge). + * + * @returns Code verifier, challenge, and method ('S256') + */ + async generate(): Promise { + const codeVerifier = this.generateCodeVerifier(); + const codeChallenge = await this.generateCodeChallenge(codeVerifier); + return { codeVerifier, codeChallenge, codeChallengeMethod: 'S256' }; + } + + private base64UrlEncode(buffer: Uint8Array): string { + const base64 = btoa(String.fromCharCode(...buffer)); + return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); + } +} diff --git a/src/portal/portal.spec.ts b/src/portal/portal.spec.ts index 5f4a07056..40afd3428 100644 --- a/src/portal/portal.spec.ts +++ b/src/portal/portal.spec.ts @@ -151,7 +151,7 @@ describe('Portal', () => { organization: 'bogus-id', returnUrl: 'https://www.example.com', }), - ).rejects.toThrowError( + ).rejects.toThrow( 'Could not find an organization with the id, bogus-id.', ); expect(fetchBody()).toEqual({ @@ -175,7 +175,7 @@ describe('Portal', () => { organization: 'bogus-id', returnUrl: 'https://www.example.com', }), - ).rejects.toThrowError( + ).rejects.toThrow( 'Could not find an organization with the id, bogus-id.', ); expect(fetchBody()).toEqual({ diff --git a/src/sso/__snapshots__/sso.spec.ts.snap b/src/sso/__snapshots__/sso.spec.ts.snap index a1abf1a00..5941b55a8 100644 --- a/src/sso/__snapshots__/sso.spec.ts.snap +++ b/src/sso/__snapshots__/sso.spec.ts.snap @@ -1,33 +1,24 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`SSO SSO getAuthorizationUrl with a connection generates an authorize url with the connection 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&connection=connection_123&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; -exports[`SSO SSO getAuthorizationUrl with a custom api hostname generates an authorize url with the custom api hostname 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&domain=lyft.com&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; +exports[`SSO SSO getAuthorizationUrl with a custom api hostname generates an authorize url with the custom api hostname 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&provider=GoogleOAuth&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; -exports[`SSO SSO getAuthorizationUrl with a provider generates an authorize url with the provider 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&provider=Google&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; +exports[`SSO SSO getAuthorizationUrl with a provider generates an authorize url with the provider 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&provider=GoogleOAuth&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; exports[`SSO SSO getAuthorizationUrl with an \`organization\` generates an authorization URL with the organization 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&organization=organization_123&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; -exports[`SSO SSO getAuthorizationUrl with no custom api hostname generates an authorize url with the default api hostname 1`] = `"https://api.workos.com/sso/authorize?client_id=proj_123&domain=lyft.com&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; +exports[`SSO SSO getAuthorizationUrl with no custom api hostname generates an authorize url with the default api hostname 1`] = `"https://api.workos.com/sso/authorize?client_id=proj_123&provider=GoogleOAuth&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; -exports[`SSO SSO getAuthorizationUrl with no domain or provider throws an error for incomplete arguments 1`] = `"Incomplete arguments. Need to specify either a 'connection', 'organization', 'domain', or 'provider'."`; +exports[`SSO SSO getAuthorizationUrl with no domain or provider throws an error for incomplete arguments 1`] = `"Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'."`; exports[`SSO SSO getAuthorizationUrl with providerScopes generates an authorize url with the provided provider scopes 1`] = `"https://api.workos.com/sso/authorize?client_id=proj_123&provider=Google&provider_scopes=profile&provider_scopes=email&provider_scopes=calendar&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`; -exports[`SSO SSO getAuthorizationUrl with state generates an authorize url with the provided state 1`] = `"https://api.workos.com/sso/authorize?client_id=proj_123&domain=lyft.com&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code&state=custom+state"`; +exports[`SSO SSO getAuthorizationUrl with state generates an authorize url with the provided state 1`] = `"https://api.workos.com/sso/authorize?client_id=proj_123&provider=GoogleOAuth&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code&state=custom+state"`; -exports[`SSO SSO getProfileAndToken with all information provided sends a request to the WorkOS api for a profile 1`] = `"client_id=proj_123&client_secret=sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU&grant_type=authorization_code&code=authorization_code"`; +exports[`SSO SSO getProfileAndToken with all information provided sends a request to the WorkOS api for a profile 1`] = `"client_id=proj_123&grant_type=authorization_code&code=authorization_code&client_secret=sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU"`; exports[`SSO SSO getProfileAndToken with all information provided sends a request to the WorkOS api for a profile 2`] = ` -{ - "Accept": "application/json, text/plain, */*", - "Authorization": "Bearer sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU", - "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", - "User-Agent": "workos-node/7.82.0/fetch", -} -`; - -exports[`SSO SSO getProfileAndToken with all information provided sends a request to the WorkOS api for a profile 3`] = ` { "connectionId": "conn_123", "connectionType": "OktaSAML", @@ -65,18 +56,9 @@ exports[`SSO SSO getProfileAndToken with all information provided sends a reques } `; -exports[`SSO SSO getProfileAndToken without a groups attribute sends a request to the WorkOS api for a profile 1`] = `"client_id=proj_123&client_secret=sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU&grant_type=authorization_code&code=authorization_code"`; +exports[`SSO SSO getProfileAndToken without a groups attribute sends a request to the WorkOS api for a profile 1`] = `"client_id=proj_123&grant_type=authorization_code&code=authorization_code&client_secret=sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU"`; exports[`SSO SSO getProfileAndToken without a groups attribute sends a request to the WorkOS api for a profile 2`] = ` -{ - "Accept": "application/json, text/plain, */*", - "Authorization": "Bearer sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU", - "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", - "User-Agent": "workos-node/7.82.0/fetch", -} -`; - -exports[`SSO SSO getProfileAndToken without a groups attribute sends a request to the WorkOS api for a profile 3`] = ` { "connectionId": "conn_123", "connectionType": "OktaSAML", diff --git a/src/sso/interfaces/authorization-url-options.interface.ts b/src/sso/interfaces/authorization-url-options.interface.ts index 85fd4eb09..a364da322 100644 --- a/src/sso/interfaces/authorization-url-options.interface.ts +++ b/src/sso/interfaces/authorization-url-options.interface.ts @@ -1,15 +1,15 @@ -export interface SSOAuthorizationURLOptions { - clientId: string; - connection?: string; - organization?: string; +/** + * PKCE fields must be provided together or not at all. + * Use workos.pkce.generate() to create a valid pair. + */ +type PKCEFields = + | { codeChallenge?: never; codeChallengeMethod?: never } + | { codeChallenge: string; codeChallengeMethod: 'S256' }; - /** - * @deprecated Please use `organization` instead. - */ - domain?: string; +interface SSOAuthorizationURLBaseFields { + clientId: string; domainHint?: string; loginHint?: string; - provider?: string; providerQueryParams?: Record; providerScopes?: string[]; redirectUri: string; @@ -17,7 +17,43 @@ export interface SSOAuthorizationURLOptions { } /** - * @deprecated Use SSOAuthorizationURLOptions instead + * Result of getAuthorizationUrlWithPKCE() containing the URL, + * state, and PKCE code verifier. + * + * The codeVerifier must be stored securely and passed to + * getProfileAndToken() during token exchange. */ -// tslint:disable-next-line:no-empty-interface -export interface AuthorizationURLOptions extends SSOAuthorizationURLOptions {} +export interface SSOPKCEAuthorizationURLResult { + /** The complete authorization URL to redirect the user to */ + url: string; + /** The state parameter (auto-generated) */ + state: string; + /** The PKCE code verifier. Store securely and pass to getProfileAndToken(). */ + codeVerifier: string; +} + +type SSOWithConnection = SSOAuthorizationURLBaseFields & + PKCEFields & { + connection: string; + organization?: never; + provider?: never; + }; + +type SSOWithOrganization = SSOAuthorizationURLBaseFields & + PKCEFields & { + organization: string; + connection?: never; + provider?: never; + }; + +type SSOWithProvider = SSOAuthorizationURLBaseFields & + PKCEFields & { + provider: string; + connection?: never; + organization?: never; + }; + +export type SSOAuthorizationURLOptions = + | SSOWithConnection + | SSOWithOrganization + | SSOWithProvider; diff --git a/src/sso/interfaces/connection.interface.ts b/src/sso/interfaces/connection.interface.ts index d8766f863..e70bec8a7 100644 --- a/src/sso/interfaces/connection.interface.ts +++ b/src/sso/interfaces/connection.interface.ts @@ -11,10 +11,6 @@ export interface Connection { id: string; organizationId?: string; name: string; - /** - * @deprecated The connectionType parameter has been deprecated. Please use type. - */ - connectionType: ConnectionType; state: 'draft' | 'active' | 'inactive' | 'validating'; domains: ConnectionDomain[]; type: ConnectionType; diff --git a/src/sso/interfaces/get-profile-and-token-options.interface.ts b/src/sso/interfaces/get-profile-and-token-options.interface.ts index 59faaa4ee..6caeae0e5 100644 --- a/src/sso/interfaces/get-profile-and-token-options.interface.ts +++ b/src/sso/interfaces/get-profile-and-token-options.interface.ts @@ -1,4 +1,10 @@ export interface GetProfileAndTokenOptions { clientId: string; code: string; + /** + * PKCE code verifier for public clients. + * Pass the codeVerifier that was generated with getAuthorizationUrlWithPKCE(). + * When provided, client_secret is not sent (public client mode). + */ + codeVerifier?: string; } diff --git a/src/sso/interfaces/index.ts b/src/sso/interfaces/index.ts index 50e6fd889..6de6bc482 100644 --- a/src/sso/interfaces/index.ts +++ b/src/sso/interfaces/index.ts @@ -6,3 +6,4 @@ export * from './get-profile-and-token-options.interface'; export * from './list-connections-options.interface'; export * from './profile-and-token.interface'; export * from './profile.interface'; +export type { SSOPKCEAuthorizationURLResult } from './authorization-url-options.interface'; diff --git a/src/sso/serializers/connection.serializer.ts b/src/sso/serializers/connection.serializer.ts index e99803fa3..4a17b1fca 100644 --- a/src/sso/serializers/connection.serializer.ts +++ b/src/sso/serializers/connection.serializer.ts @@ -7,7 +7,6 @@ export const deserializeConnection = ( id: connection.id, organizationId: connection.organization_id, name: connection.name, - connectionType: connection.connection_type, type: connection.connection_type, state: connection.state, domains: connection.domains, diff --git a/src/sso/sso.spec.ts b/src/sso/sso.spec.ts index 1d0a0e231..cc7b3b4a0 100644 --- a/src/sso/sso.spec.ts +++ b/src/sso/sso.spec.ts @@ -56,7 +56,7 @@ describe('SSO', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); const url = workos.sso.getAuthorizationUrl({ - domain: 'lyft.com', + provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/sso/workos/callback', }); @@ -70,6 +70,7 @@ describe('SSO', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); const urlFn = () => + // @ts-expect-error Testing runtime validation with invalid input workos.sso.getAuthorizationUrl({ clientId: 'proj_123', redirectUri: 'example.com/sso/workos/callback', @@ -86,7 +87,7 @@ describe('SSO', () => { }); const url = workos.sso.getAuthorizationUrl({ - provider: 'Google', + provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/sso/workos/callback', }); @@ -134,7 +135,7 @@ describe('SSO', () => { }); const url = workos.sso.getAuthorizationUrl({ - domain: 'lyft.com', + provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/sso/workos/callback', }); @@ -148,7 +149,7 @@ describe('SSO', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); const url = workos.sso.getAuthorizationUrl({ - domain: 'lyft.com', + provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/sso/workos/callback', state: 'custom state', @@ -259,6 +260,72 @@ describe('SSO', () => { ); }); }); + + describe('with PKCE parameters', () => { + it('includes codeChallenge and codeChallengeMethod in URL', () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + + const url = workos.sso.getAuthorizationUrl({ + connection: 'conn_123', + clientId: 'proj_123', + redirectUri: 'myapp://callback', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'S256', + }); + + expect(url).toContain('code_challenge=test-challenge'); + expect(url).toContain('code_challenge_method=S256'); + }); + }); + }); + + describe('getAuthorizationUrlWithPKCE', () => { + it('generates PKCE parameters and returns codeVerifier', async () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + + const result = await workos.sso.getAuthorizationUrlWithPKCE({ + connection: 'conn_123', + clientId: 'proj_123', + redirectUri: 'myapp://callback', + }); + + expect(result.codeVerifier).toBeDefined(); + expect(result.codeVerifier.length).toBeGreaterThanOrEqual(43); + expect(result.url).toContain('code_challenge='); + expect(result.url).toContain('code_challenge_method=S256'); + expect(result.state).toBeDefined(); + expect(result.state.length).toBeGreaterThanOrEqual(43); + }); + + it('includes all provided options in the URL', async () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + + const result = await workos.sso.getAuthorizationUrlWithPKCE({ + connection: 'conn_123', + clientId: 'proj_123', + redirectUri: 'myapp://callback', + domainHint: 'example.com', + loginHint: 'user@example.com', + }); + + expect(result.url).toContain('connection=conn_123'); + expect(result.url).toContain('client_id=proj_123'); + expect(result.url).toContain('domain_hint=example.com'); + expect(result.url).toContain('login_hint=user%40example.com'); + }); + + it('throws error when no connection, organization, or provider is specified', async () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + + await expect( + workos.sso.getAuthorizationUrlWithPKCE({ + clientId: 'proj_123', + redirectUri: 'myapp://callback', + } as Parameters[0]), + ).rejects.toThrow( + `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`, + ); + }); }); describe('getProfileAndToken', () => { @@ -302,7 +369,19 @@ describe('SSO', () => { expect(fetch.mock.calls.length).toEqual(1); expect(fetchBody()).toMatchSnapshot(); - expect(fetchHeaders()).toMatchSnapshot(); + + const headers = fetchHeaders() as Record; + expect(headers['Accept']).toBe('application/json, text/plain, */*'); + expect(headers['Authorization']).toBe( + 'Bearer sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + ); + expect(headers['Content-Type']).toBe( + 'application/x-www-form-urlencoded;charset=utf-8', + ); + expect(headers['User-Agent']).toMatch( + /^workos-node\/\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?\/fetch \(node\/v\d+\.\d+\.\d+\)$/, + ); + expect(accessToken).toBe('01DMEK0J53CVMC32CK5SE0KZ8Q'); expect(profile).toMatchSnapshot(); }); @@ -343,7 +422,19 @@ describe('SSO', () => { expect(fetch.mock.calls.length).toEqual(1); expect(fetchBody()).toMatchSnapshot(); - expect(fetchHeaders()).toMatchSnapshot(); + + const headers = fetchHeaders() as Record; + expect(headers['Accept']).toBe('application/json, text/plain, */*'); + expect(headers['Authorization']).toBe( + 'Bearer sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + ); + expect(headers['Content-Type']).toBe( + 'application/x-www-form-urlencoded;charset=utf-8', + ); + expect(headers['User-Agent']).toMatch( + /^workos-node\/\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?\/fetch \(node\/v\d+\.\d+\.\d+\)$/, + ); + expect(accessToken).toBe('01DMEK0J53CVMC32CK5SE0KZ8Q'); expect(profile).toMatchSnapshot(); }); @@ -441,6 +532,125 @@ describe('SSO', () => { expect(oauthTokens).toBeUndefined(); }); }); + + describe('confidential client with PKCE (API key + codeVerifier)', () => { + it('sends both client_secret and code_verifier for defense in depth', async () => { + fetchOnce({ + access_token: '01DMEK0J53CVMC32CK5SE0KZ8Q', + profile: { + id: 'prof_123', + idp_id: '123', + organization_id: 'org_123', + connection_id: 'conn_123', + connection_type: 'OktaSAML', + email: 'foo@test.com', + first_name: 'foo', + last_name: 'bar', + role: { slug: 'admin' }, + roles: [{ slug: 'admin' }], + raw_attributes: {}, + custom_attributes: {}, + }, + }); + + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + await workos.sso.getProfileAndToken({ + code: 'authorization_code', + clientId: 'proj_123', + codeVerifier: 'test_code_verifier_value', + }); + + const body = fetchBody(); + expect(body).toContain('code_verifier=test_code_verifier_value'); + expect(body).toContain( + 'client_secret=sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + ); + }); + }); + + describe('public client mode (codeVerifier without API key)', () => { + let publicWorkos: WorkOS; + let originalApiKey: string | undefined; + + beforeEach(() => { + originalApiKey = process.env.WORKOS_API_KEY; + delete process.env.WORKOS_API_KEY; + publicWorkos = new WorkOS({ clientId: 'proj_123' }); + }); + + afterEach(() => { + process.env.WORKOS_API_KEY = originalApiKey; + }); + + it('sends code_verifier without client_secret', async () => { + fetchOnce({ + access_token: '01DMEK0J53CVMC32CK5SE0KZ8Q', + profile: { + id: 'prof_123', + idp_id: '123', + organization_id: 'org_123', + connection_id: 'conn_123', + connection_type: 'OktaSAML', + email: 'foo@test.com', + first_name: 'foo', + last_name: 'bar', + role: { slug: 'admin' }, + roles: [{ slug: 'admin' }], + raw_attributes: {}, + custom_attributes: {}, + }, + }); + + const { accessToken } = await publicWorkos.sso.getProfileAndToken({ + code: 'authorization_code', + clientId: 'proj_123', + codeVerifier: 'test_code_verifier_value', + }); + + expect(accessToken).toBe('01DMEK0J53CVMC32CK5SE0KZ8Q'); + const body = fetchBody(); + expect(body).toContain('code_verifier=test_code_verifier_value'); + expect(body).not.toContain('client_secret'); + }); + + it('throws error when neither codeVerifier nor API key is provided', async () => { + await expect( + publicWorkos.sso.getProfileAndToken({ + code: 'authorization_code', + clientId: 'proj_123', + }), + ).rejects.toThrow( + 'getProfileAndToken requires either a codeVerifier (for public clients) ' + + 'or an API key configured on the WorkOS instance (for confidential clients).', + ); + }); + + it('throws error when codeVerifier is an empty string', async () => { + await expect( + publicWorkos.sso.getProfileAndToken({ + code: 'authorization_code', + clientId: 'proj_123', + codeVerifier: '', + }), + ).rejects.toThrow( + 'codeVerifier cannot be an empty string. ' + + 'Generate a valid PKCE pair using workos.pkce.generate().', + ); + }); + + it('throws error when codeVerifier is whitespace only', async () => { + await expect( + publicWorkos.sso.getProfileAndToken({ + code: 'authorization_code', + clientId: 'proj_123', + codeVerifier: ' ', + }), + ).rejects.toThrow( + 'codeVerifier cannot be an empty string. ' + + 'Generate a valid PKCE pair using workos.pkce.generate().', + ); + }); + }); }); describe('getProfile', () => { @@ -504,7 +714,7 @@ describe('SSO', () => { expect(fetchURL()).toContain('/connections/conn_123'); - expect(subject.connectionType).toEqual('OktaSAML'); + expect(subject.type).toEqual('OktaSAML'); }); }); diff --git a/src/sso/sso.ts b/src/sso/sso.ts index 41cff08e1..41925b12d 100644 --- a/src/sso/sso.ts +++ b/src/sso/sso.ts @@ -1,7 +1,7 @@ -import qs from 'qs'; import { UnknownRecord } from '../common/interfaces/unknown-record.interface'; import { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize'; import { AutoPaginatable } from '../common/utils/pagination'; +import { toQueryString } from '../common/utils/query-string'; import { WorkOS } from '../workos'; import { Connection, @@ -14,6 +14,8 @@ import { ProfileAndTokenResponse, ProfileResponse, SSOAuthorizationURLOptions, + SSOPKCEAuthorizationURLResult, + SerializedListConnectionsOptions, } from './interfaces'; import { deserializeConnection, @@ -22,27 +24,12 @@ import { serializeListConnectionsOptions, } from './serializers'; -const toQueryString = ( - options: Record< - string, - string | string[] | Record | undefined - >, -): string => { - return qs.stringify(options, { - arrayFormat: 'repeat', - // sorts the keys alphabetically to maintain backwards compatibility - sort: (a, b) => a.localeCompare(b), - // encodes space as + instead of %20 to maintain backwards compatibility - format: 'RFC1738', - }); -}; - export class SSO { constructor(private readonly workos: WorkOS) {} async listConnections( options?: ListConnectionsOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -64,35 +51,106 @@ export class SSO { await this.workos.delete(`/connections/${id}`); } - getAuthorizationUrl({ - connection, - clientId, - domain, - domainHint, - loginHint, - organization, - provider, - providerQueryParams, - providerScopes, - redirectUri, - state, - }: SSOAuthorizationURLOptions): string { - if (!domain && !provider && !connection && !organization) { - throw new Error( - `Incomplete arguments. Need to specify either a 'connection', 'organization', 'domain', or 'provider'.`, + getAuthorizationUrl(options: SSOAuthorizationURLOptions): string { + const { + codeChallenge, + codeChallengeMethod, + connection, + clientId, + domainHint, + loginHint, + organization, + provider, + providerQueryParams, + providerScopes, + redirectUri, + state, + } = options; + + if (!provider && !connection && !organization) { + throw new TypeError( + `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`, ); } - if (domain) { - this.workos.emitWarning( - 'The `domain` parameter for `getAuthorizationURL` is deprecated. Please use `organization` instead.', + const query = toQueryString({ + code_challenge: codeChallenge, + code_challenge_method: codeChallengeMethod, + connection, + organization, + domain_hint: domainHint, + login_hint: loginHint, + provider, + provider_query_params: providerQueryParams, + provider_scopes: providerScopes, + client_id: clientId, + redirect_uri: redirectUri, + response_type: 'code', + state, + }); + + return `${this.workos.baseURL}/sso/authorize?${query}`; + } + + /** + * Generates an authorization URL with PKCE parameters automatically generated. + * Use this for public clients (CLI apps, Electron, mobile) that cannot + * securely store a client secret. + * + * @returns Object containing url, state, and codeVerifier + * + * @example + * ```typescript + * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({ + * connection: 'conn_123', + * clientId: 'client_123', + * redirectUri: 'myapp://callback', + * }); + * + * // Store state and codeVerifier securely, then redirect user to url + * // After callback, exchange the code: + * const { profile, accessToken } = await workos.sso.getProfileAndToken({ + * code: authorizationCode, + * codeVerifier, + * clientId: 'client_123', + * }); + * ``` + */ + async getAuthorizationUrlWithPKCE( + options: Omit< + SSOAuthorizationURLOptions, + 'codeChallenge' | 'codeChallengeMethod' | 'state' + >, + ): Promise { + const { + connection, + clientId, + domainHint, + loginHint, + organization, + provider, + providerQueryParams, + providerScopes, + redirectUri, + } = options; + + if (!provider && !connection && !organization) { + throw new TypeError( + `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`, ); } + // Generate PKCE parameters + const pkce = await this.workos.pkce.generate(); + + // Generate secure random state + const state = this.workos.pkce.generateCodeVerifier(43); + const query = toQueryString({ + code_challenge: pkce.codeChallenge, + code_challenge_method: 'S256', connection, organization, - domain, domain_hint: domainHint, login_hint: loginHint, provider, @@ -104,7 +162,9 @@ export class SSO { state, }); - return `${this.workos.baseURL}/sso/authorize?${query}`; + const url = `${this.workos.baseURL}/sso/authorize?${query}`; + + return { url, state, codeVerifier: pkce.codeVerifier }; } async getConnection(id: string): Promise { @@ -115,24 +175,64 @@ export class SSO { return deserializeConnection(data); } + /** + * Exchange an authorization code for a profile and access token. + * + * Auto-detects public vs confidential client mode: + * - If codeVerifier is provided: Uses PKCE flow (public client) + * - If no codeVerifier: Uses client_secret from API key (confidential client) + * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE) + * + * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense + * in depth and provides additional CSRF protection on the authorization flow. + * + * @throws Error if neither codeVerifier nor API key is available + */ async getProfileAndToken< CustomAttributesType extends UnknownRecord = UnknownRecord, >({ code, clientId, + codeVerifier, }: GetProfileAndTokenOptions): Promise< ProfileAndToken > { + // Validate codeVerifier is not an empty string (common mistake) + if (codeVerifier !== undefined && codeVerifier.trim() === '') { + throw new TypeError( + 'codeVerifier cannot be an empty string. ' + + 'Generate a valid PKCE pair using workos.pkce.generate().', + ); + } + + const hasApiKey = !!this.workos.key; + const hasPKCE = !!codeVerifier; + + if (!hasPKCE && !hasApiKey) { + throw new TypeError( + 'getProfileAndToken requires either a codeVerifier (for public clients) ' + + 'or an API key configured on the WorkOS instance (for confidential clients).', + ); + } + const form = new URLSearchParams({ client_id: clientId, - client_secret: this.workos.key as string, grant_type: 'authorization_code', code, }); + // Support PKCE with confidential clients (OAuth 2.1 best practice) + // Both can be sent together for defense in depth + if (hasPKCE) { + form.set('code_verifier', codeVerifier); + } + if (hasApiKey) { + form.set('client_secret', this.workos.key as string); + } + const { data } = await this.workos.post< ProfileAndTokenResponse - >('/sso/token', form); + >('/sso/token', form, { skipApiKeyCheck: !hasApiKey }); return deserializeProfileAndToken(data); } diff --git a/src/user-management/__snapshots__/user-management.spec.ts.snap b/src/user-management/__snapshots__/user-management.spec.ts.snap deleted file mode 100644 index e7be93c21..000000000 --- a/src/user-management/__snapshots__/user-management.spec.ts.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`UserManagement getAuthorizationUrl with a code_challenge and code_challenge_method generates an authorize url 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&code_challenge=code_challenge_value&code_challenge_method=S256&provider=authkit&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a connectionId generates an authorize url with the connection 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&connection_id=connection_123&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a connectionId with providerScopes generates an authorize url that includes the specified scopes 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&connection_id=connection_123&provider_scopes=read_api&provider_scopes=read_repository&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a custom api hostname generates an authorize url with the custom api hostname 1`] = `"https://api.workos.dev/user_management/authorize?client_id=proj_123&organization_id=organization_123&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a provider generates an authorize url with the provider 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&provider=GoogleOAuth&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a provider with providerScopes generates an authorize url that includes the specified scopes 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&provider=GoogleOAuth&provider_scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar&provider_scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.group&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a provider with providerScopes with providerQueryParams generates an authorize url that includes the specified query params 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&provider=GoogleOAuth&provider_query_params%5Bbaz%5D=123&provider_query_params%5Bbool%5D=true&provider_query_params%5Bfoo%5D=bar&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with a screenHint generates an authorize url with a screenHint 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&provider=authkit&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code&screen_hint=sign-up"`; - -exports[`UserManagement getAuthorizationUrl with an organizationId generates an authorization URL with the organization 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&organization_id=organization_123&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with no custom api hostname generates an authorize url with the default api hostname 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&provider=GoogleOAuth&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`; - -exports[`UserManagement getAuthorizationUrl with no domain or provider throws an error for incomplete arguments 1`] = `"Incomplete arguments. Need to specify either a 'connectionId', 'organizationId', or 'provider'."`; - -exports[`UserManagement getAuthorizationUrl with state generates an authorize url with the provided state 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&organization_id=organization_123&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code&state=custom+state"`; diff --git a/src/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.ts b/src/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.ts index 5a8085ac6..17b40859f 100644 --- a/src/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.ts @@ -1,17 +1,15 @@ import { AuthenticateWithOptionsBase, - SerializedAuthenticateWithPKCEBase, + SerializedAuthenticatePublicClientBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithCodeAndVerifierOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithCodeAndVerifierOptions extends AuthenticateWithOptionsBase { codeVerifier: string; code: string; invitationToken?: string; } -export interface SerializedAuthenticateWithCodeAndVerifierOptions - extends SerializedAuthenticateWithPKCEBase { +export interface SerializedAuthenticateWithCodeAndVerifierOptions extends SerializedAuthenticatePublicClientBase { grant_type: 'authorization_code'; code_verifier: string; code: string; diff --git a/src/user-management/interfaces/authenticate-with-code-options.interface.ts b/src/user-management/interfaces/authenticate-with-code-options.interface.ts index aad2d60ba..29baf03db 100644 --- a/src/user-management/interfaces/authenticate-with-code-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-code-options.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithCodeOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithCodeOptions extends AuthenticateWithOptionsBase { codeVerifier?: string; code: string; invitationToken?: string; @@ -14,8 +13,7 @@ export interface AuthenticateUserWithCodeCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithCodeOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithCodeOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'authorization_code'; code_verifier?: string; code: string; diff --git a/src/user-management/interfaces/authenticate-with-email-verification-options.interface.ts b/src/user-management/interfaces/authenticate-with-email-verification-options.interface.ts index abacad02f..482a77c7b 100644 --- a/src/user-management/interfaces/authenticate-with-email-verification-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-email-verification-options.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithEmailVerificationOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithEmailVerificationOptions extends AuthenticateWithOptionsBase { code: string; pendingAuthenticationToken: string; } @@ -13,8 +12,7 @@ export interface AuthenticateUserWithEmailVerificationCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithEmailVerificationOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithEmailVerificationOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'urn:workos:oauth:grant-type:email-verification:code'; code: string; pending_authentication_token: string; diff --git a/src/user-management/interfaces/authenticate-with-magic-auth-options.interface.ts b/src/user-management/interfaces/authenticate-with-magic-auth-options.interface.ts index 6126a5ef3..91573e33b 100644 --- a/src/user-management/interfaces/authenticate-with-magic-auth-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-magic-auth-options.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithMagicAuthOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithMagicAuthOptions extends AuthenticateWithOptionsBase { code: string; email: string; invitationToken?: string; @@ -15,8 +14,7 @@ export interface AuthenticateUserWithMagicAuthCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithMagicAuthOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithMagicAuthOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'urn:workos:oauth:grant-type:magic-auth:code'; code: string; email: string; diff --git a/src/user-management/interfaces/authenticate-with-options-base.interface.ts b/src/user-management/interfaces/authenticate-with-options-base.interface.ts index 57fa869d3..f73a41fa4 100644 --- a/src/user-management/interfaces/authenticate-with-options-base.interface.ts +++ b/src/user-management/interfaces/authenticate-with-options-base.interface.ts @@ -4,7 +4,7 @@ export interface AuthenticateWithSessionOptions { } export interface AuthenticateWithOptionsBase { - clientId: string; + clientId?: string; ipAddress?: string; userAgent?: string; session?: AuthenticateWithSessionOptions; @@ -17,8 +17,25 @@ export interface SerializedAuthenticateWithOptionsBase { user_agent?: string; } -export interface SerializedAuthenticateWithPKCEBase { +/** Base for serialized auth options that don't require client_secret (public clients) */ +export interface SerializedAuthenticatePublicClientBase { client_id: string; ip_address?: string; user_agent?: string; } + +/** + * Utility type for serializer input signatures. + * + * Since `clientId` is optional in user-facing interfaces (allowing fallback to + * the constructor-provided value), but serializers require a resolved string, + * this type overrides the optional `clientId` with a required one. + * + * Usage in serializers: + * ``` + * const serialize = (options: WithResolvedClientId) => ... + * ``` + */ +export type WithResolvedClientId = Omit & { + clientId: string; +}; diff --git a/src/user-management/interfaces/authenticate-with-organization-selection.interface.ts b/src/user-management/interfaces/authenticate-with-organization-selection.interface.ts index e9f37ff6a..99972f846 100644 --- a/src/user-management/interfaces/authenticate-with-organization-selection.interface.ts +++ b/src/user-management/interfaces/authenticate-with-organization-selection.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithOrganizationSelectionOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithOrganizationSelectionOptions extends AuthenticateWithOptionsBase { organizationId: string; pendingAuthenticationToken: string; } @@ -13,8 +12,7 @@ export interface AuthenticateUserWithOrganizationSelectionCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithOrganizationSelectionOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithOrganizationSelectionOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'urn:workos:oauth:grant-type:organization-selection'; organization_id: string; pending_authentication_token: string; diff --git a/src/user-management/interfaces/authenticate-with-password-options.interface.ts b/src/user-management/interfaces/authenticate-with-password-options.interface.ts index 7f5739598..fc5454ef7 100644 --- a/src/user-management/interfaces/authenticate-with-password-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-password-options.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithPasswordOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithPasswordOptions extends AuthenticateWithOptionsBase { email: string; password: string; invitationToken?: string; @@ -14,8 +13,7 @@ export interface AuthenticateUserWithPasswordCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithPasswordOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithPasswordOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'password'; email: string; password: string; diff --git a/src/user-management/interfaces/authenticate-with-refresh-token-options.interface.ts b/src/user-management/interfaces/authenticate-with-refresh-token-options.interface.ts index cb97a58da..3d3208729 100644 --- a/src/user-management/interfaces/authenticate-with-refresh-token-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-refresh-token-options.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithRefreshTokenOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithRefreshTokenOptions extends AuthenticateWithOptionsBase { refreshToken: string; organizationId?: string; } @@ -13,8 +12,7 @@ export interface AuthenticateUserWithRefreshTokenCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithRefreshTokenOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithRefreshTokenOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'refresh_token'; refresh_token: string; organization_id: string | undefined; diff --git a/src/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.ts b/src/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.ts new file mode 100644 index 000000000..8ebf141fe --- /dev/null +++ b/src/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.ts @@ -0,0 +1,16 @@ +import { + AuthenticateWithOptionsBase, + SerializedAuthenticatePublicClientBase, +} from './authenticate-with-options-base.interface'; + +/** Options for refreshing tokens as a public client (no client_secret required) */ +export interface AuthenticateWithRefreshTokenPublicClientOptions extends AuthenticateWithOptionsBase { + refreshToken: string; + organizationId?: string; +} + +export interface SerializedAuthenticateWithRefreshTokenPublicClientOptions extends SerializedAuthenticatePublicClientBase { + grant_type: 'refresh_token'; + refresh_token: string; + organization_id: string | undefined; +} diff --git a/src/user-management/interfaces/authenticate-with-totp-options.interface.ts b/src/user-management/interfaces/authenticate-with-totp-options.interface.ts index 8afbb960a..6ea77f0b4 100644 --- a/src/user-management/interfaces/authenticate-with-totp-options.interface.ts +++ b/src/user-management/interfaces/authenticate-with-totp-options.interface.ts @@ -3,8 +3,7 @@ import { SerializedAuthenticateWithOptionsBase, } from './authenticate-with-options-base.interface'; -export interface AuthenticateWithTotpOptions - extends AuthenticateWithOptionsBase { +export interface AuthenticateWithTotpOptions extends AuthenticateWithOptionsBase { code: string; pendingAuthenticationToken: string; authenticationChallengeId: string; @@ -14,8 +13,7 @@ export interface AuthenticateUserWithTotpCredentials { clientSecret: string | undefined; } -export interface SerializedAuthenticateWithTotpOptions - extends SerializedAuthenticateWithOptionsBase { +export interface SerializedAuthenticateWithTotpOptions extends SerializedAuthenticateWithOptionsBase { grant_type: 'urn:workos:oauth:grant-type:mfa-totp'; code: string; pending_authentication_token: string; diff --git a/src/user-management/interfaces/authorization-url-options.interface.ts b/src/user-management/interfaces/authorization-url-options.interface.ts index 5cec62ee7..8ce5b8899 100644 --- a/src/user-management/interfaces/authorization-url-options.interface.ts +++ b/src/user-management/interfaces/authorization-url-options.interface.ts @@ -1,13 +1,14 @@ -export interface UserManagementAuthorizationURLOptions { - clientId: string; - codeChallenge?: string; - codeChallengeMethod?: 'S256'; +/** + * PKCE fields must be provided together or not at all. + * Use workos.pkce.generate() to create a valid pair. + */ +type PKCEFields = + | { codeChallenge?: never; codeChallengeMethod?: never } + | { codeChallenge: string; codeChallengeMethod: 'S256' }; + +interface UserManagementAuthorizationURLBaseOptions { + clientId?: string; connectionId?: string; - /** - * @deprecated We previously required initiate login endpoints to return the `context` - * query parameter when getting the authorization URL. This is no longer necessary. - */ - context?: string; organizationId?: string; domainHint?: string; loginHint?: string; @@ -19,3 +20,22 @@ export interface UserManagementAuthorizationURLOptions { state?: string; screenHint?: 'sign-up' | 'sign-in'; } + +export type UserManagementAuthorizationURLOptions = + UserManagementAuthorizationURLBaseOptions & PKCEFields; + +/** + * Result of getAuthorizationUrlWithPKCE() containing the URL, + * state, and PKCE code verifier. + * + * The codeVerifier must be stored securely and passed to + * authenticateWithCode() during token exchange. + */ +export interface PKCEAuthorizationURLResult { + /** The complete authorization URL to redirect the user to */ + url: string; + /** The state parameter (auto-generated) */ + state: string; + /** The PKCE code verifier. Store securely and pass to authenticateWithCode(). */ + codeVerifier: string; +} diff --git a/src/user-management/interfaces/index.ts b/src/user-management/interfaces/index.ts index b3e381c5a..52fd897f5 100644 --- a/src/user-management/interfaces/index.ts +++ b/src/user-management/interfaces/index.ts @@ -6,6 +6,7 @@ export * from './authenticate-with-options-base.interface'; export * from './authenticate-with-organization-selection.interface'; export * from './authenticate-with-password-options.interface'; export * from './authenticate-with-refresh-token-options.interface'; +export * from './authenticate-with-refresh-token-public-client-options.interface'; export * from './authenticate-with-session-cookie.interface'; export * from './authenticate-with-totp-options.interface'; export * from './authentication-event.interface'; @@ -28,6 +29,7 @@ export * from './list-organization-memberships-options.interface'; export * from './list-sessions-options.interface'; export * from './list-user-feature-flags-options.interface'; export * from './list-users-options.interface'; +export * from './logout-url-options.interface'; export * from './magic-auth.interface'; export * from './oauth-tokens.interface'; export * from './organization-membership.interface'; @@ -36,8 +38,6 @@ export * from './refresh-and-seal-session-data.interface'; export * from './reset-password-options.interface'; export * from './revoke-session-options.interface'; export * from './send-invitation-options.interface'; -export * from './send-magic-auth-code-options.interface'; -export * from './send-password-reset-email-options.interface'; export * from './send-verification-email-options.interface'; export * from './session.interface'; export * from './update-organization-membership-options.interface'; diff --git a/src/user-management/interfaces/list-organization-memberships-options.interface.ts b/src/user-management/interfaces/list-organization-memberships-options.interface.ts index 997ac770a..bf54db289 100644 --- a/src/user-management/interfaces/list-organization-memberships-options.interface.ts +++ b/src/user-management/interfaces/list-organization-memberships-options.interface.ts @@ -1,14 +1,14 @@ import { PaginationOptions } from '../../common/interfaces'; import { OrganizationMembershipStatus } from './organization-membership.interface'; -export interface ListOrganizationMembershipsOptions extends PaginationOptions { - organizationId?: string; - userId?: string; +export type ListOrganizationMembershipsOptions = PaginationOptions & { statuses?: OrganizationMembershipStatus[]; -} +} & ( + | { organizationId: string; userId?: string } + | { organizationId?: string; userId: string } + ); -export interface SerializedListOrganizationMembershipsOptions - extends PaginationOptions { +export interface SerializedListOrganizationMembershipsOptions extends PaginationOptions { organization_id?: string; user_id?: string; statuses?: string; diff --git a/src/user-management/interfaces/list-sessions-options.interface.ts b/src/user-management/interfaces/list-sessions-options.interface.ts index 8f374e81f..8d3622098 100644 --- a/src/user-management/interfaces/list-sessions-options.interface.ts +++ b/src/user-management/interfaces/list-sessions-options.interface.ts @@ -1,7 +1,7 @@ import { PaginationOptions } from '../../common/interfaces/pagination-options.interface'; -// tslint:disable-next-line:no-empty-interface +// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface ListSessionsOptions extends PaginationOptions {} -// tslint:disable-next-line:no-empty-interface +// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface SerializedListSessionsOptions extends PaginationOptions {} diff --git a/src/user-management/interfaces/logout-url-options.interface.ts b/src/user-management/interfaces/logout-url-options.interface.ts new file mode 100644 index 000000000..2b90ac174 --- /dev/null +++ b/src/user-management/interfaces/logout-url-options.interface.ts @@ -0,0 +1,4 @@ +export interface LogoutURLOptions { + sessionId: string; + returnTo?: string; +} diff --git a/src/user-management/interfaces/refresh-and-seal-session-data.interface.ts b/src/user-management/interfaces/refresh-and-seal-session-data.interface.ts index b0cfbba4e..0e7fb8fb0 100644 --- a/src/user-management/interfaces/refresh-and-seal-session-data.interface.ts +++ b/src/user-management/interfaces/refresh-and-seal-session-data.interface.ts @@ -1,11 +1,7 @@ import { AuthenticateWithSessionCookieSuccessResponse } from './authenticate-with-session-cookie.interface'; import { AuthenticationResponse } from './authentication-response.interface'; -export enum RefreshAndSealSessionDataFailureReason { - /** - * @deprecated To be removed in a future major version. - */ - INVALID_SESSION_COOKE = 'invalid_session_cookie', +export enum RefreshSessionFailureReason { INVALID_SESSION_COOKIE = 'invalid_session_cookie', NO_SESSION_COOKIE_PROVIDED = 'no_session_cookie_provided', @@ -13,30 +9,13 @@ export enum RefreshAndSealSessionDataFailureReason { INVALID_GRANT = 'invalid_grant', MFA_ENROLLMENT = 'mfa_enrollment', SSO_REQUIRED = 'sso_required', - /** - * @deprecated To be removed in a future major version. - */ - ORGANIZATION_NOT_AUTHORIZED = 'organization_not_authorized', } type RefreshSessionFailedResponse = { authenticated: false; - reason: RefreshAndSealSessionDataFailureReason; + reason: RefreshSessionFailureReason; }; -/** - * @deprecated To be removed in a future major version along with `refreshAndSealSessionData`. - */ -type RefreshAndSealSessionDataSuccessResponse = { - authenticated: true; - session?: AuthenticationResponse; - sealedSession?: string; -}; - -export type RefreshAndSealSessionDataResponse = - | RefreshSessionFailedResponse - | RefreshAndSealSessionDataSuccessResponse; - type RefreshSessionSuccessResponse = Omit< AuthenticateWithSessionCookieSuccessResponse, // accessToken is available in the session object and with session diff --git a/src/user-management/interfaces/send-magic-auth-code-options.interface.ts b/src/user-management/interfaces/send-magic-auth-code-options.interface.ts deleted file mode 100644 index b8e9b258f..000000000 --- a/src/user-management/interfaces/send-magic-auth-code-options.interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface SendMagicAuthCodeOptions { - email: string; -} - -export interface SerializedSendMagicAuthCodeOptions { - email: string; -} diff --git a/src/user-management/interfaces/send-password-reset-email-options.interface.ts b/src/user-management/interfaces/send-password-reset-email-options.interface.ts deleted file mode 100644 index 4d9a53670..000000000 --- a/src/user-management/interfaces/send-password-reset-email-options.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface SendPasswordResetEmailOptions { - email: string; - passwordResetUrl: string; -} - -export interface SerializedSendPasswordResetEmailOptions { - email: string; - password_reset_url: string; -} diff --git a/src/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.ts b/src/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.ts index ad64ea13b..a67c40a4a 100644 --- a/src/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.ts @@ -1,10 +1,11 @@ import { AuthenticateWithCodeAndVerifierOptions, SerializedAuthenticateWithCodeAndVerifierOptions, + WithResolvedClientId, } from '../interfaces'; export const serializeAuthenticateWithCodeAndVerifierOptions = ( - options: AuthenticateWithCodeAndVerifierOptions, + options: WithResolvedClientId, ): SerializedAuthenticateWithCodeAndVerifierOptions => ({ grant_type: 'authorization_code', client_id: options.clientId, diff --git a/src/user-management/serializers/authenticate-with-code-options.serializer.ts b/src/user-management/serializers/authenticate-with-code-options.serializer.ts index c329c3aef..4f97e8302 100644 --- a/src/user-management/serializers/authenticate-with-code-options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-code-options.serializer.ts @@ -2,10 +2,12 @@ import { AuthenticateUserWithCodeCredentials, AuthenticateWithCodeOptions, SerializedAuthenticateWithCodeOptions, + WithResolvedClientId, } from '../interfaces'; export const serializeAuthenticateWithCodeOptions = ( - options: AuthenticateWithCodeOptions & AuthenticateUserWithCodeCredentials, + options: WithResolvedClientId & + AuthenticateUserWithCodeCredentials, ): SerializedAuthenticateWithCodeOptions => ({ grant_type: 'authorization_code', client_id: options.clientId, diff --git a/src/user-management/serializers/authenticate-with-email-verification.serializer.ts b/src/user-management/serializers/authenticate-with-email-verification.serializer.ts index 2354d859f..043b98334 100644 --- a/src/user-management/serializers/authenticate-with-email-verification.serializer.ts +++ b/src/user-management/serializers/authenticate-with-email-verification.serializer.ts @@ -3,9 +3,10 @@ import { AuthenticateWithEmailVerificationOptions, SerializedAuthenticateWithEmailVerificationOptions, } from '../interfaces/authenticate-with-email-verification-options.interface'; +import { WithResolvedClientId } from '../interfaces'; export const serializeAuthenticateWithEmailVerificationOptions = ( - options: AuthenticateWithEmailVerificationOptions & + options: WithResolvedClientId & AuthenticateUserWithEmailVerificationCredentials, ): SerializedAuthenticateWithEmailVerificationOptions => ({ grant_type: 'urn:workos:oauth:grant-type:email-verification:code', diff --git a/src/user-management/serializers/authenticate-with-magic-auth-options.serializer.ts b/src/user-management/serializers/authenticate-with-magic-auth-options.serializer.ts index de5246a1a..ce7bff02c 100644 --- a/src/user-management/serializers/authenticate-with-magic-auth-options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-magic-auth-options.serializer.ts @@ -2,10 +2,11 @@ import { AuthenticateUserWithMagicAuthCredentials, AuthenticateWithMagicAuthOptions, SerializedAuthenticateWithMagicAuthOptions, + WithResolvedClientId, } from '../interfaces'; export const serializeAuthenticateWithMagicAuthOptions = ( - options: AuthenticateWithMagicAuthOptions & + options: WithResolvedClientId & AuthenticateUserWithMagicAuthCredentials, ): SerializedAuthenticateWithMagicAuthOptions => ({ grant_type: 'urn:workos:oauth:grant-type:magic-auth:code', diff --git a/src/user-management/serializers/authenticate-with-organization-selection-options.serializer.ts b/src/user-management/serializers/authenticate-with-organization-selection-options.serializer.ts index 5c569363c..bf0a8c4df 100644 --- a/src/user-management/serializers/authenticate-with-organization-selection-options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-organization-selection-options.serializer.ts @@ -3,9 +3,10 @@ import { AuthenticateWithOrganizationSelectionOptions, SerializedAuthenticateWithOrganizationSelectionOptions, } from '../interfaces/authenticate-with-organization-selection.interface'; +import { WithResolvedClientId } from '../interfaces'; export const serializeAuthenticateWithOrganizationSelectionOptions = ( - options: AuthenticateWithOrganizationSelectionOptions & + options: WithResolvedClientId & AuthenticateUserWithOrganizationSelectionCredentials, ): SerializedAuthenticateWithOrganizationSelectionOptions => ({ grant_type: 'urn:workos:oauth:grant-type:organization-selection', diff --git a/src/user-management/serializers/authenticate-with-password-options.serializer.ts b/src/user-management/serializers/authenticate-with-password-options.serializer.ts index b8b0f840d..405dadc5a 100644 --- a/src/user-management/serializers/authenticate-with-password-options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-password-options.serializer.ts @@ -2,10 +2,11 @@ import { AuthenticateUserWithPasswordCredentials, AuthenticateWithPasswordOptions, SerializedAuthenticateWithPasswordOptions, + WithResolvedClientId, } from '../interfaces'; export const serializeAuthenticateWithPasswordOptions = ( - options: AuthenticateWithPasswordOptions & + options: WithResolvedClientId & AuthenticateUserWithPasswordCredentials, ): SerializedAuthenticateWithPasswordOptions => ({ grant_type: 'password', diff --git a/src/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.ts b/src/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.ts new file mode 100644 index 000000000..398318224 --- /dev/null +++ b/src/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.ts @@ -0,0 +1,16 @@ +import { + AuthenticateWithRefreshTokenPublicClientOptions, + SerializedAuthenticateWithRefreshTokenPublicClientOptions, + WithResolvedClientId, +} from '../interfaces'; + +export const serializeAuthenticateWithRefreshTokenPublicClientOptions = ( + options: WithResolvedClientId, +): SerializedAuthenticateWithRefreshTokenPublicClientOptions => ({ + grant_type: 'refresh_token', + client_id: options.clientId, + refresh_token: options.refreshToken, + organization_id: options.organizationId, + ip_address: options.ipAddress, + user_agent: options.userAgent, +}); diff --git a/src/user-management/serializers/authenticate-with-refresh-token.options.serializer.ts b/src/user-management/serializers/authenticate-with-refresh-token.options.serializer.ts index ca819478a..0b558844c 100644 --- a/src/user-management/serializers/authenticate-with-refresh-token.options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-refresh-token.options.serializer.ts @@ -2,10 +2,11 @@ import { AuthenticateUserWithCodeCredentials, AuthenticateWithRefreshTokenOptions, SerializedAuthenticateWithRefreshTokenOptions, + WithResolvedClientId, } from '../interfaces'; export const serializeAuthenticateWithRefreshTokenOptions = ( - options: AuthenticateWithRefreshTokenOptions & + options: WithResolvedClientId & AuthenticateUserWithCodeCredentials, ): SerializedAuthenticateWithRefreshTokenOptions => ({ grant_type: 'refresh_token', diff --git a/src/user-management/serializers/authenticate-with-totp-options.serializer.ts b/src/user-management/serializers/authenticate-with-totp-options.serializer.ts index 69b8f896b..d51ed7181 100644 --- a/src/user-management/serializers/authenticate-with-totp-options.serializer.ts +++ b/src/user-management/serializers/authenticate-with-totp-options.serializer.ts @@ -2,10 +2,12 @@ import { AuthenticateUserWithTotpCredentials, AuthenticateWithTotpOptions, SerializedAuthenticateWithTotpOptions, + WithResolvedClientId, } from '../interfaces'; export const serializeAuthenticateWithTotpOptions = ( - options: AuthenticateWithTotpOptions & AuthenticateUserWithTotpCredentials, + options: WithResolvedClientId & + AuthenticateUserWithTotpCredentials, ): SerializedAuthenticateWithTotpOptions => ({ grant_type: 'urn:workos:oauth:grant-type:mfa-totp', client_id: options.clientId, diff --git a/src/user-management/serializers/index.ts b/src/user-management/serializers/index.ts index 596246939..d4cc80ebf 100644 --- a/src/user-management/serializers/index.ts +++ b/src/user-management/serializers/index.ts @@ -3,6 +3,7 @@ export * from './authenticate-with-code-and-verifier-options.serializer'; export * from './authenticate-with-magic-auth-options.serializer'; export * from './authenticate-with-password-options.serializer'; export * from './authenticate-with-refresh-token.options.serializer'; +export * from './authenticate-with-refresh-token-public-client-options.serializer'; export * from './authenticate-with-totp-options.serializer'; export * from './authentication-event.serializer'; export * from './authentication-response.serializer'; @@ -16,10 +17,8 @@ export * from './list-sessions-options.serializer'; export * from './magic-auth.serializer'; export * from './password-reset.serializer'; export * from './reset-password-options.serializer'; -export * from './send-password-reset-email.serializer'; export * from './session.serializer'; export * from './create-user-options.serializer'; -export * from './send-magic-auth-code-options.serializer'; export * from './update-user-options.serializer'; export * from './update-user-password-options.serializer'; export * from './user.serializer'; diff --git a/src/user-management/serializers/send-magic-auth-code-options.serializer.ts b/src/user-management/serializers/send-magic-auth-code-options.serializer.ts deleted file mode 100644 index eab542310..000000000 --- a/src/user-management/serializers/send-magic-auth-code-options.serializer.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { - SendMagicAuthCodeOptions, - SerializedSendMagicAuthCodeOptions, -} from '../interfaces'; - -export const serializeSendMagicAuthCodeOptions = ( - options: SendMagicAuthCodeOptions, -): SerializedSendMagicAuthCodeOptions => ({ - email: options.email, -}); diff --git a/src/user-management/serializers/send-password-reset-email.serializer.ts b/src/user-management/serializers/send-password-reset-email.serializer.ts deleted file mode 100644 index 3c132ed5a..000000000 --- a/src/user-management/serializers/send-password-reset-email.serializer.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { - SendPasswordResetEmailOptions, - SerializedSendPasswordResetEmailOptions, -} from '../interfaces'; - -export const serializeSendPasswordResetEmailOptions = ( - options: SendPasswordResetEmailOptions, -): SerializedSendPasswordResetEmailOptions => ({ - email: options.email, - password_reset_url: options.passwordResetUrl, -}); diff --git a/src/user-management/session.spec.ts b/src/user-management/session.spec.ts index 44c1d33da..d41ecec24 100644 --- a/src/user-management/session.spec.ts +++ b/src/user-management/session.spec.ts @@ -1,11 +1,16 @@ import { WorkOS } from '../workos'; import { CookieSession } from './session'; import * as jose from 'jose'; -import { sealData } from 'iron-session'; +import { sealData } from '../common/crypto/seal'; import userFixture from './fixtures/user.json'; import fetch from 'jest-fetch-mock'; import { fetchOnce } from '../common/utils/test-utils'; +jest.mock('jose', () => ({ + ...jest.requireActual('jose'), + jwtVerify: jest.fn(), +})); + describe('Session', () => { let workos: WorkOS; @@ -66,8 +71,11 @@ describe('Session', () => { }); it('returns a failed response if the accessToken is not a valid JWT', async () => { - jest.spyOn(jose, 'jwtVerify').mockImplementation(() => { - throw new Error('Invalid JWT'); + jest.mocked(jose.jwtVerify).mockImplementation(() => { + // Simulate a jose JWT validation error with the expected code property + const error = new Error('Invalid JWT'); + (error as Error & { code: string }).code = 'ERR_JWT_INVALID'; + throw error; }); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -100,7 +108,7 @@ describe('Session', () => { it('returns a successful response if the sessionData is valid', async () => { jest - .spyOn(jose, 'jwtVerify') + .mocked(jose.jwtVerify) .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -247,7 +255,7 @@ describe('Session', () => { }); jest - .spyOn(jose, 'jwtVerify') + .mocked(jose.jwtVerify) .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -283,13 +291,60 @@ describe('Session', () => { expect(resp.authenticated).toBe(true); }); + + it('rotates refresh tokens when refreshing session', async () => { + const originalRefreshToken = 'original_refresh_token_123'; + const newRefreshToken = 'new_refresh_token_456'; + const accessToken = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiSm9obiBEb2UiLAogICJpYXQiOiAxNTE2MjM5MDIyLAogICJzaWQiOiAic2Vzc2lvbl8xMjMiLAogICJvcmdfaWQiOiAib3JnXzEyMyIsCiAgInJvbGUiOiAibWVtYmVyIiwKICAicGVybWlzc2lvbnMiOiBbInBvc3RzOmNyZWF0ZSIsICJwb3N0czpkZWxldGUiXQp9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'; + + // Mock the API to return a new refresh token + fetchOnce({ + user: userFixture, + accessToken, + refreshToken: newRefreshToken, // Different from original + }); + + const cookiePassword = 'alongcookiesecretmadefortestingsessions'; + + // Create initial session with original refresh token + const sessionData = await sealData( + { + accessToken, + refreshToken: originalRefreshToken, + user: { + object: 'user', + id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', + email: 'test01@example.com', + }, + }, + { password: cookiePassword }, + ); + + const session = workos.userManagement.loadSealedSession({ + sessionData, + cookiePassword, + }); + + const response = await session.refresh(); + + expect(response.authenticated).toBe(true); + + if (!response.authenticated) { + throw new Error('Expected successful response'); + } + + // Verify we got a new sealed session (which proves the refresh token was rotated) + expect(response.sealedSession).toBeDefined(); + expect(response.sealedSession).not.toBe(sessionData); + }); }); }); describe('getLogoutUrl', () => { it('returns a logout URL for the user', async () => { jest - .spyOn(jose, 'jwtVerify') + .mocked(jose.jwtVerify) .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -334,7 +389,7 @@ describe('Session', () => { describe('when a returnTo URL is provided', () => { it('returns a logout URL for the user', async () => { jest - .spyOn(jose, 'jwtVerify') + .mocked(jose.jwtVerify) .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; diff --git a/src/user-management/session.ts b/src/user-management/session.ts index c0da3ad99..bf8577e24 100644 --- a/src/user-management/session.ts +++ b/src/user-management/session.ts @@ -1,17 +1,17 @@ -import { createRemoteJWKSet, decodeJwt, jwtVerify } from 'jose'; import { OauthException } from '../common/exceptions/oauth.exception'; -import { IronSessionProvider } from '../common/iron-session/iron-session-provider'; import { AccessToken, AuthenticateWithSessionCookieFailedResponse, AuthenticateWithSessionCookieFailureReason, AuthenticateWithSessionCookieSuccessResponse, AuthenticationResponse, - RefreshAndSealSessionDataFailureReason, + RefreshSessionFailureReason, RefreshSessionResponse, SessionCookieData, } from './interfaces'; import { UserManagement } from './user-management'; +import { unsealData } from '../common/crypto/seal'; +import { getJose } from '../utils/jose'; type RefreshOptions = { cookiePassword?: string; @@ -19,9 +19,7 @@ type RefreshOptions = { }; export class CookieSession { - private jwks: ReturnType | undefined; private userManagement: UserManagement; - private ironSessionProvider: IronSessionProvider; private cookiePassword: string; private sessionData: string; @@ -35,11 +33,8 @@ export class CookieSession { } this.userManagement = userManagement; - this.ironSessionProvider = userManagement.ironSessionProvider; this.cookiePassword = cookiePassword; this.sessionData = sessionData; - - this.jwks = this.userManagement.jwks; } /** @@ -59,22 +54,11 @@ export class CookieSession { }; } - let session: SessionCookieData; - - try { - session = await this.ironSessionProvider.unsealData( - this.sessionData, - { - password: this.cookiePassword, - }, - ); - } catch (e) { - return { - authenticated: false, - reason: - AuthenticateWithSessionCookieFailureReason.INVALID_SESSION_COOKIE, - }; - } + // unsealData returns {} for known seal errors (expired, bad hmac, etc.) + // Unknown errors propagate - don't catch them as "invalid session" + const session = await unsealData(this.sessionData, { + password: this.cookiePassword, + }); if (!session.accessToken) { return { @@ -91,6 +75,8 @@ export class CookieSession { }; } + const { decodeJwt } = await getJose(); + const { sid: sessionId, org_id: organizationId, @@ -126,18 +112,15 @@ export class CookieSession { * @returns An object indicating whether the refresh was successful or not. If successful, it will include the new sealed session data. */ async refresh(options: RefreshOptions = {}): Promise { - const session = - await this.ironSessionProvider.unsealData( - this.sessionData, - { - password: this.cookiePassword, - }, - ); + const { decodeJwt } = await getJose(); + const session = await unsealData(this.sessionData, { + password: this.cookiePassword, + }); if (!session.refreshToken || !session.user) { return { authenticated: false, - reason: RefreshAndSealSessionDataFailureReason.INVALID_SESSION_COOKIE, + reason: RefreshSessionFailureReason.INVALID_SESSION_COOKIE, }; } @@ -199,10 +182,9 @@ export class CookieSession { if ( error instanceof OauthException && // TODO: Add additional known errors and remove re-throw - (error.error === RefreshAndSealSessionDataFailureReason.INVALID_GRANT || - error.error === - RefreshAndSealSessionDataFailureReason.MFA_ENROLLMENT || - error.error === RefreshAndSealSessionDataFailureReason.SSO_REQUIRED) + (error.error === RefreshSessionFailureReason.INVALID_GRANT || + error.error === RefreshSessionFailureReason.MFA_ENROLLMENT || + error.error === RefreshSessionFailureReason.SSO_REQUIRED) ) { return { authenticated: false, @@ -236,17 +218,29 @@ export class CookieSession { } private async isValidJwt(accessToken: string): Promise { - if (!this.jwks) { + const { jwtVerify } = await getJose(); + const jwks = await this.userManagement.getJWKS(); + if (!jwks) { throw new Error( 'Missing client ID. Did you provide it when initializing WorkOS?', ); } try { - await jwtVerify(accessToken, this.jwks); + await jwtVerify(accessToken, jwks); return true; } catch (e) { - return false; + // Only treat as invalid JWT if it's an actual JWT/JWS error from jose + // Network errors, crypto failures, etc. should propagate + if ( + e instanceof Error && + 'code' in e && + typeof e.code === 'string' && + (e.code.startsWith('ERR_JWT_') || e.code.startsWith('ERR_JWS_')) + ) { + return false; + } + throw e; } } } diff --git a/src/user-management/user-management.spec.ts b/src/user-management/user-management.spec.ts index 4f09e1a23..aec3a6576 100644 --- a/src/user-management/user-management.spec.ts +++ b/src/user-management/user-management.spec.ts @@ -21,7 +21,13 @@ import passwordResetFixture from './fixtures/password_reset.json'; import userFixture from './fixtures/user.json'; import identityFixture from './fixtures/identity.json'; import * as jose from 'jose'; -import { sealData } from 'iron-session'; +import { sealData } from '../common/crypto/seal'; + +jest.mock('jose', () => ({ + ...jest.requireActual('jose'), + jwtVerify: jest.fn(), + createRemoteJWKSet: jest.fn(), +})); const userId = 'user_01H5JQDV7R7ATEYZDEG0W5PRYS'; const organizationMembershipId = 'om_01H5JQDV7R7ATEYZDEG0W5PRYS'; @@ -300,49 +306,173 @@ describe('UserManagement', () => { }); describe('authenticateWithCode', () => { - it('sends a token authentication request', async () => { - fetchOnce({ user: userFixture }); - const resp = await workos.userManagement.authenticateWithCode({ - clientId: 'proj_whatever', - code: 'or this', + describe('confidential client mode (with API key, no codeVerifier)', () => { + it('sends a token authentication request with client_secret', async () => { + fetchOnce({ user: userFixture }); + const resp = await workos.userManagement.authenticateWithCode({ + clientId: 'proj_whatever', + code: 'or this', + }); + + expect(fetchURL()).toContain('/user_management/authenticate'); + expect(fetchBody()).toEqual({ + client_id: 'proj_whatever', + client_secret: 'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + code: 'or this', + grant_type: 'authorization_code', + }); + + expect(resp).toMatchObject({ + user: { + email: 'test01@example.com', + }, + }); }); + }); - expect(fetchURL()).toContain('/user_management/authenticate'); - expect(fetchBody()).toEqual({ - client_id: 'proj_whatever', - client_secret: 'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', - code: 'or this', - grant_type: 'authorization_code', + describe('public client mode (with codeVerifier, no API key)', () => { + let publicWorkos: WorkOS; + let originalApiKey: string | undefined; + + beforeEach(() => { + originalApiKey = process.env.WORKOS_API_KEY; + delete process.env.WORKOS_API_KEY; + publicWorkos = new WorkOS({ clientId: 'proj_123' }); }); - expect(resp).toMatchObject({ - user: { - email: 'test01@example.com', - }, + afterEach(() => { + if (originalApiKey) { + process.env.WORKOS_API_KEY = originalApiKey; + } + }); + + it('sends a token authentication request with code_verifier and no client_secret', async () => { + fetchOnce({ user: userFixture }); + const resp = await publicWorkos.userManagement.authenticateWithCode({ + clientId: 'proj_whatever', + code: 'or this', + codeVerifier: 'code_verifier_value', + }); + + expect(fetchURL()).toContain('/user_management/authenticate'); + expect(fetchBody()).toEqual({ + client_id: 'proj_whatever', + code: 'or this', + code_verifier: 'code_verifier_value', + grant_type: 'authorization_code', + }); + + expect(resp).toMatchObject({ + user: { + email: 'test01@example.com', + }, + }); + }); + + it('uses clientId from constructor when not provided in options', async () => { + fetchOnce({ user: userFixture }); + await publicWorkos.userManagement.authenticateWithCode({ + code: 'or this', + codeVerifier: 'code_verifier_value', + }); + + expect(fetchBody()).toMatchObject({ + client_id: 'proj_123', + }); + }); + + it('throws error when clientId not provided anywhere', async () => { + // Use confidential client (API key) without clientId to test the error + const workosNoClientId = new WorkOS('sk_test_no_client_id'); + await expect( + workosNoClientId.userManagement.authenticateWithCode({ + code: 'some_code', + codeVerifier: 'code_verifier_value', + }), + ).rejects.toThrow( + 'clientId is required. Provide it in method options or when initializing WorkOS.', + ); }); }); - it('sends a token authentication request when including the code_verifier', async () => { - fetchOnce({ user: userFixture }); - const resp = await workos.userManagement.authenticateWithCode({ - clientId: 'proj_whatever', - code: 'or this', - codeVerifier: 'code_verifier_value', + describe('confidential client with PKCE (API key + codeVerifier)', () => { + it('sends both client_secret and code_verifier for defense in depth', async () => { + fetchOnce({ user: userFixture }); + const resp = await workos.userManagement.authenticateWithCode({ + clientId: 'proj_whatever', + code: 'or this', + codeVerifier: 'code_verifier_value', + }); + + expect(fetchURL()).toContain('/user_management/authenticate'); + expect(fetchBody()).toEqual({ + client_id: 'proj_whatever', + client_secret: 'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + code: 'or this', + code_verifier: 'code_verifier_value', + grant_type: 'authorization_code', + }); + + expect(resp).toMatchObject({ + user: { + email: 'test01@example.com', + }, + }); }); + }); - expect(fetchURL()).toContain('/user_management/authenticate'); - expect(fetchBody()).toEqual({ - client_id: 'proj_whatever', - client_secret: 'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', - code: 'or this', - code_verifier: 'code_verifier_value', - grant_type: 'authorization_code', + describe('error handling', () => { + let publicWorkos: WorkOS; + let originalApiKey: string | undefined; + + beforeEach(() => { + originalApiKey = process.env.WORKOS_API_KEY; + delete process.env.WORKOS_API_KEY; + publicWorkos = new WorkOS({ clientId: 'proj_123' }); }); - expect(resp).toMatchObject({ - user: { - email: 'test01@example.com', - }, + afterEach(() => { + if (originalApiKey) { + process.env.WORKOS_API_KEY = originalApiKey; + } + }); + + it('throws error when neither codeVerifier nor API key is provided', async () => { + await expect( + publicWorkos.userManagement.authenticateWithCode({ + clientId: 'proj_whatever', + code: 'some_code', + }), + ).rejects.toThrow( + 'authenticateWithCode requires either a codeVerifier (for public clients) ' + + 'or an API key configured on the WorkOS instance (for confidential clients).', + ); + }); + + it('throws error when codeVerifier is an empty string', async () => { + await expect( + publicWorkos.userManagement.authenticateWithCode({ + clientId: 'proj_whatever', + code: 'some_code', + codeVerifier: '', + }), + ).rejects.toThrow( + 'codeVerifier cannot be an empty string. ' + + 'Generate a valid PKCE pair using workos.pkce.generate().', + ); + }); + + it('throws error when codeVerifier is whitespace only', async () => { + await expect( + publicWorkos.userManagement.authenticateWithCode({ + clientId: 'proj_whatever', + code: 'some_code', + codeVerifier: ' ', + }), + ).rejects.toThrow( + 'codeVerifier cannot be an empty string. ' + + 'Generate a valid PKCE pair using workos.pkce.generate().', + ); }); }); @@ -565,6 +695,41 @@ describe('UserManagement', () => { }); }); }); + + describe('in public client mode (no API key)', () => { + let publicWorkos: WorkOS; + let originalApiKey: string | undefined; + + beforeEach(() => { + originalApiKey = process.env.WORKOS_API_KEY; + delete process.env.WORKOS_API_KEY; + publicWorkos = new WorkOS({ clientId: 'client_123' }); + }); + + afterEach(() => { + if (originalApiKey) { + process.env.WORKOS_API_KEY = originalApiKey; + } + }); + + it('throws error when session sealing is requested', async () => { + fetchOnce({ + user: userFixture, + access_token: 'access_token', + }); + + await expect( + publicWorkos.userManagement.authenticateWithCodeAndVerifier({ + clientId: 'client_123', + code: 'auth_code_123', + codeVerifier: 'required_code_verifier', + session: { sealSession: true, cookiePassword: 'secret' }, + }), + ).rejects.toThrow( + 'Session sealing requires server-side usage with an API key', + ); + }); + }); }); }); @@ -640,6 +805,87 @@ describe('UserManagement', () => { }); }); }); + + describe('in public client mode (no API key)', () => { + let publicWorkos: WorkOS; + let originalApiKey: string | undefined; + + beforeEach(() => { + originalApiKey = process.env.WORKOS_API_KEY; + delete process.env.WORKOS_API_KEY; + publicWorkos = new WorkOS({ clientId: 'client_123' }); + }); + + afterEach(() => { + if (originalApiKey) { + process.env.WORKOS_API_KEY = originalApiKey; + } + }); + + it('omits client_secret from request', async () => { + fetchOnce({ + user: userFixture, + access_token: 'access_token', + refresh_token: 'refreshToken2', + }); + const resp = + await publicWorkos.userManagement.authenticateWithRefreshToken({ + clientId: 'client_123', + refreshToken: 'refresh_token1', + }); + + expect(fetchURL()).toContain('/user_management/authenticate'); + expect(fetchBody()).toEqual({ + client_id: 'client_123', + refresh_token: 'refresh_token1', + grant_type: 'refresh_token', + }); + expect(fetchBody()).not.toHaveProperty('client_secret'); + + expect(resp).toMatchObject({ + accessToken: 'access_token', + refreshToken: 'refreshToken2', + }); + }); + + it('includes organization_id when provided', async () => { + fetchOnce({ + user: userFixture, + access_token: 'access_token', + refresh_token: 'refreshToken2', + }); + await publicWorkos.userManagement.authenticateWithRefreshToken({ + clientId: 'client_123', + refreshToken: 'refresh_token1', + organizationId: 'org_123', + }); + + expect(fetchBody()).toEqual({ + client_id: 'client_123', + refresh_token: 'refresh_token1', + grant_type: 'refresh_token', + organization_id: 'org_123', + }); + }); + + it('throws error when session sealing is requested', async () => { + fetchOnce({ + user: userFixture, + access_token: 'access_token', + refresh_token: 'refreshToken2', + }); + + await expect( + publicWorkos.userManagement.authenticateWithRefreshToken({ + clientId: 'client_123', + refreshToken: 'refresh_token1', + session: { sealSession: true, cookiePassword: 'secret' }, + }), + ).rejects.toThrow( + 'Session sealing requires server-side usage with an API key', + ); + }); + }); }); describe('authenticateWithTotp', () => { @@ -876,17 +1122,27 @@ describe('UserManagement', () => { }); describe('authenticateWithSessionCookie', () => { + const OLD_ENV = process.env; + + beforeEach(() => { + process.env = { ...OLD_ENV }; + delete process.env.WORKOS_COOKIE_PASSWORD; + }); + + afterEach(() => { + process.env = OLD_ENV; + }); beforeEach(() => { // Mock createRemoteJWKSet jest - .spyOn(jose, 'createRemoteJWKSet') + .mocked(jose.createRemoteJWKSet) .mockImplementation( (_url: URL, _options?: jose.RemoteJWKSetOptions) => { // This function simulates the token verification process const verifyFunction = ( _protectedHeader: jose.JWSHeaderParameters, _token: jose.FlattenedJWSInput, - ): Promise => { + ): Promise => { return Promise.resolve({ type: 'public', }); @@ -964,8 +1220,11 @@ describe('UserManagement', () => { }); it('returns authenticated = false when the JWT is invalid', async () => { - jest.spyOn(jose, 'jwtVerify').mockImplementationOnce(() => { - throw new Error('Invalid JWT'); + jest.mocked(jose.jwtVerify).mockImplementationOnce(() => { + // Simulate a jose JWT validation error with the expected code property + const error = new Error('Invalid JWT'); + (error as Error & { code: string }).code = 'ERR_JWT_INVALID'; + throw error; }); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -990,9 +1249,37 @@ describe('UserManagement', () => { ).resolves.toEqual({ authenticated: false, reason: 'invalid_jwt' }); }); + it('rethrows non-JWT errors (e.g., network failures)', async () => { + jest.mocked(jose.jwtVerify).mockImplementationOnce(() => { + // Simulate a network error (no jose error code) + throw new Error('Network error: JWKS fetch failed'); + }); + + const cookiePassword = 'alongcookiesecretmadefortestingsessions'; + const sessionData = await sealData( + { + accessToken: 'abc123', + refreshToken: 'def456', + user: { + object: 'user', + id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', + email: 'test@example.com', + }, + }, + { password: cookiePassword }, + ); + + await expect( + workos.userManagement.authenticateWithSessionCookie({ + sessionData, + cookiePassword, + }), + ).rejects.toThrow('Network error: JWKS fetch failed'); + }); + it('returns the JWT claims when provided a valid JWT', async () => { jest - .spyOn(jose, 'jwtVerify') + .mocked(jose.jwtVerify) .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -1034,7 +1321,7 @@ describe('UserManagement', () => { it('returns the JWT claims when provided a valid JWT with multiple roles', async () => { jest - .spyOn(jose, 'jwtVerify') + .mocked(jose.jwtVerify) .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); const cookiePassword = 'alongcookiesecretmadefortestingsessions'; @@ -1076,101 +1363,17 @@ describe('UserManagement', () => { }); }); - describe('refreshAndSealSessionData', () => { - it('throws an error when the cookie password is undefined', async () => { - await expect( - workos.userManagement.refreshAndSealSessionData({ - sessionData: 'session_cookie', - }), - ).rejects.toThrow('Cookie password is required'); - }); - - it('returns authenticated = false when the session cookie is empty', async () => { - await expect( - workos.userManagement.refreshAndSealSessionData({ - sessionData: '', - cookiePassword: 'secret', - }), - ).resolves.toEqual({ - authenticated: false, - reason: 'no_session_cookie_provided', - }); - }); + describe('getSessionFromCookie', () => { + const OLD_ENV = process.env; - it('returns authenticated = false when session cookie is invalid', async () => { - await expect( - workos.userManagement.refreshAndSealSessionData({ - sessionData: 'thisisacookie', - cookiePassword: 'secret', - }), - ).resolves.toEqual({ - authenticated: false, - reason: 'invalid_session_cookie', - }); + beforeEach(() => { + process.env = { ...OLD_ENV }; + delete process.env.WORKOS_COOKIE_PASSWORD; }); - it('returns authenticated = false when session cookie cannot be unsealed', async () => { - const cookiePassword = 'alongcookiesecretmadefortestingsessions'; - const sessionData = await sealData( - { - accessToken: 'abc123', - refreshToken: 'def456', - user: { - object: 'user', - id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', - email: 'test@example.com', - }, - }, - { password: cookiePassword }, - ); - - await expect( - workos.userManagement.refreshAndSealSessionData({ - sessionData, - cookiePassword: 'secretpasswordwhichisalsolongbutnottherightone', - }), - ).resolves.toEqual({ - authenticated: false, - reason: 'invalid_session_cookie', - }); + afterEach(() => { + process.env = OLD_ENV; }); - - it('returns the sealed refreshed session cookie when provided a valid existing session cookie', async () => { - fetchOnce({ - user: userFixture, - access_token: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiSm9obiBEb2UiLAogICJpYXQiOiAxNTE2MjM5MDIyLAogICJzaWQiOiAic2Vzc2lvbl8xMjMiLAogICJvcmdfaWQiOiAib3JnXzEyMyIsCiAgInJvbGUiOiAibWVtYmVyIiwKICAicGVybWlzc2lvbnMiOiBbInBvc3RzOmNyZWF0ZSIsICJwb3N0czpkZWxldGUiXQp9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', - refresh_token: 'refresh_token', - }); - - const cookiePassword = 'alongcookiesecretmadefortestingsessions'; - const sessionData = await sealData( - { - accessToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiSm9obiBEb2UiLAogICJpYXQiOiAxNTE2MjM5MDIyLAogICJzaWQiOiAic2Vzc2lvbl8xMjMiLAogICJvcmdfaWQiOiAib3JnXzEyMyIsCiAgInJvbGUiOiAibWVtYmVyIiwKICAicGVybWlzc2lvbnMiOiBbInBvc3RzOmNyZWF0ZSIsICJwb3N0czpkZWxldGUiXQp9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', - refreshToken: 'def456', - user: { - object: 'user', - id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', - email: 'test@example.com', - }, - }, - { password: cookiePassword }, - ); - - await expect( - workos.userManagement.refreshAndSealSessionData({ - sessionData, - cookiePassword, - }), - ).resolves.toEqual({ - sealedSession: expect.any(String), - authenticated: true, - }); - }); - }); - - describe('getSessionFromCookie', () => { it('throws an error when the cookie password is undefined', async () => { await expect( workos.userManagement.getSessionFromCookie({ @@ -1322,28 +1525,11 @@ describe('UserManagement', () => { }); }); - describe('sendMagicAuthCode', () => { - it('sends a Send Magic Auth Code request', async () => { - fetchOnce(); - - const response = await workos.userManagement.sendMagicAuthCode({ - email: 'bob.loblaw@example.com', - }); - - expect(fetchURL()).toContain('/user_management/magic_auth/send'); - expect(fetchBody()).toEqual({ - email: 'bob.loblaw@example.com', - }); - expect(response).toBeUndefined(); - }); - }); - describe('getPasswordReset', () => { it('sends a Get PaswordReset request', async () => { fetchOnce(passwordResetFixture); - const passwordReset = await workos.userManagement.getPasswordReset( - passwordResetId, - ); + const passwordReset = + await workos.userManagement.getPasswordReset(passwordResetId); expect(fetchURL()).toContain( `/user_management/password_reset/${passwordResetId}`, ); @@ -1385,20 +1571,6 @@ describe('UserManagement', () => { }); }); - describe('sendPasswordResetEmail', () => { - it('sends a Send Password Reset Email request', async () => { - fetchOnce(); - const resp = await workos.userManagement.sendPasswordResetEmail({ - email: 'test01@example.com', - passwordResetUrl: 'https://example.com/forgot-password', - }); - - expect(fetchURL()).toContain(`/user_management/password_reset/send`); - - expect(resp).toBeUndefined(); - }); - }); - describe('resetPassword', () => { it('sends a Reset Password request', async () => { fetchOnce({ user: userFixture }); @@ -1985,9 +2157,8 @@ describe('UserManagement', () => { describe('getInvitation', () => { it('sends a Get Invitation request', async () => { fetchOnce(invitationFixture); - const invitation = await workos.userManagement.getInvitation( - invitationId, - ); + const invitation = + await workos.userManagement.getInvitation(invitationId); expect(fetchURL()).toContain( `/user_management/invitations/${invitationId}`, ); @@ -2001,9 +2172,8 @@ describe('UserManagement', () => { describe('findInvitationByToken', () => { it('sends a find invitation by token request', async () => { fetchOnce(invitationFixture); - const invitation = await workos.userManagement.findInvitationByToken( - invitationToken, - ); + const invitation = + await workos.userManagement.findInvitationByToken(invitationToken); expect(fetchURL()).toContain( `/user_management/invitations/by_token/${invitationToken}`, ); @@ -2102,9 +2272,8 @@ describe('UserManagement', () => { accepted_user_id: 'user_01HGK4K4PXNSG85RNNV0GXYP5W', }); - const response = await workos.userManagement.acceptInvitation( - invitationId, - ); + const response = + await workos.userManagement.acceptInvitation(invitationId); expect(fetchURL()).toContain( `/user_management/invitations/${invitationId}/accept`, @@ -2123,9 +2292,8 @@ describe('UserManagement', () => { const invitationId = 'invitation_01H5JQDV7R7ATEYZDEG0W5PRYS'; fetchOnce(invitationFixture); - const response = await workos.userManagement.revokeInvitation( - invitationId, - ); + const response = + await workos.userManagement.revokeInvitation(invitationId); expect(fetchURL()).toContain( `/user_management/invitations/${invitationId}/revoke`, @@ -2142,9 +2310,8 @@ describe('UserManagement', () => { const invitationId = 'invitation_01H5JQDV7R7ATEYZDEG0W5PRYS'; fetchOnce(invitationFixture); - const response = await workos.userManagement.resendInvitation( - invitationId, - ); + const response = + await workos.userManagement.resendInvitation(invitationId); expect(fetchURL()).toContain( `/user_management/invitations/${invitationId}/resend`, @@ -2242,25 +2409,10 @@ describe('UserManagement', () => { clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', screenHint: 'sign-up', + state: 'test-state', }); - expect(url).toMatchSnapshot(); - }); - }); - - describe('with a code_challenge and code_challenge_method', () => { - it('generates an authorize url', () => { - const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - - const url = workos.userManagement.getAuthorizationUrl({ - provider: 'authkit', - clientId: 'proj_123', - redirectUri: 'example.com/auth/workos/callback', - codeChallenge: 'code_challenge_value', - codeChallengeMethod: 'S256', - }); - - expect(url).toMatchSnapshot(); + expect(url).toContain('screen_hint=sign-up'); }); }); @@ -2272,9 +2424,12 @@ describe('UserManagement', () => { provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain( + 'https://api.workos.com/user_management/authorize', + ); }); }); @@ -2282,13 +2437,14 @@ describe('UserManagement', () => { it('throws an error for incomplete arguments', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - const urlFn = () => + expect(() => workos.userManagement.getAuthorizationUrl({ clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', - }); - - expect(urlFn).toThrowErrorMatchingSnapshot(); + }), + ).toThrow( + `Incomplete arguments. Need to specify either a 'connectionId', 'organizationId', or 'provider'.`, + ); }); }); @@ -2300,9 +2456,10 @@ describe('UserManagement', () => { provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('provider=GoogleOAuth'); }); describe('with providerScopes', () => { @@ -2317,9 +2474,10 @@ describe('UserManagement', () => { ], clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('provider_scopes'); }); describe('with providerQueryParams', () => { @@ -2335,8 +2493,9 @@ describe('UserManagement', () => { baz: 123, bool: true, }, + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('provider_query_params'); }); }); }); @@ -2350,9 +2509,10 @@ describe('UserManagement', () => { connectionId: 'connection_123', clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('connection_id=connection_123'); }); describe('with providerScopes', () => { @@ -2364,9 +2524,10 @@ describe('UserManagement', () => { providerScopes: ['read_api', 'read_repository'], clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('provider_scopes'); }); }); }); @@ -2379,9 +2540,10 @@ describe('UserManagement', () => { organizationId: 'organization_123', clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('organization_id=organization_123'); }); }); @@ -2395,9 +2557,12 @@ describe('UserManagement', () => { organizationId: 'organization_123', clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain( + 'https://api.workos.dev/user_management/authorize', + ); }); }); @@ -2412,7 +2577,7 @@ describe('UserManagement', () => { state: 'custom state', }); - expect(url).toMatchSnapshot(); + expect(url).toContain('state=custom+state'); }); }); @@ -2428,9 +2593,7 @@ describe('UserManagement', () => { state: 'custom state', }); - expect(url).toMatchInlineSnapshot( - `"https://api.workos.com/user_management/authorize?client_id=proj_123&connection_id=connection_123&domain_hint=example.com&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code&state=custom+state"`, - ); + expect(url).toContain('domain_hint=example.com'); }); }); @@ -2446,9 +2609,7 @@ describe('UserManagement', () => { state: 'custom state', }); - expect(url).toMatchInlineSnapshot( - `"https://api.workos.com/user_management/authorize?client_id=proj_123&connection_id=connection_123&login_hint=foo%40workos.com&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code&state=custom+state"`, - ); + expect(url).toContain('login_hint=foo%40workos.com'); }); }); @@ -2464,9 +2625,7 @@ describe('UserManagement', () => { state: 'custom state', }); - expect(url).toMatchInlineSnapshot( - `"https://api.workos.com/user_management/authorize?client_id=proj_123&connection_id=connection_123&prompt=login&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code&state=custom+state"`, - ); + expect(url).toContain('prompt=login'); }); it('generates an authorize url with consent prompt', () => { @@ -2477,192 +2636,153 @@ describe('UserManagement', () => { provider: 'GoogleOAuth', clientId: 'proj_123', redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', }); - expect(url).toMatchInlineSnapshot( - `"https://api.workos.com/user_management/authorize?client_id=proj_123&prompt=consent&provider=GoogleOAuth&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`, - ); - }); - }); - }); - - describe('getLogoutUrl', () => { - it('returns a logout url', () => { - const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - - const url = workos.userManagement.getLogoutUrl({ - sessionId: '123456', + expect(url).toContain('prompt=consent'); }); - - expect(url).toBe( - 'https://api.workos.com/user_management/sessions/logout?session_id=123456', - ); }); - describe('when a `returnTo` is given', () => { - it('includes a `return_to` in the URL', () => { + describe('with PKCE parameters (manual)', () => { + it('includes codeChallenge and codeChallengeMethod in URL', () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - const url = workos.userManagement.getLogoutUrl({ - sessionId: '123456', - returnTo: 'https://your-app.com/signed-out', + const url = workos.userManagement.getAuthorizationUrl({ + provider: 'authkit', + clientId: 'proj_123', + redirectUri: 'example.com/auth/workos/callback', + state: 'test-state', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'S256', }); - expect(url).toBe( - 'https://api.workos.com/user_management/sessions/logout?session_id=123456&return_to=https%3A%2F%2Fyour-app.com%2Fsigned-out', - ); + expect(url).toContain('code_challenge=test-challenge'); + expect(url).toContain('code_challenge_method=S256'); }); }); }); - describe('getLogoutUrlFromSessionCookie', () => { + describe('getAuthorizationUrlWithPKCE', () => { + let publicWorkos: WorkOS; + let originalApiKey: string | undefined; + beforeEach(() => { - // Mock createRemoteJWKSet - jest - .spyOn(jose, 'createRemoteJWKSet') - .mockImplementation( - (_url: URL, _options?: jose.RemoteJWKSetOptions) => { - // This function simulates the token verification process - const verifyFunction = ( - _protectedHeader: jose.JWSHeaderParameters, - _token: jose.FlattenedJWSInput, - ): Promise => { - return Promise.resolve({ - type: 'public', - }); - }; + originalApiKey = process.env.WORKOS_API_KEY; + delete process.env.WORKOS_API_KEY; + publicWorkos = new WorkOS({ clientId: 'proj_123' }); + }); - // Return an object that includes the verify function and the additional expected properties - return { - __call__: verifyFunction, - coolingDown: false, - fresh: false, - reloading: false, - reload: jest.fn().mockResolvedValue(undefined), - jwks: () => undefined, - } as unknown as ReturnType; - }, - ); + afterEach(() => { + if (originalApiKey) { + process.env.WORKOS_API_KEY = originalApiKey; + } }); - it('throws an error when the cookie password is undefined', async () => { - await expect( - workos.userManagement.getLogoutUrlFromSessionCookie({ - sessionData: 'session_cookie', - }), - ).rejects.toThrow('Cookie password is required'); + it('generates PKCE parameters and returns codeVerifier', async () => { + const result = + await publicWorkos.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + clientId: 'proj_123', + redirectUri: 'example.com/auth/workos/callback', + }); + + expect(result.codeVerifier).toBeDefined(); + expect(result.codeVerifier.length).toBeGreaterThanOrEqual(43); + expect(result.url).toContain('code_challenge='); + expect(result.url).toContain('code_challenge_method=S256'); }); - it('returns authenticated = false when the session cookie is empty', async () => { - await expect( - workos.userManagement.getLogoutUrlFromSessionCookie({ - sessionData: '', - cookiePassword: 'secret', - }), - ).rejects.toThrowError( - new Error( - 'Failed to extract session ID for logout URL: no_session_cookie_provided', - ), - ); + it('auto-generates state parameter', async () => { + const result = + await publicWorkos.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + clientId: 'proj_123', + redirectUri: 'example.com/auth/workos/callback', + }); + + expect(result.state).toBeDefined(); + expect(result.state.length).toBeGreaterThanOrEqual(43); + expect(result.url).toContain('state='); }); - it('returns authenticated = false when session cookie is invalid', async () => { + it('includes all standard URL parameters', async () => { + const result = + await publicWorkos.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + clientId: 'proj_123', + redirectUri: 'example.com/auth/workos/callback', + screenHint: 'sign-up', + loginHint: 'test@example.com', + domainHint: 'example.com', + }); + + expect(result.url).toContain('provider=authkit'); + expect(result.url).toContain('screen_hint=sign-up'); + expect(result.url).toContain('login_hint=test%40example.com'); + expect(result.url).toContain('domain_hint=example.com'); + }); + + it('throws error when missing provider/connection/organization', async () => { await expect( - workos.userManagement.getLogoutUrlFromSessionCookie({ - sessionData: 'thisisacookie', - cookiePassword: 'secret', + publicWorkos.userManagement.getAuthorizationUrlWithPKCE({ + clientId: 'proj_123', + redirectUri: 'example.com/auth/workos/callback', }), - ).rejects.toThrowError( - new Error( - 'Failed to extract session ID for logout URL: invalid_session_cookie', - ), + ).rejects.toThrow( + `Incomplete arguments. Need to specify either a 'connectionId', 'organizationId', or 'provider'.`, ); }); - it('returns authenticated = false when session cookie cannot be unsealed', async () => { - const cookiePassword = 'alongcookiesecretmadefortestingsessions'; - const sessionData = await sealData( - { - accessToken: 'abc123', - refreshToken: 'def456', - user: { - object: 'user', - id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', - email: 'test@example.com', - }, - }, - { password: cookiePassword }, - ); + it('uses clientId from constructor when not provided in options', async () => { + const result = + await publicWorkos.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + redirectUri: 'example.com/auth/workos/callback', + }); + + expect(result.url).toContain('client_id=proj_123'); + }); + it('throws error when clientId not provided anywhere', async () => { + // Use confidential client (API key) without clientId to test the error + const workosNoClientId = new WorkOS('sk_test_no_client_id'); await expect( - workos.userManagement.getLogoutUrlFromSessionCookie({ - sessionData, - cookiePassword: 'secretpasswordwhichisalsolongbutnottherightone', + workosNoClientId.userManagement.getAuthorizationUrlWithPKCE({ + provider: 'authkit', + redirectUri: 'example.com/auth/workos/callback', }), - ).rejects.toThrowError( - new Error( - 'Failed to extract session ID for logout URL: invalid_session_cookie', - ), + ).rejects.toThrow( + 'clientId is required. Provide it in method options or when initializing WorkOS.', ); }); + }); - it('returns authenticated = false when the JWT is invalid', async () => { - jest.spyOn(jose, 'jwtVerify').mockImplementationOnce(() => { - throw new Error('Invalid JWT'); - }); + describe('getLogoutUrl', () => { + it('returns a logout url', () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - const cookiePassword = 'alongcookiesecretmadefortestingsessions'; - const sessionData = await sealData( - { - accessToken: 'abc123', - refreshToken: 'def456', - user: { - object: 'user', - id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', - email: 'test@example.com', - }, - }, - { password: cookiePassword }, - ); + const url = workos.userManagement.getLogoutUrl({ + sessionId: '123456', + }); - await expect( - workos.userManagement.getLogoutUrlFromSessionCookie({ - sessionData, - cookiePassword, - }), - ).rejects.toThrowError( - new Error('Failed to extract session ID for logout URL: invalid_jwt'), + expect(url).toBe( + 'https://api.workos.com/user_management/sessions/logout?session_id=123456', ); }); - it('returns the logout URL for the session when provided a valid JWT', async () => { - jest - .spyOn(jose, 'jwtVerify') - .mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey); + describe('when a `returnTo` is given', () => { + it('includes a `return_to` in the URL', () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - const cookiePassword = 'alongcookiesecretmadefortestingsessions'; - const sessionData = await sealData( - { - accessToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiSm9obiBEb2UiLAogICJpYXQiOiAxNTE2MjM5MDIyLAogICJzaWQiOiAic2Vzc2lvbl8xMjMiLAogICJvcmdfaWQiOiAib3JnXzEyMyIsCiAgInJvbGUiOiAibWVtYmVyIiwKICAicGVybWlzc2lvbnMiOiBbInBvc3RzOmNyZWF0ZSIsICJwb3N0czpkZWxldGUiXQp9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', - refreshToken: 'def456', - user: { - object: 'user', - id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', - email: 'test@example.com', - }, - }, - { password: cookiePassword }, - ); + const url = workos.userManagement.getLogoutUrl({ + sessionId: '123456', + returnTo: 'https://your-app.com/signed-out', + }); - await expect( - workos.userManagement.getLogoutUrlFromSessionCookie({ - sessionData, - cookiePassword, - }), - ).resolves.toEqual( - `https://api.workos.test/user_management/sessions/logout?session_id=session_123`, - ); + expect(url).toBe( + 'https://api.workos.com/user_management/sessions/logout?session_id=123456&return_to=https%3A%2F%2Fyour-app.com%2Fsigned-out', + ); + }); }); }); @@ -2680,7 +2800,7 @@ describe('UserManagement', () => { expect(() => { workos.userManagement.getJwksUrl(''); - }).toThrowError(TypeError); + }).toThrow(TypeError); }); }); }); diff --git a/src/user-management/user-management.ts b/src/user-management/user-management.ts index 44163ee0b..2e5537b5f 100644 --- a/src/user-management/user-management.ts +++ b/src/user-management/user-management.ts @@ -1,9 +1,9 @@ -import { createRemoteJWKSet, decodeJwt, jwtVerify } from 'jose'; -import qs from 'qs'; -import { OauthException } from '../common/exceptions/oauth.exception'; -import { IronSessionProvider } from '../common/iron-session/iron-session-provider'; +import { sealData, unsealData } from '../common/crypto/seal'; +import { PaginationOptions } from '../common/interfaces/pagination-options.interface'; import { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize'; import { AutoPaginatable } from '../common/utils/pagination'; +import { getEnv } from '../common/utils/env'; +import { toQueryString } from '../common/utils/query-string'; import { Challenge, ChallengeResponse } from '../mfa/interfaces'; import { deserializeChallenge } from '../mfa/serializers'; import { @@ -13,8 +13,8 @@ import { import { deserializeFeatureFlag } from '../feature-flags/serializers'; import { WorkOS } from '../workos'; import { - AuthenticateWithCodeOptions, AuthenticateWithCodeAndVerifierOptions, + AuthenticateWithCodeOptions, AuthenticateWithMagicAuthOptions, AuthenticateWithPasswordOptions, AuthenticateWithRefreshTokenOptions, @@ -32,26 +32,26 @@ import { ListSessionsOptions, ListUsersOptions, ListUserFeatureFlagsOptions, + LogoutURLOptions, MagicAuth, MagicAuthResponse, PasswordReset, PasswordResetResponse, ResetPasswordOptions, - SendMagicAuthCodeOptions, - SendPasswordResetEmailOptions, SendVerificationEmailOptions, - SerializedAuthenticateWithCodeOptions, SerializedAuthenticateWithCodeAndVerifierOptions, + SerializedAuthenticateWithCodeOptions, SerializedAuthenticateWithMagicAuthOptions, SerializedAuthenticateWithPasswordOptions, SerializedAuthenticateWithRefreshTokenOptions, + SerializedAuthenticateWithRefreshTokenPublicClientOptions, SerializedAuthenticateWithTotpOptions, SerializedCreateMagicAuthOptions, SerializedCreatePasswordResetOptions, SerializedCreateUserOptions, + SerializedListSessionsOptions, + SerializedListUsersOptions, SerializedResetPasswordOptions, - SerializedSendMagicAuthCodeOptions, - SerializedSendPasswordResetEmailOptions, SerializedVerifyEmailOptions, Session, SessionResponse, @@ -76,7 +76,10 @@ import { AuthenticateWithSessionCookieSuccessResponse, SessionCookieData, } from './interfaces/authenticate-with-session-cookie.interface'; -import { UserManagementAuthorizationURLOptions } from './interfaces/authorization-url-options.interface'; +import { + PKCEAuthorizationURLResult, + UserManagementAuthorizationURLOptions, +} from './interfaces/authorization-url-options.interface'; import { CreateOrganizationMembershipOptions, SerializedCreateOrganizationMembershipOptions, @@ -92,16 +95,18 @@ import { Invitation, InvitationResponse, } from './interfaces/invitation.interface'; -import { ListInvitationsOptions } from './interfaces/list-invitations-options.interface'; -import { ListOrganizationMembershipsOptions } from './interfaces/list-organization-memberships-options.interface'; +import { + ListInvitationsOptions, + SerializedListInvitationsOptions, +} from './interfaces/list-invitations-options.interface'; +import { + ListOrganizationMembershipsOptions, + SerializedListOrganizationMembershipsOptions, +} from './interfaces/list-organization-memberships-options.interface'; import { OrganizationMembership, OrganizationMembershipResponse, } from './interfaces/organization-membership.interface'; -import { - RefreshAndSealSessionDataFailureReason, - RefreshAndSealSessionDataResponse, -} from './interfaces/refresh-and-seal-session-data.interface'; import { RevokeSessionOptions, SerializedRevokeSessionOptions, @@ -124,11 +129,12 @@ import { deserializePasswordReset, deserializeSession, deserializeUser, - serializeAuthenticateWithCodeOptions, serializeAuthenticateWithCodeAndVerifierOptions, + serializeAuthenticateWithCodeOptions, serializeAuthenticateWithMagicAuthOptions, serializeAuthenticateWithPasswordOptions, serializeAuthenticateWithRefreshTokenOptions, + serializeAuthenticateWithRefreshTokenPublicClientOptions, serializeAuthenticateWithTotpOptions, serializeCreateMagicAuthOptions, serializeCreatePasswordResetOptions, @@ -136,8 +142,6 @@ import { serializeEnrollAuthFactorOptions, serializeListSessionsOptions, serializeResetPasswordOptions, - serializeSendMagicAuthCodeOptions, - serializeSendPasswordResetEmailOptions, serializeUpdateUserOptions, } from './serializers'; import { serializeAuthenticateWithEmailVerificationOptions } from './serializers/authenticate-with-email-verification.serializer'; @@ -153,38 +157,38 @@ import { deserializeOrganizationMembership } from './serializers/organization-me import { serializeSendInvitationOptions } from './serializers/send-invitation-options.serializer'; import { serializeUpdateOrganizationMembershipOptions } from './serializers/update-organization-membership-options.serializer'; import { CookieSession } from './session'; - -const toQueryString = ( - options: Record< - string, - string | string[] | Record | undefined - >, -): string => { - return qs.stringify(options, { - arrayFormat: 'repeat', - // sorts the keys alphabetically to maintain backwards compatibility - sort: (a, b) => a.localeCompare(b), - // encodes space as + instead of %20 to maintain backwards compatibility - format: 'RFC1738', - }); -}; +import { getJose } from '../utils/jose'; export class UserManagement { - private _jwks: ReturnType | undefined; + private _jwks: + | ReturnType + | undefined; public clientId: string | undefined; - public ironSessionProvider: IronSessionProvider; - constructor( - private readonly workos: WorkOS, - ironSessionProvider: IronSessionProvider, - ) { + constructor(private readonly workos: WorkOS) { const { clientId } = workos.options; this.clientId = clientId; - this.ironSessionProvider = ironSessionProvider; } - get jwks(): ReturnType | undefined { + /** + * Resolve clientId from method options or fall back to constructor-provided value. + * @throws TypeError if clientId is not available from either source + */ + private resolveClientId(clientId?: string): string { + const resolved = clientId ?? this.clientId; + if (!resolved) { + throw new TypeError( + 'clientId is required. Provide it in method options or when initializing WorkOS.', + ); + } + return resolved; + } + + async getJWKS(): Promise< + ReturnType | undefined + > { + const { createRemoteJWKSet } = await getJose(); if (!this.clientId) { return; } @@ -228,7 +232,9 @@ export class UserManagement { return deserializeUser(data); } - async listUsers(options?: ListUsersOptions): Promise> { + async listUsers( + options?: ListUsersOptions, + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -259,7 +265,8 @@ export class UserManagement { async authenticateWithMagicAuth( payload: AuthenticateWithMagicAuthOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); const { data } = await this.workos.post< AuthenticationResponseResponse, @@ -268,6 +275,7 @@ export class UserManagement { '/user_management/authenticate', serializeAuthenticateWithMagicAuthOptions({ ...remainingPayload, + clientId: resolvedClientId, clientSecret: this.workos.key, }), ); @@ -281,7 +289,8 @@ export class UserManagement { async authenticateWithPassword( payload: AuthenticateWithPasswordOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); const { data } = await this.workos.post< AuthenticationResponseResponse, @@ -290,6 +299,7 @@ export class UserManagement { '/user_management/authenticate', serializeAuthenticateWithPasswordOptions({ ...remainingPayload, + clientId: resolvedClientId, clientSecret: this.workos.key, }), ); @@ -300,10 +310,42 @@ export class UserManagement { }); } + /** + * Exchange an authorization code for tokens. + * + * Auto-detects public vs confidential client mode: + * - If codeVerifier is provided: Uses PKCE flow (public client) + * - If no codeVerifier: Uses client_secret from API key (confidential client) + * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE) + * + * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense + * in depth and provides additional CSRF protection on the authorization flow. + * + * @throws Error if neither codeVerifier nor API key is available + */ async authenticateWithCode( payload: AuthenticateWithCodeOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, codeVerifier, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); + + // Validate codeVerifier is not an empty string (common mistake) + if (codeVerifier !== undefined && codeVerifier.trim() === '') { + throw new TypeError( + 'codeVerifier cannot be an empty string. ' + + 'Generate a valid PKCE pair using workos.pkce.generate().', + ); + } + + const hasApiKey = !!this.workos.key; + const hasPKCE = !!codeVerifier; + + if (!hasPKCE && !hasApiKey) { + throw new TypeError( + 'authenticateWithCode requires either a codeVerifier (for public clients) ' + + 'or an API key configured on the WorkOS instance (for confidential clients).', + ); + } const { data } = await this.workos.post< AuthenticationResponseResponse, @@ -312,8 +354,11 @@ export class UserManagement { '/user_management/authenticate', serializeAuthenticateWithCodeOptions({ ...remainingPayload, - clientSecret: this.workos.key, + clientId: resolvedClientId, + codeVerifier, + clientSecret: hasApiKey ? this.workos.key : undefined, }), + { skipApiKeyCheck: !hasApiKey }, ); return this.prepareAuthenticationResponse({ @@ -322,17 +367,31 @@ export class UserManagement { }); } + /** + * Exchange an authorization code for tokens using PKCE (public client flow). + * Use this instead of authenticateWithCode() when the client cannot securely + * store a client_secret (browser, mobile, CLI, desktop apps). + * + * @param payload.clientId - Your WorkOS client ID + * @param payload.code - The authorization code from the OAuth callback + * @param payload.codeVerifier - The PKCE code verifier used to generate the code challenge + */ async authenticateWithCodeAndVerifier( payload: AuthenticateWithCodeAndVerifierOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); const { data } = await this.workos.post< AuthenticationResponseResponse, SerializedAuthenticateWithCodeAndVerifierOptions >( '/user_management/authenticate', - serializeAuthenticateWithCodeAndVerifierOptions(remainingPayload), + serializeAuthenticateWithCodeAndVerifierOptions({ + ...remainingPayload, + clientId: resolvedClientId, + }), + { skipApiKeyCheck: true }, ); return this.prepareAuthenticationResponse({ @@ -341,21 +400,36 @@ export class UserManagement { }); } + /** + * Refresh an access token using a refresh token. + * Automatically detects public client mode - if no API key is configured, + * omits client_secret from the request. + */ async authenticateWithRefreshToken( payload: AuthenticateWithRefreshTokenOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); + const isPublicClient = !this.workos.key; + + const body = isPublicClient + ? serializeAuthenticateWithRefreshTokenPublicClientOptions({ + ...remainingPayload, + clientId: resolvedClientId, + }) + : serializeAuthenticateWithRefreshTokenOptions({ + ...remainingPayload, + clientId: resolvedClientId, + clientSecret: this.workos.key, + }); const { data } = await this.workos.post< AuthenticationResponseResponse, - SerializedAuthenticateWithRefreshTokenOptions - >( - '/user_management/authenticate', - serializeAuthenticateWithRefreshTokenOptions({ - ...remainingPayload, - clientSecret: this.workos.key, - }), - ); + | SerializedAuthenticateWithRefreshTokenOptions + | SerializedAuthenticateWithRefreshTokenPublicClientOptions + >('/user_management/authenticate', body, { + skipApiKeyCheck: isPublicClient, + }); return this.prepareAuthenticationResponse({ authenticationResponse: deserializeAuthenticationResponse(data), @@ -366,7 +440,8 @@ export class UserManagement { async authenticateWithTotp( payload: AuthenticateWithTotpOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); const { data } = await this.workos.post< AuthenticationResponseResponse, @@ -375,6 +450,7 @@ export class UserManagement { '/user_management/authenticate', serializeAuthenticateWithTotpOptions({ ...remainingPayload, + clientId: resolvedClientId, clientSecret: this.workos.key, }), ); @@ -388,7 +464,8 @@ export class UserManagement { async authenticateWithEmailVerification( payload: AuthenticateWithEmailVerificationOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); const { data } = await this.workos.post< AuthenticationResponseResponse, @@ -397,6 +474,7 @@ export class UserManagement { '/user_management/authenticate', serializeAuthenticateWithEmailVerificationOptions({ ...remainingPayload, + clientId: resolvedClientId, clientSecret: this.workos.key, }), ); @@ -410,7 +488,8 @@ export class UserManagement { async authenticateWithOrganizationSelection( payload: AuthenticateWithOrganizationSelectionOptions, ): Promise { - const { session, ...remainingPayload } = payload; + const { session, clientId, ...remainingPayload } = payload; + const resolvedClientId = this.resolveClientId(clientId); const { data } = await this.workos.post< AuthenticationResponseResponse, @@ -419,6 +498,7 @@ export class UserManagement { '/user_management/authenticate', serializeAuthenticateWithOrganizationSelectionOptions({ ...remainingPayload, + clientId: resolvedClientId, clientSecret: this.workos.key, }), ); @@ -431,7 +511,7 @@ export class UserManagement { async authenticateWithSessionCookie({ sessionData, - cookiePassword = process.env.WORKOS_COOKIE_PASSWORD, + cookiePassword = getEnv('WORKOS_COOKIE_PASSWORD'), }: AuthenticateWithSessionCookieOptions): Promise< | AuthenticateWithSessionCookieSuccessResponse | AuthenticateWithSessionCookieFailedResponse @@ -440,10 +520,14 @@ export class UserManagement { throw new Error('Cookie password is required'); } - if (!this.jwks) { + const jwks = await this.getJWKS(); + + if (!jwks) { throw new Error('Must provide clientId to initialize JWKS'); } + const { decodeJwt } = await getJose(); + if (!sessionData) { return { authenticated: false, @@ -452,13 +536,9 @@ export class UserManagement { }; } - const session = - await this.ironSessionProvider.unsealData( - sessionData, - { - password: cookiePassword, - }, - ); + const session = await unsealData(sessionData, { + password: cookiePassword, + }); if (!session.accessToken) { return { @@ -501,93 +581,27 @@ export class UserManagement { } private async isValidJwt(accessToken: string): Promise { - if (!this.jwks) { + const jwks = await this.getJWKS(); + const { jwtVerify } = await getJose(); + if (!jwks) { throw new Error('Must provide clientId to initialize JWKS'); } try { - await jwtVerify(accessToken, this.jwks); + await jwtVerify(accessToken, jwks); return true; } catch (e) { - return false; - } - } - - /** - * @deprecated This method is deprecated and will be removed in a future major version. - * Please use the new `loadSealedSession` helper and its corresponding methods instead. - */ - async refreshAndSealSessionData({ - sessionData, - organizationId, - cookiePassword = process.env.WORKOS_COOKIE_PASSWORD, - }: SessionHandlerOptions): Promise { - if (!cookiePassword) { - throw new Error('Cookie password is required'); - } - - if (!sessionData) { - return { - authenticated: false, - reason: - RefreshAndSealSessionDataFailureReason.NO_SESSION_COOKIE_PROVIDED, - }; - } - - const session = - await this.ironSessionProvider.unsealData( - sessionData, - { - password: cookiePassword, - }, - ); - - if (!session.refreshToken || !session.user) { - return { - authenticated: false, - reason: RefreshAndSealSessionDataFailureReason.INVALID_SESSION_COOKIE, - }; - } - - const { org_id: organizationIdFromAccessToken } = decodeJwt( - session.accessToken, - ); - - try { - const { sealedSession } = await this.authenticateWithRefreshToken({ - clientId: this.workos.clientId as string, - refreshToken: session.refreshToken, - organizationId: organizationId ?? organizationIdFromAccessToken, - session: { sealSession: true, cookiePassword }, - }); - - if (!sealedSession) { - return { - authenticated: false, - reason: RefreshAndSealSessionDataFailureReason.INVALID_SESSION_COOKIE, - }; - } - - return { - authenticated: true, - sealedSession, - }; - } catch (error) { + // Only treat as invalid JWT if it's an actual JWT/JWS error from jose + // Network errors, crypto failures, etc. should propagate if ( - error instanceof OauthException && - // TODO: Add additional known errors and remove re-throw - (error.error === RefreshAndSealSessionDataFailureReason.INVALID_GRANT || - error.error === - RefreshAndSealSessionDataFailureReason.MFA_ENROLLMENT || - error.error === RefreshAndSealSessionDataFailureReason.SSO_REQUIRED) + e instanceof Error && + 'code' in e && + typeof e.code === 'string' && + (e.code.startsWith('ERR_JWT_') || e.code.startsWith('ERR_JWS_')) ) { - return { - authenticated: false, - reason: error.error, - }; + return false; } - - throw error; + throw e; } } @@ -599,6 +613,14 @@ export class UserManagement { session?: AuthenticateWithSessionOptions; }): Promise { if (session?.sealSession) { + if (!this.workos.key) { + throw new Error( + 'Session sealing requires server-side usage with an API key. ' + + 'Public clients should store tokens directly ' + + '(e.g., secure storage on mobile, keychain on desktop).', + ); + } + return { ...authenticationResponse, sealedSession: await this.sealSessionDataFromAuthenticationResponse({ @@ -622,6 +644,8 @@ export class UserManagement { throw new Error('Cookie password is required'); } + const { decodeJwt } = await getJose(); + const { org_id: organizationIdFromAccessToken } = decodeJwt( authenticationResponse.accessToken, ); @@ -635,26 +659,23 @@ export class UserManagement { impersonator: authenticationResponse.impersonator, }; - return this.ironSessionProvider.sealData(sessionData, { + return sealData(sessionData, { password: cookiePassword, }); } async getSessionFromCookie({ sessionData, - cookiePassword = process.env.WORKOS_COOKIE_PASSWORD, + cookiePassword = getEnv('WORKOS_COOKIE_PASSWORD'), }: SessionHandlerOptions): Promise { if (!cookiePassword) { throw new Error('Cookie password is required'); } if (sessionData) { - return this.ironSessionProvider.unsealData( - sessionData, - { - password: cookiePassword, - }, - ); + return unsealData(sessionData, { + password: cookiePassword, + }); } return undefined; @@ -703,17 +724,6 @@ export class UserManagement { return deserializeMagicAuth(data); } - /** - * @deprecated Please use `createMagicAuth` instead. - * This method will be removed in a future major version. - */ - async sendMagicAuthCode(options: SendMagicAuthCodeOptions): Promise { - await this.workos.post( - '/user_management/magic_auth/send', - serializeSendMagicAuthCodeOptions(options), - ); - } - async verifyEmail({ code, userId, @@ -752,18 +762,6 @@ export class UserManagement { return deserializePasswordReset(data); } - /** - * @deprecated Please use `createPasswordReset` instead. This method will be removed in a future major version. - */ - async sendPasswordResetEmail( - payload: SendPasswordResetEmailOptions, - ): Promise { - await this.workos.post( - '/user_management/password_reset/send', - serializeSendPasswordResetEmailOptions(payload), - ); - } - async resetPassword(payload: ResetPasswordOptions): Promise<{ user: User }> { const { data } = await this.workos.post< { user: UserResponse }, @@ -809,7 +807,7 @@ export class UserManagement { async listAuthFactors( options: ListAuthFactorsOptions, - ): Promise> { + ): Promise> { const { userId, ...restOfOptions } = options; return new AutoPaginatable( await fetchAndDeserialize( @@ -855,7 +853,7 @@ export class UserManagement { async listSessions( userId: string, options?: ListSessionsOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -902,7 +900,15 @@ export class UserManagement { async listOrganizationMemberships( options: ListOrganizationMembershipsOptions, - ): Promise> { + ): Promise< + AutoPaginatable< + OrganizationMembership, + SerializedListOrganizationMembershipsOptions + > + > { + const serializedOptions = + serializeListOrganizationMembershipsOptions(options); + return new AutoPaginatable( await fetchAndDeserialize< OrganizationMembershipResponse, @@ -911,9 +917,7 @@ export class UserManagement { this.workos, '/user_management/organization_memberships', deserializeOrganizationMembership, - options - ? serializeListOrganizationMembershipsOptions(options) - : undefined, + serializedOptions, ), (params) => fetchAndDeserialize< @@ -925,9 +929,7 @@ export class UserManagement { deserializeOrganizationMembership, params, ), - options - ? serializeListOrganizationMembershipsOptions(options) - : undefined, + serializedOptions, ); } @@ -1008,7 +1010,7 @@ export class UserManagement { async listInvitations( options: ListInvitationsOptions, - ): Promise> { + ): Promise> { return new AutoPaginatable( await fetchAndDeserialize( this.workos, @@ -1075,23 +1077,35 @@ export class UserManagement { ); } - getAuthorizationUrl({ - connectionId, - codeChallenge, - codeChallengeMethod, - context, - clientId, - domainHint, - loginHint, - organizationId, - provider, - providerQueryParams, - providerScopes, - prompt, - redirectUri, - state, - screenHint, - }: UserManagementAuthorizationURLOptions): string { + /** + * Generate an OAuth 2.0 authorization URL. + * + * For public clients (browser, mobile, CLI), include PKCE parameters: + * - Generate PKCE using workos.pkce.generate() + * - Pass codeChallenge and codeChallengeMethod here + * - Store codeVerifier and pass to authenticateWithCode() later + * + * Or use getAuthorizationUrlWithPKCE() which handles PKCE automatically. + */ + getAuthorizationUrl(options: UserManagementAuthorizationURLOptions): string { + const { + connectionId, + codeChallenge, + codeChallengeMethod, + clientId, + domainHint, + loginHint, + organizationId, + provider, + providerQueryParams, + providerScopes, + prompt, + redirectUri, + state, + screenHint, + } = options; + const resolvedClientId = this.resolveClientId(clientId); + if (!provider && !connectionId && !organizationId) { throw new TypeError( `Incomplete arguments. Need to specify either a 'connectionId', 'organizationId', or 'provider'.`, @@ -1104,18 +1118,10 @@ export class UserManagement { ); } - if (context) { - this.workos.emitWarning( - `\`context\` is deprecated. We previously required initiate login endpoints to return the -\`context\` query parameter when getting the authorization URL. This is no longer necessary.`, - ); - } - const query = toQueryString({ connection_id: connectionId, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod, - context, organization_id: organizationId, domain_hint: domainHint, login_hint: loginHint, @@ -1123,7 +1129,7 @@ export class UserManagement { provider_query_params: providerQueryParams, provider_scopes: providerScopes, prompt, - client_id: clientId, + client_id: resolvedClientId, redirect_uri: redirectUri, response_type: 'code', state, @@ -1133,13 +1139,97 @@ export class UserManagement { return `${this.workos.baseURL}/user_management/authorize?${query}`; } - getLogoutUrl({ - sessionId, - returnTo, - }: { - sessionId: string; - returnTo?: string; - }): string { + /** + * Generate an OAuth 2.0 authorization URL with automatic PKCE. + * + * This method generates PKCE parameters internally and returns them along with + * the authorization URL. Use this for public clients (CLI apps, Electron, mobile) + * that cannot securely store a client secret. + * + * @returns Object containing url, state, and codeVerifier + * + * @example + * ```typescript + * const { url, state, codeVerifier } = await workos.userManagement.getAuthorizationUrlWithPKCE({ + * provider: 'authkit', + * clientId: 'client_123', + * redirectUri: 'myapp://callback', + * }); + * + * // Store state and codeVerifier securely, then redirect user to url + * // After callback, exchange the code: + * const response = await workos.userManagement.authenticateWithCode({ + * code: authorizationCode, + * codeVerifier, + * clientId: 'client_123', + * }); + * ``` + */ + async getAuthorizationUrlWithPKCE( + options: Omit< + UserManagementAuthorizationURLOptions, + 'codeChallenge' | 'codeChallengeMethod' | 'state' + >, + ): Promise { + const { + clientId, + connectionId, + domainHint, + loginHint, + organizationId, + provider, + providerQueryParams, + providerScopes, + prompt, + redirectUri, + screenHint, + } = options; + const resolvedClientId = this.resolveClientId(clientId); + + if (!provider && !connectionId && !organizationId) { + throw new TypeError( + `Incomplete arguments. Need to specify either a 'connectionId', 'organizationId', or 'provider'.`, + ); + } + + if (provider !== 'authkit' && screenHint) { + throw new TypeError( + `'screenHint' is only supported for 'authkit' provider`, + ); + } + + // Generate PKCE parameters + const pkce = await this.workos.pkce.generate(); + + // Generate secure random state + const state = this.workos.pkce.generateCodeVerifier(43); + + const query = toQueryString({ + connection_id: connectionId, + code_challenge: pkce.codeChallenge, + code_challenge_method: 'S256', + organization_id: organizationId, + domain_hint: domainHint, + login_hint: loginHint, + provider, + provider_query_params: providerQueryParams, + provider_scopes: providerScopes, + prompt, + client_id: resolvedClientId, + redirect_uri: redirectUri, + response_type: 'code', + state, + screen_hint: screenHint, + }); + + const url = `${this.workos.baseURL}/user_management/authorize?${query}`; + + return { url, state, codeVerifier: pkce.codeVerifier }; + } + + getLogoutUrl(options: LogoutURLOptions): string { + const { sessionId, returnTo } = options; + if (!sessionId) { throw new TypeError(`Incomplete arguments. Need to specify 'sessionId'.`); } @@ -1157,35 +1247,9 @@ export class UserManagement { return url.toString(); } - /** - * @deprecated This method is deprecated and will be removed in a future major version. - * Please use the `loadSealedSession` helper and its `getLogoutUrl` method instead. - * - * getLogoutUrlFromSessionCookie takes in session cookie data, unseals the cookie, decodes the JWT claims, - * and uses the session ID to generate the logout URL. - * - * Use this over `getLogoutUrl` if you'd like to the SDK to handle session cookies for you. - */ - async getLogoutUrlFromSessionCookie({ - sessionData, - cookiePassword = process.env.WORKOS_COOKIE_PASSWORD, - }: SessionHandlerOptions): Promise { - const authenticationResponse = await this.authenticateWithSessionCookie({ - sessionData, - cookiePassword, - }); - - if (!authenticationResponse.authenticated) { - const { reason } = authenticationResponse; - throw new Error(`Failed to extract session ID for logout URL: ${reason}`); - } - - return this.getLogoutUrl({ sessionId: authenticationResponse.sessionId }); - } - getJwksUrl(clientId: string): string { if (!clientId) { - throw TypeError('clientId must be a valid clientId'); + throw new TypeError('clientId must be a valid clientId'); } return `${this.workos.baseURL}/sso/jwks/${clientId}`; diff --git a/src/utils/jose.ts b/src/utils/jose.ts new file mode 100644 index 000000000..a25a71df0 --- /dev/null +++ b/src/utils/jose.ts @@ -0,0 +1,17 @@ +let _josePromise: Promise | undefined; + +/** + * Dynamically imports the jose library using import() to support Node.js 20.0-20.18. + * + * The jose library is ESM-only and cannot be loaded via require() in Node.js versions + * before 20.19.0. This wrapper uses dynamic import() which works in both ESM and CJS + * across all Node.js 20+ versions. + * + * This workaround can be removed when Node.js 20 reaches end-of-life (April 2026), + * at which point we can bump to Node.js 22+ and use direct imports. + * + * @returns Promise that resolves to the jose module + */ +export function getJose() { + return (_josePromise ??= import('jose')); +} diff --git a/src/vault/interfaces/index.ts b/src/vault/interfaces/index.ts index 6a1fd8acf..2f2196956 100644 --- a/src/vault/interfaces/index.ts +++ b/src/vault/interfaces/index.ts @@ -8,4 +8,3 @@ export * from './object/list-objects.interface'; export * from './object/read-object.interface'; export * from './object/update-object.interface'; export * from './object.interface'; -export * from './secret.interface'; diff --git a/src/vault/interfaces/secret.interface.ts b/src/vault/interfaces/secret.interface.ts deleted file mode 100644 index 8b7d1564c..000000000 --- a/src/vault/interfaces/secret.interface.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { KeyContext } from './key.interface'; -import { - ObjectDigest, - ObjectUpdateBy, - ObjectMetadata, - VaultObject, - ObjectVersion, -} from './object.interface'; - -// tslint:disable:no-empty-interface - -/* - * @deprecated Use `KeyContext` instead. - */ -export interface SecretContext extends KeyContext {} -/* - * @deprecated Use `ObjectDigest` instead. - */ -export interface SecretDigest extends ObjectDigest {} -/* - * @deprecated Use `ObjectUpdateBy` instead. - */ -export interface SecretUpdateBy extends ObjectUpdateBy {} -/* - * @deprecated Use `ObjectMetadata` instead. - */ -export interface SecretMetadata extends ObjectMetadata {} -/* - * @deprecated Use `VaultObject` instead. - */ -export interface VaultSecret extends VaultObject {} -/* - * @deprecated Use `ObjectVersion` instead. - */ -export interface SecretVersion extends ObjectVersion {} diff --git a/src/vault/leb.d.ts b/src/vault/leb.d.ts deleted file mode 100644 index e596c5b4f..000000000 --- a/src/vault/leb.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'leb'; diff --git a/src/vault/vault.spec.ts b/src/vault/vault.spec.ts index d66c3e21c..1afd4e789 100644 --- a/src/vault/vault.spec.ts +++ b/src/vault/vault.spec.ts @@ -3,10 +3,10 @@ import { fetchMethod, fetchOnce, fetchURL } from '../common/utils/test-utils'; import { WorkOS } from '../workos'; import { List } from '../common/interfaces'; import { - SecretDigest, - SecretMetadata, - SecretVersion, - VaultSecret, + ObjectDigest, + ObjectMetadata, + ObjectVersion, + VaultObject, } from './interfaces'; import { ConflictException } from '../common/exceptions/conflict.exception'; @@ -15,9 +15,9 @@ const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); describe('Vault', () => { beforeEach(() => fetch.resetMocks()); - describe('createSecret', () => { - it('creates secret', async () => { - const secretName = 'charger'; + describe('createObject', () => { + it('creates object', async () => { + const objectName = 'charger'; fetchOnce({ id: 's1', context: { @@ -32,14 +32,14 @@ describe('Vault', () => { }, version_id: 'v1', }); - const resource = await workos.vault.createSecret({ - name: secretName, + const resource = await workos.vault.createObject({ + name: objectName, context: { type: 'spore' }, value: 'Full speed ahead', }); expect(fetchURL()).toContain(`/vault/v1/kv`); expect(fetchMethod()).toBe('POST'); - expect(resource).toStrictEqual({ + expect(resource).toStrictEqual({ id: 's1', context: { type: 'spore', @@ -55,8 +55,8 @@ describe('Vault', () => { }); }); - it('throws an error if secret exists', async () => { - const secretName = 'charger'; + it('throws an error if object exists', async () => { + const objectName = 'charger'; fetchOnce( { error: 'Item already exists', @@ -64,8 +64,8 @@ describe('Vault', () => { { status: 409 }, ); await expect( - workos.vault.createSecret({ - name: secretName, + workos.vault.createObject({ + name: objectName, context: { type: 'spore' }, value: 'Full speed ahead', }), @@ -75,14 +75,14 @@ describe('Vault', () => { }); }); - describe('readSecret', () => { - it('reads a secret by id', async () => { - const secretName = 'lima'; - const secretId = 'secret1'; + describe('readObject', () => { + it('reads a object by id', async () => { + const objectName = 'lima'; + const objectId = 'object1'; fetchOnce({ - id: secretId, + id: objectId, metadata: { - id: secretId, + id: objectId, context: { emporer: 'groove', }, @@ -95,18 +95,18 @@ describe('Vault', () => { }, version_id: 'version1', }, - name: secretName, + name: objectName, value: 'Pull the lever Gronk', }); - const resource = await workos.vault.readSecret({ - id: secretId, + const resource = await workos.vault.readObject({ + id: objectId, }); - expect(fetchURL()).toContain(`/vault/v1/kv/${secretId}`); + expect(fetchURL()).toContain(`/vault/v1/kv/${objectId}`); expect(fetchMethod()).toBe('GET'); - expect(resource).toStrictEqual({ - id: secretId, + expect(resource).toStrictEqual({ + id: objectId, metadata: { - id: secretId, + id: objectId, context: { emporer: 'groove', }, @@ -119,7 +119,7 @@ describe('Vault', () => { }, versionId: 'version1', }, - name: secretName, + name: objectName, value: 'Pull the lever Gronk', }); }); @@ -151,8 +151,8 @@ describe('Vault', () => { }); }); - describe('listSecrets', () => { - it('gets a paginated list of secrets', async () => { + describe('listObjects', () => { + it('gets a paginated list of objects', async () => { fetchOnce({ data: [ { @@ -166,10 +166,10 @@ describe('Vault', () => { before: 'charger', }, }); - const resource = await workos.vault.listSecrets(); + const resource = await workos.vault.listObjects(); expect(fetchURL()).toContain(`/vault/v1/kv`); expect(fetchMethod()).toBe('GET'); - expect(resource).toStrictEqual>({ + expect(resource).toStrictEqual>({ object: 'list', data: [ { @@ -186,8 +186,8 @@ describe('Vault', () => { }); }); - describe('listSecretVersions', () => { - it('gets a paginated list of secret versions', async () => { + describe('listObjectVersions', () => { + it('gets a paginated list of object versions', async () => { fetchOnce({ data: [ { @@ -203,10 +203,10 @@ describe('Vault', () => { before: 'raZUqoHteQkLihH6AG5bj6sYAqMcJS76', }, }); - const resource = await workos.vault.listSecretVersions({ id: 'secret1' }); - expect(fetchURL()).toContain(`/vault/v1/kv/secret1/versions`); + const resource = await workos.vault.listObjectVersions({ id: 'object1' }); + expect(fetchURL()).toContain(`/vault/v1/kv/object1/versions`); expect(fetchMethod()).toBe('GET'); - expect(resource).toStrictEqual([ + expect(resource).toStrictEqual([ { createdAt: new Date(Date.parse('2029-03-17T15:51:57.000000Z')), currentVersion: true, @@ -216,14 +216,14 @@ describe('Vault', () => { }); }); - describe('updateSecret', () => { - it('updates secret', async () => { - const secretId = 's1'; + describe('updateObject', () => { + it('updates object', async () => { + const objectId = 's1'; fetchOnce({ - id: secretId, + id: objectId, name: 'charger', metadata: { - id: secretId, + id: objectId, context: { type: 'spore', }, @@ -237,17 +237,17 @@ describe('Vault', () => { version_id: 'v1', }, }); - const resource = await workos.vault.updateSecret({ - id: secretId, + const resource = await workos.vault.updateObject({ + id: objectId, value: 'Full speed ahead', }); - expect(fetchURL()).toContain(`/vault/v1/kv/${secretId}`); + expect(fetchURL()).toContain(`/vault/v1/kv/${objectId}`); expect(fetchMethod()).toBe('PUT'); - expect(resource).toStrictEqual({ - id: secretId, + expect(resource).toStrictEqual({ + id: objectId, name: 'charger', metadata: { - id: secretId, + id: objectId, context: { type: 'spore', }, @@ -264,7 +264,7 @@ describe('Vault', () => { }); }); - it('throws an error if secret version check fails', async () => { + it('throws an error if object version check fails', async () => { fetchOnce( { error: 'Item already exists', @@ -272,13 +272,13 @@ describe('Vault', () => { { status: 409 }, ); await expect( - workos.vault.updateSecret({ - id: 'secret1', + workos.vault.updateObject({ + id: 'object1', value: 'Full speed ahead', versionCheck: 'notaversion', }), ).rejects.toThrow(ConflictException); - expect(fetchURL()).toContain(`/vault/v1/kv/secret1`); + expect(fetchURL()).toContain(`/vault/v1/kv/object1`); expect(fetchMethod()).toBe('PUT'); }); }); diff --git a/src/vault/vault.ts b/src/vault/vault.ts index c321f8af4..896c3dc1a 100644 --- a/src/vault/vault.ts +++ b/src/vault/vault.ts @@ -1,4 +1,4 @@ -import { decodeUInt32, encodeUInt32 } from 'leb'; +import { decodeUInt32, encodeUInt32 } from '../common/utils/leb128'; import { CryptoProvider } from '../common/crypto/crypto-provider'; import { List, ListResponse } from '../common/interfaces'; import { PaginationOptions } from '../index.worker'; @@ -244,33 +244,4 @@ export class Vault { return new TextDecoder().decode(decrypted); } - - /* - * @deprecated Use `createObject` instead. - */ - createSecret = this.createObject; - /* - * @deprecated Use `listObjects` instead. - */ - listSecrets = this.listObjects; - /* - * @deprecated Use `listObjectVersions` instead. - */ - listSecretVersions = this.listObjectVersions; - /* - * @deprecated Use `readObject` instead. - */ - readSecret = this.readObject; - /* - * @deprecated Use `describeObject` instead. - */ - describeSecret = this.describeObject; - /* - * @deprecated Use `updateObject` instead. - */ - updateSecret = this.updateObject; - /* - * @deprecated Use `deleteObject` instead. - */ - deleteSecret = this.deleteObject; } diff --git a/src/webhooks/fixtures/webhook.json b/src/webhooks/fixtures/webhook.json index 79915ff1f..8e54220f8 100644 --- a/src/webhooks/fixtures/webhook.json +++ b/src/webhooks/fixtures/webhook.json @@ -3,19 +3,10 @@ "data": { "id": "directory_user_01FAEAJCR3ZBZ30D8BD1924TVG", "state": "active", - "emails": [ - { - "type": "work", - "value": "blair@foo-corp.com", - "primary": true - } - ], "idp_id": "00u1e8mutl6wlH3lL4x7", "object": "directory_user", - "username": "blair@foo-corp.com", "last_name": "Lunchford", "first_name": "Blair", - "job_title": "Software Engineer", "directory_id": "directory_01F9M7F68PZP8QXP8G7X5QRHS7", "created_at": "2021-06-25T19:07:33.155Z", "updated_at": "2021-06-25T19:07:33.155Z", @@ -28,20 +19,12 @@ }, "title": "Software Engineer", "active": true, - "emails": [ - { - "type": "work", - "value": "blair@foo-corp.com", - "primary": true - } - ], "groups": [], "locale": "en-US", "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User" ], - "userName": "blair@foo-corp.com", "addresses": [ { "region": "CA", @@ -64,4 +47,5 @@ }, "event": "dsync.user.created", "created_at": "2021-06-25T19:07:33.155Z" -} \ No newline at end of file +} + diff --git a/src/webhooks/webhooks.spec.ts b/src/webhooks/webhooks.spec.ts index e6c64bb2f..2ce5b9efa 100644 --- a/src/webhooks/webhooks.spec.ts +++ b/src/webhooks/webhooks.spec.ts @@ -25,19 +25,10 @@ describe('Webhooks', () => { expectation = { id: 'directory_user_01FAEAJCR3ZBZ30D8BD1924TVG', state: 'active', - emails: [ - { - type: 'work', - value: 'blair@foo-corp.com', - primary: true, - }, - ], idpId: '00u1e8mutl6wlH3lL4x7', object: 'directory_user', - username: 'blair@foo-corp.com', lastName: 'Lunchford', firstName: 'Blair', - jobTitle: 'Software Engineer', directoryId: 'directory_01F9M7F68PZP8QXP8G7X5QRHS7', createdAt: '2021-06-25T19:07:33.155Z', updatedAt: '2021-06-25T19:07:33.155Z', @@ -50,20 +41,12 @@ describe('Webhooks', () => { }, title: 'Software Engineer', active: true, - emails: [ - { - type: 'work', - value: 'blair@foo-corp.com', - primary: true, - }, - ], groups: [], locale: 'en-US', schemas: [ 'urn:ietf:params:scim:schemas:core:2.0:User', 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User', ], - userName: 'blair@foo-corp.com', addresses: [ { region: 'CA', @@ -116,9 +99,9 @@ describe('Webhooks', () => { const sigHeader = ''; const options = { payload, sigHeader, secret }; - await expect( - workos.webhooks.constructEvent(options), - ).rejects.toThrowError(SignatureVerificationException); + await expect(workos.webhooks.constructEvent(options)).rejects.toThrow( + SignatureVerificationException, + ); }); }); @@ -127,9 +110,9 @@ describe('Webhooks', () => { const sigHeader = `t=${timestamp}, v1=`; const options = { payload, sigHeader, secret }; - await expect( - workos.webhooks.constructEvent(options), - ).rejects.toThrowError(SignatureVerificationException); + await expect(workos.webhooks.constructEvent(options)).rejects.toThrow( + SignatureVerificationException, + ); }); }); @@ -138,9 +121,9 @@ describe('Webhooks', () => { const sigHeader = `t=${timestamp}, v1=99999`; const options = { payload, sigHeader, secret }; - await expect( - workos.webhooks.constructEvent(options), - ).rejects.toThrowError(SignatureVerificationException); + await expect(workos.webhooks.constructEvent(options)).rejects.toThrow( + SignatureVerificationException, + ); }); }); @@ -150,9 +133,9 @@ describe('Webhooks', () => { payload = 'invalid'; const options = { payload, sigHeader, secret }; - await expect( - workos.webhooks.constructEvent(options), - ).rejects.toThrowError(SignatureVerificationException); + await expect(workos.webhooks.constructEvent(options)).rejects.toThrow( + SignatureVerificationException, + ); }); }); @@ -162,9 +145,9 @@ describe('Webhooks', () => { secret = 'invalid'; const options = { payload, sigHeader, secret }; - await expect( - workos.webhooks.constructEvent(options), - ).rejects.toThrowError(SignatureVerificationException); + await expect(workos.webhooks.constructEvent(options)).rejects.toThrow( + SignatureVerificationException, + ); }); }); @@ -173,9 +156,9 @@ describe('Webhooks', () => { const sigHeader = `t=9999, v1=${signatureHash}`; const options = { payload, sigHeader, secret }; - await expect( - workos.webhooks.constructEvent(options), - ).rejects.toThrowError(SignatureVerificationException); + await expect(workos.webhooks.constructEvent(options)).rejects.toThrow( + SignatureVerificationException, + ); }); }); }); diff --git a/src/webhooks/webhooks.ts b/src/webhooks/webhooks.ts index b726a43d2..f11b36deb 100644 --- a/src/webhooks/webhooks.ts +++ b/src/webhooks/webhooks.ts @@ -30,7 +30,7 @@ export class Webhooks { secret, tolerance = 180000, }: { - payload: unknown; + payload: Record; sigHeader: string; secret: string; tolerance?: number; @@ -38,7 +38,7 @@ export class Webhooks { const options = { payload, sigHeader, secret, tolerance }; await this.verifyHeader(options); - const webhookPayload = payload as EventResponse; + const webhookPayload = payload as unknown as EventResponse; return deserializeEvent(webhookPayload); } diff --git a/src/worker.spec.ts b/src/worker.spec.ts deleted file mode 100644 index d986c9693..000000000 --- a/src/worker.spec.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @jest-environment miniflare - */ - -import { WorkOS } from './index.worker'; - -test('WorkOS is initialized without errors', () => { - expect(() => new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU')).not.toThrow(); -}); diff --git a/src/workos.spec.ts b/src/workos.spec.ts index 109445880..08b6a3516 100644 --- a/src/workos.spec.ts +++ b/src/workos.spec.ts @@ -1,9 +1,8 @@ import fetch from 'jest-fetch-mock'; import { fetchOnce, fetchHeaders, fetchBody } from './common/utils/test-utils'; -import fs from 'fs/promises'; import { + ApiKeyRequiredException, GenericServerException, - NoApiKeyProvidedException, NotFoundException, OauthException, } from './common/exceptions'; @@ -12,9 +11,15 @@ import { WorkOS } from './index'; import { WorkOS as WorkOSWorker } from './index.worker'; import { RateLimitExceededException } from './common/exceptions/rate-limit-exceeded.exception'; import { FetchHttpClient } from './common/net/fetch-client'; -import { NodeHttpClient } from './common/net/node-client'; import { SubtleCryptoProvider } from './common/crypto/subtle-crypto-provider'; +jest.mock('./common/utils/runtime-info', () => ({ + getRuntimeInfo: () => ({ + name: 'node', + version: 'v18.20.7', + }), +})); + describe('WorkOS', () => { beforeEach(() => fetch.resetMocks()); @@ -31,9 +36,37 @@ describe('WorkOS', () => { process.env = OLD_ENV; }); - describe('when no API key is provided', () => { - it('throws a NoApiKeyFoundException error', async () => { - expect(() => new WorkOS()).toThrowError(NoApiKeyProvidedException); + describe('when no API key AND no clientId is provided', () => { + it('throws an error explaining both instantiation modes', async () => { + delete process.env.WORKOS_API_KEY; + delete process.env.WORKOS_CLIENT_ID; + expect(() => new WorkOS()).toThrow( + 'WorkOS requires either an API key or a clientId', + ); + }); + }); + + describe('when only clientId is provided (public client mode)', () => { + it('initializes successfully without API key', async () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + expect(workos.clientId).toBe('client_123'); + expect(workos.key).toBeUndefined(); + }); + + it('initializes with clientId from environment variable', async () => { + delete process.env.WORKOS_API_KEY; + process.env.WORKOS_CLIENT_ID = 'client_from_env'; + const workos = new WorkOS(); + expect(workos.clientId).toBe('client_from_env'); + }); + + it('does not include Authorization header in HTTP client', async () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + // HTTP client should be created without Authorization header + // We can't easily test this directly, but we verify the workos.key is undefined + expect(workos.key).toBeUndefined(); }); }); @@ -52,6 +85,26 @@ describe('WorkOS', () => { }); }); + describe('when API key is provided via options object', () => { + it('initializes with apiKey in options', async () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ + apiKey: 'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + }); + expect(workos.key).toBe('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + }); + + it('allows both apiKey and clientId in options', async () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ + apiKey: 'sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', + clientId: 'client_123', + }); + expect(workos.key).toBe('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + expect(workos.clientId).toBe('client_123'); + }); + }); + describe('with https option', () => { it('sets baseURL', () => { const workos = new WorkOS('foo', { https: false }); @@ -100,10 +153,6 @@ describe('WorkOS', () => { it('applies the configuration to the fetch client user-agent', async () => { fetchOnce('{}'); - const packageJson = JSON.parse( - await fs.readFile('package.json', 'utf8'), - ); - const workos = new WorkOS('sk_test', { appInfo: { name: 'fooApp', @@ -113,27 +162,10 @@ describe('WorkOS', () => { await workos.post('/somewhere', {}); - expect(fetchHeaders()).toMatchObject({ - 'User-Agent': `workos-node/${packageJson.version}/fetch fooApp: 1.0.0`, - }); - }); - }); - - describe('when no `appInfo` option is provided', () => { - it('adds the HTTP client name to the user-agent', async () => { - fetchOnce('{}'); - - const packageJson = JSON.parse( - await fs.readFile('package.json', 'utf8'), + const headers = fetchHeaders() as Record; + expect(headers['User-Agent']).toMatch( + /^workos-node\/\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?\/fetch \(node\/v\d+\.\d+\.\d+\) fooApp: 1\.0\.0$/, ); - - const workos = new WorkOS('sk_test'); - - await workos.post('/somewhere', {}); - - expect(fetchHeaders()).toMatchObject({ - 'User-Agent': `workos-node/${packageJson.version}/fetch`, - }); }); }); @@ -141,17 +173,14 @@ describe('WorkOS', () => { it('adds the HTTP client name to the user-agent', async () => { fetchOnce('{}'); - const packageJson = JSON.parse( - await fs.readFile('package.json', 'utf8'), - ); - const workos = new WorkOS('sk_test'); await workos.post('/somewhere', {}); - expect(fetchHeaders()).toMatchObject({ - 'User-Agent': `workos-node/${packageJson.version}/fetch`, - }); + const headers = fetchHeaders() as Record; + expect(headers['User-Agent']).toMatch( + /^workos-node\/\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?\/fetch \(node\/v\d+\.\d+\.\d+\)$/, + ); }); }); @@ -167,18 +196,71 @@ describe('WorkOS', () => { }); describe('version', () => { - it('matches the version in `package.json`', async () => { + it('is a valid semver string', async () => { const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); - // Read `package.json` using file I/O instead of `require` so we don't run - // into issues with the `require` cache. - const packageJson = JSON.parse(await fs.readFile('package.json', 'utf8')); + expect(workos.version).toMatch(/^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/); + }); + }); - expect(workos.version).toBe(packageJson.version); + describe('pkce', () => { + it('is available as a property', () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + expect(workos.pkce).toBeDefined(); + }); + + it('is available in PKCE-only mode', () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + expect(workos.pkce).toBeDefined(); + }); + }); + + describe('requireApiKey', () => { + it('does not throw when API key is provided', () => { + const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + expect(() => workos.requireApiKey('someMethod')).not.toThrow(); + }); + + it('throws ApiKeyRequiredException when no API key (public client mode)', () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + expect(() => workos.requireApiKey('listOrganizations')).toThrow( + ApiKeyRequiredException, + ); + }); + + it('includes path in error message', () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + expect(() => workos.requireApiKey('/organizations')).toThrow( + 'API key required for "/organizations"', + ); }); }); describe('post', () => { + describe('when no API key is provided (public client mode)', () => { + it('throws ApiKeyRequiredException', async () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + + await expect(workos.post('/path', {})).rejects.toThrow( + ApiKeyRequiredException, + ); + }); + + it('allows bypass with skipApiKeyCheck option', async () => { + delete process.env.WORKOS_API_KEY; + fetchOnce('{}'); + const workos = new WorkOS({ clientId: 'client_123' }); + + await expect( + workos.post('/path', {}, { skipApiKeyCheck: true }), + ).resolves.toBeDefined(); + }); + }); + describe('when the api responds with a 404', () => { it('throws a NotFoundException', async () => { const message = 'Not Found'; @@ -337,6 +419,17 @@ describe('WorkOS', () => { }); describe('get', () => { + describe('when no API key is provided (public client mode)', () => { + it('throws ApiKeyRequiredException', async () => { + delete process.env.WORKOS_API_KEY; + const workos = new WorkOS({ clientId: 'client_123' }); + + await expect(workos.get('/path')).rejects.toThrow( + ApiKeyRequiredException, + ); + }); + }); + describe('when the api responds with invalid JSON', () => { it('throws a ParseError', async () => { const mockResponse = { @@ -390,35 +483,6 @@ describe('WorkOS', () => { }); }); - describe('when in an environment that does not support fetch', () => { - const fetchFn = globalThis.fetch; - - beforeEach(() => { - // @ts-ignore - delete globalThis.fetch; - }); - - afterEach(() => { - globalThis.fetch = fetchFn; - }); - - it('automatically uses the node HTTP client', () => { - const workos = new WorkOS('sk_test_key'); - - // tslint:disable-next-line - expect(workos['client']).toBeInstanceOf(NodeHttpClient); - }); - - it('uses a fetch function if provided', () => { - const workos = new WorkOS('sk_test_key', { - fetchFn, - }); - - // tslint:disable-next-line - expect(workos['client']).toBeInstanceOf(FetchHttpClient); - }); - }); - describe('when in a worker environment', () => { it('uses the worker client', () => { const workos = new WorkOSWorker('sk_test_key'); diff --git a/src/workos.ts b/src/workos.ts index 742380849..74b39b017 100644 --- a/src/workos.ts +++ b/src/workos.ts @@ -1,12 +1,13 @@ import { + ApiKeyRequiredException, GenericServerException, - NoApiKeyProvidedException, NotFoundException, UnauthorizedException, UnprocessableEntityException, OauthException, RateLimitExceededException, } from './common/exceptions'; +import { PKCE } from './pkce/pkce'; import { GetOptions, HttpClientResponseInterface, @@ -35,15 +36,16 @@ import { FeatureFlags } from './feature-flags/feature-flags'; import { HttpClient, HttpClientError } from './common/net/http-client'; import { SubtleCryptoProvider } from './common/crypto/subtle-crypto-provider'; import { FetchHttpClient } from './common/net/fetch-client'; -import { IronSessionProvider } from './common/iron-session/iron-session-provider'; import { Widgets } from './widgets/widgets'; import { Actions } from './actions/actions'; import { Vault } from './vault/vault'; import { ConflictException } from './common/exceptions/conflict.exception'; import { CryptoProvider } from './common/crypto/crypto-provider'; import { ParseError } from './common/exceptions/parse-error'; +import { getEnv } from './common/utils/env'; +import { getRuntimeInfo } from './common/utils/runtime-info'; -const VERSION = '7.82.0'; +const VERSION = '8.0.0-rc.10'; const DEFAULT_HOSTNAME = 'api.workos.com'; @@ -55,6 +57,11 @@ export class WorkOS { readonly baseURL: string; readonly client: HttpClient; readonly clientId?: string; + readonly key?: string; + readonly options: WorkOSOptions; + readonly pkce: PKCE; + + private readonly hasApiKey: boolean; readonly actions: Actions; readonly apiKeys = new ApiKeys(this); @@ -75,26 +82,57 @@ export class WorkOS { readonly webhooks: Webhooks; readonly widgets = new Widgets(this); - constructor(readonly key?: string, readonly options: WorkOSOptions = {}) { - if (!key) { - // process might be undefined in some environments - this.key = - typeof process !== 'undefined' - ? process?.env.WORKOS_API_KEY - : undefined; + /** + * Create a new WorkOS client. + * + * @param keyOrOptions - API key string, or options object + * @param maybeOptions - Options when first argument is API key + * + * @example + * // Server-side with API key (string) + * const workos = new WorkOS('sk_...'); + * + * @example + * // Server-side with API key (object) + * const workos = new WorkOS({ apiKey: 'sk_...', clientId: 'client_...' }); + * + * @example + * // PKCE/public client (no API key) + * const workos = new WorkOS({ clientId: 'client_...' }); + */ + constructor( + keyOrOptions?: string | WorkOSOptions, + maybeOptions?: WorkOSOptions, + ) { + if (typeof keyOrOptions === 'object') { + this.key = keyOrOptions.apiKey; + this.options = keyOrOptions; + } else { + this.key = keyOrOptions; + this.options = maybeOptions ?? {}; + } - if (!this.key) { - throw new NoApiKeyProvidedException(); - } + if (!this.key) { + this.key = getEnv('WORKOS_API_KEY'); } + this.hasApiKey = !!this.key; + if (this.options.https === undefined) { this.options.https = true; } this.clientId = this.options.clientId; - if (!this.clientId && typeof process !== 'undefined') { - this.clientId = process?.env.WORKOS_CLIENT_ID; + if (!this.clientId) { + this.clientId = getEnv('WORKOS_CLIENT_ID'); + } + + if (!this.hasApiKey && !this.clientId) { + throw new Error( + 'WorkOS requires either an API key or a clientId. ' + + 'For server-side: new WorkOS("sk_...") or new WorkOS({ apiKey: "sk_..." }). ' + + 'For PKCE/public clients: new WorkOS({ clientId: "client_..." })', + ); } const protocol: string = this.options.https ? 'https' : 'http'; @@ -106,24 +144,31 @@ export class WorkOS { this.baseURL = this.baseURL + `:${port}`; } - let userAgent: string = `workos-node/${VERSION}`; - - if (options.appInfo) { - const { name, version }: { name: string; version: string } = - options.appInfo; - userAgent += ` ${name}: ${version}`; - } + this.pkce = new PKCE(); this.webhooks = this.createWebhookClient(); this.actions = this.createActionsClient(); // Must initialize UserManagement after baseURL is configured - this.userManagement = new UserManagement( - this, - this.createIronSessionProvider(), - ); + this.userManagement = new UserManagement(this); + + const userAgent = this.createUserAgent(this.options); + + this.client = this.createHttpClient(this.options, userAgent); + } + + private createUserAgent(options: WorkOSOptions): string { + let userAgent: string = `workos-node/${VERSION}`; + + const { name: runtimeName, version: runtimeVersion } = getRuntimeInfo(); + userAgent += ` (${runtimeName}${runtimeVersion ? `/${runtimeVersion}` : ''})`; + + if (options.appInfo) { + const { name, version } = options.appInfo; + userAgent += ` ${name}: ${version}`; + } - this.client = this.createHttpClient(options, userAgent); + return userAgent; } createWebhookClient() { @@ -139,32 +184,55 @@ export class WorkOS { } createHttpClient(options: WorkOSOptions, userAgent: string) { + const headers: Record = { + 'User-Agent': userAgent, + }; + + const configHeaders = options.config?.headers; + if ( + configHeaders && + typeof configHeaders === 'object' && + !Array.isArray(configHeaders) && + !(configHeaders instanceof Headers) + ) { + Object.assign(headers, configHeaders); + } + + if (this.key) { + headers['Authorization'] = `Bearer ${this.key}`; + } + return new FetchHttpClient(this.baseURL, { ...options.config, timeout: options.timeout, - headers: { - ...options.config?.headers, - Authorization: `Bearer ${this.key}`, - 'User-Agent': userAgent, - }, + headers, }) as HttpClient; } - createIronSessionProvider(): IronSessionProvider { - throw new Error( - 'IronSessionProvider not implemented. Use WorkOSNode or WorkOSWorker instead.', - ); - } - get version() { return VERSION; } + /** + * Require API key for methods that need it. + * @param methodName - Name of the method requiring API key (for error message) + * @throws ApiKeyRequiredException if no API key was provided + */ + requireApiKey(methodName: string): void { + if (!this.hasApiKey) { + throw new ApiKeyRequiredException(methodName); + } + } + async post( path: string, entity: Entity, options: PostOptions = {}, ): Promise<{ data: Result }> { + if (!options.skipApiKeyCheck) { + this.requireApiKey(path); + } + const requestHeaders: Record = {}; if (options.idempotencyKey) { @@ -199,6 +267,10 @@ export class WorkOS { path: string, options: GetOptions = {}, ): Promise<{ data: Result }> { + if (!options.skipApiKeyCheck) { + this.requireApiKey(path); + } + const requestHeaders: Record = {}; if (options.accessToken) { @@ -234,6 +306,10 @@ export class WorkOS { entity: Entity, options: PutOptions = {}, ): Promise<{ data: Result }> { + if (!options.skipApiKeyCheck) { + this.requireApiKey(path); + } + const requestHeaders: Record = {}; if (options.idempotencyKey) { @@ -262,6 +338,8 @@ export class WorkOS { } async delete(path: string, query?: any): Promise { + this.requireApiKey(path); + try { await this.client.delete(path, { params: query, diff --git a/tsconfig.json b/tsconfig.json index c204aa20d..6cd09f2e7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,21 +1,23 @@ { "compilerOptions": { + "baseUrl": ".", "allowSyntheticDefaultImports": true, "alwaysStrict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "moduleResolution": "node", + "moduleResolution": "bundler", "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, "resolveJsonModule": true, - "target": "es6", - "module": "commonjs", + "target": "es2022", + "module": "esnext", "declaration": true, "outDir": "lib", "strict": true, "lib": ["dom", "es2022"], - "types": ["jest", "jest-environment-miniflare/globals"] + "types": ["jest", "jest-environment-miniflare/globals"], + "noImplicitAny": true }, "include": ["src"] } diff --git a/tsdown.config.ts b/tsdown.config.ts new file mode 100644 index 000000000..e15b410d5 --- /dev/null +++ b/tsdown.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'tsdown'; + +const sharedEntry = [ + 'src/**/*.ts', + '!src/**/*.spec.ts', + '!src/**/*.test.ts', + '!src/**/fixtures/**', + '!src/**/*.d.ts', + '!src/**/test-utils.ts', +]; + +export default defineConfig([ + // ESM - unbundled, external deps (ESM consumers can import ESM deps directly) + { + entry: sharedEntry, + format: ['esm'], + outDir: 'lib', + target: 'es2022', + sourcemap: true, + clean: true, + dts: true, + unbundle: true, + outExtensions: () => ({ js: '.js', dts: '.d.ts' }), + }, + // CJS - bundled, inline ESM-only deps for compatibility + { + entry: sharedEntry, + format: ['cjs'], + outDir: 'lib', + target: 'es2022', + sourcemap: true, + // no clean - ESM build already cleaned + dts: true, // Generate .d.cts for CJS consumers + // no unbundle - allows proper inlining of ESM-only deps + noExternal: ['iron-webcrypto', 'uint8array-extras'], + outExtensions: () => ({ js: '.cjs', dts: '.d.cts' }), + }, +]); diff --git a/tslint.json b/tslint.json deleted file mode 100644 index c62decd97..000000000 --- a/tslint.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "defaultSeverity": "error", - "extends": ["tslint:recommended"], - "jsRules": { - "no-unused-expression": true - }, - "rules": { - "object-literal-key-quotes": false, - "arrow-parens": false, - "interface-name": [false], - "max-line-length": [true, 150], - "member-access": [false], - "member-ordering": [false], - "object-literal-sort-keys": false, - "ordered-imports": [false], - "quotemark": [true, "single", "jsx-double", "avoid-escape"], - "variable-name": [true, "allow-leading-underscore"], - "semicolon": [true, "always", "ignore-bound-class-methods"], - "no-default-export": true, - "no-shadowed-variable": false - }, - "rulesDirectory": [] -}