From 809c4888890899abeed9ec0d9a512e11b3694ea3 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 15 Jan 2026 15:24:42 -0800 Subject: [PATCH 01/57] add new smoke test for cloudflare + vite --- js/smoke/tests/vite-react-hono/.gitignore | 5 + js/smoke/tests/vite-react-hono/README.md | 142 + js/smoke/tests/vite-react-hono/index.html | 13 + .../tests/vite-react-hono/package-lock.json | 5419 +++++++++++++++++ js/smoke/tests/vite-react-hono/package.json | 33 + js/smoke/tests/vite-react-hono/run-test.mjs | 79 + .../vite-react-hono/src/react-app/App.css | 40 + .../vite-react-hono/src/react-app/App.tsx | 55 + .../vite-react-hono/src/react-app/index.css | 31 + .../vite-react-hono/src/react-app/main.tsx | 10 + .../src/react-app/vite-env.d.ts | 1 + .../tests/vite-react-hono/src/worker/index.ts | 118 + .../tests/vite-react-hono/tsconfig.app.json | 21 + js/smoke/tests/vite-react-hono/tsconfig.json | 19 + .../tests/vite-react-hono/tsconfig.node.json | 18 + .../vite-react-hono/tsconfig.worker.json | 8 + js/smoke/tests/vite-react-hono/vite.config.ts | 7 + js/smoke/tests/vite-react-hono/wrangler.json | 7 + 18 files changed, 6026 insertions(+) create mode 100644 js/smoke/tests/vite-react-hono/.gitignore create mode 100644 js/smoke/tests/vite-react-hono/README.md create mode 100644 js/smoke/tests/vite-react-hono/index.html create mode 100644 js/smoke/tests/vite-react-hono/package-lock.json create mode 100644 js/smoke/tests/vite-react-hono/package.json create mode 100644 js/smoke/tests/vite-react-hono/run-test.mjs create mode 100644 js/smoke/tests/vite-react-hono/src/react-app/App.css create mode 100644 js/smoke/tests/vite-react-hono/src/react-app/App.tsx create mode 100644 js/smoke/tests/vite-react-hono/src/react-app/index.css create mode 100644 js/smoke/tests/vite-react-hono/src/react-app/main.tsx create mode 100644 js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts create mode 100644 js/smoke/tests/vite-react-hono/src/worker/index.ts create mode 100644 js/smoke/tests/vite-react-hono/tsconfig.app.json create mode 100644 js/smoke/tests/vite-react-hono/tsconfig.json create mode 100644 js/smoke/tests/vite-react-hono/tsconfig.node.json create mode 100644 js/smoke/tests/vite-react-hono/tsconfig.worker.json create mode 100644 js/smoke/tests/vite-react-hono/vite.config.ts create mode 100644 js/smoke/tests/vite-react-hono/wrangler.json diff --git a/js/smoke/tests/vite-react-hono/.gitignore b/js/smoke/tests/vite-react-hono/.gitignore new file mode 100644 index 000000000..81cd1ebf9 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/.gitignore @@ -0,0 +1,5 @@ +node_modules +dist +.wrangler +.dev.vars +*.log diff --git a/js/smoke/tests/vite-react-hono/README.md b/js/smoke/tests/vite-react-hono/README.md new file mode 100644 index 000000000..0b35fa970 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/README.md @@ -0,0 +1,142 @@ +# Braintrust Vite + React + Hono Smoke Test + +Smoke test for the Braintrust SDK in a Vite + React + Hono + Cloudflare Workers environment. + +This test demonstrates: + +- Using Braintrust SDK with Hono routing framework +- Running shared test suites in a Cloudflare Worker +- Integration with Vite for both frontend and backend +- React frontend that can trigger smoke tests + +Based on the [Cloudflare Vite + React + Hono template](https://github.com/cloudflare/templates/tree/main/vite-react-template). + +## Architecture + +- **Backend**: Hono app running in Cloudflare Worker (`src/worker/index.ts`) +- **Frontend**: React app built with Vite (`src/react-app/`) +- **Tests**: Shared test suites from `../../shared/` +- **Bundler**: Vite with Cloudflare plugin +- **Framework**: Hono for routing + +## Project Structure + +``` +vite-react-hono/ +├── src/ +│ ├── worker/ +│ │ └── index.ts # Hono worker with test endpoints +│ └── react-app/ +│ ├── App.tsx # React app with test UI +│ ├── main.tsx # React entry point +│ └── *.css # Styles +├── index.html # HTML entry point +├── vite.config.ts # Vite configuration +├── wrangler.json # Cloudflare Workers config +├── tsconfig.json # TypeScript config (worker) +├── tsconfig.app.json # TypeScript config (React) +├── tsconfig.worker.json # TypeScript config (worker) +└── run-test.mjs # Test runner script +``` + +## Running the Test + +```bash +# Install dependencies +npm install + +# Run the automated smoke test (CI mode) +npm test + +# Or run in development mode with React UI +npm run dev +# Then visit http://localhost:5173 + +# Build for production +npm run build +``` + +## Test Endpoints + +When running (`npm run dev` or via `wrangler dev`): + +- `GET /` - Home page with test information (text response) +- `GET /api/` - Basic API endpoint returning JSON +- `GET /api/test` - Run shared test suites (returns JSON test results) + +## What's Tested + +This smoke test runs the full shared test suite: + +1. **Import Verification Tests** (~13 tests) + + - All Braintrust exports are accessible + - Core logging, Dataset, Prompt, Experiment, Eval exports + - Tracing, client wrappers, utilities + +2. **Functional Tests** (~3 tests) + + - Basic span logging + - Multiple sequential spans + - Direct logging operations + +3. **Eval Smoke Test** (1 test) + + - Evaluation functionality works + +4. **Prompt Templating Tests** (~2 tests) + - Prompt template rendering + +All tests use the shared test suite package for consistency across environments. + +## Development + +### Running with React Frontend (Optional) + +The React frontend provides a UI to trigger the smoke tests manually. To use it: + +1. Build the frontend: `npm run build` +2. Update `wrangler.json` to add assets configuration: + ```json + "assets": { + "directory": "./dist/client", + "not_found_handling": "single-page-application" + } + ``` +3. Start dev server: `npm run dev` +4. Visit http://localhost:5173 +5. Click "Run Smoke Tests" button + +**Note**: The automated smoke test (`npm test`) only needs the worker API endpoints and doesn't require building the React frontend. + +## CI Integration + +This test is automatically discovered and run by `../../run-tests.sh`: + +```bash +cd ../../ +./run-tests.sh vite-react-hono +``` + +The test runs in CI alongside other smoke tests: + +- Builds the SDK from source +- Installs the build artifact +- Runs the test via HTTP endpoint +- Verifies all shared test suites pass + +## Key Features + +1. **Hono Integration**: Uses Hono's elegant routing instead of raw Worker API +2. **Vite Bundling**: Tests the Braintrust SDK through Vite's bundler +3. **React Frontend**: Optional UI for manual testing +4. **Cloudflare Workers**: Tests in actual Workers runtime environment +5. **Shared Test Suites**: Consistent test coverage across all environments + +## Notes + +- The automated test (`npm test`) only exercises the `/api/test` endpoint +- The React frontend is optional and not tested in CI +- Tests run in Cloudflare Workers environment (V8 isolates) +- Uses Wrangler dev server for local testing +- Port 8800 is used to avoid conflicts with other smoke tests diff --git a/js/smoke/tests/vite-react-hono/index.html b/js/smoke/tests/vite-react-hono/index.html new file mode 100644 index 000000000..c99c0fe61 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/index.html @@ -0,0 +1,13 @@ + + + + + + + Braintrust Vite + React + Hono Smoke Test + + +
+ + + diff --git a/js/smoke/tests/vite-react-hono/package-lock.json b/js/smoke/tests/vite-react-hono/package-lock.json new file mode 100644 index 000000000..ff774c70f --- /dev/null +++ b/js/smoke/tests/vite-react-hono/package-lock.json @@ -0,0 +1,5419 @@ +{ + "name": "braintrust-vite-react-hono-smoke-test", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "braintrust-vite-react-hono-smoke-test", + "dependencies": { + "braintrust": "latest", + "hono": "^4.11.1", + "react": "^19.2.1", + "react-dom": "^19.2.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/vite-plugin": "^1.15.3", + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^24.10.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "tsx": "^4.19.2", + "typescript": "^5.8.3", + "vite": "^6.0.0", + "wrangler": "^4.56.0" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", + "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", + "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", + "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", + "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", + "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.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-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "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.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" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "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": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "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-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "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/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", + "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", + "dev": true, + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.10.0.tgz", + "integrity": "sha512-/uII4vLQXhzCAZzEVeYAjFLBNg2nqTJ1JGzd2lRF6ItYe6U2zVoYGfeKpGx/EkBF6euiU+cyBXgMdtJih+nQ6g==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": "^1.20251221.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/vite-plugin": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@cloudflare/vite-plugin/-/vite-plugin-1.21.0.tgz", + "integrity": "sha512-3VXtkfjOQL+k3Plj+t0BHRyw8iIIRBQ8RJU6KJHJQKdYHA6rJE/WlSa/lRd0A8MMhvP8e8QiMLuDqveEN8gCZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cloudflare/unenv-preset": "2.10.0", + "miniflare": "4.20260114.0", + "unenv": "2.0.0-rc.24", + "wrangler": "4.59.2", + "ws": "8.18.0" + }, + "peerDependencies": { + "vite": "^6.1.0 || ^7.0.0", + "wrangler": "^4.59.2" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260114.0.tgz", + "integrity": "sha512-HNlsRkfNgardCig2P/5bp/dqDECsZ4+NU5XewqArWxMseqt3C5daSuptI620s4pn7Wr0ZKg7jVLH0PDEBkA+aA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260114.0.tgz", + "integrity": "sha512-qyE1UdFnAlxzb+uCfN/d9c8icch7XRiH49/DjoqEa+bCDihTuRS7GL1RmhVIqHJhb3pX3DzxmKgQZBDBL83Inw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260114.0.tgz", + "integrity": "sha512-Z0BLvAj/JPOabzads2ddDEfgExWTlD22pnwsuNbPwZAGTSZeQa3Y47eGUWyHk+rSGngknk++S7zHTGbKuG7RRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260114.0.tgz", + "integrity": "sha512-kPUmEtUxUWlr9PQ64kuhdK0qyo8idPe5IIXUgi7xCD7mDd6EOe5J7ugDpbfvfbYKEjx4DpLvN2t45izyI/Sodw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260114.0.tgz", + "integrity": "sha512-MJnKgm6i1jZGyt2ZHQYCnRlpFTEZcK2rv9y7asS3KdVEXaDgGF8kOns5u6YL6/+eMogfZuHRjfDS+UqRTUYIFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20260115.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260115.0.tgz", + "integrity": "sha512-vi68ZODh6m9fH9wdBOzDsyWgrYRIZbzZEAGGkvFn4b1FQSukxaWS8NAtSd/h9mL4gVK9hG8FEYq/jipdOo4RJg==", + "dev": true, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "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": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "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": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "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/@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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "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" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "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.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "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.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "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-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "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.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "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.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "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.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "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-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "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-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "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.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "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.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "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.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "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.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "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-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "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.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "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/@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/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT" + }, + "node_modules/@next/env": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", + "license": "MIT" + }, + "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/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/@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/@rollup/rollup-android-arm-eabi": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "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/@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/@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/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/node": { + "version": "24.10.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz", + "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/nunjucks": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", + "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", + "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vercel/functions": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", + "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", + "license": "Apache-2.0", + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-web-identity": "*" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-provider-web-identity": { + "optional": true + } + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz", + "integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.5", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.53", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/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==", + "license": "MIT" + }, + "node_modules/ansi-align/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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "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==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", + "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/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==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braintrust": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-2.0.2.tgz", + "integrity": "sha512-TOfdi2acpDnne3Pcew/shbwda0SKQvjTsGprr0gLWloaeYehhOPyrsWmwKsRNXOJa01D0czTGyetWpUbcH+euw==", + "license": "MIT", + "dependencies": { + "@ai-sdk/provider": "^1.1.3", + "@next/env": "^14.2.3", + "@types/nunjucks": "^3.2.6", + "@vercel/functions": "^1.0.2", + "argparse": "^2.0.1", + "boxen": "^8.0.1", + "chalk": "^4.1.2", + "cli-progress": "^3.12.0", + "cli-table3": "^0.6.5", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "esbuild": "^0.27.0", + "eventsource-parser": "^1.1.2", + "express": "^4.21.2", + "graceful-fs": "^4.2.11", + "http-errors": "^2.0.0", + "minimatch": "^9.0.3", + "mustache": "^4.2.0", + "nunjucks": "^3.2.4", + "pluralize": "^8.0.0", + "simple-git": "^3.21.0", + "source-map": "^0.7.4", + "termi-link": "^1.0.1", + "uuid": "^9.0.1", + "zod-to-json-schema": "^3.25.0" + }, + "bin": { + "braintrust": "dist/cli.js" + }, + "peerDependencies": { + "zod": "^3.25.34 || ^4.0" + } + }, + "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", + "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/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001764", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", + "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", + "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==", + "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/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-progress/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-progress/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==", + "license": "MIT" + }, + "node_modules/cli-progress/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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-progress/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3/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==", + "license": "MIT" + }, + "node_modules/cli-table3/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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "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==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "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/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "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/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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/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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "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-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource-parser": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", + "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", + "license": "MIT", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "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": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "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": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.11.4", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", + "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "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_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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/miniflare": { + "version": "4.20260114.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260114.0.tgz", + "integrity": "sha512-QwHT7S6XqGdQxIvql1uirH/7/i3zDEt0B/YBXTYzMfJtVCR4+ue3KPkU+Bl0zMxvpgkvjh9+eCHhJbKEqya70A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "^0.34.5", + "undici": "7.14.0", + "workerd": "1.20260114.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "^3.25.76" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "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, + "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": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.3" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rollup": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "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/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/sharp/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": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-git": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "license": "MIT", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/termi-link": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", + "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "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, + "license": "0BSD", + "optional": true + }, + "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": { + "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/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "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": [ + { + "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", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workerd": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260114.0.tgz", + "integrity": "sha512-kTJ+jNdIllOzWuVA3NRQRvywP0T135zdCjAE2dAUY1BFbxM6fmMZV8BbskEoQ4hAODVQUfZQmyGctcwvVCKxFA==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260114.0", + "@cloudflare/workerd-darwin-arm64": "1.20260114.0", + "@cloudflare/workerd-linux-64": "1.20260114.0", + "@cloudflare/workerd-linux-arm64": "1.20260114.0", + "@cloudflare/workerd-windows-64": "1.20260114.0" + } + }, + "node_modules/wrangler": { + "version": "4.59.2", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.59.2.tgz", + "integrity": "sha512-Z4xn6jFZTaugcOKz42xvRAYKgkVUERHVbuCJ5+f+gK+R6k12L02unakPGOA0L0ejhUl16dqDjKe4tmL9sedHcw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.4.2", + "@cloudflare/unenv-preset": "2.10.0", + "blake3-wasm": "2.1.5", + "esbuild": "0.27.0", + "miniflare": "4.20260114.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20260114.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20260114.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", + "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", + "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", + "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", + "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", + "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", + "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", + "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", + "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", + "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", + "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", + "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", + "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", + "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", + "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", + "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", + "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", + "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", + "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", + "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", + "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", + "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", + "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", + "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", + "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", + "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", + "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/esbuild": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", + "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.0", + "@esbuild/android-arm": "0.27.0", + "@esbuild/android-arm64": "0.27.0", + "@esbuild/android-x64": "0.27.0", + "@esbuild/darwin-arm64": "0.27.0", + "@esbuild/darwin-x64": "0.27.0", + "@esbuild/freebsd-arm64": "0.27.0", + "@esbuild/freebsd-x64": "0.27.0", + "@esbuild/linux-arm": "0.27.0", + "@esbuild/linux-arm64": "0.27.0", + "@esbuild/linux-ia32": "0.27.0", + "@esbuild/linux-loong64": "0.27.0", + "@esbuild/linux-mips64el": "0.27.0", + "@esbuild/linux-ppc64": "0.27.0", + "@esbuild/linux-riscv64": "0.27.0", + "@esbuild/linux-s390x": "0.27.0", + "@esbuild/linux-x64": "0.27.0", + "@esbuild/netbsd-arm64": "0.27.0", + "@esbuild/netbsd-x64": "0.27.0", + "@esbuild/openbsd-arm64": "0.27.0", + "@esbuild/openbsd-x64": "0.27.0", + "@esbuild/openharmony-arm64": "0.27.0", + "@esbuild/sunos-x64": "0.27.0", + "@esbuild/win32-arm64": "0.27.0", + "@esbuild/win32-ia32": "0.27.0", + "@esbuild/win32-x64": "0.27.0" + } + }, + "node_modules/wrangler/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "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/youch/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/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25 || ^4" + } + } + } +} diff --git a/js/smoke/tests/vite-react-hono/package.json b/js/smoke/tests/vite-react-hono/package.json new file mode 100644 index 000000000..cd6253f59 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/package.json @@ -0,0 +1,33 @@ +{ + "name": "braintrust-vite-react-hono-smoke-test", + "description": "Smoke test for Braintrust SDK in Vite + React + Hono + Cloudflare Workers", + "private": true, + "type": "module", + "scripts": { + "test": "node run-test.mjs", + "dev": "vite", + "build": "tsc -b && vite build", + "backup": "npx tsx ../../backup-and-restore.ts backup", + "restore": "npx tsx ../../backup-and-restore.ts restore", + "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" + }, + "dependencies": { + "braintrust": "latest", + "hono": "^4.11.1", + "react": "^19.2.1", + "react-dom": "^19.2.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/vite-plugin": "^1.15.3", + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^24.10.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "tsx": "^4.19.2", + "typescript": "^5.8.3", + "vite": "^6.0.0", + "wrangler": "^4.56.0" + } +} diff --git a/js/smoke/tests/vite-react-hono/run-test.mjs b/js/smoke/tests/vite-react-hono/run-test.mjs new file mode 100644 index 000000000..38008af47 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/run-test.mjs @@ -0,0 +1,79 @@ +import { spawn, execSync } from "node:child_process"; + +const PORT = 8800; +const MAX_RETRIES = 20; +const RETRY_DELAY_MS = 250; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +function killPort(port) { + try { + execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { + stdio: "ignore", + }); + } catch {} +} + +async function waitForServer() { + for (let i = 0; i < MAX_RETRIES; i++) { + try { + const res = await fetch(`http://localhost:${PORT}/`); + if (res.ok) return true; + } catch {} + await sleep(RETRY_DELAY_MS); + } + return false; +} + +async function runTest() { + killPort(PORT); + + const wrangler = spawn("npx", ["wrangler", "dev", "--port", String(PORT)], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let output = ""; + wrangler.stdout.on("data", (d) => (output += d)); + wrangler.stderr.on("data", (d) => (output += d)); + + const killWrangler = () => { + return new Promise((resolve) => { + if (wrangler.exitCode !== null) { + resolve(); + return; + } + wrangler.once("exit", resolve); + wrangler.kill("SIGTERM"); + setTimeout(() => { + if (wrangler.exitCode === null) { + wrangler.kill("SIGKILL"); + } + }, 1000); + }); + }; + + let exitCode = 1; + + try { + if (!(await waitForServer())) { + console.error("Server failed to start:\n", output); + await killWrangler(); + return 1; + } + + const response = await fetch(`http://localhost:${PORT}/api/test`); + const result = await response.json(); + + console.log(JSON.stringify(result, null, 2)); + exitCode = result.success ? 0 : 1; + } catch (error) { + console.error("Error:", error.message, "\n", output); + exitCode = 1; + } + + await killWrangler(); + return exitCode; +} + +runTest().then((code) => process.exit(code)); diff --git a/js/smoke/tests/vite-react-hono/src/react-app/App.css b/js/smoke/tests/vite-react-hono/src/react-app/App.css new file mode 100644 index 000000000..5d701319f --- /dev/null +++ b/js/smoke/tests/vite-react-hono/src/react-app/App.css @@ -0,0 +1,40 @@ +.App { + max-width: 800px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.card { + padding: 2rem; + background: #f4f4f4; + border-radius: 8px; + margin: 1rem 0; +} + +button { + padding: 0.75rem 1.5rem; + font-size: 1rem; + border: none; + border-radius: 4px; + background: #0070f3; + color: white; + cursor: pointer; + margin-bottom: 1rem; +} + +button:hover:not(:disabled) { + background: #0051cc; +} + +button:disabled { + background: #ccc; + cursor: not-allowed; +} + +pre { + background: white; + padding: 1rem; + border-radius: 4px; + min-height: 100px; +} diff --git a/js/smoke/tests/vite-react-hono/src/react-app/App.tsx b/js/smoke/tests/vite-react-hono/src/react-app/App.tsx new file mode 100644 index 000000000..a4106557b --- /dev/null +++ b/js/smoke/tests/vite-react-hono/src/react-app/App.tsx @@ -0,0 +1,55 @@ +import { useState } from "react"; +import "./App.css"; + +function App() { + const [testResult, setTestResult] = useState("Not run"); + const [isRunning, setIsRunning] = useState(false); + + const runSmokeTest = async () => { + setIsRunning(true); + setTestResult("Running tests..."); + + try { + const response = await fetch("/api/test"); + const result = await response.json(); + + if (result.success) { + setTestResult( + `✅ All ${result.totalTests} tests passed!\n${result.message}`, + ); + } else { + setTestResult( + `❌ ${result.failedTests}/${result.totalTests} tests failed\n${result.message}`, + ); + } + } catch (error) { + setTestResult( + `❌ Error: ${error instanceof Error ? error.message : String(error)}`, + ); + } finally { + setIsRunning(false); + } + }; + + return ( +
+

Braintrust Vite + React + Hono Smoke Test

+
+ +
+          {testResult}
+        
+
+
+ ); +} + +export default App; diff --git a/js/smoke/tests/vite-react-hono/src/react-app/index.css b/js/smoke/tests/vite-react-hono/src/react-app/index.css new file mode 100644 index 000000000..8b59f4df1 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/src/react-app/index.css @@ -0,0 +1,31 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + color: #213547; + background-color: #ffffff; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +#root { + width: 100%; +} + +h1 { + font-size: 2.5em; + line-height: 1.1; +} + +@media (prefers-color-scheme: dark) { + :root { + color: #ffffff; + background-color: #242424; + } +} diff --git a/js/smoke/tests/vite-react-hono/src/react-app/main.tsx b/js/smoke/tests/vite-react-hono/src/react-app/main.tsx new file mode 100644 index 000000000..ef474bf64 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/src/react-app/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App.tsx"; +import "./index.css"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts b/js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/js/smoke/tests/vite-react-hono/src/worker/index.ts b/js/smoke/tests/vite-react-hono/src/worker/index.ts new file mode 100644 index 000000000..686a276f8 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/src/worker/index.ts @@ -0,0 +1,118 @@ +/** + * Vite + React + Hono + Cloudflare Worker smoke test using shared test suites + * This test demonstrates using the Braintrust SDK with Hono routing framework + */ + +import { Hono } from "hono"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + runPromptTemplatingTests, + type TestResult, +} from "../../../../shared/dist/index.mjs"; + +import * as braintrust from "braintrust"; +const { initLogger, _exportsForTestingOnly } = braintrust; + +const app = new Hono<{ Bindings: Env }>(); + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +/** + * Run the shared test suites in Hono + Cloudflare Worker environment + */ +async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "vite-react-hono", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + const promptTemplatingResults = await runPromptTemplatingTests( + { + Prompt: braintrust.Prompt, + }, + adapters.environment, + ); + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + ...promptTemplatingResults, + ]; + + const failures = results.filter((r) => !r.success); + + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed in Vite + Hono environment", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +app.get("/", (c) => + c.text(`Braintrust Vite + React + Hono Smoke Test + +GET /api/ - Basic API endpoint +GET /api/test - Run shared test suites + +This worker tests the Braintrust SDK in a Vite + Hono + Cloudflare Workers environment.`), +); + +app.get("/api/", (c) => c.json({ name: "Braintrust", framework: "Hono" })); + +app.get("/api/test", async (c) => { + const result = await runSharedTestSuites(); + + return c.json(result, result.success ? 200 : 500); +}); + +export default app; diff --git a/js/smoke/tests/vite-react-hono/tsconfig.app.json b/js/smoke/tests/vite-react-hono/tsconfig.app.json new file mode 100644 index 000000000..9393b4e33 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/tsconfig.app.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src/react-app"] +} diff --git a/js/smoke/tests/vite-react-hono/tsconfig.json b/js/smoke/tests/vite-react-hono/tsconfig.json new file mode 100644 index 000000000..3dfdf73ff --- /dev/null +++ b/js/smoke/tests/vite-react-hono/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "types": ["@cloudflare/workers-types"] + }, + "include": ["src/**/*"] +} diff --git a/js/smoke/tests/vite-react-hono/tsconfig.node.json b/js/smoke/tests/vite-react-hono/tsconfig.node.json new file mode 100644 index 000000000..8e5b203b7 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/tsconfig.node.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/js/smoke/tests/vite-react-hono/tsconfig.worker.json b/js/smoke/tests/vite-react-hono/tsconfig.worker.json new file mode 100644 index 000000000..60579cdf0 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/tsconfig.worker.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "types": ["@cloudflare/workers-types"] + }, + "include": ["src/worker"] +} diff --git a/js/smoke/tests/vite-react-hono/vite.config.ts b/js/smoke/tests/vite-react-hono/vite.config.ts new file mode 100644 index 000000000..451a7b3a4 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { cloudflare } from "@cloudflare/vite-plugin"; + +export default defineConfig({ + plugins: [react(), cloudflare()], +}); diff --git a/js/smoke/tests/vite-react-hono/wrangler.json b/js/smoke/tests/vite-react-hono/wrangler.json new file mode 100644 index 000000000..0b750d0be --- /dev/null +++ b/js/smoke/tests/vite-react-hono/wrangler.json @@ -0,0 +1,7 @@ +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "braintrust-vite-react-hono-smoke-test", + "main": "./src/worker/index.ts", + "compatibility_date": "2025-01-15", + "compatibility_flags": ["nodejs_compat"] +} From 1a5f0b36e88b9bd1c5ef150e47043561d24566cf Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 15 Jan 2026 15:47:05 -0800 Subject: [PATCH 02/57] add vite dev test --- .github/workflows/js.yaml | 19 +- js/smoke/tests/vite-react-hono/README.md | 69 ++++++- js/smoke/tests/vite-react-hono/package.json | 1 + .../tests/vite-react-hono/test-vite-dev.mjs | 180 ++++++++++++++++++ 4 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 js/smoke/tests/vite-react-hono/test-vite-dev.mjs diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 1dee38552..1b6c6a949 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -397,6 +397,7 @@ jobs: strategy: fail-fast: false matrix: + integration: [cloudflare-worker, vite-react-hono] node-version: [20, 22] steps: @@ -409,7 +410,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Backup original package manifests - working-directory: js/smoke/tests/cloudflare-worker + working-directory: js/smoke/tests/${{ matrix.integration }} run: | npm run backup @@ -422,7 +423,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Install dependencies and local build - working-directory: js/smoke/tests/cloudflare-worker + working-directory: js/smoke/tests/${{ matrix.integration }} shell: bash run: | # Remove package-lock.json to avoid version mismatch with downloaded artifacts @@ -436,15 +437,23 @@ jobs: npm ci npm run build - - name: Run Cloudflare Worker smoke test + - name: Run ${{ matrix.integration }} smoke test working-directory: js/smoke shell: bash run: | - ./run-tests.sh cloudflare-worker + ./run-tests.sh ${{ matrix.integration }} + + - name: Run Vite dev server compatibility test (allowed to fail) + if: matrix.integration == 'vite-react-hono' + continue-on-error: true + working-directory: js/smoke/tests/vite-react-hono + shell: bash + run: | + npm run test:vite-dev - name: Restore original package.json files if: always() - working-directory: js/smoke/tests/cloudflare-worker + working-directory: js/smoke/tests/${{ matrix.integration }} run: | npm run restore diff --git a/js/smoke/tests/vite-react-hono/README.md b/js/smoke/tests/vite-react-hono/README.md index 0b35fa970..6ce326070 100644 --- a/js/smoke/tests/vite-react-hono/README.md +++ b/js/smoke/tests/vite-react-hono/README.md @@ -11,6 +11,8 @@ This test demonstrates: Based on the [Cloudflare Vite + React + Hono template](https://github.com/cloudflare/templates/tree/main/vite-react-template). +📚 **See [TESTING.md](./TESTING.md) for detailed testing guide and issue documentation.** + ## Architecture - **Backend**: Hono app running in Cloudflare Worker (`src/worker/index.ts`) @@ -48,14 +50,39 @@ npm install # Run the automated smoke test (CI mode) npm test -# Or run in development mode with React UI -npm run dev -# Then visit http://localhost:5173 +# Test Vite dev server compatibility (documents known issue) +npm run test:vite-dev # Build for production npm run build ``` +### Known Issue: Vite Dev Server + +**⚠️ The Vite dev server (`npm run dev`) currently fails** with the following error: + +``` +TypeError: Object prototype may only be an Object or null: undefined + at _inheritsLoose (node_modules/nunjucks/src/object.js:8:77) +``` + +**Root Cause**: When Vite tries to pre-bundle dependencies, it encounters Nunjucks (used by Braintrust for prompt templating). Nunjucks uses `Object.setPrototypeOf` with potentially undefined values, which fails in Vite's ESM bundler. + +**Workarounds**: + +1. Use `braintrust/browser` import instead of full `braintrust` package +2. Configure Vite to exclude Nunjucks from optimization: + ```js + // vite.config.ts + export default defineConfig({ + optimizeDeps: { + exclude: ["nunjucks"], + }, + }); + ``` + +**Testing**: Run `npm run test:vite-dev` to verify this known issue is reproducible. The test will fail (exit code 1), which is expected. CI is configured to allow this failure. + ## Test Endpoints When running (`npm run dev` or via `wrangler dev`): @@ -128,15 +155,41 @@ The test runs in CI alongside other smoke tests: ## Key Features 1. **Hono Integration**: Uses Hono's elegant routing instead of raw Worker API -2. **Vite Bundling**: Tests the Braintrust SDK through Vite's bundler -3. **React Frontend**: Optional UI for manual testing +2. **Vite Bundling**: Tests the Braintrust SDK through Vite's bundler (production mode) +3. **Compatibility Testing**: Documents and tests Vite dev server limitations 4. **Cloudflare Workers**: Tests in actual Workers runtime environment 5. **Shared Test Suites**: Consistent test coverage across all environments +## Test Coverage + +This smoke test suite includes: + +### 1. Production Worker Test (`npm test`) + +Tests the Braintrust SDK in a production-like Cloudflare Workers environment: + +- ✅ 18/19 tests pass +- ✅ All import verification tests +- ✅ All functional logging tests +- ✅ Eval smoke test +- ✅ Mustache prompt templating +- ❌ Nunjucks templating (expected failure - Cloudflare security policy) + +### 2. Vite Dev Server Compatibility Test (`npm run test:vite-dev`) + +Documents a known limitation with Vite's dev server: + +- ❌ Reproduces the Nunjucks bundling issue (exits with code 1) +- ✅ Provides clear error messages and workarounds +- ✅ Helps verify if the issue persists in new versions + +This test **reports honest failures**. CI is configured with `continue-on-error: true` to allow this expected failure without blocking the build. + ## Notes -- The automated test (`npm test`) only exercises the `/api/test` endpoint -- The React frontend is optional and not tested in CI +- The automated test (`npm test`) only exercises the `/api/test` endpoint via Wrangler +- The React frontend is optional and not used in CI - Tests run in Cloudflare Workers environment (V8 isolates) -- Uses Wrangler dev server for local testing +- Uses Wrangler dev server for local testing (not Vite) - Port 8800 is used to avoid conflicts with other smoke tests +- The Vite dev server issue is documented and testable but not blocking diff --git a/js/smoke/tests/vite-react-hono/package.json b/js/smoke/tests/vite-react-hono/package.json index cd6253f59..edb50c959 100644 --- a/js/smoke/tests/vite-react-hono/package.json +++ b/js/smoke/tests/vite-react-hono/package.json @@ -5,6 +5,7 @@ "type": "module", "scripts": { "test": "node run-test.mjs", + "test:vite-dev": "node test-vite-dev.mjs", "dev": "vite", "build": "tsc -b && vite build", "backup": "npx tsx ../../backup-and-restore.ts backup", diff --git a/js/smoke/tests/vite-react-hono/test-vite-dev.mjs b/js/smoke/tests/vite-react-hono/test-vite-dev.mjs new file mode 100644 index 000000000..8991d8106 --- /dev/null +++ b/js/smoke/tests/vite-react-hono/test-vite-dev.mjs @@ -0,0 +1,180 @@ +#!/usr/bin/env node +/** + * Test for Vite dev server compatibility with Braintrust SDK + * + * This test verifies a known issue: When Vite tries to pre-bundle the Braintrust SDK, + * it encounters Nunjucks (used for prompt templating) which doesn't work in Vite's + * ESM bundler due to its use of Object.setPrototypeOf with undefined values. + * + * Error: TypeError: Object prototype may only be an Object or null: undefined + * at _inheritsLoose (node_modules/nunjucks/src/object.js:8:77) + * + * This is a known limitation when using the full Braintrust SDK in Vite dev mode. + */ + +import { spawn, execSync } from "node:child_process"; +import { rmSync } from "node:fs"; + +const MAX_RETRIES = 20; +const RETRY_DELAY_MS = 500; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +async function testViteDevServer() { + console.log("Testing Vite dev server compatibility with Braintrust SDK...\n"); + + // Clear Vite cache to force fresh dependency pre-bundling + console.log("1. Clearing Vite cache..."); + try { + rmSync("node_modules/.vite", { recursive: true, force: true }); + console.log(" ✓ Vite cache cleared\n"); + } catch (error) { + console.log(" ℹ No cache to clear\n"); + } + + // Try to start Vite dev server + console.log("2. Starting Vite dev server..."); + + const vite = spawn("npx", ["vite"], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let output = ""; + let errorOutput = ""; + + vite.stdout.on("data", (d) => (output += d.toString())); + vite.stderr.on("data", (d) => (errorOutput += d.toString())); + + // Wait for either success or error + let resolved = false; + let testResult = null; + + const checkOutput = () => { + const combined = output + errorOutput; + + // Check for the Nunjucks error + if (combined.includes("Object prototype may only be an Object or null")) { + resolved = true; + testResult = { + success: false, + issue: "vite-nunjucks-incompatibility", + message: + "Vite dev server fails to start due to Nunjucks incompatibility", + error: + "TypeError: Object prototype may only be an Object or null: undefined", + details: + "Vite's dependency pre-bundler cannot handle Nunjucks' use of Object.setPrototypeOf", + recommendation: + "Use 'braintrust/browser' import or configure Vite to exclude Nunjucks from optimization", + }; + } + + // Check for successful startup + if (combined.includes("Local:") || combined.includes("http://localhost")) { + resolved = true; + testResult = { + success: true, + message: "Vite dev server started successfully", + }; + } + }; + + // Monitor for 10 seconds + for (let i = 0; i < MAX_RETRIES && !resolved; i++) { + await sleep(RETRY_DELAY_MS); + checkOutput(); + } + + // Kill the process + try { + vite.kill("SIGTERM"); + await sleep(500); + if (vite.exitCode === null) { + vite.kill("SIGKILL"); + } + } catch {} + + // Final check + if (!resolved) { + checkOutput(); + } + + if (!testResult) { + testResult = { + success: false, + issue: "timeout", + message: "Vite dev server did not start or error within timeout", + output: (output + errorOutput).slice(-500), + }; + } + + // Print results + console.log("\n" + "=".repeat(60)); + console.log("VITE DEV SERVER TEST RESULTS"); + console.log("=".repeat(60) + "\n"); + + if (testResult.success) { + console.log("✓ Status: PASS - Vite dev server started successfully"); + console.log("\n🎉 The Nunjucks issue may have been fixed!"); + console.log( + "Consider updating documentation if this is consistently passing.\n", + ); + } else if (testResult.issue === "vite-nunjucks-incompatibility") { + console.log("✗ Status: FAIL - Known Nunjucks incompatibility\n"); + console.log("Actual error from Vite:"); + console.log("-".repeat(60)); + // Show the actual error output + const errorLines = (output + errorOutput) + .split("\n") + .filter( + (line) => + line.includes("error") || + line.includes("Error") || + line.includes("at "), + ) + .slice(0, 15); // Show first 15 relevant lines + console.log(errorLines.join("\n")); + console.log("-".repeat(60)); + console.log( + "\nRoot cause: Nunjucks uses Object.setPrototypeOf in ways that", + ); + console.log("fail in Vite's ESM bundler during dependency pre-bundling.\n"); + console.log("Recommendation: Use 'braintrust/browser' import or configure"); + console.log("Vite to exclude Nunjucks from optimization.\n"); + console.log("Documented in: sdk/js/smoke/tests/vite-react-hono/README.md"); + } else { + console.log("✗ Status: UNEXPECTED FAILURE"); + console.log(" Issue:", testResult.issue); + console.log(" Message:", testResult.message); + if (testResult.output) { + console.log("\nOutput:"); + console.log("-".repeat(60)); + console.log(testResult.output); + console.log("-".repeat(60)); + } + } + + console.log("\n" + "=".repeat(60) + "\n"); + + // Return the actual test status + // CI should configure this as allowed-to-fail if desired + if (testResult.issue === "vite-nunjucks-incompatibility") { + console.log("Test result: FAIL (Known issue - expected to fail)"); + console.log( + "\n💡 This is a known limitation. Configure CI to allow this failure.", + ); + return 1; // Actual failure + } else if (testResult.success) { + console.log("Test result: PASS (Vite dev server started successfully!)"); + console.log( + "\n🎉 The Nunjucks issue may be fixed! Review and update documentation.", + ); + return 0; + } else { + console.log("Test result: FAIL (Unexpected behavior)"); + return 1; + } +} + +testViteDevServer().then((code) => process.exit(code)); From 257e639303bb1c92504192ea78a1f84545b4b526 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 15 Jan 2026 19:30:03 -0800 Subject: [PATCH 03/57] revert --- js/smoke/tests/vite-react-hono/package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/smoke/tests/vite-react-hono/package.json b/js/smoke/tests/vite-react-hono/package.json index edb50c959..b1dfa9533 100644 --- a/js/smoke/tests/vite-react-hono/package.json +++ b/js/smoke/tests/vite-react-hono/package.json @@ -6,8 +6,6 @@ "scripts": { "test": "node run-test.mjs", "test:vite-dev": "node test-vite-dev.mjs", - "dev": "vite", - "build": "tsc -b && vite build", "backup": "npx tsx ../../backup-and-restore.ts backup", "restore": "npx tsx ../../backup-and-restore.ts restore", "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" From d5a0d9c6c9a4e74aeb52b1eb38dafe3aabc9c3c1 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 15 Jan 2026 19:33:39 -0800 Subject: [PATCH 04/57] split smoke jobs --- .github/workflows/js.yaml | 72 ++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 1b6c6a949..f5bdff3ef 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -390,14 +390,13 @@ jobs: run: | npm run restore - smoke-tests-cloudflare: + smoke-tests-cloudflare-worker: needs: build runs-on: ubuntu-latest strategy: fail-fast: false matrix: - integration: [cloudflare-worker, vite-react-hono] node-version: [20, 22] steps: @@ -410,7 +409,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Backup original package manifests - working-directory: js/smoke/tests/${{ matrix.integration }} + working-directory: js/smoke/tests/cloudflare-worker run: | npm run backup @@ -423,7 +422,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Install dependencies and local build - working-directory: js/smoke/tests/${{ matrix.integration }} + working-directory: js/smoke/tests/cloudflare-worker shell: bash run: | # Remove package-lock.json to avoid version mismatch with downloaded artifacts @@ -437,14 +436,71 @@ jobs: npm ci npm run build - - name: Run ${{ matrix.integration }} smoke test + - name: Run cloudflare-worker smoke test working-directory: js/smoke shell: bash run: | - ./run-tests.sh ${{ matrix.integration }} + ./run-tests.sh cloudflare-worker + + - name: Restore original package.json files + if: always() + working-directory: js/smoke/tests/cloudflare-worker + run: | + npm run restore + + smoke-tests-vite-react-hono: + needs: build + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node-version: [20, 22] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Backup original package manifests + working-directory: js/smoke/tests/vite-react-hono + run: | + npm run backup + + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist + path: js/artifacts + run-id: ${{ github.run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies and local build + working-directory: js/smoke/tests/vite-react-hono + shell: bash + run: | + # Remove package-lock.json to avoid version mismatch with downloaded artifacts + rm -f package-lock.json + npm install + npx tsx ../../install-build.ts ../../../artifacts braintrust + + - name: Build shared test package + working-directory: js/smoke/shared + run: | + npm ci + npm run build + + - name: Run vite-react-hono smoke test + working-directory: js/smoke + shell: bash + run: | + ./run-tests.sh vite-react-hono - name: Run Vite dev server compatibility test (allowed to fail) - if: matrix.integration == 'vite-react-hono' continue-on-error: true working-directory: js/smoke/tests/vite-react-hono shell: bash @@ -453,7 +509,7 @@ jobs: - name: Restore original package.json files if: always() - working-directory: js/smoke/tests/${{ matrix.integration }} + working-directory: js/smoke/tests/vite-react-hono run: | npm run restore From b2f2f03711d8e6372cde262cdf329cde4ac86cf4 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 15 Jan 2026 20:34:27 -0800 Subject: [PATCH 05/57] make sure to run the npm run test:vitest-dev always --- .github/workflows/js.yaml | 7 ------- js/smoke/tests/vite-react-hono/package.json | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index f5bdff3ef..913f28d27 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -500,13 +500,6 @@ jobs: run: | ./run-tests.sh vite-react-hono - - name: Run Vite dev server compatibility test (allowed to fail) - continue-on-error: true - working-directory: js/smoke/tests/vite-react-hono - shell: bash - run: | - npm run test:vite-dev - - name: Restore original package.json files if: always() working-directory: js/smoke/tests/vite-react-hono diff --git a/js/smoke/tests/vite-react-hono/package.json b/js/smoke/tests/vite-react-hono/package.json index b1dfa9533..3db0ef46e 100644 --- a/js/smoke/tests/vite-react-hono/package.json +++ b/js/smoke/tests/vite-react-hono/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "test": "node run-test.mjs", + "test": "node run-test.mjs; TEST1=$?; node test-vite-dev.mjs; TEST2=$?; exit $((TEST1 || TEST2))", "test:vite-dev": "node test-vite-dev.mjs", "backup": "npx tsx ../../backup-and-restore.ts backup", "restore": "npx tsx ../../backup-and-restore.ts restore", From c99e94502851fd82d124d5cfdbd6194756044c1a Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 15:09:54 -0800 Subject: [PATCH 06/57] add multiple cloudflare tests and change bundling for the browser build --- .../shared/src/suites/prompt-templating.ts | 15 ++ js/smoke/tests/cloudflare-worker/run-test.mjs | 38 +++-- .../tests/cloudflare-worker/src/browser.ts | 4 + js/smoke/tests/cloudflare-worker/src/index.ts | 136 +----------------- js/smoke/tests/cloudflare-worker/src/node.ts | 4 + .../tests/cloudflare-worker/src/worker.ts | 115 +++++++++++++++ .../cloudflare-worker/wrangler.browser.toml | 3 + .../{wrangler.toml => wrangler.node.toml} | 4 +- js/src/template/nunjucks-env.browser.ts | 11 ++ js/src/template/nunjucks-utils.browser.ts | 5 + js/tsup.config.ts | 42 +++++- 11 files changed, 231 insertions(+), 146 deletions(-) create mode 100644 js/smoke/tests/cloudflare-worker/src/browser.ts create mode 100644 js/smoke/tests/cloudflare-worker/src/node.ts create mode 100644 js/smoke/tests/cloudflare-worker/src/worker.ts create mode 100644 js/smoke/tests/cloudflare-worker/wrangler.browser.toml rename js/smoke/tests/cloudflare-worker/{wrangler.toml => wrangler.node.toml} (57%) create mode 100644 js/src/template/nunjucks-env.browser.ts create mode 100644 js/src/template/nunjucks-utils.browser.ts diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index c3d44a7a7..05105af10 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -143,6 +143,21 @@ export async function testNunjucksTemplate( const errorMessage = buildError instanceof Error ? buildError.message : String(buildError); + // Some builds/environments intentionally do not ship nunjucks support. + if ( + (environment === "browser" || environment === "cloudflare-worker") && + errorMessage.includes( + "Nunjucks templating is not supported in this build", + ) + ) { + return { + success: true, + testName, + message: + "Nunjucks template test passed - threw expected unsupported error", + }; + } + // Special handling for Cloudflare Workers environment, they disallow code generation if ( environment === "cloudflare-worker" && diff --git a/js/smoke/tests/cloudflare-worker/run-test.mjs b/js/smoke/tests/cloudflare-worker/run-test.mjs index f5cfabc67..7ed26f6d8 100644 --- a/js/smoke/tests/cloudflare-worker/run-test.mjs +++ b/js/smoke/tests/cloudflare-worker/run-test.mjs @@ -25,13 +25,17 @@ async function waitForServer() { return false; } -async function runTest() { +async function runWranglerTest({ config, label }) { killPort(PORT); - const wrangler = spawn("npx", ["wrangler", "dev", "--port", String(PORT)], { - stdio: ["ignore", "pipe", "pipe"], - shell: true, - }); + const wrangler = spawn( + "npx", + ["wrangler", "dev", "--config", config, "--port", String(PORT)], + { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }, + ); let output = ""; wrangler.stdout.on("data", (d) => (output += d)); @@ -57,7 +61,7 @@ async function runTest() { try { if (!(await waitForServer())) { - console.error("Server failed to start:\n", output); + console.error(`[${label}] Server failed to start:\n`, output); await killWrangler(); return 1; } @@ -65,10 +69,11 @@ async function runTest() { const response = await fetch(`http://localhost:${PORT}/test`); const result = await response.json(); + console.log(`\n=== ${label} ===\n`); console.log(JSON.stringify(result, null, 2)); exitCode = result.success ? 0 : 1; } catch (error) { - console.error("Error:", error.message, "\n", output); + console.error(`[${label}] Error:`, error.message, "\n", output); exitCode = 1; } @@ -76,4 +81,21 @@ async function runTest() { return exitCode; } -runTest().then((code) => process.exit(code)); +async function main() { + const a = await runWranglerTest({ + config: "wrangler.node.toml", + label: "nodejs_compat_v2 + braintrust", + }); + if (a !== 0) process.exit(a); + + const b = await runWranglerTest({ + config: "wrangler.browser.toml", + label: "no compatibility_flags + braintrust/browser", + }); + process.exit(b); +} + +main().catch((err) => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/js/smoke/tests/cloudflare-worker/src/browser.ts b/js/smoke/tests/cloudflare-worker/src/browser.ts new file mode 100644 index 000000000..d6f039d99 --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/browser.ts @@ -0,0 +1,4 @@ +import * as braintrust from "braintrust/browser"; +import { createWorker } from "./worker"; + +export default createWorker(braintrust); diff --git a/js/smoke/tests/cloudflare-worker/src/index.ts b/js/smoke/tests/cloudflare-worker/src/index.ts index 22ed4f4a8..5531f9e7a 100644 --- a/js/smoke/tests/cloudflare-worker/src/index.ts +++ b/js/smoke/tests/cloudflare-worker/src/index.ts @@ -1,135 +1 @@ -/** - * Cloudflare Worker smoke test using shared test suites - * This test demonstrates using the shared test package in Cloudflare Workers - */ - -import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - type TestResult, -} from "../../../shared/dist/index.mjs"; - -import * as braintrust from "braintrust"; -const { initLogger, _exportsForTestingOnly } = braintrust; - -// Cloudflare Worker environment bindings (empty for this test) -interface Env {} - -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -/** - * Run the shared test suites in Cloudflare Worker environment - */ -async function runSharedTestSuites(): Promise { - try { - // Setup test environment - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, // No filesystem in Workers - canUseCLI: false, // No CLI in Workers - environment: "cloudflare-worker", - }); - - try { - // Run import verification tests first (forces all exports to be processed) - const importResults = await runImportVerificationTests(braintrust); - - // Run functional tests - const functionalResults = await runBasicLoggingTests(adapters); - - // Run eval smoke test - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests( - { - Prompt: braintrust.Prompt, - }, - adapters.environment, - ); - - // Combine results - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - // Verify all tests passed - const failures = results.filter((r) => !r.success); - - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - -export default { - async fetch(request: Request, _env: Env): Promise { - const url = new URL(request.url); - - if (url.pathname === "/test") { - const result = await runSharedTestSuites(); - - return new Response(JSON.stringify(result, null, 2), { - headers: { "Content-Type": "application/json" }, - status: result.success ? 200 : 500, - }); - } - - return new Response( - `Braintrust Cloudflare Worker Smoke Test - -GET /test - Run shared test suites - -This worker tests the Braintrust SDK in a Cloudflare Workers environment -using shared test suites for consistency across runtime environments.`, - { - headers: { "Content-Type": "text/plain" }, - }, - ); - }, -}; +export { default } from "./node"; diff --git a/js/smoke/tests/cloudflare-worker/src/node.ts b/js/smoke/tests/cloudflare-worker/src/node.ts new file mode 100644 index 000000000..23e7c00f0 --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/node.ts @@ -0,0 +1,4 @@ +import * as braintrust from "braintrust"; +import { createWorker } from "./worker"; + +export default createWorker(braintrust); diff --git a/js/smoke/tests/cloudflare-worker/src/worker.ts b/js/smoke/tests/cloudflare-worker/src/worker.ts new file mode 100644 index 000000000..58393212a --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/worker.ts @@ -0,0 +1,115 @@ +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + runPromptTemplatingTests, + type TestResult, +} from "../../../shared/dist/index.mjs"; + +// Cloudflare Worker environment bindings (empty for this test) +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +export function createWorker( + braintrust: typeof import("braintrust") | typeof import("braintrust/browser"), +): { + fetch(request: Request, _env: Env): Promise; +} { + const { initLogger, _exportsForTestingOnly } = braintrust; + + async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "cloudflare-worker", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + const promptTemplatingResults = await runPromptTemplatingTests( + { Prompt: braintrust.Prompt }, + adapters.environment, + ); + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + ...promptTemplatingResults, + ]; + + const failures = results.filter((r) => !r.success); + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } + } + + return { + async fetch(request: Request, _env: Env): Promise { + const url = new URL(request.url); + + if (url.pathname === "/test") { + const result = await runSharedTestSuites(); + return new Response(JSON.stringify(result, null, 2), { + headers: { "Content-Type": "application/json" }, + status: result.success ? 200 : 500, + }); + } + + return new Response( + `Braintrust Cloudflare Worker Smoke Test + +GET /test - Run shared test suites + +This worker tests the Braintrust SDK in a Cloudflare Workers environment +using shared test suites for consistency across runtime environments.`, + { headers: { "Content-Type": "text/plain" } }, + ); + }, + }; +} diff --git a/js/smoke/tests/cloudflare-worker/wrangler.browser.toml b/js/smoke/tests/cloudflare-worker/wrangler.browser.toml new file mode 100644 index 000000000..cbbd2e4f1 --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/wrangler.browser.toml @@ -0,0 +1,3 @@ +name = "braintrust-smoke-test-browser" +main = "src/browser.ts" +compatibility_date = "2024-09-23" diff --git a/js/smoke/tests/cloudflare-worker/wrangler.toml b/js/smoke/tests/cloudflare-worker/wrangler.node.toml similarity index 57% rename from js/smoke/tests/cloudflare-worker/wrangler.toml rename to js/smoke/tests/cloudflare-worker/wrangler.node.toml index 209f954f6..35b9b71cb 100644 --- a/js/smoke/tests/cloudflare-worker/wrangler.toml +++ b/js/smoke/tests/cloudflare-worker/wrangler.node.toml @@ -1,4 +1,4 @@ -name = "braintrust-smoke-test" -main = "src/index.ts" +name = "braintrust-smoke-test-node" +main = "src/node.ts" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/src/template/nunjucks-env.browser.ts b/js/src/template/nunjucks-env.browser.ts new file mode 100644 index 000000000..000176c04 --- /dev/null +++ b/js/src/template/nunjucks-env.browser.ts @@ -0,0 +1,11 @@ +export function getNunjucksEnv(): never { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); +} + +export function renderNunjucksString(): never { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); +} diff --git a/js/src/template/nunjucks-utils.browser.ts b/js/src/template/nunjucks-utils.browser.ts new file mode 100644 index 000000000..cdf1a5c77 --- /dev/null +++ b/js/src/template/nunjucks-utils.browser.ts @@ -0,0 +1,5 @@ +export function lintTemplate(): never { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); +} diff --git a/js/tsup.config.ts b/js/tsup.config.ts index e7674688e..566f3645b 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -1,4 +1,5 @@ import { defineConfig } from "tsup"; +import path from "node:path"; export default defineConfig([ { @@ -19,7 +20,46 @@ export default defineConfig([ entry: ["src/browser.ts"], format: ["cjs", "esm"], outDir: "dist", - external: ["zod"], + external: ["zod", "nunjucks"], + esbuildPlugins: [ + { + name: "browser-stubs", + setup(build) { + const resolveTo = (p: string) => ({ + path: p, + namespace: "file", + }); + + build.onResolve({ filter: /^\.\/template\/nunjucks-env$/ }, () => + resolveTo( + path.join(process.cwd(), "src/template/nunjucks-env.browser.ts"), + ), + ); + build.onResolve({ filter: /^\.\/template\/nunjucks-utils$/ }, () => + resolveTo( + path.join( + process.cwd(), + "src/template/nunjucks-utils.browser.ts", + ), + ), + ); + + build.onResolve({ filter: /^\.\/nunjucks-env$/ }, (args) => + resolveTo( + path.join(path.dirname(args.importer), "nunjucks-env.browser.ts"), + ), + ); + build.onResolve({ filter: /^\.\/nunjucks-utils$/ }, (args) => + resolveTo( + path.join( + path.dirname(args.importer), + "nunjucks-utils.browser.ts", + ), + ), + ); + }, + }, + ], dts: { // Split DTS generation to reduce memory usage compilerOptions: { From 0e3026bc9267d8ccc0a78ebb511951bc0c936ddb Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 15:55:13 -0800 Subject: [PATCH 07/57] remove support in nextjs --- .github/workflows/js.yaml | 5 +- js/smoke/run-tests.sh | 13 ++++-- .../shared/src/suites/import-verification.ts | 13 ++++++ .../shared/src/suites/prompt-templating.ts | 46 +++++++++---------- js/smoke/tests/cloudflare-worker/package.json | 2 + js/smoke/tests/cloudflare-worker/run-test.mjs | 30 ++++++++++++ js/smoke/tests/deno/shared_suite_test.ts | 9 ++-- js/smoke/tests/deno/span_test.ts | 2 +- .../app/api/smoke-test/edge/route.ts | 9 ++-- 9 files changed, 94 insertions(+), 35 deletions(-) diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 913f28d27..3c6fd5555 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -398,6 +398,7 @@ jobs: fail-fast: false matrix: node-version: [20, 22] + mode: [node, browser] steps: - name: Checkout repository @@ -439,6 +440,8 @@ jobs: - name: Run cloudflare-worker smoke test working-directory: js/smoke shell: bash + env: + CLOUDFLARE_WORKER_MODE: ${{ matrix.mode }} run: | ./run-tests.sh cloudflare-worker @@ -625,6 +628,6 @@ jobs: - name: Run Deno smoke test working-directory: js/smoke env: - BRAINTRUST_BUILD_DIR: ${{ github.workspace }}/js/smoke/tests/deno/build/braintrust/dist/browser.mjs + BRAINTRUST_BUILD_DIR: ${{ github.workspace }}/js/smoke/tests/deno/build/braintrust/dist/index.mjs run: | ./run-tests.sh deno diff --git a/js/smoke/run-tests.sh b/js/smoke/run-tests.sh index ff46415df..70ab82c73 100755 --- a/js/smoke/run-tests.sh +++ b/js/smoke/run-tests.sh @@ -161,11 +161,18 @@ run_test() { cd "$test_dir" - log_info "Running: npm test" + local npm_script="test" + + # Allow CI to run Cloudflare Worker variants as separate pipeline jobs + if [ "$test_name" = "cloudflare-worker" ] && [ -n "${CLOUDFLARE_WORKER_MODE:-}" ]; then + npm_script="test:${CLOUDFLARE_WORKER_MODE}" + fi + + log_info "Running: npm run $npm_script" # Set BRAINTRUST_BUILD_DIR for Deno tests if not already set if [ "$test_name" = "deno" ] && [ -z "${BRAINTRUST_BUILD_DIR:-}" ]; then - local deno_build_file="$TESTS_DIR/deno/build/braintrust/dist/browser.mjs" + local deno_build_file="$TESTS_DIR/deno/build/braintrust/dist/index.mjs" if [ -f "$deno_build_file" ]; then # Convert to absolute path for Deno file:// imports local abs_dir="$(cd "$(dirname "$deno_build_file")" && pwd)" @@ -178,7 +185,7 @@ run_test() { local test_output local test_exit_code - if test_output=$(npm test 2>&1); then + if test_output=$(npm run "$npm_script" 2>&1); then test_exit_code=0 else test_exit_code=$? diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index 23c7b3043..1d1127c8c 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -150,6 +150,7 @@ export async function testCoreLoggingExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -183,6 +184,7 @@ export async function testDatasetExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -219,6 +221,7 @@ export async function testPromptExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -263,6 +266,7 @@ export async function testExperimentExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -333,6 +337,7 @@ export async function testEvalExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -375,6 +380,7 @@ export async function testTracingExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -424,6 +430,7 @@ export async function testClientWrapperExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -467,6 +474,7 @@ export async function testUtilityExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -500,6 +508,7 @@ export async function testFunctionExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -536,6 +545,7 @@ export async function testFramework2Exports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -566,6 +576,7 @@ export async function testIDGeneratorExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -599,6 +610,7 @@ export async function testTestingExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } @@ -632,6 +644,7 @@ export async function testStateManagementExports( success: false, testName, error: error as Error, + message: error instanceof Error ? error.message : String(error), }; } } diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index 05105af10..db4767b49 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -94,6 +94,15 @@ export async function testNunjucksTemplate( ): Promise { const testName = "testNunjucksTemplate"; + if (environment === "cloudflare-worker") { + return { + success: true, + testName, + message: + "Nunjucks template test skipped - not supported in Cloudflare Workers", + }; + } + try { const { Prompt } = module; @@ -143,33 +152,20 @@ export async function testNunjucksTemplate( const errorMessage = buildError instanceof Error ? buildError.message : String(buildError); - // Some builds/environments intentionally do not ship nunjucks support. - if ( - (environment === "browser" || environment === "cloudflare-worker") && - errorMessage.includes( - "Nunjucks templating is not supported in this build", - ) - ) { - return { - success: true, - testName, - message: - "Nunjucks template test passed - threw expected unsupported error", - }; - } + const isUnsupported = errorMessage.includes( + "Nunjucks templating is not supported in this build", + ); - // Special handling for Cloudflare Workers environment, they disallow code generation if ( - environment === "cloudflare-worker" && - errorMessage.includes( - "String template rendering. Disallowed in this environment for security reasons", - ) + (environment === "browser" || + environment === "cloudflare-worker" || + environment === "nextjs-edge-runtime") && + isUnsupported ) { return { success: true, testName, - message: - "Nunjucks template test skipped - Cloudflare Workers does not support string template rendering", + message: "Nunjucks template test skipped - nunjucks unsupported", }; } @@ -182,10 +178,12 @@ export async function testNunjucksTemplate( } try { + const expected = "Items: apple, banana, cherry"; + const actual = nunjucksResult.messages[0]?.content; assertEqual( - nunjucksResult.messages[0]?.content, - "Items: apple, banana, cherry", - "Nunjucks template should render loop correctly", + actual, + expected, + `Nunjucks template should render loop correctly (expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)})`, ); } catch (assertError) { return { diff --git a/js/smoke/tests/cloudflare-worker/package.json b/js/smoke/tests/cloudflare-worker/package.json index 9a58e9af9..a57ccef14 100644 --- a/js/smoke/tests/cloudflare-worker/package.json +++ b/js/smoke/tests/cloudflare-worker/package.json @@ -5,6 +5,8 @@ "private": true, "scripts": { "test": "node run-test.mjs", + "test:node": "node run-test.mjs --config wrangler.node.toml", + "test:browser": "node run-test.mjs --config wrangler.browser.toml", "backup": "npx tsx ../../backup-and-restore.ts backup", "restore": "npx tsx ../../backup-and-restore.ts restore", "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" diff --git a/js/smoke/tests/cloudflare-worker/run-test.mjs b/js/smoke/tests/cloudflare-worker/run-test.mjs index 7ed26f6d8..9a3e6641d 100644 --- a/js/smoke/tests/cloudflare-worker/run-test.mjs +++ b/js/smoke/tests/cloudflare-worker/run-test.mjs @@ -6,6 +6,21 @@ const RETRY_DELAY_MS = 250; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +function parseArgs(argv) { + const out = {}; + for (let i = 0; i < argv.length; i++) { + const a = argv[i]; + if (a === "--config") { + const v = argv[i + 1]; + if (!v) throw new Error("Missing value for --config"); + out.config = v; + i++; + continue; + } + } + return out; +} + function killPort(port) { try { execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { @@ -82,6 +97,21 @@ async function runWranglerTest({ config, label }) { } async function main() { + const args = parseArgs(process.argv.slice(2)); + if (args.config) { + const label = + args.config === "wrangler.node.toml" + ? "nodejs_compat_v2 + braintrust" + : args.config === "wrangler.browser.toml" + ? "no compatibility_flags + braintrust/browser" + : args.config; + const code = await runWranglerTest({ + config: args.config, + label, + }); + process.exit(code); + } + const a = await runWranglerTest({ config: "wrangler.node.toml", label: "nodejs_compat_v2 + braintrust", diff --git a/js/smoke/tests/deno/shared_suite_test.ts b/js/smoke/tests/deno/shared_suite_test.ts index a5265ca19..8e6a337eb 100644 --- a/js/smoke/tests/deno/shared_suite_test.ts +++ b/js/smoke/tests/deno/shared_suite_test.ts @@ -49,9 +49,12 @@ export async function runSharedTestSuites() { const evalResult = await runEvalSmokeTest(adapters, braintrust); // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); + const promptTemplatingResults = await runPromptTemplatingTests( + { + Prompt: braintrust.Prompt, + }, + adapters.environment, + ); // Combine results const results = [ diff --git a/js/smoke/tests/deno/span_test.ts b/js/smoke/tests/deno/span_test.ts index 0ebdc885f..c546e2cea 100644 --- a/js/smoke/tests/deno/span_test.ts +++ b/js/smoke/tests/deno/span_test.ts @@ -9,7 +9,7 @@ import { /** * This is a simple test to send a span to the braintrust API * Uses BRAINTRUST_BUILD_DIR environment variable to import the braintrust package - * ie. BRAINTRUST_BUILD_DIR=./package/dist/browser.mjs + * ie. BRAINTRUST_BUILD_DIR=./package/dist/index.mjs */ export async function runBrowserLoggerSmokeTest() { const buildDir = Deno.env.get("BRAINTRUST_BUILD_DIR"); diff --git a/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts b/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts index 25e3adce0..ecf6b74f1 100644 --- a/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts +++ b/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts @@ -60,9 +60,12 @@ export async function GET(): Promise> { const evalResult = await runEvalSmokeTest(adapters, braintrust); // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); + const promptTemplatingResults = await runPromptTemplatingTests( + { + Prompt: braintrust.Prompt, + }, + adapters.environment, + ); // Combine results const results = [ From 0e8dc7b4bb80d0b6f44ab4fac2dec4e716cfef84 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 16:06:12 -0800 Subject: [PATCH 08/57] updates --- .../shared/src/suites/prompt-templating.ts | 29 +- .../tests/cloudflare-worker/package-lock.json | 1153 ++++++++--------- js/smoke/tests/cloudflare-worker/package.json | 2 +- .../tests/cloudflare-worker/src/browser.ts | 2 +- js/smoke/tests/cloudflare-worker/src/node.ts | 2 +- .../tests/cloudflare-worker/src/worker.ts | 3 +- js/src/template/nunjucks-env.ts | 10 - 7 files changed, 540 insertions(+), 661 deletions(-) diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index db4767b49..2db349a11 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -94,15 +94,6 @@ export async function testNunjucksTemplate( ): Promise { const testName = "testNunjucksTemplate"; - if (environment === "cloudflare-worker") { - return { - success: true, - testName, - message: - "Nunjucks template test skipped - not supported in Cloudflare Workers", - }; - } - try { const { Prompt } = module; @@ -158,14 +149,30 @@ export async function testNunjucksTemplate( if ( (environment === "browser" || - environment === "cloudflare-worker" || + environment === "cloudflare-worker-browser" || environment === "nextjs-edge-runtime") && isUnsupported ) { return { success: true, testName, - message: "Nunjucks template test skipped - nunjucks unsupported", + message: + "Nunjucks template test passed - threw expected unsupported error", + }; + } + + // In Cloudflare Workers (even with nodejs_compat), string-based template codegen is disallowed. + if ( + environment === "cloudflare-worker-node" && + errorMessage.includes( + "Code generation from strings disallowed for this context", + ) + ) { + return { + success: true, + testName, + message: + "Nunjucks template test passed - threw expected codegen-disallowed error", }; } diff --git a/js/smoke/tests/cloudflare-worker/package-lock.json b/js/smoke/tests/cloudflare-worker/package-lock.json index 84ed25a59..1e11dff58 100644 --- a/js/smoke/tests/cloudflare-worker/package-lock.json +++ b/js/smoke/tests/cloudflare-worker/package-lock.json @@ -8,7 +8,7 @@ "name": "braintrust-cloudflare-worker-smoke-test", "version": "1.0.0", "dependencies": { - "braintrust": "latest", + "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", "zod": "^3.25.76" }, "devDependencies": { @@ -164,6 +164,16 @@ "dev": true, "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "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", @@ -189,9 +199,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "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" ], @@ -205,9 +215,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "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" ], @@ -221,9 +231,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "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" ], @@ -237,9 +247,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -253,9 +263,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -269,9 +279,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "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" ], @@ -285,9 +295,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "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" ], @@ -301,9 +311,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "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" ], @@ -317,9 +327,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "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" ], @@ -333,9 +343,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ "arm64" ], @@ -349,9 +359,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "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" ], @@ -365,9 +375,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "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" ], @@ -381,9 +391,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "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" ], @@ -397,9 +407,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "cpu": [ "ppc64" ], @@ -413,9 +423,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "cpu": [ "riscv64" ], @@ -429,9 +439,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "cpu": [ "s390x" ], @@ -445,9 +455,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "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" ], @@ -461,9 +471,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "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" ], @@ -477,9 +487,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "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" ], @@ -493,9 +503,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "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" ], @@ -509,9 +519,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "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" ], @@ -525,9 +535,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "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" ], @@ -541,9 +551,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "cpu": [ "x64" ], @@ -557,9 +567,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "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" ], @@ -573,9 +583,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "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" ], @@ -589,9 +599,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "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" ], @@ -1118,6 +1128,12 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/@types/nunjucks": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", + "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", + "license": "MIT" + }, "node_modules/@vercel/functions": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", @@ -1135,6 +1151,12 @@ } } }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1171,6 +1193,15 @@ "node": ">=0.4.0" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1207,6 +1238,12 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1244,6 +1281,90 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/boxen/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==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/boxen/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -1254,39 +1375,42 @@ } }, "node_modules/braintrust": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-0.4.10.tgz", - "integrity": "sha512-Dk4aVsHWjgeTyGcM056vleXZGLz3qIHw6rDYP4iyY4DOZeD6JSDGSepGb1dulpcwqf2WC6w9XIFTF7Y/4gfahg==", + "version": "2.0.2", + "resolved": "file:../../../artifacts/braintrust-2.0.2.tgz", + "integrity": "sha512-Vr+KB64EeHXaWWNHLiCHPz01Cc/hx6zdEb5Nlft0W6RSYUZcbWPVttAce6ixyrbs/fBfRCNI4pclGIQOzRPD5w==", "license": "MIT", "dependencies": { "@ai-sdk/provider": "^1.1.3", "@next/env": "^14.2.3", + "@types/nunjucks": "^3.2.6", "@vercel/functions": "^1.0.2", "argparse": "^2.0.1", + "boxen": "^8.0.1", "chalk": "^4.1.2", "cli-progress": "^3.12.0", + "cli-table3": "^0.6.5", "cors": "^2.8.5", "dotenv": "^16.4.5", - "esbuild": "^0.25.10", + "esbuild": "^0.27.0", "eventsource-parser": "^1.1.2", "express": "^4.21.2", "graceful-fs": "^4.2.11", "http-errors": "^2.0.0", "minimatch": "^9.0.3", "mustache": "^4.2.0", + "nunjucks": "^3.2.4", "pluralize": "^8.0.0", "simple-git": "^3.21.0", - "slugify": "^1.6.6", "source-map": "^0.7.4", + "termi-link": "^1.0.1", "uuid": "^9.0.1", - "zod": "^3.25.34", - "zod-to-json-schema": "^3.22.5" + "zod-to-json-schema": "^3.25.0" }, "bin": { "braintrust": "dist/cli.js" }, "peerDependencies": { - "zod": "^3.25.34" + "zod": "^3.25.34 || ^4.0" } }, "node_modules/bytes": { @@ -1327,6 +1451,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1343,6 +1479,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-progress": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", @@ -1355,6 +1503,21 @@ "node": ">=4" } }, + "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==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -1398,6 +1561,15 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1573,9 +1745,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -1585,32 +1757,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "@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/escape-html": { @@ -1756,6 +1928,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -2088,6 +2272,31 @@ "node": ">= 0.6" } }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2553,15 +2762,6 @@ "is-arrayish": "^0.3.1" } }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/source-map": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", @@ -2629,6 +2829,15 @@ "node": ">=8" } }, + "node_modules/termi-link": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", + "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -2666,575 +2875,168 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", - "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=18" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", - "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", - "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", - "cpu": [ - "arm64" - ], + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=18" + "node": ">=14.17" } }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", - "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", - "cpu": [ - "x64" - ], + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">=20.18.1" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", - "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", - "cpu": [ - "arm64" - ], + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "pathe": "^2.0.3" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", - "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": ">= 0.8" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", - "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=18" + "node": ">= 0.4.0" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", - "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", - "cpu": [ - "x64" + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", - "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", - "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", - "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", - "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", - "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", - "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", - "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", - "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", - "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", - "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", - "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", - "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", - "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", - "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", - "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">= 0.8" } }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", - "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "string-width": "^7.0.0" + }, "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", - "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", - "cpu": [ - "ia32" - ], - "dev": true, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", - "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", - "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", - "dev": true, - "hasInstallScript": true, + "node_modules/widest-line/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.1", - "@esbuild/android-arm": "0.27.1", - "@esbuild/android-arm64": "0.27.1", - "@esbuild/android-x64": "0.27.1", - "@esbuild/darwin-arm64": "0.27.1", - "@esbuild/darwin-x64": "0.27.1", - "@esbuild/freebsd-arm64": "0.27.1", - "@esbuild/freebsd-x64": "0.27.1", - "@esbuild/linux-arm": "0.27.1", - "@esbuild/linux-arm64": "0.27.1", - "@esbuild/linux-ia32": "0.27.1", - "@esbuild/linux-loong64": "0.27.1", - "@esbuild/linux-mips64el": "0.27.1", - "@esbuild/linux-ppc64": "0.27.1", - "@esbuild/linux-riscv64": "0.27.1", - "@esbuild/linux-s390x": "0.27.1", - "@esbuild/linux-x64": "0.27.1", - "@esbuild/netbsd-arm64": "0.27.1", - "@esbuild/netbsd-x64": "0.27.1", - "@esbuild/openbsd-arm64": "0.27.1", - "@esbuild/openbsd-x64": "0.27.1", - "@esbuild/openharmony-arm64": "0.27.1", - "@esbuild/sunos-x64": "0.27.1", - "@esbuild/win32-arm64": "0.27.1", - "@esbuild/win32-ia32": "0.27.1", - "@esbuild/win32-x64": "0.27.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/widest-line/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==", "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node": ">=12" }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/unenv": { - "version": "2.0.0-rc.24", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", - "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pathe": "^2.0.3" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/workerd": { @@ -3784,6 +3586,85 @@ "dev": true, "license": "MIT" }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", diff --git a/js/smoke/tests/cloudflare-worker/package.json b/js/smoke/tests/cloudflare-worker/package.json index a57ccef14..73a4e801f 100644 --- a/js/smoke/tests/cloudflare-worker/package.json +++ b/js/smoke/tests/cloudflare-worker/package.json @@ -12,7 +12,7 @@ "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" }, "dependencies": { - "braintrust": "latest", + "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", "zod": "^3.25.76" }, "devDependencies": { diff --git a/js/smoke/tests/cloudflare-worker/src/browser.ts b/js/smoke/tests/cloudflare-worker/src/browser.ts index d6f039d99..8957c1c81 100644 --- a/js/smoke/tests/cloudflare-worker/src/browser.ts +++ b/js/smoke/tests/cloudflare-worker/src/browser.ts @@ -1,4 +1,4 @@ import * as braintrust from "braintrust/browser"; import { createWorker } from "./worker"; -export default createWorker(braintrust); +export default createWorker(braintrust, "cloudflare-worker-browser"); diff --git a/js/smoke/tests/cloudflare-worker/src/node.ts b/js/smoke/tests/cloudflare-worker/src/node.ts index 23e7c00f0..4e9efff06 100644 --- a/js/smoke/tests/cloudflare-worker/src/node.ts +++ b/js/smoke/tests/cloudflare-worker/src/node.ts @@ -1,4 +1,4 @@ import * as braintrust from "braintrust"; import { createWorker } from "./worker"; -export default createWorker(braintrust); +export default createWorker(braintrust, "cloudflare-worker-node"); diff --git a/js/smoke/tests/cloudflare-worker/src/worker.ts b/js/smoke/tests/cloudflare-worker/src/worker.ts index 58393212a..f64fef263 100644 --- a/js/smoke/tests/cloudflare-worker/src/worker.ts +++ b/js/smoke/tests/cloudflare-worker/src/worker.ts @@ -23,6 +23,7 @@ interface TestResponse { export function createWorker( braintrust: typeof import("braintrust") | typeof import("braintrust/browser"), + environment: string, ): { fetch(request: Request, _env: Env): Promise; } { @@ -35,7 +36,7 @@ export function createWorker( testingExports: _exportsForTestingOnly, canUseFileSystem: false, canUseCLI: false, - environment: "cloudflare-worker", + environment, }); try { diff --git a/js/src/template/nunjucks-env.ts b/js/src/template/nunjucks-env.ts index 82a4951fd..b23f1cf44 100644 --- a/js/src/template/nunjucks-env.ts +++ b/js/src/template/nunjucks-env.ts @@ -29,16 +29,6 @@ export function renderNunjucksString( try { return getNunjucksEnv(strict).renderString(template, variables); } catch (error) { - if ( - error instanceof Error && - error.message.includes( - "Code generation from strings disallowed for this context", - ) - ) { - throw new Error( - `String template rendering. Disallowed in this environment for security reasons. Try a different template renderer. Original error: ${error.message}`, - ); - } throw error; } } From 5f77bc6355ae657fd3002943208fc5ab8bc60064 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 16:30:18 -0800 Subject: [PATCH 09/57] add full matrix of compatibility --- .github/workflows/js.yaml | 8 +++++++- js/smoke/tests/browser/package-lock.json | 8 ++++---- js/smoke/tests/browser/package.json | 2 +- js/smoke/tests/cloudflare-worker/package.json | 6 ++++-- js/smoke/tests/cloudflare-worker/run-test.mjs | 19 +++++++++++++++++-- .../wrangler.browser-node-compat.toml | 4 ++++ .../wrangler.node-no-compat.toml | 3 +++ 7 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml create mode 100644 js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 3c6fd5555..68b48a52c 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -398,7 +398,13 @@ jobs: fail-fast: false matrix: node-version: [20, 22] - mode: [node, browser] + mode: + [ + braintrust-node-compat, + braintrust-browser-node-compat, + braintrust-browser-no-compat, + braintrust-no-compat, + ] steps: - name: Checkout repository diff --git a/js/smoke/tests/browser/package-lock.json b/js/smoke/tests/browser/package-lock.json index bf4a6b3cc..2376d7835 100644 --- a/js/smoke/tests/browser/package-lock.json +++ b/js/smoke/tests/browser/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "hasInstallScript": true, "dependencies": { - "braintrust": "latest", + "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", "zod": "^4.3.5" }, "devDependencies": { @@ -767,9 +767,9 @@ } }, "node_modules/braintrust": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-2.0.1.tgz", - "integrity": "sha512-YU5IDDWcPtZDfbI4Zm67YD7c+HiXjAeXa+CuQvwmNDpoViU4eKijeP6drbqgzA3chp6fN4+S11xgdvwGrYqteg==", + "version": "2.0.2", + "resolved": "file:../../../artifacts/braintrust-2.0.2.tgz", + "integrity": "sha512-NwEjar0jc/bEalnQuOZmOcUeUY4GhtzE41rjA2KWOotHNF7Nk4ppyXo6GWlJ9QOAGG465l9MTuuekFJzU+Goag==", "license": "MIT", "dependencies": { "@ai-sdk/provider": "^1.1.3", diff --git a/js/smoke/tests/browser/package.json b/js/smoke/tests/browser/package.json index 98f978d3c..0d69d94f8 100644 --- a/js/smoke/tests/browser/package.json +++ b/js/smoke/tests/browser/package.json @@ -16,7 +16,7 @@ "install-build": "npm install --legacy-peer-deps && npx tsx ../../install-build.ts ../../../artifacts braintrust" }, "dependencies": { - "braintrust": "latest", + "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", "zod": "^4.3.5" }, "devDependencies": { diff --git a/js/smoke/tests/cloudflare-worker/package.json b/js/smoke/tests/cloudflare-worker/package.json index 73a4e801f..b7f24aac8 100644 --- a/js/smoke/tests/cloudflare-worker/package.json +++ b/js/smoke/tests/cloudflare-worker/package.json @@ -5,8 +5,10 @@ "private": true, "scripts": { "test": "node run-test.mjs", - "test:node": "node run-test.mjs --config wrangler.node.toml", - "test:browser": "node run-test.mjs --config wrangler.browser.toml", + "test:braintrust-node-compat": "node run-test.mjs --config wrangler.node.toml", + "test:braintrust-browser-node-compat": "node run-test.mjs --config wrangler.browser-node-compat.toml", + "test:braintrust-browser-no-compat": "node run-test.mjs --config wrangler.browser.toml", + "test:braintrust-no-compat": "node run-test.mjs --config wrangler.node-no-compat.toml --expect-start-fail", "backup": "npx tsx ../../backup-and-restore.ts backup", "restore": "npx tsx ../../backup-and-restore.ts restore", "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" diff --git a/js/smoke/tests/cloudflare-worker/run-test.mjs b/js/smoke/tests/cloudflare-worker/run-test.mjs index 9a3e6641d..66e3cd7a1 100644 --- a/js/smoke/tests/cloudflare-worker/run-test.mjs +++ b/js/smoke/tests/cloudflare-worker/run-test.mjs @@ -17,6 +17,10 @@ function parseArgs(argv) { i++; continue; } + if (a === "--expect-start-fail") { + out.expectStartFail = true; + continue; + } } return out; } @@ -40,7 +44,7 @@ async function waitForServer() { return false; } -async function runWranglerTest({ config, label }) { +async function runWranglerTest({ config, label, expectStartFail = false }) { killPort(PORT); const wrangler = spawn( @@ -76,6 +80,12 @@ async function runWranglerTest({ config, label }) { try { if (!(await waitForServer())) { + if (expectStartFail) { + console.log(`\n=== ${label} (expected startup failure) ===\n`); + console.log(output.trim() ? output : "(no output)"); + await killWrangler(); + return 0; + } console.error(`[${label}] Server failed to start:\n`, output); await killWrangler(); return 1; @@ -104,10 +114,15 @@ async function main() { ? "nodejs_compat_v2 + braintrust" : args.config === "wrangler.browser.toml" ? "no compatibility_flags + braintrust/browser" - : args.config; + : args.config === "wrangler.browser-node-compat.toml" + ? "nodejs_compat_v2 + braintrust/browser" + : args.config === "wrangler.node-no-compat.toml" + ? "no compatibility_flags + braintrust" + : args.config; const code = await runWranglerTest({ config: args.config, label, + expectStartFail: !!args.expectStartFail, }); process.exit(code); } diff --git a/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml b/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml new file mode 100644 index 000000000..42615b360 --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml @@ -0,0 +1,4 @@ +name = "braintrust-smoke-test-browser-node-compat" +main = "src/browser.ts" +compatibility_date = "2024-09-23" +compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml b/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml new file mode 100644 index 000000000..d807867db --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml @@ -0,0 +1,3 @@ +name = "braintrust-smoke-test-node-no-compat" +main = "src/node.ts" +compatibility_date = "2024-09-23" From c63ff0723057a907148383224829d006f21698ca Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 16:35:41 -0800 Subject: [PATCH 10/57] ensure all 4 environments are checked --- js/smoke/shared/src/suites/prompt-templating.ts | 5 +++-- js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts | 4 ++++ .../tests/cloudflare-worker/src/browser-node-compat.ts | 7 +++++++ js/smoke/tests/cloudflare-worker/src/browser.ts | 2 +- js/smoke/tests/cloudflare-worker/src/node-no-compat.ts | 4 ++++ js/smoke/tests/cloudflare-worker/src/node-node-compat.ts | 4 ++++ js/smoke/tests/cloudflare-worker/src/node.ts | 2 +- .../cloudflare-worker/wrangler.browser-node-compat.toml | 2 +- js/smoke/tests/cloudflare-worker/wrangler.browser.toml | 2 +- .../tests/cloudflare-worker/wrangler.node-no-compat.toml | 2 +- js/smoke/tests/cloudflare-worker/wrangler.node.toml | 2 +- 11 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts create mode 100644 js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts create mode 100644 js/smoke/tests/cloudflare-worker/src/node-no-compat.ts create mode 100644 js/smoke/tests/cloudflare-worker/src/node-node-compat.ts diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index 2db349a11..50489ee3c 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -149,7 +149,8 @@ export async function testNunjucksTemplate( if ( (environment === "browser" || - environment === "cloudflare-worker-browser" || + environment === "cloudflare-worker-browser-no-compat" || + environment === "cloudflare-worker-browser-node-compat" || environment === "nextjs-edge-runtime") && isUnsupported ) { @@ -163,7 +164,7 @@ export async function testNunjucksTemplate( // In Cloudflare Workers (even with nodejs_compat), string-based template codegen is disallowed. if ( - environment === "cloudflare-worker-node" && + environment === "cloudflare-worker-node-node-compat" && errorMessage.includes( "Code generation from strings disallowed for this context", ) diff --git a/js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts b/js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts new file mode 100644 index 000000000..c594f3fe3 --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts @@ -0,0 +1,4 @@ +import * as braintrust from "braintrust/browser"; +import { createWorker } from "./worker"; + +export default createWorker(braintrust, "cloudflare-worker-browser-no-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts b/js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts new file mode 100644 index 000000000..80f345d3d --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts @@ -0,0 +1,7 @@ +import * as braintrust from "braintrust/browser"; +import { createWorker } from "./worker"; + +export default createWorker( + braintrust, + "cloudflare-worker-browser-node-compat", +); diff --git a/js/smoke/tests/cloudflare-worker/src/browser.ts b/js/smoke/tests/cloudflare-worker/src/browser.ts index 8957c1c81..c594f3fe3 100644 --- a/js/smoke/tests/cloudflare-worker/src/browser.ts +++ b/js/smoke/tests/cloudflare-worker/src/browser.ts @@ -1,4 +1,4 @@ import * as braintrust from "braintrust/browser"; import { createWorker } from "./worker"; -export default createWorker(braintrust, "cloudflare-worker-browser"); +export default createWorker(braintrust, "cloudflare-worker-browser-no-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/node-no-compat.ts b/js/smoke/tests/cloudflare-worker/src/node-no-compat.ts new file mode 100644 index 000000000..98a8e9e1d --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/node-no-compat.ts @@ -0,0 +1,4 @@ +import * as braintrust from "braintrust"; +import { createWorker } from "./worker"; + +export default createWorker(braintrust, "cloudflare-worker-node-no-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/node-node-compat.ts b/js/smoke/tests/cloudflare-worker/src/node-node-compat.ts new file mode 100644 index 000000000..9339aa6a8 --- /dev/null +++ b/js/smoke/tests/cloudflare-worker/src/node-node-compat.ts @@ -0,0 +1,4 @@ +import * as braintrust from "braintrust"; +import { createWorker } from "./worker"; + +export default createWorker(braintrust, "cloudflare-worker-node-node-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/node.ts b/js/smoke/tests/cloudflare-worker/src/node.ts index 4e9efff06..9339aa6a8 100644 --- a/js/smoke/tests/cloudflare-worker/src/node.ts +++ b/js/smoke/tests/cloudflare-worker/src/node.ts @@ -1,4 +1,4 @@ import * as braintrust from "braintrust"; import { createWorker } from "./worker"; -export default createWorker(braintrust, "cloudflare-worker-node"); +export default createWorker(braintrust, "cloudflare-worker-node-node-compat"); diff --git a/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml b/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml index 42615b360..508e049b1 100644 --- a/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml +++ b/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml @@ -1,4 +1,4 @@ name = "braintrust-smoke-test-browser-node-compat" -main = "src/browser.ts" +main = "src/browser-node-compat.ts" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/tests/cloudflare-worker/wrangler.browser.toml b/js/smoke/tests/cloudflare-worker/wrangler.browser.toml index cbbd2e4f1..6048efa1d 100644 --- a/js/smoke/tests/cloudflare-worker/wrangler.browser.toml +++ b/js/smoke/tests/cloudflare-worker/wrangler.browser.toml @@ -1,3 +1,3 @@ name = "braintrust-smoke-test-browser" -main = "src/browser.ts" +main = "src/browser-no-compat.ts" compatibility_date = "2024-09-23" diff --git a/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml b/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml index d807867db..98528470d 100644 --- a/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml +++ b/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml @@ -1,3 +1,3 @@ name = "braintrust-smoke-test-node-no-compat" -main = "src/node.ts" +main = "src/node-no-compat.ts" compatibility_date = "2024-09-23" diff --git a/js/smoke/tests/cloudflare-worker/wrangler.node.toml b/js/smoke/tests/cloudflare-worker/wrangler.node.toml index 35b9b71cb..6e94cceb6 100644 --- a/js/smoke/tests/cloudflare-worker/wrangler.node.toml +++ b/js/smoke/tests/cloudflare-worker/wrangler.node.toml @@ -1,4 +1,4 @@ name = "braintrust-smoke-test-node" -main = "src/node.ts" +main = "src/node-node-compat.ts" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat_v2"] From f4f105baeb1090470c1b609521547f0895c4ec84 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 16:41:26 -0800 Subject: [PATCH 11/57] add back proper error, undo browser test changes --- js/smoke/shared/src/suites/prompt-templating.ts | 2 +- js/smoke/tests/browser/package-lock.json | 6 +++--- js/smoke/tests/browser/package.json | 2 +- js/smoke/tests/cloudflare-worker/package-lock.json | 2 +- js/src/template/nunjucks-env.ts | 10 ++++++++++ 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index 50489ee3c..0e82d3a2e 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -166,7 +166,7 @@ export async function testNunjucksTemplate( if ( environment === "cloudflare-worker-node-node-compat" && errorMessage.includes( - "Code generation from strings disallowed for this context", + "String template rendering. Disallowed in this environment for security reasons", ) ) { return { diff --git a/js/smoke/tests/browser/package-lock.json b/js/smoke/tests/browser/package-lock.json index 2376d7835..b665d9b86 100644 --- a/js/smoke/tests/browser/package-lock.json +++ b/js/smoke/tests/browser/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "hasInstallScript": true, "dependencies": { - "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", + "braintrust": "latest", "zod": "^4.3.5" }, "devDependencies": { @@ -768,8 +768,8 @@ }, "node_modules/braintrust": { "version": "2.0.2", - "resolved": "file:../../../artifacts/braintrust-2.0.2.tgz", - "integrity": "sha512-NwEjar0jc/bEalnQuOZmOcUeUY4GhtzE41rjA2KWOotHNF7Nk4ppyXo6GWlJ9QOAGG465l9MTuuekFJzU+Goag==", + "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-2.0.2.tgz", + "integrity": "sha512-TOfdi2acpDnne3Pcew/shbwda0SKQvjTsGprr0gLWloaeYehhOPyrsWmwKsRNXOJa01D0czTGyetWpUbcH+euw==", "license": "MIT", "dependencies": { "@ai-sdk/provider": "^1.1.3", diff --git a/js/smoke/tests/browser/package.json b/js/smoke/tests/browser/package.json index 0d69d94f8..98f978d3c 100644 --- a/js/smoke/tests/browser/package.json +++ b/js/smoke/tests/browser/package.json @@ -16,7 +16,7 @@ "install-build": "npm install --legacy-peer-deps && npx tsx ../../install-build.ts ../../../artifacts braintrust" }, "dependencies": { - "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", + "braintrust": "latest", "zod": "^4.3.5" }, "devDependencies": { diff --git a/js/smoke/tests/cloudflare-worker/package-lock.json b/js/smoke/tests/cloudflare-worker/package-lock.json index 1e11dff58..8e428b02c 100644 --- a/js/smoke/tests/cloudflare-worker/package-lock.json +++ b/js/smoke/tests/cloudflare-worker/package-lock.json @@ -1377,7 +1377,7 @@ "node_modules/braintrust": { "version": "2.0.2", "resolved": "file:../../../artifacts/braintrust-2.0.2.tgz", - "integrity": "sha512-Vr+KB64EeHXaWWNHLiCHPz01Cc/hx6zdEb5Nlft0W6RSYUZcbWPVttAce6ixyrbs/fBfRCNI4pclGIQOzRPD5w==", + "integrity": "sha512-nU5mFGGJEzth094Hs1qiCRZ59s5PJjW35BgFjx2YBJg38HkMBflvf73NBLeYvgoqBfPFs1OyoGpyEyOB16YASw==", "license": "MIT", "dependencies": { "@ai-sdk/provider": "^1.1.3", diff --git a/js/src/template/nunjucks-env.ts b/js/src/template/nunjucks-env.ts index b23f1cf44..82a4951fd 100644 --- a/js/src/template/nunjucks-env.ts +++ b/js/src/template/nunjucks-env.ts @@ -29,6 +29,16 @@ export function renderNunjucksString( try { return getNunjucksEnv(strict).renderString(template, variables); } catch (error) { + if ( + error instanceof Error && + error.message.includes( + "Code generation from strings disallowed for this context", + ) + ) { + throw new Error( + `String template rendering. Disallowed in this environment for security reasons. Try a different template renderer. Original error: ${error.message}`, + ); + } throw error; } } From 0c5f0918d7f85dd278443994a15e12f930ce5b91 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 21:00:46 -0800 Subject: [PATCH 12/57] modifications to run deno mjs and deno browser --- .github/workflows/js.yaml | 26 +--- js/smoke/run-tests.sh | 41 +++++-- js/smoke/tests/deno-browser/deno.json | 37 ++++++ js/smoke/tests/deno-browser/deno.lock | 113 ++++++++++++++++++ js/smoke/tests/deno-browser/package.json | 13 ++ .../tests/deno-browser/shared_suite_test.ts | 63 ++++++++++ js/smoke/tests/deno/deno.json | 16 ++- js/smoke/tests/deno/deno.lock | 46 ++++++- js/smoke/tests/deno/shared_suite_test.ts | 9 +- js/smoke/tests/deno/span_test.ts | 7 +- 10 files changed, 322 insertions(+), 49 deletions(-) create mode 100644 js/smoke/tests/deno-browser/deno.json create mode 100644 js/smoke/tests/deno-browser/deno.lock create mode 100644 js/smoke/tests/deno-browser/package.json create mode 100644 js/smoke/tests/deno-browser/shared_suite_test.ts diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 68b48a52c..0173f50a4 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -586,8 +586,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest] node-version: [20, 22] + mode: [deno, deno-browser] steps: - uses: actions/checkout@v4 @@ -604,24 +604,8 @@ jobs: run-id: ${{ github.run_id }} github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Extract build artifact - working-directory: js/smoke/tests/deno - shell: bash - run: | - set -euo pipefail - ARTIFACT_DIR=../../../artifacts - TARBALL=$(ls "$ARTIFACT_DIR"/braintrust-*.tgz | head -n 1 || true) - if [ -z "$TARBALL" ]; then - echo "No braintrust build found" - exit 1 - fi - rm -rf build - mkdir -p build - tar -xzf "$TARBALL" -C build - [ -d build/package ] && mv build/package build/braintrust - - name: Install Deno dependencies - working-directory: js/smoke/tests/deno + working-directory: js/smoke/tests/${{ matrix.mode }} run: | deno install @@ -631,9 +615,7 @@ jobs: npm ci npm run build - - name: Run Deno smoke test + - name: Run Deno smoke test (${{ matrix.mode }}) working-directory: js/smoke - env: - BRAINTRUST_BUILD_DIR: ${{ github.workspace }}/js/smoke/tests/deno/build/braintrust/dist/index.mjs run: | - ./run-tests.sh deno + ./run-tests.sh ${{ matrix.mode }} diff --git a/js/smoke/run-tests.sh b/js/smoke/run-tests.sh index 70ab82c73..57e57fda7 100755 --- a/js/smoke/run-tests.sh +++ b/js/smoke/run-tests.sh @@ -170,15 +170,40 @@ run_test() { log_info "Running: npm run $npm_script" - # Set BRAINTRUST_BUILD_DIR for Deno tests if not already set - if [ "$test_name" = "deno" ] && [ -z "${BRAINTRUST_BUILD_DIR:-}" ]; then - local deno_build_file="$TESTS_DIR/deno/build/braintrust/dist/index.mjs" - if [ -f "$deno_build_file" ]; then - # Convert to absolute path for Deno file:// imports - local abs_dir="$(cd "$(dirname "$deno_build_file")" && pwd)" - export BRAINTRUST_BUILD_DIR="$abs_dir/$(basename "$deno_build_file")" - log_info "Set BRAINTRUST_BUILD_DIR=$BRAINTRUST_BUILD_DIR" + # Ensure Deno has a local file:// module to import (deno.json maps `braintrust` to ./build/braintrust/dist/index.mjs) + if [ "$test_name" = "deno" ] || [ "$test_name" = "deno-browser" ]; then + local deno_dir="$TESTS_DIR/$test_name" + local deno_build_file="$deno_dir/build/braintrust/dist/index.mjs" + if [ ! -f "$deno_build_file" ]; then + log_info "Preparing Deno build directory from packed braintrust tarball..." + local artifacts_dir="$SCRIPT_DIR/../artifacts" + local tarball + tarball=$(ls "$artifacts_dir"/braintrust-*.tgz 2>/dev/null | grep -v "braintrust-otel-" | grep -v "braintrust-template-nunjucks-" | head -n 1 || true) + if [ -z "${tarball:-}" ]; then + log_error "No braintrust tarball found in $artifacts_dir" + FAILED_TESTS+=("$test_name (missing braintrust tarball)") + return 1 + fi + + rm -rf "$deno_dir/build" + mkdir -p "$deno_dir/build" + tar -xzf "$tarball" -C "$deno_dir/build" + if [ -d "$deno_dir/build/package" ]; then + mv "$deno_dir/build/package" "$deno_dir/build/braintrust" + fi + + if [ ! -f "$deno_build_file" ]; then + log_error "Deno build file not found after extraction: $deno_build_file" + FAILED_TESTS+=("$test_name (deno extraction failed)") + return 1 + fi + log_success "Deno build extracted" fi + + # Convert to absolute path for any remaining file:// imports + local abs_dir="$(cd "$(dirname "$deno_build_file")" && pwd)" + export BRAINTRUST_BUILD_DIR="$abs_dir/$(basename "$deno_build_file")" + log_info "Set BRAINTRUST_BUILD_DIR=$BRAINTRUST_BUILD_DIR" fi # Run test and capture output diff --git a/js/smoke/tests/deno-browser/deno.json b/js/smoke/tests/deno-browser/deno.json new file mode 100644 index 000000000..68c6d5adc --- /dev/null +++ b/js/smoke/tests/deno-browser/deno.json @@ -0,0 +1,37 @@ +{ + "nodeModulesDir": "auto", + "npmDependencies": { + "@next/env": "14.2.3", + "eventsource-parser": "1.1.2", + "uuid": "9.0.1", + "dotenv": "16.4.5", + "argparse": "2.0.1", + "chalk": "4.1.2" + }, + "workspace": { + "members": [] + }, + "imports": { + "@vercel/functions": "npm:@vercel/functions@^3.3.0", + "async_hooks": "node:async_hooks", + "child_process": "node:child_process", + "crypto": "node:crypto", + "eventsource-parser": "npm:eventsource-parser@^3.0.6", + "fs": "node:fs", + "fs/promises": "node:fs/promises", + "mustache": "npm:mustache@^4.2.0", + "uuid": "npm:uuid@^13.0.0", + "os": "node:os", + "path": "node:path", + "simple-git": "npm:simple-git@^3.21.0", + "zod": "npm:zod@^4.1.12", + "nunjucks": "npm:nunjucks@^3.2.4", + "util": "node:util", + "zlib": "node:zlib", + "braintrust/browser": "./build/braintrust/dist/browser.mjs", + "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" + }, + "tasks": { + "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts" + } +} diff --git a/js/smoke/tests/deno-browser/deno.lock b/js/smoke/tests/deno-browser/deno.lock new file mode 100644 index 000000000..4111fa708 --- /dev/null +++ b/js/smoke/tests/deno-browser/deno.lock @@ -0,0 +1,113 @@ +{ + "version": "5", + "specifiers": { + "jsr:@std/assert@^1.0.14": "1.0.15", + "jsr:@std/internal@^1.0.12": "1.0.12", + "npm:@vercel/functions@^3.3.0": "3.3.4", + "npm:eventsource-parser@^3.0.6": "3.0.6", + "npm:mustache@^4.2.0": "4.2.0", + "npm:nunjucks@^3.2.4": "3.2.4", + "npm:simple-git@^3.21.0": "3.30.0", + "npm:uuid@13": "13.0.0", + "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@4.2.1", + "npm:zod@^4.1.12": "4.2.1" + }, + "jsr": { + "@std/assert@1.0.15": { + "integrity": "d64018e951dbdfab9777335ecdb000c0b4e3df036984083be219ce5941e4703b", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + } + }, + "npm": { + "@kwsites/file-exists@1.1.1": { + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dependencies": [ + "debug" + ] + }, + "@kwsites/promise-deferred@1.1.1": { + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + }, + "@vercel/functions@3.3.4": { + "integrity": "sha512-IoP8Xfr1QeCm+Dv5od3bfPiw/VgLKsA7IBd/88M/Wr421HdbH4b6bW5z8CTxiz1QRpalrPFZcLdMdxu+2hAjZg==", + "dependencies": [ + "@vercel/oidc" + ] + }, + "@vercel/oidc@3.0.5": { + "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==" + }, + "a-sync-waterfall@1.0.1": { + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + }, + "asap@2.0.6": { + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "commander@5.1.0": { + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms" + ] + }, + "eventsource-parser@3.0.6": { + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "mustache@4.2.0": { + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": true + }, + "nunjucks@3.2.4": { + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dependencies": [ + "a-sync-waterfall", + "asap", + "commander" + ], + "bin": true + }, + "simple-git@3.30.0": { + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "dependencies": [ + "@kwsites/file-exists", + "@kwsites/promise-deferred", + "debug" + ] + }, + "uuid@13.0.0": { + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "bin": true + }, + "zod-to-json-schema@3.25.0_zod@4.2.1": { + "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", + "dependencies": [ + "zod" + ] + }, + "zod@4.2.1": { + "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==" + } + }, + "workspace": { + "dependencies": [ + "npm:@vercel/functions@^3.3.0", + "npm:eventsource-parser@^3.0.6", + "npm:mustache@^4.2.0", + "npm:nunjucks@^3.2.4", + "npm:simple-git@^3.21.0", + "npm:uuid@13", + "npm:zod-to-json-schema@^3.25.0", + "npm:zod@^4.1.12" + ] + } +} diff --git a/js/smoke/tests/deno-browser/package.json b/js/smoke/tests/deno-browser/package.json new file mode 100644 index 000000000..b16828bcd --- /dev/null +++ b/js/smoke/tests/deno-browser/package.json @@ -0,0 +1,13 @@ +{ + "name": "braintrust-deno-browser-smoke-test", + "version": "1.0.0", + "description": "Smoke test for Braintrust SDK browser build in Deno runtime", + "private": true, + "scripts": { + "test": "npm run test:shared", + "test:shared": "deno task test:shared", + "backup": "npx tsx ../../backup-and-restore.ts backup", + "restore": "npx tsx ../../backup-and-restore.ts restore", + "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" + } +} diff --git a/js/smoke/tests/deno-browser/shared_suite_test.ts b/js/smoke/tests/deno-browser/shared_suite_test.ts new file mode 100644 index 000000000..70958f262 --- /dev/null +++ b/js/smoke/tests/deno-browser/shared_suite_test.ts @@ -0,0 +1,63 @@ +// @ts-nocheck +/** + * Deno smoke test using shared test suites, but importing the browser build. + */ + +import { assertEquals } from "jsr:@std/assert@^1.0.14"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + runPromptTemplatingTests, + type TestResult, +} from "../../shared/dist/index.mjs"; +import * as braintrust from "braintrust/browser"; + +export async function runSharedTestSuites(): Promise { + const { initLogger, _exportsForTestingOnly } = braintrust; + + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: true, + canUseCLI: false, + environment: "browser", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + const promptTemplatingResults = await runPromptTemplatingTests( + { Prompt: braintrust.Prompt }, + adapters.environment, + ); + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + ...promptTemplatingResults, + ]; + + const failures = results.filter((r) => !r.success); + if (failures.length > 0) { + for (const failure of failures) { + console.error(` ❌ ${failure.testName}: ${failure.error?.message}`); + } + throw new Error(`${failures.length} test(s) failed`); + } + + return results; + } finally { + await cleanupTestEnvironment(adapters); + } +} + +Deno.test("Run shared test suites (browser build)", async () => { + const results = await runSharedTestSuites(); + assertEquals(results.filter((r) => !r.success).length, 0); + console.log(`\n✅ All ${results.length} tests passed`); +}); diff --git a/js/smoke/tests/deno/deno.json b/js/smoke/tests/deno/deno.json index 028882843..b41938eca 100644 --- a/js/smoke/tests/deno/deno.json +++ b/js/smoke/tests/deno/deno.json @@ -1,4 +1,5 @@ { + "nodeModulesDir": "auto", "npmDependencies": { "@next/env": "14.2.3", "eventsource-parser": "1.1.2", @@ -12,15 +13,26 @@ }, "imports": { "@vercel/functions": "npm:@vercel/functions@^3.3.0", + "async_hooks": "node:async_hooks", + "child_process": "node:child_process", + "crypto": "node:crypto", "eventsource-parser": "npm:eventsource-parser@^3.0.6", + "fs": "node:fs", + "fs/promises": "node:fs/promises", "mustache": "npm:mustache@^4.2.0", "uuid": "npm:uuid@^13.0.0", + "os": "node:os", + "path": "node:path", + "simple-git": "npm:simple-git@^3.21.0", "zod": "npm:zod@^4.1.12", "nunjucks": "npm:nunjucks@^3.2.4", + "braintrust": "./build/braintrust/dist/index.mjs", + "util": "node:util", + "zlib": "node:zlib", "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" }, "tasks": { - "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,$BRAINTRUST_BUILD_DIR --allow-net shared_suite_test.ts", - "test:legacy": "deno test --config ./deno.json --allow-env --allow-read=.,$BRAINTRUST_BUILD_DIR --allow-net span_test.ts" + "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts", + "test:legacy": "deno test --config ./deno.json --allow-env --allow-read=.,./build --allow-net span_test.ts" } } diff --git a/js/smoke/tests/deno/deno.lock b/js/smoke/tests/deno/deno.lock index 3e02533ca..43c96d0ee 100644 --- a/js/smoke/tests/deno/deno.lock +++ b/js/smoke/tests/deno/deno.lock @@ -1,12 +1,14 @@ { - "version": "4", + "version": "5", "specifiers": { "jsr:@std/assert@^1.0.14": "1.0.16", "jsr:@std/internal@^1.0.12": "1.0.12", + "npm:@types/node@*": "24.2.0", "npm:@vercel/functions@^3.3.0": "3.3.4", "npm:eventsource-parser@^3.0.6": "3.0.6", "npm:mustache@^4.2.0": "4.2.0", "npm:nunjucks@^3.2.4": "3.2.4", + "npm:simple-git@^3.21.0": "3.30.0", "npm:uuid@13": "13.0.0", "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@4.1.13", "npm:zod@^4.1.12": "4.1.13" @@ -23,6 +25,21 @@ } }, "npm": { + "@kwsites/file-exists@1.1.1": { + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dependencies": [ + "debug" + ] + }, + "@kwsites/promise-deferred@1.1.1": { + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + }, + "@types/node@24.2.0": { + "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==", + "dependencies": [ + "undici-types" + ] + }, "@vercel/functions@3.3.4": { "integrity": "sha512-IoP8Xfr1QeCm+Dv5od3bfPiw/VgLKsA7IBd/88M/Wr421HdbH4b6bW5z8CTxiz1QRpalrPFZcLdMdxu+2hAjZg==", "dependencies": [ @@ -41,11 +58,21 @@ "commander@5.1.0": { "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms" + ] + }, "eventsource-parser@3.0.6": { "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "mustache@4.2.0": { - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": true }, "nunjucks@3.2.4": { "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", @@ -56,8 +83,20 @@ ], "bin": true }, + "simple-git@3.30.0": { + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "dependencies": [ + "@kwsites/file-exists", + "@kwsites/promise-deferred", + "debug" + ] + }, + "undici-types@7.10.0": { + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" + }, "uuid@13.0.0": { - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==" + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "bin": true }, "zod-to-json-schema@3.25.0_zod@4.1.13": { "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", @@ -78,6 +117,7 @@ "npm:eventsource-parser@^3.0.6", "npm:mustache@^4.2.0", "npm:nunjucks@^3.2.4", + "npm:simple-git@^3.21.0", "npm:uuid@13", "npm:zod-to-json-schema@^3.25.0", "npm:zod@^4.1.12" diff --git a/js/smoke/tests/deno/shared_suite_test.ts b/js/smoke/tests/deno/shared_suite_test.ts index 8e6a337eb..666cf2b1a 100644 --- a/js/smoke/tests/deno/shared_suite_test.ts +++ b/js/smoke/tests/deno/shared_suite_test.ts @@ -14,19 +14,12 @@ import { runPromptTemplatingTests, type TestResult, } from "../../shared/dist/index.mjs"; +import * as braintrust from "braintrust"; /** * Run the shared test suites in Deno environment */ export async function runSharedTestSuites() { - const buildDir = Deno.env.get("BRAINTRUST_BUILD_DIR"); - if (!buildDir) { - throw new Error("BRAINTRUST_BUILD_DIR environment variable is not set"); - } - - // Dynamically import Braintrust from the build directory - // Import as namespace to get all exports for verification - const braintrust = await import(`file://${buildDir}`); const { initLogger, _exportsForTestingOnly } = braintrust; // Setup test environment diff --git a/js/smoke/tests/deno/span_test.ts b/js/smoke/tests/deno/span_test.ts index c546e2cea..8ed4a26ff 100644 --- a/js/smoke/tests/deno/span_test.ts +++ b/js/smoke/tests/deno/span_test.ts @@ -12,13 +12,8 @@ import { * ie. BRAINTRUST_BUILD_DIR=./package/dist/index.mjs */ export async function runBrowserLoggerSmokeTest() { - const buildDir = Deno.env.get("BRAINTRUST_BUILD_DIR"); - if (!buildDir) { - throw new Error("BRAINTRUST_BUILD_DIR environment variable is not set"); - } - const { initLogger, _exportsForTestingOnly, Prompt } = await import( - `file://${Deno.env.get("BRAINTRUST_BUILD_DIR")}` + "braintrust" ); const events = await runSpanSmokeTest({ From 8d2e5e2ea538b5b62e31030b21c3c96fd50f5eea Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 21:12:43 -0800 Subject: [PATCH 13/57] initial isomorph commit --- js/src/browser-config.ts | 11 ++++++++++ js/src/isomorph.ts | 19 ++++++++++++++++++ js/src/logger.ts | 6 ++---- js/src/node.ts | 4 ++++ js/src/template/renderer.ts | 7 +++---- js/tsup.config.ts | 40 ------------------------------------- 6 files changed, 39 insertions(+), 48 deletions(-) diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts index 86c4c6e99..0f0883b81 100644 --- a/js/src/browser-config.ts +++ b/js/src/browser-config.ts @@ -30,6 +30,17 @@ export function configureBrowser() { return process.env[name]; }; + iso.renderNunjucksString = () => { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); + }; + iso.lintNunjucksTemplate = () => { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); + }; + // Implement browser-compatible hash function using a simple hash algorithm iso.hash = (data: string): string => { // Simple hash function for browser compatibility diff --git a/js/src/isomorph.ts b/js/src/isomorph.ts index 0095e7c5c..5e4b4aca4 100644 --- a/js/src/isomorph.ts +++ b/js/src/isomorph.ts @@ -38,6 +38,15 @@ export interface Common { getCallerLocation: () => CallerLocation | undefined; newAsyncLocalStorage: () => IsoAsyncLocalStorage; processOn: (event: string, handler: (code: any) => void) => void; + renderNunjucksString: ( + template: string, + variables: Record, + strict?: boolean, + ) => string; + lintNunjucksTemplate: ( + template: string, + context: Record, + ) => void; // hash a string. not guaranteed to be crypto safe. hash?: (data: string) => string; @@ -74,6 +83,16 @@ const iso: Common = { getCallerLocation: () => undefined, newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(), processOn: (_0, _1) => {}, + renderNunjucksString: () => { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); + }, + lintNunjucksTemplate: () => { + throw new Error( + "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", + ); + }, basename: (filepath: string) => filepath.split(/[\\/]/).pop() || filepath, writeln: (text: string) => console.log(text), }; diff --git a/js/src/logger.ts b/js/src/logger.ts index c4627ffb4..5be0d8c5a 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -77,7 +77,6 @@ import { renderTemplateContent, type TemplateFormat, } from "./template/renderer"; -import { renderNunjucksString } from "./template/nunjucks-env"; import { z, ZodError } from "zod/v3"; import { @@ -99,7 +98,6 @@ import { runCatchFinally, } from "./util"; import { lintTemplate as lintMustacheTemplate } from "./template/mustache-utils"; -import { lintTemplate as lintNunjucksTemplate } from "./template/nunjucks-utils"; import { prettifyXact } from "../util/index"; // Context management interfaces @@ -6408,9 +6406,9 @@ function renderTemplatedObject( const strict = !!options.strict; if (options.templateFormat === "nunjucks") { if (strict) { - lintNunjucksTemplate(obj, args); + iso.lintNunjucksTemplate(obj, args); } - return renderNunjucksString(obj, args, strict); + return iso.renderNunjucksString(obj, args, strict); } if (options.templateFormat === "mustache") { if (strict) { diff --git a/js/src/node.ts b/js/src/node.ts index 3ec477263..6433428d0 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -9,6 +9,8 @@ import iso from "./isomorph"; import { getRepoInfo, getPastNAncestors } from "./gitutil"; import { getCallerLocation } from "./stackutil"; import { _internalSetInitialState } from "./logger"; +import { renderNunjucksString } from "./template/nunjucks-env"; +import { lintTemplate as lintNunjucksTemplate } from "./template/nunjucks-utils"; import { promisify } from "util"; import * as zlib from "zlib"; @@ -21,6 +23,8 @@ export function configureNode() { iso.processOn = (event: string, handler: (code: any) => void) => { process.on(event, handler); }; + iso.renderNunjucksString = renderNunjucksString; + iso.lintNunjucksTemplate = lintNunjucksTemplate; iso.basename = path.basename; iso.writeln = (text: string) => process.stdout.write(text + "\n"); iso.pathJoin = path.join; diff --git a/js/src/template/renderer.ts b/js/src/template/renderer.ts index 1c6f71dbd..552d1632d 100644 --- a/js/src/template/renderer.ts +++ b/js/src/template/renderer.ts @@ -1,7 +1,6 @@ import Mustache from "mustache"; import { lintTemplate as lintMustacheTemplate } from "./mustache-utils"; -import { lintTemplate as lintNunjucksTemplate } from "./nunjucks-utils"; -import { renderNunjucksString } from "./nunjucks-env"; +import iso from "../isomorph"; export type TemplateFormat = "mustache" | "nunjucks" | "none"; @@ -26,9 +25,9 @@ export function renderTemplateContent( const templateFormat = parseTemplateFormat(options.templateFormat); if (templateFormat === "nunjucks") { if (strict) { - lintNunjucksTemplate(template, variables); + iso.lintNunjucksTemplate(template, variables); } - return renderNunjucksString(template, variables, strict); + return iso.renderNunjucksString(template, variables, strict); } else if (templateFormat === "mustache") { if (strict) { lintMustacheTemplate(template, variables); diff --git a/js/tsup.config.ts b/js/tsup.config.ts index 566f3645b..edbd0ffd1 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -1,5 +1,4 @@ import { defineConfig } from "tsup"; -import path from "node:path"; export default defineConfig([ { @@ -21,45 +20,6 @@ export default defineConfig([ format: ["cjs", "esm"], outDir: "dist", external: ["zod", "nunjucks"], - esbuildPlugins: [ - { - name: "browser-stubs", - setup(build) { - const resolveTo = (p: string) => ({ - path: p, - namespace: "file", - }); - - build.onResolve({ filter: /^\.\/template\/nunjucks-env$/ }, () => - resolveTo( - path.join(process.cwd(), "src/template/nunjucks-env.browser.ts"), - ), - ); - build.onResolve({ filter: /^\.\/template\/nunjucks-utils$/ }, () => - resolveTo( - path.join( - process.cwd(), - "src/template/nunjucks-utils.browser.ts", - ), - ), - ); - - build.onResolve({ filter: /^\.\/nunjucks-env$/ }, (args) => - resolveTo( - path.join(path.dirname(args.importer), "nunjucks-env.browser.ts"), - ), - ); - build.onResolve({ filter: /^\.\/nunjucks-utils$/ }, (args) => - resolveTo( - path.join( - path.dirname(args.importer), - "nunjucks-utils.browser.ts", - ), - ), - ); - }, - }, - ], dts: { // Split DTS generation to reduce memory usage compilerOptions: { From 7da0b6f7e2056293219c78c21d3eb5e0e2d0bebc Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 21:29:04 -0800 Subject: [PATCH 14/57] fix nunjucks prompt tests and add a bit of cleanup --- js/src/prompt.test.ts | 86 ++++++++++++++++- js/src/template/nunjucks-env.ts | 7 +- js/src/template/nunjucks-render.test.ts | 12 +-- js/src/template/nunjucks-utils.ts | 7 +- pnpm-lock.yaml | 123 +++--------------------- 5 files changed, 111 insertions(+), 124 deletions(-) diff --git a/js/src/prompt.test.ts b/js/src/prompt.test.ts index 53c6e7af4..6b468ec64 100644 --- a/js/src/prompt.test.ts +++ b/js/src/prompt.test.ts @@ -1,7 +1,10 @@ -import { describe, test, expect } from "vitest"; +import { describe, test, expect, vi } from "vitest"; +import { configureNode } from "./node"; import { Prompt } from "./logger"; import { type PromptDataType as PromptData } from "./generated_types"; +configureNode(); + describe("prompt strict mode", () => { test("strict mode", () => { for (const strict of [true, false]) { @@ -257,3 +260,84 @@ describe("prompt template_format", () => { expect(result.prompt).toBe("Complete this: Hello"); }); }); + +describe("prompt template_format (unconfigured/browser-like)", () => { + test("throws unsupported error for nunjucks template_format when not configured", async () => { + vi.resetModules(); + const { Prompt: UnconfiguredPrompt } = await import("./logger"); + + const prompt = new UnconfiguredPrompt( + { + id: "1", + _xact_id: "xact_123", + created: "2023-10-01T00:00:00Z", + project_id: "project_123", + prompt_session_id: "session_123", + name: "test", + slug: "test", + prompt_data: { + template_format: "nunjucks", + options: { + model: "gpt-4o", + }, + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "Hello {% if name %}{{name}}{% endif %}", + }, + ], + }, + }, + }, + {}, + true, + ); + + expect(() => prompt.build({ name: "World" })).toThrowError( + /Nunjucks templating is not supported in this build/, + ); + }); + + test("throws unsupported error after configureBrowser()", async () => { + vi.resetModules(); + const { configureBrowser } = await import("./browser-config"); + const { Prompt: BrowserConfiguredPrompt } = await import("./logger"); + + configureBrowser(); + + const prompt = new BrowserConfiguredPrompt( + { + id: "1", + _xact_id: "xact_123", + created: "2023-10-01T00:00:00Z", + project_id: "project_123", + prompt_session_id: "session_123", + name: "test", + slug: "test", + prompt_data: { + template_format: "nunjucks", + options: { + model: "gpt-4o", + }, + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "Hello {% if name %}{{name}}{% endif %}", + }, + ], + }, + }, + }, + {}, + true, + ); + + expect(() => prompt.build({ name: "World" })).toThrowError( + /Nunjucks templating is not supported in this build/, + ); + }); +}); diff --git a/js/src/template/nunjucks-env.ts b/js/src/template/nunjucks-env.ts index 82a4951fd..efb3c1ab8 100644 --- a/js/src/template/nunjucks-env.ts +++ b/js/src/template/nunjucks-env.ts @@ -17,7 +17,10 @@ const nunjucksStrictEnv = new SyncLazyValue(() => createNunjucksEnv(true), ); -export function getNunjucksEnv(strict = false): NunjucksEnvironment { +export function getNunjucksEnv(options?: { + strict?: boolean; +}): NunjucksEnvironment { + const strict = options?.strict ?? false; return strict ? nunjucksStrictEnv.get() : nunjucksEnv.get(); } @@ -27,7 +30,7 @@ export function renderNunjucksString( strict = false, ): string { try { - return getNunjucksEnv(strict).renderString(template, variables); + return getNunjucksEnv({ strict }).renderString(template, variables); } catch (error) { if ( error instanceof Error && diff --git a/js/src/template/nunjucks-render.test.ts b/js/src/template/nunjucks-render.test.ts index 91b896ed1..e6dd85ae1 100644 --- a/js/src/template/nunjucks-render.test.ts +++ b/js/src/template/nunjucks-render.test.ts @@ -1,19 +1,13 @@ import { describe, test, expect } from "vitest"; import { lintTemplate } from "./nunjucks-utils"; -import { nunjucks } from "./nunjucks"; +import { getNunjucksEnv } from "./nunjucks-env"; function getEnv() { - return new nunjucks.Environment(null, { - autoescape: true, - throwOnUndefined: false, - }); + return getNunjucksEnv({ strict: false }); } function getStrictEnv() { - return new nunjucks.Environment(null, { - autoescape: true, - throwOnUndefined: true, - }); + return getNunjucksEnv({ strict: true }); } describe("nunjucks rendering", () => { diff --git a/js/src/template/nunjucks-utils.ts b/js/src/template/nunjucks-utils.ts index 048bb210f..7afd682cd 100644 --- a/js/src/template/nunjucks-utils.ts +++ b/js/src/template/nunjucks-utils.ts @@ -1,9 +1,6 @@ -import * as nunjucks from "nunjucks"; +import { getNunjucksEnv } from "./nunjucks-env"; export function lintTemplate(template: string, context: any): void { - const env = new nunjucks.Environment(null, { - autoescape: true, - throwOnUndefined: true, - }); + const env = getNunjucksEnv({ strict: true }); env.renderString(template, context); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1cd8ef9c..f1a8aae65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 2.6.6(@types/node@20.10.5)(typescript@5.3.3) tsup: specifier: ^8.3.5 - version: 8.3.5(postcss@8.5.6)(typescript@5.3.3)(yaml@2.8.2) + version: 8.3.5(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2) typedoc: specifier: ^0.25.13 version: 0.25.13(typescript@5.3.3) @@ -110,7 +110,7 @@ importers: version: link:../../js tsup: specifier: ^8.5.0 - version: 8.5.1(postcss@8.5.6)(typescript@5.5.4)(yaml@2.8.2) + version: 8.5.1(postcss@8.5.6)(tsx@4.21.0)(typescript@5.5.4)(yaml@2.8.2) typedoc: specifier: ^0.28.15 version: 0.28.15(typescript@5.5.4) @@ -135,7 +135,7 @@ importers: version: 20.10.5 tsup: specifier: ^8.3.5 - version: 8.3.5(postcss@8.5.6)(typescript@5.3.3)(yaml@2.8.2) + version: 8.3.5(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2) typescript: specifier: ^5.3.3 version: 5.3.3 @@ -155,34 +155,6 @@ importers: specifier: ^3.23.8 version: 3.25.76 - internal/golden/ai-sdk-v5: - dependencies: - '@ai-sdk/anthropic': - specifier: ^2.0.39 - version: 2.0.57(zod@3.25.76) - '@ai-sdk/openai': - specifier: ^2.0.56 - version: 2.0.89(zod@3.25.76) - ai: - specifier: ^5.0.116 - version: 5.0.121(zod@3.25.76) - braintrust: - specifier: link:../../../js - version: link:../../../js - zod: - specifier: ^3.23.8 - version: 3.25.76 - devDependencies: - '@types/node': - specifier: ^20.0.0 - version: 20.19.16 - tsx: - specifier: ^4.7.0 - version: 4.21.0 - typescript: - specifier: ^5.3.0 - version: 5.5.4 - js: dependencies: '@ai-sdk/provider': @@ -405,30 +377,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/anthropic@2.0.57': - resolution: {integrity: sha512-DREpYqW2pylgaj69gZ+K8u92bo9DaMgFdictYnY+IwYeY3bawQ4zI7l/o1VkDsBDljAx8iYz5lPURwVZNu+Xpg==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/gateway@2.0.27': - resolution: {integrity: sha512-8hbezMsGa0crSt7/DKjkYL1UbbJJW/UFxTfhmf5qcIeYeeWG4dTNmm+DWbUdIsTaWvp59KC4eeC9gYXBbTHd7w==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@3.0.11': resolution: {integrity: sha512-gLrgNXA95wdo/zAlA0miX/SJEYKSYCHg+e0Y/uQeABLScZAMjPw3jWaeANta/Db1T4xfi8cBvY3nnV8Pa27z+w==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/openai@2.0.89': - resolution: {integrity: sha512-4+qWkBCbL9HPKbgrUO/F2uXZ8GqrYxHa8SWEYIzxEJ9zvWw3ISr3t1/27O1i8MGSym+PzEyHBT48EV4LAwWaEw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@1.0.0': resolution: {integrity: sha512-Akq7MmGQII8xAuoVjJns/n/2BTUrF6qaXIj/3nEuXk/hPSdETlLWRSrjrTmLpte1VIPE5ecNzTALST+6nz47UQ==} engines: {node: '>=18'} @@ -444,12 +398,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@3.0.20': - resolution: {integrity: sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@4.0.4': resolution: {integrity: sha512-VxhX0B/dWGbpNHxrKCWUAJKXIXV015J4e7qYjdIU9lLWeptk0KMLGcqkB4wFxff5Njqur8dt8wRi1MN9lZtDqg==} engines: {node: '>=18'} @@ -468,10 +416,6 @@ packages: resolution: {integrity: sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==} engines: {node: '>=18'} - '@ai-sdk/provider@2.0.1': - resolution: {integrity: sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng==} - engines: {node: '>=18'} - '@ai-sdk/provider@3.0.2': resolution: {integrity: sha512-HrEmNt/BH/hkQ7zpi2o6N3k1ZR1QTb7z85WYhYygiTxOQuaml4CMtHCWRbric5WPU+RNsYI7r1EpyVQMKO1pYw==} engines: {node: '>=18'} @@ -2389,12 +2333,6 @@ packages: zod: optional: true - ai@5.0.121: - resolution: {integrity: sha512-3iYPdARKGLryC/7OA9RgBUaym1gynvWS7UPy8NwoRNCKP52lshldtHB5xcEfVviw7liWH2zJlW9yEzsDglcIEQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - ai@6.0.27: resolution: {integrity: sha512-a4ToMt5+4xOzHuYdoTy2GQXuNa2/Tpuhxfs5QESHtEV/Vf2HAzSwmTwikrIs8CDKPuMWV1I9YqAvaN5xexMCiQ==} engines: {node: '>=18'} @@ -5510,19 +5448,6 @@ snapshots: '@ai-sdk/provider-utils': 3.0.12(zod@3.25.76) zod: 3.25.76 - '@ai-sdk/anthropic@2.0.57(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 2.0.1 - '@ai-sdk/provider-utils': 3.0.20(zod@3.25.76) - zod: 3.25.76 - - '@ai-sdk/gateway@2.0.27(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 2.0.1 - '@ai-sdk/provider-utils': 3.0.20(zod@3.25.76) - '@vercel/oidc': 3.1.0 - zod: 3.25.76 - '@ai-sdk/gateway@3.0.11(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.2 @@ -5530,12 +5455,6 @@ snapshots: '@vercel/oidc': 3.1.0 zod: 3.25.76 - '@ai-sdk/openai@2.0.89(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 2.0.1 - '@ai-sdk/provider-utils': 3.0.20(zod@3.25.76) - zod: 3.25.76 - '@ai-sdk/provider-utils@1.0.0(zod@4.2.1)': dependencies: '@ai-sdk/provider': 0.0.11 @@ -5552,13 +5471,6 @@ snapshots: eventsource-parser: 3.0.6 zod: 3.25.76 - '@ai-sdk/provider-utils@3.0.20(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 2.0.1 - '@standard-schema/spec': 1.1.0 - eventsource-parser: 3.0.6 - zod: 3.25.76 - '@ai-sdk/provider-utils@4.0.4(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.2 @@ -5578,10 +5490,6 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/provider@2.0.1': - dependencies: - json-schema: 0.4.0 - '@ai-sdk/provider@3.0.2': dependencies: json-schema: 0.4.0 @@ -7799,14 +7707,6 @@ snapshots: - solid-js - vue - ai@5.0.121(zod@3.25.76): - dependencies: - '@ai-sdk/gateway': 2.0.27(zod@3.25.76) - '@ai-sdk/provider': 2.0.1 - '@ai-sdk/provider-utils': 3.0.20(zod@3.25.76) - '@opentelemetry/api': 1.9.0 - zod: 3.25.76 - ai@6.0.27(zod@3.25.76): dependencies: '@ai-sdk/gateway': 3.0.11(zod@3.25.76) @@ -10387,6 +10287,14 @@ snapshots: tsx: 3.14.0 yaml: 2.8.2 + postcss-load-config@6.0.1(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + postcss: 8.5.6 + tsx: 4.21.0 + yaml: 2.8.2 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -11049,7 +10957,7 @@ snapshots: - tsx - yaml - tsup@8.3.5(postcss@8.5.6)(typescript@5.3.3)(yaml@2.8.2): + tsup@8.3.5(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.24.2) cac: 6.7.14 @@ -11059,7 +10967,7 @@ snapshots: esbuild: 0.24.2 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.35.0 source-map: 0.8.0-beta.0 @@ -11104,7 +11012,7 @@ snapshots: - tsx - yaml - tsup@8.5.1(postcss@8.5.6)(typescript@5.5.4)(yaml@2.8.2): + tsup@8.5.1(postcss@8.5.6)(tsx@4.21.0)(typescript@5.5.4)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.27.0) cac: 6.7.14 @@ -11115,7 +11023,7 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.35.0 source-map: 0.7.6 @@ -11146,6 +11054,7 @@ snapshots: get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 + optional: true turbo-darwin-64@2.5.6: optional: true From 91f012dc561445ed5e1c0f0052e97f8e851e2124 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 15 Jan 2026 21:36:08 -0800 Subject: [PATCH 15/57] only include configure node in the test that needs it --- js/src/prompt.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/src/prompt.test.ts b/js/src/prompt.test.ts index 6b468ec64..c822a39d7 100644 --- a/js/src/prompt.test.ts +++ b/js/src/prompt.test.ts @@ -1,10 +1,8 @@ -import { describe, test, expect, vi } from "vitest"; +import { beforeAll, describe, test, expect, vi } from "vitest"; import { configureNode } from "./node"; import { Prompt } from "./logger"; import { type PromptDataType as PromptData } from "./generated_types"; -configureNode(); - describe("prompt strict mode", () => { test("strict mode", () => { for (const strict of [true, false]) { @@ -136,6 +134,10 @@ function testPromptBuild({ } describe("prompt template_format", () => { + beforeAll(() => { + configureNode(); + }); + test("uses template_format when building", () => { const prompt = new Prompt( { From 9159c37bb9321259b676924caf0b26746e7aa870 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 09:50:32 -0800 Subject: [PATCH 16/57] refactor cloudflare worker tests and add more information on the test results --- js/smoke/tests/cloudflare-worker/package.json | 2 +- js/smoke/tests/cloudflare-worker/run-test.mjs | 199 ++++++++++++------ 2 files changed, 135 insertions(+), 66 deletions(-) diff --git a/js/smoke/tests/cloudflare-worker/package.json b/js/smoke/tests/cloudflare-worker/package.json index b7f24aac8..0cc781f88 100644 --- a/js/smoke/tests/cloudflare-worker/package.json +++ b/js/smoke/tests/cloudflare-worker/package.json @@ -8,7 +8,7 @@ "test:braintrust-node-compat": "node run-test.mjs --config wrangler.node.toml", "test:braintrust-browser-node-compat": "node run-test.mjs --config wrangler.browser-node-compat.toml", "test:braintrust-browser-no-compat": "node run-test.mjs --config wrangler.browser.toml", - "test:braintrust-no-compat": "node run-test.mjs --config wrangler.node-no-compat.toml --expect-start-fail", + "test:braintrust-no-compat": "node run-test.mjs --config wrangler.node-no-compat.toml", "backup": "npx tsx ../../backup-and-restore.ts backup", "restore": "npx tsx ../../backup-and-restore.ts restore", "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" diff --git a/js/smoke/tests/cloudflare-worker/run-test.mjs b/js/smoke/tests/cloudflare-worker/run-test.mjs index 66e3cd7a1..b03daa1fa 100644 --- a/js/smoke/tests/cloudflare-worker/run-test.mjs +++ b/js/smoke/tests/cloudflare-worker/run-test.mjs @@ -1,4 +1,5 @@ import { spawn, execSync } from "node:child_process"; +import { parseArgs } from "node:util"; const PORT = 8799; const MAX_RETRIES = 20; @@ -6,23 +7,75 @@ const RETRY_DELAY_MS = 250; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); -function parseArgs(argv) { - const out = {}; - for (let i = 0; i < argv.length; i++) { - const a = argv[i]; - if (a === "--config") { - const v = argv[i + 1]; - if (!v) throw new Error("Missing value for --config"); - out.config = v; - i++; - continue; - } - if (a === "--expect-start-fail") { - out.expectStartFail = true; - continue; +const ENTRYPOINT = { + node: "braintrust", + browser: "braintrust/browser", +}; + +const COMPAT = { + enabled: "nodejs_compat_v2", + disabled: "no nodejs_compat", +}; + +const VARIANTS = { + "node-node-compat": { + config: "wrangler.node.toml", + entrypoint: ENTRYPOINT.node, + nodejsCompat: true, + }, + "browser-no-compat": { + config: "wrangler.browser.toml", + entrypoint: ENTRYPOINT.browser, + nodejsCompat: false, + }, + "browser-node-compat": { + config: "wrangler.browser-node-compat.toml", + entrypoint: ENTRYPOINT.browser, + nodejsCompat: true, + }, + "node-no-compat": { + config: "wrangler.node-no-compat.toml", + entrypoint: ENTRYPOINT.node, + nodejsCompat: false, + }, +}; + +function shouldExpectStartupFailure(variant) { + // Node entrypoint requires nodejs_compat to access Node.js APIs + return variant.entrypoint === ENTRYPOINT.node && !variant.nodejsCompat; +} + +function displayTestResults(testResult, testLabel) { + console.log(`\n=== ${testLabel} ===\n`); + + // Display individual test results if available + if (testResult.results && testResult.results.length > 0) { + console.log( + `Tests: ${testResult.passedTests}/${testResult.totalTests} passed\n`, + ); + + for (const result of testResult.results) { + const status = result.success ? "✓" : "✗"; + const statusColor = result.success ? "\x1b[32m" : "\x1b[31m"; + const resetColor = "\x1b[0m"; + + console.log(`${statusColor}${status}${resetColor} ${result.name}`); + + if (!result.success && result.error) { + console.log(` Error: ${result.error}`); + } } + } else { + console.log(JSON.stringify(testResult, null, 2)); } - return out; +} + +const VARIANTS_BY_CONFIG = Object.fromEntries( + Object.entries(VARIANTS).map(([id, v]) => [v.config, { id, ...v }]), +); + +function labelForVariant(variant) { + return `${variant.nodejsCompat ? COMPAT.enabled : COMPAT.disabled} + ${variant.entrypoint}`; } function killPort(port) { @@ -44,21 +97,25 @@ async function waitForServer() { return false; } -async function runWranglerTest({ config, label, expectStartFail = false }) { +async function runVariant(variant) { + const testLabel = labelForVariant(variant); + const wranglerConfig = variant.config; + const startupShouldFail = shouldExpectStartupFailure(variant); + killPort(PORT); const wrangler = spawn( "npx", - ["wrangler", "dev", "--config", config, "--port", String(PORT)], + ["wrangler", "dev", "--config", wranglerConfig, "--port", String(PORT)], { stdio: ["ignore", "pipe", "pipe"], shell: true, }, ); - let output = ""; - wrangler.stdout.on("data", (d) => (output += d)); - wrangler.stderr.on("data", (d) => (output += d)); + let wranglerOutput = ""; + wrangler.stdout.on("data", (data) => (wranglerOutput += data)); + wrangler.stderr.on("data", (data) => (wranglerOutput += data)); const killWrangler = () => { return new Promise((resolve) => { @@ -76,68 +133,80 @@ async function runWranglerTest({ config, label, expectStartFail = false }) { }); }; - let exitCode = 1; - try { - if (!(await waitForServer())) { - if (expectStartFail) { - console.log(`\n=== ${label} (expected startup failure) ===\n`); - console.log(output.trim() ? output : "(no output)"); + const serverStartedSuccessfully = await waitForServer(); + + if (!serverStartedSuccessfully) { + if (startupShouldFail) { + console.log(`\n=== ${testLabel} (expected startup failure) ===\n`); + console.log(wranglerOutput.trim() || "(no output)"); await killWrangler(); return 0; } - console.error(`[${label}] Server failed to start:\n`, output); + console.error(`[${testLabel}] Server failed to start:\n`, wranglerOutput); await killWrangler(); return 1; } - const response = await fetch(`http://localhost:${PORT}/test`); - const result = await response.json(); + const testResponse = await fetch(`http://localhost:${PORT}/test`); + const testResult = await testResponse.json(); - console.log(`\n=== ${label} ===\n`); - console.log(JSON.stringify(result, null, 2)); - exitCode = result.success ? 0 : 1; + displayTestResults(testResult, testLabel); + + const exitCode = testResult.success ? 0 : 1; + await killWrangler(); + return exitCode; } catch (error) { - console.error(`[${label}] Error:`, error.message, "\n", output); - exitCode = 1; + console.error(`[${testLabel}] Error:`, error.message, "\n", wranglerOutput); + await killWrangler(); + return 1; } - - await killWrangler(); - return exitCode; } async function main() { - const args = parseArgs(process.argv.slice(2)); - if (args.config) { - const label = - args.config === "wrangler.node.toml" - ? "nodejs_compat_v2 + braintrust" - : args.config === "wrangler.browser.toml" - ? "no compatibility_flags + braintrust/browser" - : args.config === "wrangler.browser-node-compat.toml" - ? "nodejs_compat_v2 + braintrust/browser" - : args.config === "wrangler.node-no-compat.toml" - ? "no compatibility_flags + braintrust" - : args.config; - const code = await runWranglerTest({ - config: args.config, - label, - expectStartFail: !!args.expectStartFail, - }); - process.exit(code); + const { values } = parseArgs({ + args: process.argv.slice(2), + options: { + config: { type: "string" }, + variant: { type: "string" }, + }, + allowPositionals: false, + }); + + const requestedConfig = values.config; + const requestedVariantId = values.variant; + + // If a specific variant/config was requested, run only that one + if (requestedConfig || requestedVariantId) { + const variant = requestedVariantId + ? VARIANTS[requestedVariantId] + : VARIANTS_BY_CONFIG[requestedConfig]; + + if (!variant) { + const availableVariants = Object.keys(VARIANTS).sort().join(", "); + throw new Error( + `Unknown variant/config. Use --variant <${availableVariants}> or --config .`, + ); + } + + const exitCode = await runVariant(variant); + process.exit(exitCode); } - const a = await runWranglerTest({ - config: "wrangler.node.toml", - label: "nodejs_compat_v2 + braintrust", - }); - if (a !== 0) process.exit(a); + // Run default test suite (both node and browser variants) + const defaultTestSuite = [ + VARIANTS["node-node-compat"], + VARIANTS["browser-no-compat"], + ]; - const b = await runWranglerTest({ - config: "wrangler.browser.toml", - label: "no compatibility_flags + braintrust/browser", - }); - process.exit(b); + for (const variant of defaultTestSuite) { + const exitCode = await runVariant(variant); + if (exitCode !== 0) { + process.exit(exitCode); + } + } + + process.exit(0); } main().catch((err) => { From 07135b306f02fc199b7ddc01d859867246d6b6f5 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 10:03:32 -0800 Subject: [PATCH 17/57] modify vite react hono cloudflare test to use braintrust/browser --- js/smoke/tests/cloudflare-worker/src/index.ts | 1 - js/smoke/tests/vite-react-hono/src/worker/index.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 js/smoke/tests/cloudflare-worker/src/index.ts diff --git a/js/smoke/tests/cloudflare-worker/src/index.ts b/js/smoke/tests/cloudflare-worker/src/index.ts deleted file mode 100644 index 5531f9e7a..000000000 --- a/js/smoke/tests/cloudflare-worker/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./node"; diff --git a/js/smoke/tests/vite-react-hono/src/worker/index.ts b/js/smoke/tests/vite-react-hono/src/worker/index.ts index 686a276f8..7667a90f1 100644 --- a/js/smoke/tests/vite-react-hono/src/worker/index.ts +++ b/js/smoke/tests/vite-react-hono/src/worker/index.ts @@ -14,7 +14,7 @@ import { type TestResult, } from "../../../../shared/dist/index.mjs"; -import * as braintrust from "braintrust"; +import * as braintrust from "braintrust/browser"; const { initLogger, _exportsForTestingOnly } = braintrust; const app = new Hono<{ Bindings: Env }>(); From bb237166e92247475c47b7da67fe90b79ad09b4e Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 10:15:38 -0800 Subject: [PATCH 18/57] modify isomorph configuration, cleanup --- js/smoke/shared/src/suites/import-verification.ts | 13 ------------- js/smoke/shared/src/suites/prompt-templating.ts | 2 +- js/src/browser-config.ts | 5 ----- js/src/isomorph.ts | 12 +++++++----- js/src/logger.ts | 5 +---- js/src/node.ts | 15 +++++++++++---- js/src/template/renderer.ts | 5 +---- 7 files changed, 21 insertions(+), 36 deletions(-) diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index 1d1127c8c..23c7b3043 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -150,7 +150,6 @@ export async function testCoreLoggingExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -184,7 +183,6 @@ export async function testDatasetExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -221,7 +219,6 @@ export async function testPromptExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -266,7 +263,6 @@ export async function testExperimentExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -337,7 +333,6 @@ export async function testEvalExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -380,7 +375,6 @@ export async function testTracingExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -430,7 +424,6 @@ export async function testClientWrapperExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -474,7 +467,6 @@ export async function testUtilityExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -508,7 +500,6 @@ export async function testFunctionExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -545,7 +536,6 @@ export async function testFramework2Exports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -576,7 +566,6 @@ export async function testIDGeneratorExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -610,7 +599,6 @@ export async function testTestingExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } @@ -644,7 +632,6 @@ export async function testStateManagementExports( success: false, testName, error: error as Error, - message: error instanceof Error ? error.message : String(error), }; } } diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index 0e82d3a2e..bf4e4e50e 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -191,7 +191,7 @@ export async function testNunjucksTemplate( assertEqual( actual, expected, - `Nunjucks template should render loop correctly (expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)})`, + `Nunjucks template should render loop correctly`, ); } catch (assertError) { return { diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts index 0f0883b81..3b69e2588 100644 --- a/js/src/browser-config.ts +++ b/js/src/browser-config.ts @@ -35,11 +35,6 @@ export function configureBrowser() { "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", ); }; - iso.lintNunjucksTemplate = () => { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); - }; // Implement browser-compatible hash function using a simple hash algorithm iso.hash = (data: string): string => { diff --git a/js/src/isomorph.ts b/js/src/isomorph.ts index 5e4b4aca4..1828ad60d 100644 --- a/js/src/isomorph.ts +++ b/js/src/isomorph.ts @@ -74,6 +74,13 @@ export interface Common { // zlib (promisified and type-erased). gunzip?: (data: any) => Promise; gzip?: (data: any) => Promise; + + // Nunjucks template rendering (lints if strict is true) + renderNunjucksString: ( + template: string, + variables: Record, + options?: { strict?: boolean }, + ) => string; } const iso: Common = { @@ -88,11 +95,6 @@ const iso: Common = { "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", ); }, - lintNunjucksTemplate: () => { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); - }, basename: (filepath: string) => filepath.split(/[\\/]/).pop() || filepath, writeln: (text: string) => console.log(text), }; diff --git a/js/src/logger.ts b/js/src/logger.ts index 5be0d8c5a..69449dbfa 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -6405,10 +6405,7 @@ function renderTemplatedObject( if (typeof obj === "string") { const strict = !!options.strict; if (options.templateFormat === "nunjucks") { - if (strict) { - iso.lintNunjucksTemplate(obj, args); - } - return iso.renderNunjucksString(obj, args, strict); + return iso.renderNunjucksString(obj, args, { strict }); } if (options.templateFormat === "mustache") { if (strict) { diff --git a/js/src/node.ts b/js/src/node.ts index 6433428d0..a6b8657c7 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -9,8 +9,8 @@ import iso from "./isomorph"; import { getRepoInfo, getPastNAncestors } from "./gitutil"; import { getCallerLocation } from "./stackutil"; import { _internalSetInitialState } from "./logger"; -import { renderNunjucksString } from "./template/nunjucks-env"; -import { lintTemplate as lintNunjucksTemplate } from "./template/nunjucks-utils"; +import { renderNunjucksString as nunjucksRender } from "./template/nunjucks-env"; +import { lintTemplate as nunjucksLint } from "./template/nunjucks-utils"; import { promisify } from "util"; import * as zlib from "zlib"; @@ -23,8 +23,15 @@ export function configureNode() { iso.processOn = (event: string, handler: (code: any) => void) => { process.on(event, handler); }; - iso.renderNunjucksString = renderNunjucksString; - iso.lintNunjucksTemplate = lintNunjucksTemplate; + iso.renderNunjucksString = (template, variables, options = {}) => { + const strict = options.strict ?? false; + + if (strict) { + nunjucksLint(template, variables); + } + + return nunjucksRender(template, variables, strict); + }; iso.basename = path.basename; iso.writeln = (text: string) => process.stdout.write(text + "\n"); iso.pathJoin = path.join; diff --git a/js/src/template/renderer.ts b/js/src/template/renderer.ts index 552d1632d..2d002cde7 100644 --- a/js/src/template/renderer.ts +++ b/js/src/template/renderer.ts @@ -24,10 +24,7 @@ export function renderTemplateContent( const strict = !!options.strict; const templateFormat = parseTemplateFormat(options.templateFormat); if (templateFormat === "nunjucks") { - if (strict) { - iso.lintNunjucksTemplate(template, variables); - } - return iso.renderNunjucksString(template, variables, strict); + return iso.renderNunjucksString(template, variables, { strict }); } else if (templateFormat === "mustache") { if (strict) { lintMustacheTemplate(template, variables); From c418c7722ee3da945b65ccb8721634af4ef8bcd0 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 10:18:28 -0800 Subject: [PATCH 19/57] allow error to be thrown for vite-react-hono --- js/smoke/shared/src/suites/prompt-templating.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index bf4e4e50e..f2b14eb88 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -151,7 +151,8 @@ export async function testNunjucksTemplate( (environment === "browser" || environment === "cloudflare-worker-browser-no-compat" || environment === "cloudflare-worker-browser-node-compat" || - environment === "nextjs-edge-runtime") && + environment === "nextjs-edge-runtime" || + environment === "vite-react-hono") && isUnsupported ) { return { From a8b782469612cd481edb6227854c072e50bf7a61 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 10:33:20 -0800 Subject: [PATCH 20/57] fix the type errors --- js/src/isomorph.ts | 9 --------- js/src/node.ts | 2 +- js/src/template/nunjucks-env.ts | 3 ++- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/js/src/isomorph.ts b/js/src/isomorph.ts index 1828ad60d..38d8999ff 100644 --- a/js/src/isomorph.ts +++ b/js/src/isomorph.ts @@ -38,15 +38,6 @@ export interface Common { getCallerLocation: () => CallerLocation | undefined; newAsyncLocalStorage: () => IsoAsyncLocalStorage; processOn: (event: string, handler: (code: any) => void) => void; - renderNunjucksString: ( - template: string, - variables: Record, - strict?: boolean, - ) => string; - lintNunjucksTemplate: ( - template: string, - context: Record, - ) => void; // hash a string. not guaranteed to be crypto safe. hash?: (data: string) => string; diff --git a/js/src/node.ts b/js/src/node.ts index a6b8657c7..72af4d6e2 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -30,7 +30,7 @@ export function configureNode() { nunjucksLint(template, variables); } - return nunjucksRender(template, variables, strict); + return nunjucksRender(template, variables, { strict }); }; iso.basename = path.basename; iso.writeln = (text: string) => process.stdout.write(text + "\n"); diff --git a/js/src/template/nunjucks-env.ts b/js/src/template/nunjucks-env.ts index efb3c1ab8..16232f72b 100644 --- a/js/src/template/nunjucks-env.ts +++ b/js/src/template/nunjucks-env.ts @@ -27,8 +27,9 @@ export function getNunjucksEnv(options?: { export function renderNunjucksString( template: string, variables: Record, - strict = false, + options?: { strict?: boolean }, ): string { + const strict = options?.strict ?? false; try { return getNunjucksEnv({ strict }).renderString(template, variables); } catch (error) { From ae411335f49f9aa56af66b1db9eb7a08cea5ac95 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 16 Jan 2026 15:20:11 -0800 Subject: [PATCH 21/57] fix missing node: prefix, require eslint node: prefix, and update tsup to avoid removing the prefix --- js/eslint.config.ts | 5 +++ js/package.json | 2 + js/src/node.ts | 6 +-- js/tsup.config.ts | 7 ++++ pnpm-lock.yaml | 94 +++++++++++++++++++++++++++++---------------- 5 files changed, 77 insertions(+), 37 deletions(-) diff --git a/js/eslint.config.ts b/js/eslint.config.ts index 2df170c65..31b778ffd 100644 --- a/js/eslint.config.ts +++ b/js/eslint.config.ts @@ -1,5 +1,6 @@ import tseslint from "@typescript-eslint/eslint-plugin"; import tsparser from "@typescript-eslint/parser"; +import nodeImport from "eslint-plugin-node-import"; import tsupConfigImport from "./tsup.config"; // Handle both ESM and CJS module formats @@ -30,6 +31,7 @@ export default [ }, plugins: { "@typescript-eslint": tseslint, + "node-import": nodeImport, }, rules: { // Base TypeScript rules @@ -54,6 +56,9 @@ export default [ ], "no-unused-expressions": ["error", { allowShortCircuit: true }], "@typescript-eslint/no-unused-expressions": "off", + // Require node: protocol for Node.js built-in imports (for Deno compatibility) + // This plugin automatically detects ALL Node.js built-ins - no manual list needed! + "node-import/prefer-node-protocol": "error", }, }, { diff --git a/js/package.json b/js/package.json index 4652bc6c0..e33d0df50 100644 --- a/js/package.json +++ b/js/package.json @@ -99,6 +99,8 @@ "async": "^3.2.5", "autoevals": "^0.0.131", "cross-env": "^7.0.3", + "eslint-plugin-node-import": "^1.0.5", + "jiti": "^2.6.1", "npm-run-all": "^4.1.5", "openapi-zod-client": "^1.18.3", "prettier": "^3.5.3", diff --git a/js/src/node.ts b/js/src/node.ts index 72af4d6e2..719fa5558 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -11,8 +11,8 @@ import { getCallerLocation } from "./stackutil"; import { _internalSetInitialState } from "./logger"; import { renderNunjucksString as nunjucksRender } from "./template/nunjucks-env"; import { lintTemplate as nunjucksLint } from "./template/nunjucks-utils"; -import { promisify } from "util"; -import * as zlib from "zlib"; +import { promisify } from "node:util"; +import * as zlib from "node:zlib"; export function configureNode() { iso.getRepoInfo = getRepoInfo; @@ -20,7 +20,7 @@ export function configureNode() { iso.getEnv = (name) => process.env[name]; iso.getCallerLocation = getCallerLocation; iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); - iso.processOn = (event: string, handler: (code: any) => void) => { + iso.processOn = (event: string, handler: (code: unknown) => void) => { process.on(event, handler); }; iso.renderNunjucksString = (template, variables, options = {}) => { diff --git a/js/tsup.config.ts b/js/tsup.config.ts index edbd0ffd1..0e00034ad 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -1,4 +1,6 @@ import { defineConfig } from "tsup"; +import fs from "node:fs"; +import { builtinModules } from "node:module"; export default defineConfig([ { @@ -6,6 +8,7 @@ export default defineConfig([ format: ["cjs", "esm"], outDir: "dist", external: ["zod"], + removeNodeProtocol: false, dts: { // Split DTS generation to reduce memory usage compilerOptions: { @@ -19,6 +22,7 @@ export default defineConfig([ entry: ["src/browser.ts"], format: ["cjs", "esm"], outDir: "dist", + removeNodeProtocol: false, external: ["zod", "nunjucks"], dts: { // Split DTS generation to reduce memory usage @@ -32,6 +36,7 @@ export default defineConfig([ { entry: { cli: "src/cli/index.ts" }, format: ["cjs"], + removeNodeProtocol: false, outDir: "dist", external: ["esbuild", "prettier", "typescript", "zod"], // CLI doesn't need DTS @@ -42,6 +47,7 @@ export default defineConfig([ entry: ["dev/index.ts"], format: ["cjs", "esm"], outDir: "dev/dist", + removeNodeProtocol: false, external: ["esbuild", "prettier", "typescript", "zod"], dts: { // Split DTS generation to reduce memory usage @@ -57,6 +63,7 @@ export default defineConfig([ format: ["cjs", "esm"], outDir: "util/dist", external: ["esbuild", "prettier", "typescript", "zod"], + removeNodeProtocol: false, dts: { // Split DTS generation to reduce memory usage compilerOptions: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1a8aae65..a0cb9fd10 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 2.6.6(@types/node@20.10.5)(typescript@5.3.3) tsup: specifier: ^8.3.5 - version: 8.3.5(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2) + version: 8.3.5(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2) typedoc: specifier: ^0.25.13 version: 0.25.13(typescript@5.3.3) @@ -70,7 +70,7 @@ importers: version: link:../../js tsup: specifier: ^8.3.5 - version: 8.3.5(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2) + version: 8.3.5(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2) tsx: specifier: ^3.14.0 version: 3.14.0 @@ -110,7 +110,7 @@ importers: version: link:../../js tsup: specifier: ^8.5.0 - version: 8.5.1(postcss@8.5.6)(tsx@4.21.0)(typescript@5.5.4)(yaml@2.8.2) + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.5.4)(yaml@2.8.2) typedoc: specifier: ^0.28.15 version: 0.28.15(typescript@5.5.4) @@ -135,7 +135,7 @@ importers: version: 20.10.5 tsup: specifier: ^8.3.5 - version: 8.3.5(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2) + version: 8.3.5(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2) typescript: specifier: ^5.3.3 version: 5.3.3 @@ -289,10 +289,10 @@ importers: version: 9.0.7 '@typescript-eslint/eslint-plugin': specifier: ^8.49.0 - version: 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.4.4))(eslint@9.39.2)(typescript@5.4.4) + version: 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4))(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4) '@typescript-eslint/parser': specifier: ^8.49.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.4.4) + version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4) ai: specifier: ^6.0.0 version: 6.0.27(zod@3.25.76) @@ -305,6 +305,12 @@ importers: cross-env: specifier: ^7.0.3 version: 7.0.3 + eslint-plugin-node-import: + specifier: ^1.0.5 + version: 1.0.5(eslint@9.39.2(jiti@2.6.1)) + jiti: + specifier: ^2.6.1 + version: 2.6.1 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -325,7 +331,7 @@ importers: version: 29.1.4(@babel/core@7.28.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(esbuild@0.27.0)(jest@29.7.0(@types/node@20.10.5))(typescript@5.4.4) tsup: specifier: ^8.5.1 - version: 8.5.1(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2) + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2) tsx: specifier: ^3.14.0 version: 3.14.0 @@ -2974,6 +2980,12 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-plugin-node-import@1.0.5: + resolution: {integrity: sha512-razzgbr3EcB5+bm8/gqTqzTJ7Bpiu8PIChiAMRfZCNigr9GZBtnVSI+wPw+RGbWYCCIzWAsK/A7ihoAeSz5j7A==} + engines: {node: ^14.18.0 || ^16.0.0 || >= 18.0.0} + peerDependencies: + eslint: '>=7' + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3699,6 +3711,10 @@ packages: node-notifier: optional: true + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -6425,9 +6441,9 @@ snapshots: '@esbuild/win32-x64@0.27.0': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))': dependencies: - eslint: 9.39.2 + eslint: 9.39.2(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -7431,15 +7447,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.4.4))(eslint@9.39.2)(typescript@5.4.4)': + '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4))(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.4.4) + '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4) '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2)(typescript@5.4.4) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.4.4) + '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4) + '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4) '@typescript-eslint/visitor-keys': 8.50.0 - eslint: 9.39.2 + eslint: 9.39.2(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.1.0(typescript@5.4.4) @@ -7447,14 +7463,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.4.4)': + '@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4)': dependencies: '@typescript-eslint/scope-manager': 8.50.0 '@typescript-eslint/types': 8.50.0 '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.4.4) '@typescript-eslint/visitor-keys': 8.50.0 debug: 4.4.3 - eslint: 9.39.2 + eslint: 9.39.2(jiti@2.6.1) typescript: 5.4.4 transitivePeerDependencies: - supports-color @@ -7477,13 +7493,13 @@ snapshots: dependencies: typescript: 5.4.4 - '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2)(typescript@5.4.4)': + '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4)': dependencies: '@typescript-eslint/types': 8.50.0 '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.4.4) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.4.4) + '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4) debug: 4.4.3 - eslint: 9.39.2 + eslint: 9.39.2(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.4.4) typescript: 5.4.4 transitivePeerDependencies: @@ -7506,13 +7522,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.4.4)': + '@typescript-eslint/utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.4.4)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.50.0 '@typescript-eslint/types': 8.50.0 '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.4.4) - eslint: 9.39.2 + eslint: 9.39.2(jiti@2.6.1) typescript: 5.4.4 transitivePeerDependencies: - supports-color @@ -8531,6 +8547,10 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-plugin-node-import@1.0.5(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -8540,9 +8560,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.2: + eslint@9.39.2(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 @@ -8576,6 +8596,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 transitivePeerDependencies: - supports-color @@ -9578,6 +9600,8 @@ snapshots: - supports-color - ts-node + jiti@2.6.1: {} + joycon@3.1.1: {} js-levenshtein@1.1.6: {} @@ -10279,18 +10303,20 @@ snapshots: pluralize@8.0.0: {} - postcss-load-config@6.0.1(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2): dependencies: lilconfig: 3.1.3 optionalDependencies: + jiti: 2.6.1 postcss: 8.5.6 tsx: 3.14.0 yaml: 2.8.2 - postcss-load-config@6.0.1(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2): dependencies: lilconfig: 3.1.3 optionalDependencies: + jiti: 2.6.1 postcss: 8.5.6 tsx: 4.21.0 yaml: 2.8.2 @@ -10930,7 +10956,7 @@ snapshots: tslib@2.8.1: {} - tsup@8.3.5(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2): + tsup@8.3.5(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.24.2) cac: 6.7.14 @@ -10940,7 +10966,7 @@ snapshots: esbuild: 0.24.2 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.35.0 source-map: 0.8.0-beta.0 @@ -10957,7 +10983,7 @@ snapshots: - tsx - yaml - tsup@8.3.5(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2): + tsup@8.3.5(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.3.3)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.24.2) cac: 6.7.14 @@ -10967,7 +10993,7 @@ snapshots: esbuild: 0.24.2 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.35.0 source-map: 0.8.0-beta.0 @@ -10984,7 +11010,7 @@ snapshots: - tsx - yaml - tsup@8.5.1(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2): + tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(typescript@5.4.4)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.27.0) cac: 6.7.14 @@ -10995,7 +11021,7 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@3.14.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.35.0 source-map: 0.7.6 @@ -11012,7 +11038,7 @@ snapshots: - tsx - yaml - tsup@8.5.1(postcss@8.5.6)(tsx@4.21.0)(typescript@5.5.4)(yaml@2.8.2): + tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.5.4)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.27.0) cac: 6.7.14 @@ -11023,7 +11049,7 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.35.0 source-map: 0.7.6 From 6d2287c5f0decaf1697f218910c850db3cb250c6 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 16 Jan 2026 15:20:39 -0800 Subject: [PATCH 22/57] tweak prepare to use turbo --- js/Makefile | 36 +++----- js/smoke/prepare-tests.sh | 188 ++++++++++++++++++++++++-------------- 2 files changed, 134 insertions(+), 90 deletions(-) diff --git a/js/Makefile b/js/Makefile index 473c7af08..125beef2b 100644 --- a/js/Makefile +++ b/js/Makefile @@ -17,9 +17,15 @@ help: @echo " make test-ai-sdk-v6 - Run AI SDK v6 wrapper tests" @echo " make test-claude-agent-sdk - Run Claude Agent SDK wrapper tests" @echo " make test-api-compat - Run API compatibility tests" - @echo " make test-smoke - Run smoke tests" @echo " make bench - Run queue performance benchmarks" @echo " make test-latest - Run core + latest versions of wrappers" + @echo "" + @echo "Smoke tests (mimics CI workflow):" + @echo " make test-smoke - Run all smoke tests (auto-prepares)" + @echo " make test-smoke deno - Run deno smoke test only" + @echo " make test-smoke span - Run span smoke test only" + @echo "" + @echo "See smoke/README.md for details on smoke test infrastructure" .PHONY: help bench build clean test test-core test-openai test-anthropic test-google-genai test-ai-sdk test-ai-sdk-v5 test-ai-sdk-v6 test-claude-agent-sdk test-latest install-optional-deps publish-beta-local test-smoke @@ -155,33 +161,19 @@ clean: # Smoke tests # ------------------------------------------------------------------------------------------------- -# Marker file to track when smoke tests were last prepared -SMOKE_PREPARE_MARKER := smoke/.prepare-marker SMOKE_DIR := smoke -# Run smoke tests (prepares if source changed) +# Run smoke tests (always prepares - relies on turbo/tsup caching for build efficiency) # Usage: make test-smoke [TEST_NAME...] test-smoke: - @if [ ! -f "$(SMOKE_PREPARE_MARKER)" ]; then \ - echo "⚠ Smoke tests not prepared, preparing..."; \ - cd $(SMOKE_DIR) && ./prepare-tests.sh && touch .prepare-marker; \ - elif [ -n "$$(find src -type f \( -name '*.ts' -o -name '*.tsx' \) -newer "$(SMOKE_PREPARE_MARKER)" 2>/dev/null | head -1)" ]; then \ - echo "⚠ SDK source files changed, preparing smoke tests..."; \ - cd $(SMOKE_DIR) && ./prepare-tests.sh && touch .prepare-marker; \ - elif [ -n "$$(find dist -type f -name '*.js' -newer "$(SMOKE_PREPARE_MARKER)" 2>/dev/null | head -1)" ]; then \ - echo "⚠ SDK build artifacts changed, preparing smoke tests..."; \ - cd $(SMOKE_DIR) && ./prepare-tests.sh && touch .prepare-marker; \ - elif [ ! -d "artifacts" ] || [ -z "$$(ls artifacts/*.tgz 2>/dev/null | head -1)" ]; then \ - echo "⚠ Smoke test artifacts missing, preparing..."; \ - cd $(SMOKE_DIR) && ./prepare-tests.sh && touch .prepare-marker; \ - else \ - echo "✓ Smoke tests are up to date"; \ - fi - @echo "Running smoke tests..." - @EXIT_CODE=0; \ - cd $(SMOKE_DIR) && ./run-tests.sh $(filter-out test-smoke,$(MAKECMDGOALS)) || EXIT_CODE=$$?; \ + @TESTS="$(filter-out test-smoke,$(MAKECMDGOALS))"; \ + SMOKE_ABS="$$(pwd)/$(SMOKE_DIR)"; \ + cd $(SMOKE_DIR) && ./prepare-tests.sh $$TESTS; \ + EXIT_CODE=0; \ + cd $$SMOKE_ABS && ./run-tests.sh $$TESTS || EXIT_CODE=$$?; \ echo ""; \ echo "Restoring package files..."; \ + cd $$SMOKE_ABS && \ for dir in tests/*/; do \ if [ -f "$$dir/package.json" ] && grep -q '"restore"' "$$dir/package.json" 2>/dev/null; then \ (cd "$$dir" && npm run restore >/dev/null 2>&1 && echo " ✓ Restored $$(basename $$dir)") || true; \ diff --git a/js/smoke/prepare-tests.sh b/js/smoke/prepare-tests.sh index cbfc439eb..55558eac7 100755 --- a/js/smoke/prepare-tests.sh +++ b/js/smoke/prepare-tests.sh @@ -3,15 +3,44 @@ set -euo pipefail # Script to prepare smoke tests by building SDK and installing into test directories # This mimics what CI does +# Usage: ./prepare-tests.sh [test-name...] +# If no test names provided, prepares all tests SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" JS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" SDK_DIR="$(cd "$JS_DIR/.." && pwd)" ARTIFACTS_DIR="$JS_DIR/artifacts" -echo "============================================================" -echo "Preparing Smoke Tests" -echo "============================================================" +# Parse which tests to prepare +REQUESTED_TESTS=("$@") +PREPARE_ALL=false +if [ ${#REQUESTED_TESTS[@]} -eq 0 ]; then + PREPARE_ALL=true +fi + +# Helper to check if we should prepare a specific test +should_prepare() { + local test_name=$1 + if [ "$PREPARE_ALL" = true ]; then + return 0 + fi + for requested in "${REQUESTED_TESTS[@]}"; do + if [ "$requested" = "$test_name" ]; then + return 0 + fi + done + return 1 +} + +if [ "$PREPARE_ALL" = true ]; then + echo "============================================================" + echo "Preparing All Smoke Tests" + echo "============================================================" +else + echo "============================================================" + echo "Preparing Smoke Tests: ${REQUESTED_TESTS[*]}" + echo "============================================================" +fi echo "" # Step 0: Restore test files to clean git state @@ -47,36 +76,46 @@ echo "✓ Packed: $PACKED_TARBALL" echo "" # Step 3: Build and pack @braintrust/otel (needed for otel-v1 and nextjs tests) -echo "Step 3: Building @braintrust/otel..." -OTEL_DIR="$SDK_DIR/integrations/otel-js" -if [ -d "$OTEL_DIR" ]; then - cd "$OTEL_DIR" - - # Install the built braintrust package as a dependency - BRAINTRUST_TARBALL=$(ls "$ARTIFACTS_DIR"/braintrust-*.tgz | head -n 1) - if [ -z "$BRAINTRUST_TARBALL" ]; then - echo "Error: braintrust tarball not found" - exit 1 - fi - - echo "Installing braintrust and OpenTelemetry dependencies..." - npm_config_save=false npm_config_lockfile=false pnpm add \ - "file:$BRAINTRUST_TARBALL" \ - "@opentelemetry/api@^1.9.0" \ - "@opentelemetry/core@^1.9.0" \ - "@opentelemetry/exporter-trace-otlp-http@^0.35.0" \ - "@opentelemetry/sdk-trace-base@^1.9.0" || true +NEEDS_OTEL=false +if should_prepare "otel-v1" || should_prepare "nextjs-instrumentation"; then + NEEDS_OTEL=true +fi - echo "Building @braintrust/otel..." - pnpm run build +if [ "$NEEDS_OTEL" = true ]; then + echo "Step 3: Building @braintrust/otel..." + OTEL_DIR="$SDK_DIR/integrations/otel-js" + if [ -d "$OTEL_DIR" ]; then + cd "$OTEL_DIR" + + # Install the built braintrust package as a dependency + BRAINTRUST_TARBALL=$(ls "$ARTIFACTS_DIR"/braintrust-*.tgz | head -n 1) + if [ -z "$BRAINTRUST_TARBALL" ]; then + echo "Error: braintrust tarball not found" + exit 1 + fi - echo "Packing @braintrust/otel..." - OTEL_TARBALL=$(npm pack --pack-destination "$ARTIFACTS_DIR" 2>&1 | tail -1) - echo "✓ Packed: $OTEL_TARBALL" + echo "Installing braintrust and OpenTelemetry dependencies..." + npm_config_save=false npm_config_lockfile=false pnpm add \ + "file:$BRAINTRUST_TARBALL" \ + "@opentelemetry/api@^1.9.0" \ + "@opentelemetry/core@^1.9.0" \ + "@opentelemetry/exporter-trace-otlp-http@^0.35.0" \ + "@opentelemetry/sdk-trace-base@^1.9.0" || true + + echo "Building @braintrust/otel..." + pnpm run build + + echo "Packing @braintrust/otel..." + OTEL_TARBALL=$(npm pack --pack-destination "$ARTIFACTS_DIR" 2>&1 | tail -1) + echo "✓ Packed: $OTEL_TARBALL" + else + echo "⚠ @braintrust/otel directory not found, skipping" + fi + echo "" else - echo "⚠ @braintrust/otel directory not found, skipping" + echo "Step 3: Skipping @braintrust/otel (not needed for requested tests)" + echo "" fi -echo "" # Step 4: Backup package.json files before modifications echo "Step 4: Creating backups of package.json files..." @@ -89,6 +128,7 @@ TESTS_NEEDING_BRAINTRUST=( "otel-v1" "span" "span-jest" + "browser" ) # Tests that also need @braintrust/otel @@ -97,17 +137,18 @@ TESTS_NEEDING_OTEL=( "nextjs-instrumentation" ) -# Create backups for all tests that will be modified -ALL_TESTS=("${TESTS_NEEDING_BRAINTRUST[@]}" "${TESTS_NEEDING_OTEL[@]}") -for test_name in $(printf '%s\n' "${ALL_TESTS[@]}" | sort -u); do - test_dir="$SCRIPT_DIR/tests/$test_name" - if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then - cd "$test_dir" - # Remove old backups first to ensure fresh backups - rm -f package.json.bak package-lock.json.bak - if grep -q '"backup"' package.json 2>/dev/null; then - npm run backup 2>/dev/null || true - echo " ✓ Backed up $test_name/package.json" +# Create backups only for tests we're preparing +for test_name in "${TESTS_NEEDING_BRAINTRUST[@]}"; do + if should_prepare "$test_name"; then + test_dir="$SCRIPT_DIR/tests/$test_name" + if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then + cd "$test_dir" + # Remove old backups first to ensure fresh backups + rm -f package.json.bak package-lock.json.bak + if grep -q '"backup"' package.json 2>/dev/null; then + npm run backup 2>/dev/null || true + echo " ✓ Backed up $test_name/package.json" + fi fi fi done @@ -118,44 +159,55 @@ echo "Step 5: Installing built packages into test directories..." cd "$SCRIPT_DIR" for test_name in "${TESTS_NEEDING_BRAINTRUST[@]}"; do - test_dir="$SCRIPT_DIR/tests/$test_name" - if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then - echo "Installing braintrust into $test_name..." - cd "$test_dir" - # Remove package-lock.json to avoid version conflicts - rm -f package-lock.json - npm install --legacy-peer-deps 2>/dev/null || npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - echo " ✓ $test_name" + if should_prepare "$test_name"; then + test_dir="$SCRIPT_DIR/tests/$test_name" + if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then + echo "Installing braintrust into $test_name..." + cd "$test_dir" + # Remove package-lock.json to avoid version conflicts + rm -f package-lock.json + npm install --legacy-peer-deps 2>/dev/null || npm install + npx tsx ../../install-build.ts ../../../artifacts braintrust + echo " ✓ $test_name" + fi fi done for test_name in "${TESTS_NEEDING_OTEL[@]}"; do - test_dir="$SCRIPT_DIR/tests/$test_name" - if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then - echo "Installing @braintrust/otel into $test_name..." - cd "$test_dir" - npx tsx ../../install-build.ts ../../../artifacts otel - echo " ✓ $test_name (otel)" + if should_prepare "$test_name"; then + test_dir="$SCRIPT_DIR/tests/$test_name" + if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then + echo "Installing @braintrust/otel into $test_name..." + cd "$test_dir" + npx tsx ../../install-build.ts ../../../artifacts otel + echo " ✓ $test_name (otel)" + fi fi done # Special handling for Deno - extract tarball for file:// import -echo "Setting up Deno test..." -DENO_DIR="$SCRIPT_DIR/tests/deno" -if [ -d "$DENO_DIR" ]; then - cd "$DENO_DIR" - TARBALL=$(ls "$ARTIFACTS_DIR"/braintrust-*.tgz | head -n 1) - if [ -n "$TARBALL" ]; then - echo "Extracting braintrust tarball for Deno..." - rm -rf build - mkdir -p build - tar -xzf "$TARBALL" -C build - [ -d build/package ] && mv build/package build/braintrust - echo " ✓ Deno build extracted" +if should_prepare "deno"; then + echo "Setting up Deno test..." + DENO_DIR="$SCRIPT_DIR/tests/deno" + if [ -d "$DENO_DIR" ]; then + cd "$DENO_DIR" + TARBALL=$(ls "$ARTIFACTS_DIR"/braintrust-*.tgz | head -n 1) + if [ -n "$TARBALL" ]; then + echo "Extracting braintrust tarball for Deno..." + rm -rf build + mkdir -p build + tar -xzf "$TARBALL" -C build + [ -d build/package ] && mv build/package build/braintrust + echo " ✓ Deno build extracted" + + # Install Deno dependencies (npm packages in deno.json) + echo "Installing Deno dependencies..." + deno install + echo " ✓ Deno dependencies installed" + fi fi + echo "" fi -echo "" # Step 6: Build shared test package echo "Step 6: Building shared test package..." From 34775965d2a50dbb82d4a43239ef472621f9687a Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 15:47:44 -0800 Subject: [PATCH 23/57] nest deno browser and deno node under deno --- js/smoke/tests/deno-browser/deno.json | 37 ---------- js/smoke/tests/deno-browser/package.json | 13 ---- js/smoke/tests/deno/browser/README.md | 69 +++++++++++++++++++ js/smoke/tests/deno/browser/deno.json | 15 ++++ .../{deno-browser => deno/browser}/deno.lock | 49 ++----------- js/smoke/tests/deno/browser/package.json | 10 +++ .../browser}/shared_suite_test.ts | 2 +- js/smoke/tests/deno/{ => node}/deno.json | 6 +- js/smoke/tests/deno/{ => node}/deno.lock | 0 js/smoke/tests/deno/node/package.json | 12 ++++ .../deno/{ => node}/shared_suite_test.ts | 2 +- js/smoke/tests/deno/{ => node}/span_test.ts | 2 +- js/smoke/tests/deno/package.json | 9 +-- 13 files changed, 122 insertions(+), 104 deletions(-) delete mode 100644 js/smoke/tests/deno-browser/deno.json delete mode 100644 js/smoke/tests/deno-browser/package.json create mode 100644 js/smoke/tests/deno/browser/README.md create mode 100644 js/smoke/tests/deno/browser/deno.json rename js/smoke/tests/{deno-browser => deno/browser}/deno.lock (64%) create mode 100644 js/smoke/tests/deno/browser/package.json rename js/smoke/tests/{deno-browser => deno/browser}/shared_suite_test.ts (97%) rename js/smoke/tests/deno/{ => node}/deno.json (86%) rename js/smoke/tests/deno/{ => node}/deno.lock (100%) create mode 100644 js/smoke/tests/deno/node/package.json rename js/smoke/tests/deno/{ => node}/shared_suite_test.ts (98%) rename js/smoke/tests/deno/{ => node}/span_test.ts (97%) diff --git a/js/smoke/tests/deno-browser/deno.json b/js/smoke/tests/deno-browser/deno.json deleted file mode 100644 index 68c6d5adc..000000000 --- a/js/smoke/tests/deno-browser/deno.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "nodeModulesDir": "auto", - "npmDependencies": { - "@next/env": "14.2.3", - "eventsource-parser": "1.1.2", - "uuid": "9.0.1", - "dotenv": "16.4.5", - "argparse": "2.0.1", - "chalk": "4.1.2" - }, - "workspace": { - "members": [] - }, - "imports": { - "@vercel/functions": "npm:@vercel/functions@^3.3.0", - "async_hooks": "node:async_hooks", - "child_process": "node:child_process", - "crypto": "node:crypto", - "eventsource-parser": "npm:eventsource-parser@^3.0.6", - "fs": "node:fs", - "fs/promises": "node:fs/promises", - "mustache": "npm:mustache@^4.2.0", - "uuid": "npm:uuid@^13.0.0", - "os": "node:os", - "path": "node:path", - "simple-git": "npm:simple-git@^3.21.0", - "zod": "npm:zod@^4.1.12", - "nunjucks": "npm:nunjucks@^3.2.4", - "util": "node:util", - "zlib": "node:zlib", - "braintrust/browser": "./build/braintrust/dist/browser.mjs", - "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" - }, - "tasks": { - "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts" - } -} diff --git a/js/smoke/tests/deno-browser/package.json b/js/smoke/tests/deno-browser/package.json deleted file mode 100644 index b16828bcd..000000000 --- a/js/smoke/tests/deno-browser/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "braintrust-deno-browser-smoke-test", - "version": "1.0.0", - "description": "Smoke test for Braintrust SDK browser build in Deno runtime", - "private": true, - "scripts": { - "test": "npm run test:shared", - "test:shared": "deno task test:shared", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" - } -} diff --git a/js/smoke/tests/deno/browser/README.md b/js/smoke/tests/deno/browser/README.md new file mode 100644 index 000000000..541e193f4 --- /dev/null +++ b/js/smoke/tests/deno/browser/README.md @@ -0,0 +1,69 @@ +# Deno Browser Build Test + +This directory tests the browser build (`braintrust/browser`) in Deno. + +## Dependencies + +The browser build requires these npm packages (marked as `external` in tsup but still imported): + +### Required Dependencies + +- **`uuid`** - Used by `IDGenerator` for generating span and trace IDs + - Could potentially be replaced with `node:crypto.randomUUID()` but would require SDK code changes +- **`zod`** (v3 and v4) - Schema validation, used throughout the SDK + - Core dependency, cannot be removed +- **`mustache`** - Template rendering (default template engine for browser) + - Used by `Prompt` class for template rendering +- **`eventsource-parser`** - Streaming response parsing + - Used by OpenAI/Anthropic wrappers for streaming +- **`@vercel/functions`** - Vercel Edge Runtime utilities + - Used for `waitUntil` in serverless environments +- **`zod-to-json-schema`** - Convert Zod schemas to JSON Schema + - Used for schema serialization + +### Removed Dependencies + +- ~~**`nunjucks`**~~ - **REMOVED** by using `.browser.ts` variants + - The browser build now uses stub implementations that throw errors + - Browser users should use `templateFormat: 'mustache'` instead + +### Why Not Use `node:` Prefix? + +The `node:` prefix only works for **Node.js built-in modules** like `node:fs`, `node:crypto`, `node:path`, etc. + +It does **NOT** work for npm packages like `uuid`, `zod`, `mustache` - these must be resolved from npm via Deno's import map. + +## Build Configuration + +The browser build is configured in `sdk/js/tsup.config.ts` with: + +- `platform: "browser"` - Enables browser-specific optimizations +- `esbuildPlugins: [browserResolvePlugin]` - Resolves `.browser.ts` variants for platform-specific code +- `external: ["zod"]` - Marks zod as external (still needs to be in import map) + +### Browser Variants + +Files with `.browser.ts` extensions provide browser-specific implementations: + +- `src/template/nunjucks-env.browser.ts` - Throws error instead of using nunjucks +- `src/template/nunjucks-utils.browser.ts` - Throws error for nunjucks linting + +The `browserResolvePlugin` in tsup.config.ts automatically resolves these during the browser build. + +## Running Tests + +```bash +# Using deno task +deno task test:shared + +# Or directly +deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts +``` + +Note: We use `--no-config` to avoid Deno's workspace detection which can cause issues with the parent pnpm workspace. + +## Updating Lock File + +```bash +deno cache --no-config --import-map=./deno.json --lock=deno.lock --frozen=false shared_suite_test.ts +``` diff --git a/js/smoke/tests/deno/browser/deno.json b/js/smoke/tests/deno/browser/deno.json new file mode 100644 index 000000000..2c882272c --- /dev/null +++ b/js/smoke/tests/deno/browser/deno.json @@ -0,0 +1,15 @@ +{ + "imports": { + "braintrust/browser": "../build/braintrust/dist/browser.mjs", + "uuid": "npm:uuid@^13.0.0", + "zod/v3": "npm:zod@^3.24.1", + "zod/v4": "npm:zod@^4.1.12", + "@vercel/functions": "npm:@vercel/functions@^3.3.0", + "mustache": "npm:mustache@^4.2.0", + "eventsource-parser": "npm:eventsource-parser@^3.0.6", + "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" + }, + "tasks": { + "test:shared": "deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts" + } +} diff --git a/js/smoke/tests/deno-browser/deno.lock b/js/smoke/tests/deno/browser/deno.lock similarity index 64% rename from js/smoke/tests/deno-browser/deno.lock rename to js/smoke/tests/deno/browser/deno.lock index 4111fa708..a72da34d1 100644 --- a/js/smoke/tests/deno-browser/deno.lock +++ b/js/smoke/tests/deno/browser/deno.lock @@ -7,9 +7,9 @@ "npm:eventsource-parser@^3.0.6": "3.0.6", "npm:mustache@^4.2.0": "4.2.0", "npm:nunjucks@^3.2.4": "3.2.4", - "npm:simple-git@^3.21.0": "3.30.0", "npm:uuid@13": "13.0.0", - "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@4.2.1", + "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@3.25.76", + "npm:zod@^3.24.1": "3.25.76", "npm:zod@^4.1.12": "4.2.1" }, "jsr": { @@ -24,15 +24,6 @@ } }, "npm": { - "@kwsites/file-exists@1.1.1": { - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dependencies": [ - "debug" - ] - }, - "@kwsites/promise-deferred@1.1.1": { - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" - }, "@vercel/functions@3.3.4": { "integrity": "sha512-IoP8Xfr1QeCm+Dv5od3bfPiw/VgLKsA7IBd/88M/Wr421HdbH4b6bW5z8CTxiz1QRpalrPFZcLdMdxu+2hAjZg==", "dependencies": [ @@ -51,18 +42,9 @@ "commander@5.1.0": { "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" }, - "debug@4.4.3": { - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": [ - "ms" - ] - }, "eventsource-parser@3.0.6": { "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" }, - "ms@2.1.3": { - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "mustache@4.2.0": { "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "bin": true @@ -76,38 +58,21 @@ ], "bin": true }, - "simple-git@3.30.0": { - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "dependencies": [ - "@kwsites/file-exists", - "@kwsites/promise-deferred", - "debug" - ] - }, "uuid@13.0.0": { "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "bin": true }, - "zod-to-json-schema@3.25.0_zod@4.2.1": { + "zod-to-json-schema@3.25.0_zod@3.25.76": { "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", "dependencies": [ - "zod" + "zod@3.25.76" ] }, + "zod@3.25.76": { + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" + }, "zod@4.2.1": { "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==" } - }, - "workspace": { - "dependencies": [ - "npm:@vercel/functions@^3.3.0", - "npm:eventsource-parser@^3.0.6", - "npm:mustache@^4.2.0", - "npm:nunjucks@^3.2.4", - "npm:simple-git@^3.21.0", - "npm:uuid@13", - "npm:zod-to-json-schema@^3.25.0", - "npm:zod@^4.1.12" - ] } } diff --git a/js/smoke/tests/deno/browser/package.json b/js/smoke/tests/deno/browser/package.json new file mode 100644 index 000000000..6384ea936 --- /dev/null +++ b/js/smoke/tests/deno/browser/package.json @@ -0,0 +1,10 @@ +{ + "name": "braintrust-deno-browser-smoke-test", + "version": "1.0.0", + "description": "Smoke test for Braintrust browser build in Deno runtime", + "private": true, + "scripts": { + "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts", + "install-build": "npx tsx ../../../install-build.ts ../../../../artifacts braintrust" + } +} diff --git a/js/smoke/tests/deno-browser/shared_suite_test.ts b/js/smoke/tests/deno/browser/shared_suite_test.ts similarity index 97% rename from js/smoke/tests/deno-browser/shared_suite_test.ts rename to js/smoke/tests/deno/browser/shared_suite_test.ts index 70958f262..bf78eb8e0 100644 --- a/js/smoke/tests/deno-browser/shared_suite_test.ts +++ b/js/smoke/tests/deno/browser/shared_suite_test.ts @@ -12,7 +12,7 @@ import { runImportVerificationTests, runPromptTemplatingTests, type TestResult, -} from "../../shared/dist/index.mjs"; +} from "../../../shared/dist/index.mjs"; import * as braintrust from "braintrust/browser"; export async function runSharedTestSuites(): Promise { diff --git a/js/smoke/tests/deno/deno.json b/js/smoke/tests/deno/node/deno.json similarity index 86% rename from js/smoke/tests/deno/deno.json rename to js/smoke/tests/deno/node/deno.json index b41938eca..9ae227e26 100644 --- a/js/smoke/tests/deno/deno.json +++ b/js/smoke/tests/deno/node/deno.json @@ -26,13 +26,13 @@ "simple-git": "npm:simple-git@^3.21.0", "zod": "npm:zod@^4.1.12", "nunjucks": "npm:nunjucks@^3.2.4", - "braintrust": "./build/braintrust/dist/index.mjs", + "braintrust": "../build/braintrust/dist/index.mjs", "util": "node:util", "zlib": "node:zlib", "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" }, "tasks": { - "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts", - "test:legacy": "deno test --config ./deno.json --allow-env --allow-read=.,./build --allow-net span_test.ts" + "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts", + "test:legacy": "deno test --config ./deno.json --allow-env --allow-read=.,../build --allow-net span_test.ts" } } diff --git a/js/smoke/tests/deno/deno.lock b/js/smoke/tests/deno/node/deno.lock similarity index 100% rename from js/smoke/tests/deno/deno.lock rename to js/smoke/tests/deno/node/deno.lock diff --git a/js/smoke/tests/deno/node/package.json b/js/smoke/tests/deno/node/package.json new file mode 100644 index 000000000..ae8f25cab --- /dev/null +++ b/js/smoke/tests/deno/node/package.json @@ -0,0 +1,12 @@ +{ + "name": "braintrust-deno-node-smoke-test", + "version": "1.0.0", + "description": "Smoke test for Braintrust Node build in Deno runtime", + "private": true, + "scripts": { + "test": "npm run test:shared && npm run test:legacy", + "test:shared": "deno task test:shared", + "test:legacy": "deno task test:legacy", + "install-build": "npx tsx ../../../install-build.ts ../../../../artifacts braintrust" + } +} diff --git a/js/smoke/tests/deno/shared_suite_test.ts b/js/smoke/tests/deno/node/shared_suite_test.ts similarity index 98% rename from js/smoke/tests/deno/shared_suite_test.ts rename to js/smoke/tests/deno/node/shared_suite_test.ts index 666cf2b1a..d6bece4a4 100644 --- a/js/smoke/tests/deno/shared_suite_test.ts +++ b/js/smoke/tests/deno/node/shared_suite_test.ts @@ -13,7 +13,7 @@ import { runImportVerificationTests, runPromptTemplatingTests, type TestResult, -} from "../../shared/dist/index.mjs"; +} from "../../../shared/dist/index.mjs"; import * as braintrust from "braintrust"; /** diff --git a/js/smoke/tests/deno/span_test.ts b/js/smoke/tests/deno/node/span_test.ts similarity index 97% rename from js/smoke/tests/deno/span_test.ts rename to js/smoke/tests/deno/node/span_test.ts index 8ed4a26ff..bf31deb82 100644 --- a/js/smoke/tests/deno/span_test.ts +++ b/js/smoke/tests/deno/node/span_test.ts @@ -4,7 +4,7 @@ import { runSpanSmokeTest, runMustacheTemplateTest, runNunjucksTemplateTest, -} from "../span/span_test_helper.ts"; +} from "../../span/span_test_helper.ts"; /** * This is a simple test to send a span to the braintrust API diff --git a/js/smoke/tests/deno/package.json b/js/smoke/tests/deno/package.json index 0b97e7aa3..572a9f3fe 100644 --- a/js/smoke/tests/deno/package.json +++ b/js/smoke/tests/deno/package.json @@ -4,11 +4,8 @@ "description": "Smoke test for Braintrust SDK in Deno runtime", "private": true, "scripts": { - "test": "npm run test:shared && npm run test:legacy", - "test:shared": "deno task test:shared", - "test:legacy": "deno task test:legacy", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" + "test": "npm run test:node && npm run test:browser", + "test:node": "cd node && npm test", + "test:browser": "cd browser && npm test" } } From fa95170d3c657d6f6121bdf6b4bd0a2c8dac7c45 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 15:57:19 -0800 Subject: [PATCH 24/57] still requiring some node modules in deno node, fix cloudflare packagejson --- js/smoke/tests/cloudflare-worker/package.json | 2 +- js/smoke/tests/deno/node/deno.json | 31 +++++----------- js/smoke/tests/deno/node/deno.lock | 37 +++++++------------ js/smoke/tests/deno/node/package.json | 4 +- 4 files changed, 25 insertions(+), 49 deletions(-) diff --git a/js/smoke/tests/cloudflare-worker/package.json b/js/smoke/tests/cloudflare-worker/package.json index 0cc781f88..b973f8d9e 100644 --- a/js/smoke/tests/cloudflare-worker/package.json +++ b/js/smoke/tests/cloudflare-worker/package.json @@ -14,7 +14,7 @@ "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" }, "dependencies": { - "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", + "braintrust": "latest", "zod": "^3.25.76" }, "devDependencies": { diff --git a/js/smoke/tests/deno/node/deno.json b/js/smoke/tests/deno/node/deno.json index 9ae227e26..3467160fb 100644 --- a/js/smoke/tests/deno/node/deno.json +++ b/js/smoke/tests/deno/node/deno.json @@ -1,35 +1,24 @@ { - "nodeModulesDir": "auto", - "npmDependencies": { - "@next/env": "14.2.3", - "eventsource-parser": "1.1.2", - "uuid": "9.0.1", - "dotenv": "16.4.5", - "argparse": "2.0.1", - "chalk": "4.1.2" - }, - "workspace": { - "members": [] - }, "imports": { + "braintrust": "../build/braintrust/dist/index.mjs", + "uuid": "npm:uuid@^13.0.0", + "zod/v3": "npm:zod@^3.24.1", + "zod/v4": "npm:zod@^4.1.12", "@vercel/functions": "npm:@vercel/functions@^3.3.0", + "mustache": "npm:mustache@^4.2.0", + "nunjucks": "npm:nunjucks@^3.2.4", + "eventsource-parser": "npm:eventsource-parser@^3.0.6", + "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0", + "simple-git": "npm:simple-git@^3.21.0", "async_hooks": "node:async_hooks", "child_process": "node:child_process", "crypto": "node:crypto", - "eventsource-parser": "npm:eventsource-parser@^3.0.6", "fs": "node:fs", "fs/promises": "node:fs/promises", - "mustache": "npm:mustache@^4.2.0", - "uuid": "npm:uuid@^13.0.0", "os": "node:os", "path": "node:path", - "simple-git": "npm:simple-git@^3.21.0", - "zod": "npm:zod@^4.1.12", - "nunjucks": "npm:nunjucks@^3.2.4", - "braintrust": "../build/braintrust/dist/index.mjs", "util": "node:util", - "zlib": "node:zlib", - "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" + "zlib": "node:zlib" }, "tasks": { "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts", diff --git a/js/smoke/tests/deno/node/deno.lock b/js/smoke/tests/deno/node/deno.lock index 43c96d0ee..5132365b1 100644 --- a/js/smoke/tests/deno/node/deno.lock +++ b/js/smoke/tests/deno/node/deno.lock @@ -1,7 +1,7 @@ { "version": "5", "specifiers": { - "jsr:@std/assert@^1.0.14": "1.0.16", + "jsr:@std/assert@^1.0.14": "1.0.15", "jsr:@std/internal@^1.0.12": "1.0.12", "npm:@types/node@*": "24.2.0", "npm:@vercel/functions@^3.3.0": "3.3.4", @@ -10,12 +10,13 @@ "npm:nunjucks@^3.2.4": "3.2.4", "npm:simple-git@^3.21.0": "3.30.0", "npm:uuid@13": "13.0.0", - "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@4.1.13", - "npm:zod@^4.1.12": "4.1.13" + "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@3.25.76", + "npm:zod@^3.24.1": "3.25.76", + "npm:zod@^4.1.12": "4.2.1" }, "jsr": { - "@std/assert@1.0.16": { - "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", + "@std/assert@1.0.15": { + "integrity": "d64018e951dbdfab9777335ecdb000c0b4e3df036984083be219ce5941e4703b", "dependencies": [ "jsr:@std/internal" ] @@ -98,29 +99,17 @@ "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "bin": true }, - "zod-to-json-schema@3.25.0_zod@4.1.13": { + "zod-to-json-schema@3.25.0_zod@3.25.76": { "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", "dependencies": [ - "zod" + "zod@3.25.76" ] }, - "zod@4.1.13": { - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==" + "zod@3.25.76": { + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" + }, + "zod@4.2.1": { + "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==" } - }, - "remote": { - "https://mozilla.github.io/nunjucks/files/nunjucks.min.js": "36b31fabed0b7d923a840f963d9c7465ce390d3a6e71a2fe29b8287fad35dbd6" - }, - "workspace": { - "dependencies": [ - "npm:@vercel/functions@^3.3.0", - "npm:eventsource-parser@^3.0.6", - "npm:mustache@^4.2.0", - "npm:nunjucks@^3.2.4", - "npm:simple-git@^3.21.0", - "npm:uuid@13", - "npm:zod-to-json-schema@^3.25.0", - "npm:zod@^4.1.12" - ] } } diff --git a/js/smoke/tests/deno/node/package.json b/js/smoke/tests/deno/node/package.json index ae8f25cab..153b63a3f 100644 --- a/js/smoke/tests/deno/node/package.json +++ b/js/smoke/tests/deno/node/package.json @@ -4,9 +4,7 @@ "description": "Smoke test for Braintrust Node build in Deno runtime", "private": true, "scripts": { - "test": "npm run test:shared && npm run test:legacy", - "test:shared": "deno task test:shared", - "test:legacy": "deno task test:legacy", + "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts span_test.ts", "install-build": "npx tsx ../../../install-build.ts ../../../../artifacts braintrust" } } From 369434d63e8aa1fa12c55c05f7fe0a758dbc9737 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 16:04:04 -0800 Subject: [PATCH 25/57] small workflow update, deno update --- .github/workflows/js.yaml | 11 +++++------ js/smoke/tests/deno/browser/deno.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 0173f50a4..989fb5d73 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -604,11 +604,6 @@ jobs: run-id: ${{ github.run_id }} github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install Deno dependencies - working-directory: js/smoke/tests/${{ matrix.mode }} - run: | - deno install - - name: Build shared test package working-directory: js/smoke/shared run: | @@ -618,4 +613,8 @@ jobs: - name: Run Deno smoke test (${{ matrix.mode }}) working-directory: js/smoke run: | - ./run-tests.sh ${{ matrix.mode }} + if [ "${{ matrix.mode }}" = "deno" ]; then + ./run-tests.sh deno + else + cd tests/deno/browser && npm test + fi diff --git a/js/smoke/tests/deno/browser/deno.json b/js/smoke/tests/deno/browser/deno.json index 2c882272c..999922cec 100644 --- a/js/smoke/tests/deno/browser/deno.json +++ b/js/smoke/tests/deno/browser/deno.json @@ -10,6 +10,6 @@ "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" }, "tasks": { - "test:shared": "deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts" + "test:shared": "deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts" } } From 1539428998a072a6aa8d79e01f28b79bac8850ac Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 16:21:28 -0800 Subject: [PATCH 26/57] remove all the node modules in the node deno file --- js/smoke/tests/deno/node/deno.json | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/js/smoke/tests/deno/node/deno.json b/js/smoke/tests/deno/node/deno.json index 3467160fb..f0536127d 100644 --- a/js/smoke/tests/deno/node/deno.json +++ b/js/smoke/tests/deno/node/deno.json @@ -9,16 +9,7 @@ "nunjucks": "npm:nunjucks@^3.2.4", "eventsource-parser": "npm:eventsource-parser@^3.0.6", "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0", - "simple-git": "npm:simple-git@^3.21.0", - "async_hooks": "node:async_hooks", - "child_process": "node:child_process", - "crypto": "node:crypto", - "fs": "node:fs", - "fs/promises": "node:fs/promises", - "os": "node:os", - "path": "node:path", - "util": "node:util", - "zlib": "node:zlib" + "simple-git": "npm:simple-git@^3.21.0" }, "tasks": { "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts", From 24392f7506b20a71aff7066db1bf8f143b242ecc Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 16:41:28 -0800 Subject: [PATCH 27/57] mark a few packages as noexternal to be easier for deno --- js/smoke/tests/deno/browser/deno.json | 6 +----- js/smoke/tests/deno/browser/deno.lock | 19 ------------------- js/smoke/tests/deno/node/deno.json | 4 ---- js/smoke/tests/deno/node/deno.lock | 26 -------------------------- js/tsup.config.ts | 15 ++++++++++++++- 5 files changed, 15 insertions(+), 55 deletions(-) diff --git a/js/smoke/tests/deno/browser/deno.json b/js/smoke/tests/deno/browser/deno.json index 999922cec..5e7845d6e 100644 --- a/js/smoke/tests/deno/browser/deno.json +++ b/js/smoke/tests/deno/browser/deno.json @@ -3,11 +3,7 @@ "braintrust/browser": "../build/braintrust/dist/browser.mjs", "uuid": "npm:uuid@^13.0.0", "zod/v3": "npm:zod@^3.24.1", - "zod/v4": "npm:zod@^4.1.12", - "@vercel/functions": "npm:@vercel/functions@^3.3.0", - "mustache": "npm:mustache@^4.2.0", - "eventsource-parser": "npm:eventsource-parser@^3.0.6", - "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0" + "zod/v4": "npm:zod@^4.1.12" }, "tasks": { "test:shared": "deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts" diff --git a/js/smoke/tests/deno/browser/deno.lock b/js/smoke/tests/deno/browser/deno.lock index a72da34d1..c66217d4f 100644 --- a/js/smoke/tests/deno/browser/deno.lock +++ b/js/smoke/tests/deno/browser/deno.lock @@ -6,7 +6,6 @@ "npm:@vercel/functions@^3.3.0": "3.3.4", "npm:eventsource-parser@^3.0.6": "3.0.6", "npm:mustache@^4.2.0": "4.2.0", - "npm:nunjucks@^3.2.4": "3.2.4", "npm:uuid@13": "13.0.0", "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@3.25.76", "npm:zod@^3.24.1": "3.25.76", @@ -33,15 +32,6 @@ "@vercel/oidc@3.0.5": { "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==" }, - "a-sync-waterfall@1.0.1": { - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" - }, - "asap@2.0.6": { - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "commander@5.1.0": { - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, "eventsource-parser@3.0.6": { "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" }, @@ -49,15 +39,6 @@ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "bin": true }, - "nunjucks@3.2.4": { - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "dependencies": [ - "a-sync-waterfall", - "asap", - "commander" - ], - "bin": true - }, "uuid@13.0.0": { "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "bin": true diff --git a/js/smoke/tests/deno/node/deno.json b/js/smoke/tests/deno/node/deno.json index f0536127d..301391da6 100644 --- a/js/smoke/tests/deno/node/deno.json +++ b/js/smoke/tests/deno/node/deno.json @@ -4,11 +4,7 @@ "uuid": "npm:uuid@^13.0.0", "zod/v3": "npm:zod@^3.24.1", "zod/v4": "npm:zod@^4.1.12", - "@vercel/functions": "npm:@vercel/functions@^3.3.0", - "mustache": "npm:mustache@^4.2.0", "nunjucks": "npm:nunjucks@^3.2.4", - "eventsource-parser": "npm:eventsource-parser@^3.0.6", - "zod-to-json-schema": "npm:zod-to-json-schema@^3.25.0", "simple-git": "npm:simple-git@^3.21.0" }, "tasks": { diff --git a/js/smoke/tests/deno/node/deno.lock b/js/smoke/tests/deno/node/deno.lock index 5132365b1..f134d92a5 100644 --- a/js/smoke/tests/deno/node/deno.lock +++ b/js/smoke/tests/deno/node/deno.lock @@ -4,13 +4,9 @@ "jsr:@std/assert@^1.0.14": "1.0.15", "jsr:@std/internal@^1.0.12": "1.0.12", "npm:@types/node@*": "24.2.0", - "npm:@vercel/functions@^3.3.0": "3.3.4", - "npm:eventsource-parser@^3.0.6": "3.0.6", - "npm:mustache@^4.2.0": "4.2.0", "npm:nunjucks@^3.2.4": "3.2.4", "npm:simple-git@^3.21.0": "3.30.0", "npm:uuid@13": "13.0.0", - "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@3.25.76", "npm:zod@^3.24.1": "3.25.76", "npm:zod@^4.1.12": "4.2.1" }, @@ -41,15 +37,6 @@ "undici-types" ] }, - "@vercel/functions@3.3.4": { - "integrity": "sha512-IoP8Xfr1QeCm+Dv5od3bfPiw/VgLKsA7IBd/88M/Wr421HdbH4b6bW5z8CTxiz1QRpalrPFZcLdMdxu+2hAjZg==", - "dependencies": [ - "@vercel/oidc" - ] - }, - "@vercel/oidc@3.0.5": { - "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==" - }, "a-sync-waterfall@1.0.1": { "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" }, @@ -65,16 +52,9 @@ "ms" ] }, - "eventsource-parser@3.0.6": { - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" - }, "ms@2.1.3": { "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "mustache@4.2.0": { - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": true - }, "nunjucks@3.2.4": { "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", "dependencies": [ @@ -99,12 +79,6 @@ "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "bin": true }, - "zod-to-json-schema@3.25.0_zod@3.25.76": { - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "dependencies": [ - "zod@3.25.76" - ] - }, "zod@3.25.76": { "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" }, diff --git a/js/tsup.config.ts b/js/tsup.config.ts index 0e00034ad..a22616f14 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -8,6 +8,12 @@ export default defineConfig([ format: ["cjs", "esm"], outDir: "dist", external: ["zod"], + noExternal: [ + "mustache", + "eventsource-parser", + "zod-to-json-schema", + "@vercel/functions", + ], removeNodeProtocol: false, dts: { // Split DTS generation to reduce memory usage @@ -23,7 +29,14 @@ export default defineConfig([ format: ["cjs", "esm"], outDir: "dist", removeNodeProtocol: false, - external: ["zod", "nunjucks"], + external: ["zod"], + noExternal: [ + "mustache", + "eventsource-parser", + "zod-to-json-schema", + "@vercel/functions", + ], + platform: "browser", dts: { // Split DTS generation to reduce memory usage compilerOptions: { From bc25fdae2bf06286ce8b11833e9fc3c4b67a9500 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 16 Jan 2026 16:51:15 -0800 Subject: [PATCH 28/57] add simplifications to the deno flow --- .github/workflows/js.yaml | 8 ++----- js/smoke/run-tests.sh | 29 +++++++++++++++++++++--- js/smoke/tests/deno/browser/package.json | 3 +-- js/smoke/tests/deno/node/package.json | 3 +-- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 989fb5d73..8c17f68a5 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -587,7 +587,7 @@ jobs: fail-fast: false matrix: node-version: [20, 22] - mode: [deno, deno-browser] + mode: [deno-node, deno-browser] steps: - uses: actions/checkout@v4 @@ -613,8 +613,4 @@ jobs: - name: Run Deno smoke test (${{ matrix.mode }}) working-directory: js/smoke run: | - if [ "${{ matrix.mode }}" = "deno" ]; then - ./run-tests.sh deno - else - cd tests/deno/browser && npm test - fi + ./run-tests.sh ${{ matrix.mode }} diff --git a/js/smoke/run-tests.sh b/js/smoke/run-tests.sh index 57e57fda7..e3c25c075 100755 --- a/js/smoke/run-tests.sh +++ b/js/smoke/run-tests.sh @@ -70,8 +70,19 @@ discover_tests() { local -a tests for dir in "$TESTS_DIR"/*/; do [ -d "$dir" ] || continue + local dirname=$(basename "$dir") + # deno-node and deno-browser + if [ "$dirname" = "deno" ]; then + continue + fi if [ -f "$dir/package.json" ]; then - tests+=("$(basename "$dir")") + tests+=("$dirname") + fi + done + # Add deno nested tests (deno-node, deno-browser, etc.) + for nested in node browser; do + if [ -d "$TESTS_DIR/deno/$nested" ] && [ -f "$TESTS_DIR/deno/$nested/package.json" ]; then + tests+=("deno-$nested") fi done echo "${tests[@]}" @@ -89,6 +100,11 @@ list_tests() { # Show description from package.json if available local pkg="$TESTS_DIR/$test_name/package.json" + # Handle nested deno tests (deno-node, deno-browser, etc.) + if [[ "$test_name" =~ ^deno- ]]; then + local nested="${test_name#deno-}" + pkg="$TESTS_DIR/deno/$nested/package.json" + fi if [ -f "$pkg" ]; then local desc=$(jq -r '.description // ""' "$pkg" 2>/dev/null || echo "") if [ -n "$desc" ]; then @@ -147,6 +163,12 @@ run_test() { local test_name=$1 local test_dir="$TESTS_DIR/$test_name" + # Handle nested deno tests (deno-node, deno-browser, etc.) + if [[ "$test_name" =~ ^deno- ]]; then + local nested="${test_name#deno-}" + test_dir="$TESTS_DIR/deno/$nested" + fi + if [ ! -d "$test_dir" ]; then log_error "Test directory not found: $test_name" FAILED_TESTS+=("$test_name (not found)") @@ -171,8 +193,9 @@ run_test() { log_info "Running: npm run $npm_script" # Ensure Deno has a local file:// module to import (deno.json maps `braintrust` to ./build/braintrust/dist/index.mjs) - if [ "$test_name" = "deno" ] || [ "$test_name" = "deno-browser" ]; then - local deno_dir="$TESTS_DIR/$test_name" + # All deno tests (deno, deno-node, deno-browser, etc.) extract build to tests/deno/build/ (shared location) + if [ "$test_name" = "deno" ] || [[ "$test_name" =~ ^deno- ]]; then + local deno_dir="$TESTS_DIR/deno" local deno_build_file="$deno_dir/build/braintrust/dist/index.mjs" if [ ! -f "$deno_build_file" ]; then log_info "Preparing Deno build directory from packed braintrust tarball..." diff --git a/js/smoke/tests/deno/browser/package.json b/js/smoke/tests/deno/browser/package.json index 6384ea936..f8b400a12 100644 --- a/js/smoke/tests/deno/browser/package.json +++ b/js/smoke/tests/deno/browser/package.json @@ -4,7 +4,6 @@ "description": "Smoke test for Braintrust browser build in Deno runtime", "private": true, "scripts": { - "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts", - "install-build": "npx tsx ../../../install-build.ts ../../../../artifacts braintrust" + "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts" } } diff --git a/js/smoke/tests/deno/node/package.json b/js/smoke/tests/deno/node/package.json index 153b63a3f..c38349cbc 100644 --- a/js/smoke/tests/deno/node/package.json +++ b/js/smoke/tests/deno/node/package.json @@ -4,7 +4,6 @@ "description": "Smoke test for Braintrust Node build in Deno runtime", "private": true, "scripts": { - "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts span_test.ts", - "install-build": "npx tsx ../../../install-build.ts ../../../../artifacts braintrust" + "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts span_test.ts" } } From 6233f9c68a1eb3a934275dd8e0d0a823a4049b36 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 20 Jan 2026 14:57:38 -0800 Subject: [PATCH 29/57] remove no-external --- js/tsup.config.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/js/tsup.config.ts b/js/tsup.config.ts index a22616f14..9fe7424c0 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -8,12 +8,6 @@ export default defineConfig([ format: ["cjs", "esm"], outDir: "dist", external: ["zod"], - noExternal: [ - "mustache", - "eventsource-parser", - "zod-to-json-schema", - "@vercel/functions", - ], removeNodeProtocol: false, dts: { // Split DTS generation to reduce memory usage From 9108e849aae77557b181876daf944f4e32dfe256 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 20 Jan 2026 15:00:00 -0800 Subject: [PATCH 30/57] remove browser templates --- js/src/template/nunjucks-env.browser.ts | 11 ----------- js/src/template/nunjucks-utils.browser.ts | 5 ----- 2 files changed, 16 deletions(-) delete mode 100644 js/src/template/nunjucks-env.browser.ts delete mode 100644 js/src/template/nunjucks-utils.browser.ts diff --git a/js/src/template/nunjucks-env.browser.ts b/js/src/template/nunjucks-env.browser.ts deleted file mode 100644 index 000176c04..000000000 --- a/js/src/template/nunjucks-env.browser.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function getNunjucksEnv(): never { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); -} - -export function renderNunjucksString(): never { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); -} diff --git a/js/src/template/nunjucks-utils.browser.ts b/js/src/template/nunjucks-utils.browser.ts deleted file mode 100644 index cdf1a5c77..000000000 --- a/js/src/template/nunjucks-utils.browser.ts +++ /dev/null @@ -1,5 +0,0 @@ -export function lintTemplate(): never { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); -} From 9ec8e9dfcc5ea63fd59c2b2cc34a0308dd1a7ddb Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 20 Jan 2026 15:43:21 -0800 Subject: [PATCH 31/57] Smoke v2 (#1283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Braintrust JS SDK Smoke Tests v2 ### Design Principles 1. **Well-Known Tarball Paths**: Uses version-agnostic paths like `braintrust-latest.tgz` so package.json never changes 2. **Build Before Install**: Ensures artifacts exist before npm tries to install them 3. **Track Lock Files**: Commits lock files to catch transitive dependency issues 4. **Makefile as Source of Truth**: Single clear interface (`make test`) for every scenario 5. **Expected Failures Support**: Uses `xfail` status to document known platform limitations without failing tests ### Quick Start ```bash # Run all scenarios make test # Run specific scenario make test otel-v1 # List available scenarios make list ``` ### What's Improved from v1 - ✅ No version-specific tarballs (eliminates package.json churn) - ✅ Peer dependencies fully specified (no `--legacy-peer-deps` workaround) - ✅ Auto-discovery (no manual registration) - ✅ Shared test package for DRY test logic - ✅ Lock files tracked (surfaces packaging issues early) This infrastructure ensures the Braintrust SDK "just works" across the JavaScript ecosystem's diverse runtime landscape. --- .github/workflows/js.yaml | 432 +- js/smoke/.gitignore | 1 - js/smoke/Makefile | 129 + js/smoke/README.md | 476 +- js/smoke/backup-and-restore.ts | 38 - js/smoke/enable-esm.ts | 8 - js/smoke/install-build.ts | 77 - js/smoke/prepare-tests.sh | 228 - js/smoke/run-tests.sh | 385 -- .../scenarios/cloudflare-vite-hono/.gitignore | 7 + .../scenarios/cloudflare-vite-hono/Makefile | 33 + .../scenarios/cloudflare-vite-hono/README.md | 51 + .../scenarios/cloudflare-vite-hono/mise.toml | 3 + .../cloudflare-vite-hono/package.json | 24 + .../cloudflare-vite-hono/src/worker.ts} | 52 +- .../tests/vite-dev.test.mjs} | 91 +- .../tests/worker.test.mjs} | 14 +- .../cloudflare-vite-hono}/tsconfig.json | 15 +- .../cloudflare-vite-hono}/vite.config.ts | 0 .../cloudflare-vite-hono/wrangler.toml | 3 + .../.gitignore | 4 + .../cloudflare-worker-browser-compat/Makefile | 29 + .../README.md | 25 + .../mise.toml | 3 + .../package.json | 16 + .../src/worker.ts | 157 + .../tests/worker.test.mjs | 98 + .../tsconfig.json | 17 + .../wrangler.toml | 4 + .../.gitignore | 4 + .../Makefile | 29 + .../README.md | 25 + .../mise.toml | 3 + .../package.json | 16 + .../src/worker.ts | 157 + .../tests/worker.test.mjs | 98 + .../tsconfig.json | 17 + .../wrangler.toml | 3 + .../cloudflare-worker-node-compat/.gitignore | 4 + .../cloudflare-worker-node-compat/Makefile | 29 + .../cloudflare-worker-node-compat/README.md | 24 + .../cloudflare-worker-node-compat/mise.toml | 3 + .../package.json | 16 + .../src/worker.ts | 157 + .../tests/worker.test.mjs | 98 + .../tsconfig.json | 17 + .../wrangler.toml} | 4 +- .../.gitignore | 4 + .../cloudflare-worker-node-no-compat/Makefile | 29 + .../README.md | 26 + .../mise.toml | 3 + .../package.json | 16 + .../src/worker.ts | 135 + .../tests/worker.test.mjs | 106 + .../tsconfig.json | 17 + .../wrangler.toml | 3 + js/smoke/scenarios/deno-browser/.gitignore | 3 + js/smoke/scenarios/deno-browser/Makefile | 21 + js/smoke/scenarios/deno-browser/README.md | 35 + js/smoke/scenarios/deno-browser/deno.json | 12 + js/smoke/scenarios/deno-browser/deno.lock | 908 +++ js/smoke/scenarios/deno-browser/mise.toml | 3 + .../deno-browser/tests/shared-suite.test.ts | 87 + js/smoke/scenarios/deno-node/.gitignore | 3 + js/smoke/scenarios/deno-node/Makefile | 21 + js/smoke/scenarios/deno-node/README.md | 27 + js/smoke/scenarios/deno-node/deno.json | 12 + js/smoke/scenarios/deno-node/deno.lock | 908 +++ js/smoke/scenarios/deno-node/mise.toml | 3 + .../deno-node/tests/shared-suite.test.ts} | 62 +- js/smoke/scenarios/jest-node/.gitignore | 6 + js/smoke/scenarios/jest-node/Makefile | 39 + js/smoke/scenarios/jest-node/README.md | 13 + js/smoke/scenarios/jest-node/mise.toml | 3 + js/smoke/scenarios/jest-node/package.json | 15 + .../jest-node/tests/basic-span.test.js | 117 + .../jest-node/tests/shared-suite.test.js | 60 + js/smoke/scenarios/jest-node/tsconfig.json | 15 + .../nextjs-instrumentation/.gitignore | 5 + .../scenarios/nextjs-instrumentation/Makefile | 48 + .../nextjs-instrumentation/README.md | 40 + .../nextjs-instrumentation/mise.toml | 6 + .../nextjs-instrumentation/next-env.d.ts | 5 + .../nextjs-instrumentation/next.config.mjs | 0 .../nextjs-instrumentation/package.json | 17 +- .../src}/app/api/smoke-test/edge/route.ts | 50 +- .../src}/app/api/smoke-test/node/route.ts | 28 +- .../src}/app/layout.tsx | 0 .../nextjs-instrumentation/src}/app/page.tsx | 0 .../src}/instrumentation.ts | 2 +- .../tests/api-routes.test.mjs} | 85 +- .../nextjs-instrumentation/tsconfig.json | 0 js/smoke/scenarios/otel-v1/.gitignore | 4 + js/smoke/scenarios/otel-v1/Makefile | 60 + js/smoke/scenarios/otel-v1/README.md | 32 + js/smoke/scenarios/otel-v1/mise.toml | 6 + js/smoke/scenarios/otel-v1/package.json | 20 + .../scenarios/otel-v1/src/test-helpers.ts | 53 + .../scenarios/otel-v1/tests/basic.test.ts | 80 + .../scenarios/otel-v1/tests/filtering.test.ts | 144 + .../otel-v1/tests/shared-suite.test.ts | 63 + .../otel-v1}/tsconfig.json | 10 +- .../scenarios/playwright-browser/.gitignore | 8 + .../scenarios/playwright-browser/Makefile | 29 + .../scenarios/playwright-browser/README.md | 45 + .../playwright-browser/esbuild.config.mjs} | 3 - .../scenarios/playwright-browser/mise.toml | 3 + .../scenarios/playwright-browser/package.json | 18 + .../pages/browser-tests.html | 0 .../playwright-browser}/playwright.config.ts | 3 - .../playwright-browser/src/browser-tests.ts | 165 + .../playwright-browser}/src/harness.ts | 2 - .../playwright-browser/tests/browser.test.ts | 181 + .../playwright-browser}/tsconfig.json | 2 +- js/smoke/shared/README.md | 43 + js/smoke/shared/deno.json | 6 + js/smoke/shared/package-lock.json | 3 - js/smoke/shared/src/helpers/display.ts | 101 + js/smoke/shared/src/helpers/types.ts | 9 +- js/smoke/shared/src/index.ts | 10 + js/smoke/shared/src/suites/basic-logging.ts | 153 +- js/smoke/shared/src/suites/eval-smoke.ts | 13 +- .../shared/src/suites/import-verification.ts | 169 +- .../shared/src/suites/prompt-templating.ts | 109 +- js/smoke/tests/browser/.gitignore | 6 - js/smoke/tests/browser/README.md | 84 - js/smoke/tests/browser/global-setup.ts | 34 - js/smoke/tests/browser/package-lock.json | 2480 ------- js/smoke/tests/browser/package.json | 30 - js/smoke/tests/browser/src/browser-tests.ts | 127 - js/smoke/tests/browser/tests/browser.test.ts | 115 - .../tests/cloudflare-worker/package-lock.json | 3748 ----------- js/smoke/tests/cloudflare-worker/package.json | 26 - js/smoke/tests/cloudflare-worker/run-test.mjs | 215 - .../src/browser-no-compat.ts | 4 - .../src/browser-node-compat.ts | 7 - .../tests/cloudflare-worker/src/browser.ts | 4 - .../cloudflare-worker/src/node-no-compat.ts | 4 - .../cloudflare-worker/src/node-node-compat.ts | 4 - js/smoke/tests/cloudflare-worker/src/node.ts | 4 - .../tests/cloudflare-worker/src/worker.ts | 116 - .../tests/cloudflare-worker/tsconfig.json | 19 - .../wrangler.browser-node-compat.toml | 4 - .../cloudflare-worker/wrangler.browser.toml | 3 - .../wrangler.node-no-compat.toml | 3 - js/smoke/tests/deno/.gitignore | 6 - js/smoke/tests/deno/browser/README.md | 69 - js/smoke/tests/deno/browser/deno.json | 11 - js/smoke/tests/deno/browser/deno.lock | 59 - js/smoke/tests/deno/browser/package.json | 9 - .../tests/deno/browser/shared_suite_test.ts | 63 - js/smoke/tests/deno/node/deno.json | 14 - js/smoke/tests/deno/node/deno.lock | 89 - js/smoke/tests/deno/node/package.json | 9 - js/smoke/tests/deno/node/span_test.ts | 59 - js/smoke/tests/deno/package-lock.json | 2069 ------ js/smoke/tests/deno/package.json | 11 - .../tests/nextjs-instrumentation/.gitignore | 23 - .../tests/nextjs-instrumentation/README.md | 176 - .../nextjs-instrumentation/package-lock.json | 3305 ---------- js/smoke/tests/otel-v1/README.md | 50 - js/smoke/tests/otel-v1/otel_example.ts | 150 - js/smoke/tests/otel-v1/package-lock.json | 3253 ---------- js/smoke/tests/otel-v1/package.json | 30 - js/smoke/tests/otel-v1/tsconfig.json | 17 - js/smoke/tests/span-jest/package-lock.json | 5749 ----------------- js/smoke/tests/span-jest/package.json | 25 - .../span-jest/shared_suite_test.jest.test.js | 96 - .../simple_span_example.jest.test.js | 65 - js/smoke/tests/span/package-lock.json | 1855 ------ js/smoke/tests/span/package.json | 25 - js/smoke/tests/span/shared_suite_test.ts | 114 - js/smoke/tests/span/simple_span_example.ts | 34 - js/smoke/tests/span/span_test_helper.ts | 155 - js/smoke/tests/span/tsconfig.json | 17 - js/smoke/tests/vite-react-hono/.gitignore | 5 - js/smoke/tests/vite-react-hono/README.md | 195 - js/smoke/tests/vite-react-hono/index.html | 13 - .../tests/vite-react-hono/package-lock.json | 5419 ---------------- js/smoke/tests/vite-react-hono/package.json | 32 - .../vite-react-hono/src/react-app/App.css | 40 - .../vite-react-hono/src/react-app/App.tsx | 55 - .../vite-react-hono/src/react-app/index.css | 31 - .../vite-react-hono/src/react-app/main.tsx | 10 - .../src/react-app/vite-env.d.ts | 1 - .../tests/vite-react-hono/tsconfig.app.json | 21 - .../tests/vite-react-hono/tsconfig.node.json | 18 - .../vite-react-hono/tsconfig.worker.json | 8 - js/smoke/tests/vite-react-hono/wrangler.json | 7 - package.json | 5 +- pnpm-workspace.yaml | 1 - 191 files changed, 5815 insertions(+), 32359 deletions(-) delete mode 100644 js/smoke/.gitignore create mode 100644 js/smoke/Makefile delete mode 100644 js/smoke/backup-and-restore.ts delete mode 100644 js/smoke/enable-esm.ts delete mode 100644 js/smoke/install-build.ts delete mode 100755 js/smoke/prepare-tests.sh delete mode 100755 js/smoke/run-tests.sh create mode 100644 js/smoke/scenarios/cloudflare-vite-hono/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-vite-hono/Makefile create mode 100644 js/smoke/scenarios/cloudflare-vite-hono/README.md create mode 100644 js/smoke/scenarios/cloudflare-vite-hono/mise.toml create mode 100644 js/smoke/scenarios/cloudflare-vite-hono/package.json rename js/smoke/{tests/vite-react-hono/src/worker/index.ts => scenarios/cloudflare-vite-hono/src/worker.ts} (68%) rename js/smoke/{tests/vite-react-hono/test-vite-dev.mjs => scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs} (64%) mode change 100644 => 100755 rename js/smoke/{tests/vite-react-hono/run-test.mjs => scenarios/cloudflare-vite-hono/tests/worker.test.mjs} (83%) rename js/smoke/{tests/vite-react-hono => scenarios/cloudflare-vite-hono}/tsconfig.json (54%) rename js/smoke/{tests/vite-react-hono => scenarios/cloudflare-vite-hono}/vite.config.ts (100%) create mode 100644 js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/Makefile create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/README.md create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/mise.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/package.json create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/tests/worker.test.mjs create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/tsconfig.json create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/Makefile create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/README.md create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/mise.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/tests/worker.test.mjs create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/tsconfig.json create mode 100644 js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/Makefile create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/README.md create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/mise.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/package.json create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/tests/worker.test.mjs create mode 100644 js/smoke/scenarios/cloudflare-worker-node-compat/tsconfig.json rename js/smoke/{tests/cloudflare-worker/wrangler.node.toml => scenarios/cloudflare-worker-node-compat/wrangler.toml} (52%) create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/Makefile create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/README.md create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/mise.toml create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/package.json create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/tests/worker.test.mjs create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/tsconfig.json create mode 100644 js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml create mode 100644 js/smoke/scenarios/deno-browser/.gitignore create mode 100644 js/smoke/scenarios/deno-browser/Makefile create mode 100644 js/smoke/scenarios/deno-browser/README.md create mode 100644 js/smoke/scenarios/deno-browser/deno.json create mode 100644 js/smoke/scenarios/deno-browser/deno.lock create mode 100644 js/smoke/scenarios/deno-browser/mise.toml create mode 100644 js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts create mode 100644 js/smoke/scenarios/deno-node/.gitignore create mode 100644 js/smoke/scenarios/deno-node/Makefile create mode 100644 js/smoke/scenarios/deno-node/README.md create mode 100644 js/smoke/scenarios/deno-node/deno.json create mode 100644 js/smoke/scenarios/deno-node/deno.lock create mode 100644 js/smoke/scenarios/deno-node/mise.toml rename js/smoke/{tests/deno/node/shared_suite_test.ts => scenarios/deno-node/tests/shared-suite.test.ts} (52%) create mode 100644 js/smoke/scenarios/jest-node/.gitignore create mode 100644 js/smoke/scenarios/jest-node/Makefile create mode 100644 js/smoke/scenarios/jest-node/README.md create mode 100644 js/smoke/scenarios/jest-node/mise.toml create mode 100644 js/smoke/scenarios/jest-node/package.json create mode 100644 js/smoke/scenarios/jest-node/tests/basic-span.test.js create mode 100644 js/smoke/scenarios/jest-node/tests/shared-suite.test.js create mode 100644 js/smoke/scenarios/jest-node/tsconfig.json create mode 100644 js/smoke/scenarios/nextjs-instrumentation/.gitignore create mode 100644 js/smoke/scenarios/nextjs-instrumentation/Makefile create mode 100644 js/smoke/scenarios/nextjs-instrumentation/README.md create mode 100644 js/smoke/scenarios/nextjs-instrumentation/mise.toml create mode 100644 js/smoke/scenarios/nextjs-instrumentation/next-env.d.ts rename js/smoke/{tests => scenarios}/nextjs-instrumentation/next.config.mjs (100%) rename js/smoke/{tests => scenarios}/nextjs-instrumentation/package.json (55%) rename js/smoke/{tests/nextjs-instrumentation => scenarios/nextjs-instrumentation/src}/app/api/smoke-test/edge/route.ts (73%) rename js/smoke/{tests/nextjs-instrumentation => scenarios/nextjs-instrumentation/src}/app/api/smoke-test/node/route.ts (87%) rename js/smoke/{tests/nextjs-instrumentation => scenarios/nextjs-instrumentation/src}/app/layout.tsx (100%) rename js/smoke/{tests/nextjs-instrumentation => scenarios/nextjs-instrumentation/src}/app/page.tsx (100%) rename js/smoke/{tests/nextjs-instrumentation => scenarios/nextjs-instrumentation/src}/instrumentation.ts (98%) rename js/smoke/{tests/nextjs-instrumentation/test-api-routes.mjs => scenarios/nextjs-instrumentation/tests/api-routes.test.mjs} (57%) rename js/smoke/{tests => scenarios}/nextjs-instrumentation/tsconfig.json (100%) create mode 100644 js/smoke/scenarios/otel-v1/.gitignore create mode 100644 js/smoke/scenarios/otel-v1/Makefile create mode 100644 js/smoke/scenarios/otel-v1/README.md create mode 100644 js/smoke/scenarios/otel-v1/mise.toml create mode 100644 js/smoke/scenarios/otel-v1/package.json create mode 100644 js/smoke/scenarios/otel-v1/src/test-helpers.ts create mode 100644 js/smoke/scenarios/otel-v1/tests/basic.test.ts create mode 100644 js/smoke/scenarios/otel-v1/tests/filtering.test.ts create mode 100644 js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts rename js/smoke/{tests/span-jest => scenarios/otel-v1}/tsconfig.json (66%) create mode 100644 js/smoke/scenarios/playwright-browser/.gitignore create mode 100644 js/smoke/scenarios/playwright-browser/Makefile create mode 100644 js/smoke/scenarios/playwright-browser/README.md rename js/smoke/{tests/browser/esbuild.config.js => scenarios/playwright-browser/esbuild.config.mjs} (77%) create mode 100644 js/smoke/scenarios/playwright-browser/mise.toml create mode 100644 js/smoke/scenarios/playwright-browser/package.json rename js/smoke/{tests/browser => scenarios/playwright-browser}/pages/browser-tests.html (100%) rename js/smoke/{tests/browser => scenarios/playwright-browser}/playwright.config.ts (83%) create mode 100644 js/smoke/scenarios/playwright-browser/src/browser-tests.ts rename js/smoke/{tests/browser => scenarios/playwright-browser}/src/harness.ts (96%) create mode 100644 js/smoke/scenarios/playwright-browser/tests/browser.test.ts rename js/smoke/{tests/browser => scenarios/playwright-browser}/tsconfig.json (85%) create mode 100644 js/smoke/shared/deno.json create mode 100644 js/smoke/shared/src/helpers/display.ts delete mode 100644 js/smoke/tests/browser/.gitignore delete mode 100644 js/smoke/tests/browser/README.md delete mode 100644 js/smoke/tests/browser/global-setup.ts delete mode 100644 js/smoke/tests/browser/package-lock.json delete mode 100644 js/smoke/tests/browser/package.json delete mode 100644 js/smoke/tests/browser/src/browser-tests.ts delete mode 100644 js/smoke/tests/browser/tests/browser.test.ts delete mode 100644 js/smoke/tests/cloudflare-worker/package-lock.json delete mode 100644 js/smoke/tests/cloudflare-worker/package.json delete mode 100644 js/smoke/tests/cloudflare-worker/run-test.mjs delete mode 100644 js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts delete mode 100644 js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts delete mode 100644 js/smoke/tests/cloudflare-worker/src/browser.ts delete mode 100644 js/smoke/tests/cloudflare-worker/src/node-no-compat.ts delete mode 100644 js/smoke/tests/cloudflare-worker/src/node-node-compat.ts delete mode 100644 js/smoke/tests/cloudflare-worker/src/node.ts delete mode 100644 js/smoke/tests/cloudflare-worker/src/worker.ts delete mode 100644 js/smoke/tests/cloudflare-worker/tsconfig.json delete mode 100644 js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml delete mode 100644 js/smoke/tests/cloudflare-worker/wrangler.browser.toml delete mode 100644 js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml delete mode 100644 js/smoke/tests/deno/.gitignore delete mode 100644 js/smoke/tests/deno/browser/README.md delete mode 100644 js/smoke/tests/deno/browser/deno.json delete mode 100644 js/smoke/tests/deno/browser/deno.lock delete mode 100644 js/smoke/tests/deno/browser/package.json delete mode 100644 js/smoke/tests/deno/browser/shared_suite_test.ts delete mode 100644 js/smoke/tests/deno/node/deno.json delete mode 100644 js/smoke/tests/deno/node/deno.lock delete mode 100644 js/smoke/tests/deno/node/package.json delete mode 100644 js/smoke/tests/deno/node/span_test.ts delete mode 100644 js/smoke/tests/deno/package-lock.json delete mode 100644 js/smoke/tests/deno/package.json delete mode 100644 js/smoke/tests/nextjs-instrumentation/.gitignore delete mode 100644 js/smoke/tests/nextjs-instrumentation/README.md delete mode 100644 js/smoke/tests/nextjs-instrumentation/package-lock.json delete mode 100644 js/smoke/tests/otel-v1/README.md delete mode 100644 js/smoke/tests/otel-v1/otel_example.ts delete mode 100644 js/smoke/tests/otel-v1/package-lock.json delete mode 100644 js/smoke/tests/otel-v1/package.json delete mode 100644 js/smoke/tests/otel-v1/tsconfig.json delete mode 100644 js/smoke/tests/span-jest/package-lock.json delete mode 100644 js/smoke/tests/span-jest/package.json delete mode 100644 js/smoke/tests/span-jest/shared_suite_test.jest.test.js delete mode 100644 js/smoke/tests/span-jest/simple_span_example.jest.test.js delete mode 100644 js/smoke/tests/span/package-lock.json delete mode 100644 js/smoke/tests/span/package.json delete mode 100644 js/smoke/tests/span/shared_suite_test.ts delete mode 100644 js/smoke/tests/span/simple_span_example.ts delete mode 100644 js/smoke/tests/span/span_test_helper.ts delete mode 100644 js/smoke/tests/span/tsconfig.json delete mode 100644 js/smoke/tests/vite-react-hono/.gitignore delete mode 100644 js/smoke/tests/vite-react-hono/README.md delete mode 100644 js/smoke/tests/vite-react-hono/index.html delete mode 100644 js/smoke/tests/vite-react-hono/package-lock.json delete mode 100644 js/smoke/tests/vite-react-hono/package.json delete mode 100644 js/smoke/tests/vite-react-hono/src/react-app/App.css delete mode 100644 js/smoke/tests/vite-react-hono/src/react-app/App.tsx delete mode 100644 js/smoke/tests/vite-react-hono/src/react-app/index.css delete mode 100644 js/smoke/tests/vite-react-hono/src/react-app/main.tsx delete mode 100644 js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts delete mode 100644 js/smoke/tests/vite-react-hono/tsconfig.app.json delete mode 100644 js/smoke/tests/vite-react-hono/tsconfig.node.json delete mode 100644 js/smoke/tests/vite-react-hono/tsconfig.worker.json delete mode 100644 js/smoke/tests/vite-react-hono/wrangler.json diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index 8c17f68a5..ba40b3cad 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -108,7 +108,6 @@ jobs: api-compatibility: runs-on: ubuntu-latest # Run in parallel with build job - strategy: fail-fast: false matrix: @@ -199,418 +198,87 @@ jobs: run: | cd js && pnpm test:api-compat - smoke-tests-node: - needs: build - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - integration: [otel-v1, span] - os: [ubuntu-latest, windows-latest] - node-version: [20, 22] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Backup original integration package manifests - working-directory: js/smoke/tests/${{ matrix.integration }} - run: | - npm run backup - - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist - path: js/artifacts - run-id: ${{ github.run_id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install SDK artifacts for ${{ matrix.integration }} - working-directory: js/smoke/tests/${{ matrix.integration }} - shell: bash - run: | - # Remove package-lock.json to avoid version mismatch with downloaded artifacts - rm -f package-lock.json - - if [ "${{ matrix.integration }}" != "otel-v1" ]; then - npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - else - npm install --legacy-peer-deps - npx tsx ../../install-build.ts ../../../artifacts braintrust - npx tsx ../../install-build.ts ../../../artifacts otel - fi - - - name: Build shared test package - working-directory: js/smoke/shared - run: | - npm ci - npm run build - - - name: Run smoke test for ${{ matrix.integration }} - working-directory: js/smoke - shell: bash - env: - BRAINTRUST_API_KEY: ${{ matrix.integration == 'otel-v1' && secrets.BRAINTRUST_API_KEY || '' }} - BRAINTRUST_OTEL_COMPAT: ${{ matrix.integration == 'otel-v1' && secrets.BRAINTRUST_API_KEY || '' }} - run: | - ./run-tests.sh ${{ matrix.integration }} - - - name: Restore original package.json files - if: always() - working-directory: js/smoke/tests/${{ matrix.integration }} - run: | - npm run restore - - smoke-tests-jest: - needs: build - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - node-version: [20, 22] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Backup original span-jest package manifests - working-directory: js/smoke/tests/span-jest - run: | - npm run backup - - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist - path: js/artifacts - run-id: ${{ github.run_id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies and local build for Jest span smoke test - working-directory: js/smoke/tests/span-jest - shell: bash - run: | - # Remove package-lock.json to avoid version mismatch with downloaded artifacts - rm -f package-lock.json - npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - - - name: Build shared test package - working-directory: js/smoke/shared - run: | - npm ci - npm run build - - - name: Run Jest span smoke test - working-directory: js/smoke - shell: bash - run: | - ./run-tests.sh span-jest - - - name: Restore original span-jest package.json files - if: always() - working-directory: js/smoke/tests/span-jest - run: | - npm run restore - - smoke-tests-nextjs: - needs: build - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - node-version: [20, 22] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Backup original package manifests - working-directory: js/smoke/tests/nextjs-instrumentation - run: | - npm run backup - - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist - path: js/artifacts - run-id: ${{ github.run_id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies and local builds - working-directory: js/smoke/tests/nextjs-instrumentation - shell: bash - run: | - # Remove package-lock.json to avoid version mismatch with downloaded artifacts - rm -f package-lock.json - npm install --legacy-peer-deps - npx tsx ../../install-build.ts ../../../artifacts braintrust - npx tsx ../../install-build.ts ../../../artifacts otel - - - name: Build shared test package - working-directory: js/smoke/shared - run: | - npm ci - npm run build - - - name: Run Next.js smoke test - working-directory: js/smoke - shell: bash - env: - BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }} - run: | - ./run-tests.sh nextjs-instrumentation - - - name: Restore original package.json files - if: always() - working-directory: js/smoke/tests/nextjs-instrumentation - run: | - npm run restore - - smoke-tests-cloudflare-worker: - needs: build + # Smoke v2: Auto-discovery of scenarios + smoke-discover: runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - node-version: [20, 22] - mode: - [ - braintrust-node-compat, - braintrust-browser-node-compat, - braintrust-browser-no-compat, - braintrust-no-compat, - ] - + outputs: + scenarios: ${{ steps.discover.outputs.scenarios }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Backup original package manifests - working-directory: js/smoke/tests/cloudflare-worker - run: | - npm run backup - - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist - path: js/artifacts - run-id: ${{ github.run_id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies and local build - working-directory: js/smoke/tests/cloudflare-worker - shell: bash - run: | - # Remove package-lock.json to avoid version mismatch with downloaded artifacts - rm -f package-lock.json - npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - - - name: Build shared test package - working-directory: js/smoke/shared - run: | - npm ci - npm run build - - - name: Run cloudflare-worker smoke test + - uses: actions/checkout@v4 + - name: Discover scenarios + id: discover working-directory: js/smoke shell: bash - env: - CLOUDFLARE_WORKER_MODE: ${{ matrix.mode }} run: | - ./run-tests.sh cloudflare-worker + # Use the same auto-discovery logic as the Makefile + SCENARIOS=$(command find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | sort | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "scenarios=$SCENARIOS" >> "$GITHUB_OUTPUT" + echo "Discovered scenarios: $SCENARIOS" - - name: Restore original package.json files - if: always() - working-directory: js/smoke/tests/cloudflare-worker - run: | - npm run restore - - smoke-tests-vite-react-hono: - needs: build + smoke-test: + needs: [build, smoke-discover] runs-on: ubuntu-latest strategy: fail-fast: false matrix: - node-version: [20, 22] + scenario: ${{ fromJson(needs.smoke-discover.outputs.scenarios) }} steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - name: Setup mise + uses: jdx/mise-action@v2 with: - node-version: ${{ matrix.node-version }} + working_directory: js/smoke - - name: Backup original package manifests - working-directory: js/smoke/tests/vite-react-hono - run: | - npm run backup + - uses: pnpm/action-setup@v4 - - name: Download build artifact + - name: Download build artifact (node 20) uses: actions/download-artifact@v4 with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist + name: ${{ needs.build.outputs.artifact-name }}-20-dist path: js/artifacts run-id: ${{ github.run_id }} github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install dependencies and local build - working-directory: js/smoke/tests/vite-react-hono + - name: Prepare artifacts at well-known paths + working-directory: js/artifacts shell: bash run: | - # Remove package-lock.json to avoid version mismatch with downloaded artifacts - rm -f package-lock.json - npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - - - name: Build shared test package + # Copy braintrust tarball to well-known path + for f in braintrust-[0-9]*.tgz; do + if [ -f "$f" ]; then + cp "$f" braintrust-latest.tgz + echo "Copied $f to braintrust-latest.tgz" + break + fi + done + + # Copy otel tarball to well-known path + for f in braintrust-otel-[0-9]*.tgz; do + if [ -f "$f" ]; then + cp "$f" braintrust-otel-latest.tgz + echo "Copied $f to braintrust-otel-latest.tgz" + break + fi + done + + - name: Build shared test package (once for all scenarios) working-directory: js/smoke/shared - run: | - npm ci - npm run build - - - name: Run vite-react-hono smoke test - working-directory: js/smoke - shell: bash - run: | - ./run-tests.sh vite-react-hono - - - name: Restore original package.json files - if: always() - working-directory: js/smoke/tests/vite-react-hono - run: | - npm run restore - - smoke-tests-browser: - needs: build - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - node-version: [20, 22] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Backup original package manifests - working-directory: js/smoke/tests/browser - run: | - npm run backup - - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist - path: js/artifacts - run-id: ${{ github.run_id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dependencies and local build - working-directory: js/smoke/tests/browser - shell: bash - run: | - # Remove package-lock.json to avoid version mismatch with downloaded artifacts - rm -f package-lock.json - npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - - - name: Install Playwright Chromium (with OS deps) - working-directory: js/smoke/tests/browser shell: bash - run: | - npx playwright install --with-deps chromium - - - name: Build shared test package - working-directory: js/smoke/shared run: | npm ci npm run build - - name: Run Browser (Playwright) smoke test + - name: Run scenario ${{ matrix.scenario }} working-directory: js/smoke shell: bash + env: + BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }} + CI: true + BRAINTRUST_TAR: ../artifacts/braintrust-latest.tgz + BRAINTRUST_OTEL_TAR: ../artifacts/braintrust-otel-latest.tgz + SMOKE_V2_SHARED_DIST: shared/dist run: | - ./run-tests.sh browser - - - name: Restore original package.json files - if: always() - working-directory: js/smoke/tests/browser - run: | - npm run restore - - smoke-tests-deno: - needs: build - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - node-version: [20, 22] - mode: [deno-node, deno-browser] - - steps: - - uses: actions/checkout@v4 - - name: Setup Deno - uses: denoland/setup-deno@v2 - with: - deno-version: v2.x - - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }}-${{ matrix.node-version }}-dist - path: js/artifacts - run-id: ${{ github.run_id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Build shared test package - working-directory: js/smoke/shared - run: | - npm ci - npm run build - - - name: Run Deno smoke test (${{ matrix.mode }}) - working-directory: js/smoke - run: | - ./run-tests.sh ${{ matrix.mode }} + make test ${{ matrix.scenario }} diff --git a/js/smoke/.gitignore b/js/smoke/.gitignore deleted file mode 100644 index 46719c370..000000000 --- a/js/smoke/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.prepare-marker diff --git a/js/smoke/Makefile b/js/smoke/Makefile new file mode 100644 index 000000000..7fa08d910 --- /dev/null +++ b/js/smoke/Makefile @@ -0,0 +1,129 @@ +# Auto-discover scenarios (any folder in scenarios/ with a Makefile) +SCENARIOS := $(shell find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | sort) + +.PHONY: help setup test list clean + +# ============================================================================= +# Help +# ============================================================================= + +help: + @echo "Smoke Test Infrastructure" + @echo "" + @echo "Available targets:" + @echo " make test - Run all scenarios (builds SDK once if needed)" + @echo " make test - Run specific scenario (e.g., make test otel-v1)" + @echo " make setup - Ensure SDK artifacts + shared package are ready" + @echo " make clean - Remove all build artifacts (force rebuild)" + @echo " make list - List discovered scenarios" + @echo "" + @echo "Environment variables:" + @echo " BRAINTRUST_TAR - Path to braintrust tarball (auto-set by parent when running locally)" + @echo " BRAINTRUST_OTEL_TAR - Path to otel tarball (auto-set by parent when running locally)" + @echo " SMOKE_V2_SHARED_DIST - Path to shared package dist (auto-set by parent when running locally)" + @echo "" + @echo "Running individual scenarios:" + @echo " cd scenarios/otel-v1 && make test - Runs standalone, builds if needed" + @echo "" + @echo "Discovered scenarios:" + @for scenario in $(SCENARIOS); do echo " - $$scenario"; done + +# ============================================================================= +# Setup - Build SDK + shared package +# ============================================================================= + +setup: + @echo "==> Setting up smoke" + @mkdir -p ../artifacts + + @# Build SDK and create tarball if not provided + @if [ -n "$(BRAINTRUST_TAR)" ] && [ -f "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using provided BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK and creating tarball"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && pnpm --filter=braintrust pack --pack-destination sdk/js/artifacts; \ + \ + for f in sdk/js/artifacts/braintrust-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ + cp "$$f" sdk/js/artifacts/braintrust-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @# Build shared package if not provided + @if [ -n "$(SMOKE_V2_SHARED_DIST)" ] && [ -d "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Using provided SMOKE_V2_SHARED_DIST: $(SMOKE_V2_SHARED_DIST)"; \ + else \ + if [ ! -d shared/dist ]; then \ + echo "==> Building shared package"; \ + cd shared && npm ci && npm run build; \ + else \ + echo "==> Shared package already built"; \ + fi; \ + fi + +# ============================================================================= +# Clean - Remove all build artifacts +# ============================================================================= + +clean: + @echo "==> Cleaning smoke artifacts" + rm -rf ../artifacts/*.tgz + rm -rf shared/dist shared/node_modules + +# ============================================================================= +# Test - Run scenarios +# ============================================================================= + +test: + @REQUESTED="$(filter-out test,$(MAKECMDGOALS))"; \ + \ + if [ -z "$$REQUESTED" ]; then \ + SCENARIOS_TO_RUN="$(SCENARIOS)"; \ + echo "==> Running all scenarios"; \ + else \ + SCENARIOS_TO_RUN=""; \ + for scenario in $$REQUESTED; do \ + if [ ! -d "scenarios/$$scenario" ]; then \ + echo "Error: Scenario '$$scenario' not found"; \ + echo "Available scenarios:"; \ + for s in $(SCENARIOS); do echo " - $$s"; done; \ + exit 1; \ + fi; \ + SCENARIOS_TO_RUN="$$SCENARIOS_TO_RUN $$scenario"; \ + done; \ + echo "==> Running scenarios:$$SCENARIOS_TO_RUN"; \ + fi; \ + \ + $(MAKE) setup; \ + \ + : $${BRAINTRUST_TAR:=../artifacts/braintrust-latest.tgz}; \ + : $${BRAINTRUST_OTEL_TAR:=../artifacts/braintrust-otel-latest.tgz}; \ + : $${SMOKE_V2_SHARED_DIST:=shared/dist}; \ + export BRAINTRUST_TAR BRAINTRUST_OTEL_TAR SMOKE_V2_SHARED_DIST; \ + \ + for scenario in $$SCENARIOS_TO_RUN; do \ + echo ""; \ + echo "=== Testing $$scenario ==="; \ + $(MAKE) -C scenarios/$$scenario test || exit 1; \ + done; \ + \ + echo ""; \ + echo "✓ All requested scenarios passed" + +# ============================================================================= +# List - Show discovered scenarios +# ============================================================================= + +list: + @echo "Discovered scenarios:" + @for scenario in $(SCENARIOS); do echo " - $$scenario"; done + +# ============================================================================= +# Make scenario names valid targets (no-ops to support "make test otel-v1") +# ============================================================================= + +$(SCENARIOS): + @: diff --git a/js/smoke/README.md b/js/smoke/README.md index 71832747b..a483fef07 100644 --- a/js/smoke/README.md +++ b/js/smoke/README.md @@ -1,404 +1,200 @@ -# Braintrust JS SDK Smoke Tests +# Braintrust JS SDK Smoke Tests v2 -The smoke tests ensure that a freshly packed `braintrust` build installs -cleanly and can run basic user workflows. These tests run on any PR. +Smoke test infrastructure verifying SDK installation across different runtimes and integrations. -The tests utilize the newly built braintrust package to run first using the CommonJS (CJS) build file and then using the ECMAScript Module (ESM) build file. - -The tests are written without the use of vitest in order to work in both CJS and ESM environments. Vitest is a testing framework that is ESM native and did not support running using CJS. - -## Standardized Test Infrastructure - -The smoke test suite follows **pure "convention over configuration"**: - -- **Auto-discovery** - Any `tests/*/` directory with `package.json` is a test -- **Universal interface** - All tests run via `npm test` -- **Zero registration** - Just create a directory, CI picks it up automatically -- **Master runner** - `run-tests.sh` discovers and runs tests automatically - -### Key Files - -- `run-tests.sh` - Master test runner with auto-discovery -- `tests/*/package.json` - Standard `npm test` script -- `shared/` - Reusable test suites (see below) - -### Convention - -``` -tests/ -├── my-test/ -│ ├── package.json # Must have "test" script -│ └── run-test.js # Test implementation -└── another-test/ - ├── package.json # "test": "npm test" or "deno task test" etc - └── ... -``` - -**That's it!** Test name = directory name. All tests run via `npm test`. - -## Running Tests - -### Build the shared package first - -The shared test package must be built before running any tests: +## Quick Reference ```bash -cd shared -npm install -npm run build +make test # Run all scenarios +make test otel-v1 # Run specific scenario +make list # List available scenarios ``` -### Run tests in specific environments +## Output Standardization (REQUIRED) -All environments now support shared test suites via `test:shared` scripts: +**ALL test files MUST use `displayTestResults()` from the shared package:** -```bash -# Node.js CJS tests -cd tests/span -npm run test:shared - -# Jest tests -cd tests/span-jest -npm run test:shared - -# Deno tests -cd tests/deno -deno task test:shared # Shared test suites -deno task test # Original simple test - -# Cloudflare Worker tests -cd tests/cloudflare-worker -npm test # Runs shared suites via HTTP endpoint - -# Next.js tests -cd tests/nextjs-instrumentation -npm run test:shared # Runs shared suites in Edge + Node.js runtimes -npm run build # Build-time verification (webpack bundling) -``` - -## Shared Test Package - -To maximize test coverage while maintaining DRY principles, common test logic is now shared across environments via the `shared/` package. This package: - -- Provides reusable test suites and helpers -- Builds to both CJS (`dist/index.js`) and ESM (`dist/index.mjs`) formats -- Allows the same test logic to run in Node.js, Deno, Cloudflare Workers, etc. -- Helps catch bundler-specific issues (webpack, esbuild, Deno's bundler handle imports differently) - -See `shared/README.md` for detailed documentation on the shared test package. - -## Repository Layout - - +```typescript +import { + displayTestResults, + hasFailures, + getFailureCount, +} from "../../shared/dist/index.mjs"; - +// Run your tests +const results = [...importResults, ...functionalResults]; -## Repository Layout +// Display with standardized format +displayTestResults({ + scenarioName: "My Scenario Test Results", + results, +}); -- `shared/` - Shared test package providing reusable test suites - - - Builds to both CJS (`dist/index.js`) and ESM (`dist/index.mjs`) - - Contains test suites: `basic-logging`, `import-verification` - - See `shared/README.md` for detailed documentation - -- `tests/` - Test projects for different runtime environments - - `span/` - Node.js CJS tests (uses shared suites) - - `span-jest/` - Jest framework tests (uses shared suites) - - `deno/` - Deno environment tests (uses shared suites) - - `cloudflare-worker/` - Cloudflare Workers tests (uses shared suites) - - `nextjs-instrumentation/` - Next.js tests (Edge + Node.js runtimes via API routes) - - `otel-v1/` - OpenTelemetry v1 ingestion test (specialized) - -## Running Tests - -### Build the shared package first - -The shared test package must be built before running any tests: - -```bash -cd shared -npm install -npm run build -``` - -### Run tests in specific environments - -All environments now support shared test suites via `test:shared` scripts: - -```bash -# Node.js CJS tests -cd tests/span -npm run test:shared - -# Jest tests -cd tests/span-jest -npm run test:shared - -# Deno tests -cd tests/deno -deno task test:shared # Shared test suites -deno task test # Original simple test - -# Cloudflare Worker tests -cd tests/cloudflare-worker -npm test # Runs shared suites via HTTP endpoint - -# Next.js tests -cd tests/nextjs-instrumentation -npm run test:shared # Runs shared suites in Edge + Node.js runtimes -npm run build # Build-time verification (webpack bundling) +// Check for failures +if (hasFailures(results)) { + process.exit(1); +} ``` -## CI Integration - -### SDK Submodule CI +**Keep logging minimal:** No status messages, banners, or summaries. Let `displayTestResults()` do the talking. -The smoke tests run automatically in the **SDK submodule's CI** (`sdk/.github/workflows/js.yaml`) that **builds the SDK from source** and tests against the actual build artifacts. +## Creating a New Scenario -#### Workflow: `sdk/.github/workflows/js.yaml` +### Requirements -Runs on: +- [ ] Makefile with `setup` and `test` targets +- [ ] Environment spec (mise.toml, deno.json, etc.) +- [ ] Dependencies declared (package.json, deno.json, etc.) +- [ ] README.md explaining design decisions (15-25 lines) +- [ ] .gitignore (ignore artifacts, track lock files) +- [ ] **Tests use `displayTestResults()`** +- [ ] **Minimal logging** (errors only) +- [ ] **POSIX shell syntax** (`[ ]` not `[[ ]]`) -- Pull requests to SDK repository -- Pushes to `main` branch in SDK repository +### Patterns -**Build stage:** +**Node.js + npm:** Use tarball paths in package.json. See `scenarios/otel-v1/`. -1. **Builds the SDK** from source (`js/`) - - Runs `npm ci && npm run build` - - Packs into tarball: `npm pack --pack-destination artifacts` -2. **Uploads artifacts** for test jobs to download +**Deno:** Use workspace links via `deno.json`. See `scenarios/deno-node/`. -**Test stages** (parallel jobs): +**Multi-test:** Each test uses `displayTestResults()`. Makefile runs all tests (don't fail early), then exits with failure if any failed. See `scenarios/otel-v1/` for example. -Each smoke test runs in its own job: - -- `smoke-tests-node` - Tests `span` and `otel-v1` -- `smoke-tests-jest` - Tests `span-jest` -- `smoke-tests-nextjs` - Tests `nextjs-instrumentation` -- `smoke-tests-cloudflare` - Tests `cloudflare-worker` -- `smoke-tests-browser` - Tests `browser` (Playwright / browser bundle) -- `smoke-tests-deno` - Tests `deno` - -**Each job:** - -1. Downloads SDK build artifacts -2. Installs SDK into test directory via `install-build.ts` -3. Builds shared test package -4. Runs test via `./run-tests.sh ` - -**Workflow visualization:** - -``` -┌─────────────────────────────────────────────────────────┐ -│ SDK CI: sdk/.github/workflows/js.yaml │ -└─────────────────────────────────────────────────────────┘ - ↓ - ┌───────────────────────────┐ - │ Build Job │ - │ 1. Build SDK from source │ - │ js/ │ - │ 2. Pack into tarball │ - │ 3. Upload artifacts │ - └───────────┬───────────────┘ - ↓ - ┌───────┴────────┬─────────────┬──────────────┐ - ↓ ↓ ↓ ↓ - ┌───────────────┐ ┌────────────┐ ┌─────────┐ ┌──────────┐ - │ smoke-tests- │ │ smoke- │ │ smoke- │ │ smoke- │ - │ node │ │ tests-jest │ │ tests- │ │ tests- │ - │ (span,otel-v1)│ │ (span-jest)│ │ nextjs │ │ deno │ - └───────┬───────┘ └─────┬──────┘ └────┬────┘ └────┬─────┘ - │ │ │ │ - │ For each test job: │ │ - │ 1. Download artifacts │ │ - │ 2. Install SDK │ │ - │ 3. Build shared package │ │ - │ 4. ./run-tests.sh │ │ - │ │ │ - └─────────────┬───────────────┴───────────┘ - ↓ - ✅ Pass or ❌ Fail -``` +### Example Test File -**Key benefit**: Tests run against the **actual build** from the PR, not the npm registry version. +```typescript +import { + setupTestEnvironment, + cleanupTestEnvironment, + runImportVerificationTests, + runBasicLoggingTests, + displayTestResults, + hasFailures, +} from "../../shared/dist/index.mjs"; -### How Individual Test Jobs Work +import { initLogger, _exportsForTestingOnly } from "braintrust"; -Example from `sdk/.github/workflows/js.yaml`: +async function runTests() { + const braintrust = await import("braintrust"); -```yaml -smoke-tests-cloudflare: - needs: build - runs-on: ubuntu-latest + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: true, + canUseCLI: true, + environment: "my-scenario", + }); - steps: - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }} - path: js/artifacts + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters, braintrust); + const results = [...importResults, ...functionalResults]; - - name: Install dependencies and local build - working-directory: js/smoke/tests/cloudflare-worker - run: | - npm ci - npx tsx ../../install-build.ts ../../../artifacts braintrust + displayTestResults({ + scenarioName: "My Scenario Test Results", + results, + }); - - name: Build shared test package - working-directory: js/smoke/shared - run: | - npm ci - npm run build + if (hasFailures(results)) { + process.exit(1); + } + } finally { + await cleanupTestEnvironment(adapters); + } +} - - name: Run Cloudflare Worker smoke test - working-directory: js/smoke - run: | - ./run-tests.sh cloudflare-worker +runTests().catch((error) => { + console.error(error); + process.exit(1); +}); ``` -**Pattern**: Build SDK → Download artifacts → Install in test → Build shared → Run specific test +### Example Makefile (Multiple Tests) -### Running Multiple Tests in One Job +**IMPORTANT:** Run all tests even if one fails. Don't exit early. -```yaml -- name: Run multiple smoke tests - working-directory: js/smoke - run: ./run-tests.sh span cloudflare-worker deno +```makefile +test: setup + @echo "==> Running tests" + @FAILED=0; \ + npx tsx tests/test1.test.ts || FAILED=1; \ + npx tsx tests/test2.test.ts || FAILED=1; \ + npx tsx tests/test3.test.ts || FAILED=1; \ + exit $$FAILED ``` -Or run all tests: - -```yaml -- name: Run all smoke tests - working-directory: js/smoke - run: ./run-tests.sh -``` - -### Test Discovery and Build Process - -Tests are **automatically discovered** by scanning `tests/*/`. To add a new test: - -1. Create `tests/my-test/` directory -2. Add `package.json` with `"test"` script -3. Done! +This ensures all tests run and display their results, but the suite still fails if any test failed. -CI will automatically: +## Design Principles -- Build the SDK from source -- Install the build artifact into your test directory -- Run your test against the actual build +### Well-Known Tarball Paths -**No registration or configuration needed!** +Use version-agnostic paths: `braintrust-latest.tgz` not `braintrust-2.0.2.tgz`. Prevents package.json from changing on version bumps. -### What Gets Tested +### No Workarounds -The smoke tests verify the **actual SDK build** (not the published npm package): +Never use `--legacy-peer-deps`, `--no-check`, `--ignore-errors`, or mocks. Smoke tests must expose issues users will encounter. -1. **Build**: SDK is built from source in `sdk/js/` -2. **Package**: Built SDK is packed into tarball (`.tgz`) -3. **Install**: Tarball is installed into each test's `node_modules/` -4. **Test**: Tests import and verify the **built** SDK +### Build Before Install -This ensures that: +Build all artifacts BEFORE installing dependencies that reference them. Prevents "ENOENT" errors. -- ✅ The build process works correctly -- ✅ All exports are present and functional -- ✅ No tree-shaking issues or missing dependencies -- ✅ SDK works in diverse runtime environments +### Track Lock Files -## Test Coverage +Commit `package-lock.json` and `deno.lock`. Changes signal new dependencies, version conflicts, or packaging issues. -The shared test suites currently include: +### Makefiles Are the Source of Truth -### Import Verification Tests (13 tests) +No npm scripts in package.json. All commands in Makefile. Single clear path to run tests. -- Core logging exports (initLogger, wrapLogger, etc.) -- Dataset exports (initDataset, Dataset) -- Prompt exports (loadPrompt, Prompt) -- Experiment exports (Experiment, init) -- Eval exports (Eval, ReporterDef, EvalCase) -- Tracing exports (traced, wrapTraced, currentSpan, etc.) -- Client wrappers (wrapOpenAI, wrapAnthropic, etc.) -- Utility exports (getCurrentUnixTimestamp, JSONAttachment, etc.) -- Function, Framework, ID generator, Testing, and State management exports +## Troubleshooting -### Functional Tests (3 tests) +### "ENOENT: no such file or directory" for tarball -- Basic span logging (single span with input/output/expected) -- Multiple spans (sequential span creation) -- Direct logging (logger.log() if available) +Ensure Makefile builds packages BEFORE `npm install`. -**Total: 16+ tests running in each environment** +### "Unsupported URL Type 'workspace:'" -## Environment Status +Use `pnpm pack` (not `npm pack`) for packages with `workspace:*` dependencies. -| Environment | Shared Tests | Import Verification | Functional Tests | -| ----------------------- | -------------- | ------------------- | ---------------- | -| Node.js CJS | ✅ | ✅ | ✅ | -| Jest | ✅ | ✅ | ✅ | -| Deno | ✅ | ✅ | ✅ | -| Cloudflare Workers | ✅ | ✅ | ✅ | -| Next.js Edge Runtime | ✅ | ✅ | ✅ | -| Next.js Node.js Runtime | ✅ | ✅ | ✅ | -| OTEL v1 | ⚪ Specialized | N/A | ⚪ Custom | +### package.json gets modified by npm -## Adding New Tests +Use well-known tarball paths: `braintrust-latest.tgz` not version-specific paths. -Adding a new smoke test is trivial: +### Tests can't find braintrust imports -1. **Create directory**: `mkdir tests/my-test` -2. **Add package.json**: - ```json - { - "name": "braintrust-my-test", - "scripts": { - "test": "node run-test.js" - }, - "dependencies": { - "braintrust": "latest" - } - } - ``` -3. **Write test**: Create `run-test.js` (can use shared test suites) -4. **Run it**: `./run-tests.sh my-test` +Verify tarball paths in package.json are correct relative to scenario directory. -Done! CI automatically discovers and runs it. +## Directory Structure -## Convention Over Configuration - -Tests are **auto-discovered** by scanning `tests/*/` for directories with `package.json`. - -**Rules:** +``` +smoke/ +├── shared/ # Cross-scenario test utilities +├── scenarios/ # Individual test scenarios +│ ├── otel-v1/ +│ │ ├── tests/ # Test files +│ │ ├── Makefile # setup + test targets +│ │ ├── mise.toml # Environment definition +│ │ ├── package.json # Dependencies only (no scripts) +│ │ └── README.md +│ └── deno-node/ +├── Makefile # Top-level orchestration (auto-discovery) +└── README.md # This file +``` -- Test name = directory name -- All tests run via: `npm test` -- For Deno: `package.json` calls `deno task test` -- For Bun: `package.json` calls `bun test` +## How Auto-Discovery Works -**Example (Deno test):** +The top-level Makefile finds scenarios: -```json -{ - "scripts": { - "test": "deno task test" - } -} +```makefile +SCENARIOS := $(shell find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||') ``` -**Benefits:** - -- Zero registration needed -- Pure convention -- Add directory → CI runs it -- Can't forget to register +Any folder in `scenarios/` with a `Makefile` is automatically discovered. No registration needed. -## Notes +## Reference Scenarios -- There were some caching issues with pnpm, so tests use npm ci and package-lock.json files -- Tests use `_exportsForTestingOnly` to avoid hitting real Braintrust APIs -- The shared package allows adding test coverage once and automatically running it in all environments -- Import verification tests help catch tree-shaking issues across different bundlers -- Each environment runs the same test logic, ensuring consistent behavior -- All tests use `npm test` for consistency (universal interface) -- Tests are auto-discovered from `tests/*/` directories with `package.json` +- **Node.js + OTEL:** `scenarios/otel-v1/` +- **Deno:** `scenarios/deno-node/`, `scenarios/deno-browser/` +- **Cloudflare Workers:** `scenarios/cloudflare-worker-*/` +- **Multi-test:** `scenarios/cloudflare-vite-hono/` +- **Next.js:** `scenarios/nextjs-instrumentation/` diff --git a/js/smoke/backup-and-restore.ts b/js/smoke/backup-and-restore.ts deleted file mode 100644 index e74322fd7..000000000 --- a/js/smoke/backup-and-restore.ts +++ /dev/null @@ -1,38 +0,0 @@ -import fs from "fs"; - -const files = [ - { path: "package.json", backupPath: "package.json.bak" }, - { path: "package-lock.json", backupPath: "package-lock.json.bak" }, -]; - -const command = process.argv[2]; - -if (!command) { - console.error('Please provide "backup" or "restore" as argument.'); - process.exit(1); -} - -if (command === "backup") { - for (const { path, backupPath } of files) { - if (fs.existsSync(path)) { - fs.copyFileSync(path, backupPath); - console.log(`${path} backed up to ${backupPath}`); - } - } -} else if (command === "restore") { - let restored = 0; - for (const { path, backupPath } of files) { - if (fs.existsSync(backupPath)) { - fs.renameSync(backupPath, path); - console.log(`${path} restored from ${backupPath}`); - restored++; - } - } - if (restored === 0) { - console.error("No backup files found."); - process.exit(1); - } -} else { - console.error('Invalid argument. Use "backup" or "restore".'); - process.exit(1); -} diff --git a/js/smoke/enable-esm.ts b/js/smoke/enable-esm.ts deleted file mode 100644 index e84eea6e4..000000000 --- a/js/smoke/enable-esm.ts +++ /dev/null @@ -1,8 +0,0 @@ -import fs from "fs"; -const path = "package.json"; - -const pkg = JSON.parse(fs.readFileSync(path, "utf8")); -pkg.type = "module"; -fs.writeFileSync(path, JSON.stringify(pkg, null, 2)); - -console.log("package.json updated to ESM build"); diff --git a/js/smoke/install-build.ts b/js/smoke/install-build.ts deleted file mode 100644 index d63c1beae..000000000 --- a/js/smoke/install-build.ts +++ /dev/null @@ -1,77 +0,0 @@ -import fs from "fs"; -import path from "path"; -import { execSync } from "child_process"; - -const artifactsDir = path.resolve(process.argv[2] || "../../artifacts"); -const packageToInstall = process.argv[3] || "both"; // "braintrust", "otel", or "both" - -function findLatestTarball(prefixes: string[]): string | null { - if (!fs.existsSync(artifactsDir)) { - return null; - } - const files = fs - .readdirSync(artifactsDir) - .filter((f) => prefixes.some((p) => f.startsWith(p)) && f.endsWith(".tgz")) - .map((f) => ({ f, mtime: fs.statSync(path.join(artifactsDir, f)).mtime })) - .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); - - return files[0]?.f || null; -} - -function installTarball(label: string, tarPath: string): void { - console.log(`Installing ${label} from: ${tarPath}`); - try { - execSync(`npm install --legacy-peer-deps --save file:${tarPath}`, { - stdio: "inherit", - }); - console.log(`Successfully installed ${path.basename(tarPath)}`); - } catch (err) { - console.error(`Failed to install ${label}:`, err.message); - process.exit(1); - } -} - -// Install braintrust -if (packageToInstall === "braintrust") { - // Find braintrust tarball, but exclude braintrust-otel- packages - if (!fs.existsSync(artifactsDir)) { - console.error(`Artifacts directory not found: ${artifactsDir}`); - process.exit(1); - } - const files = fs - .readdirSync(artifactsDir) - .filter( - (f) => - f.startsWith("braintrust-") && - !f.startsWith("braintrust-otel-") && - f.endsWith(".tgz"), - ) - .map((f) => ({ - f, - mtime: fs.statSync(path.join(artifactsDir, f)).mtime, - })) - .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); - - const braintrustTar = files[0]?.f || null; - if (!braintrustTar) { - console.error(`No braintrust tarball found in ${artifactsDir}.`); - console.error( - "Build it first: cd js && npm run build && npm pack --pack-destination artifacts", - ); - process.exit(1); - } - installTarball("braintrust", path.join(artifactsDir, braintrustTar)); -} - -// Install @braintrust/otel -if (packageToInstall === "otel") { - const otelTar = findLatestTarball(["braintrust-otel-"]); - if (!otelTar) { - console.error(`No @braintrust/otel tarball found in ${artifactsDir}.`); - console.error( - "Build it first: cd integrations/otel-js && npm run build && npm pack --pack-destination ../../../js/artifacts", - ); - process.exit(1); - } - installTarball("@braintrust/otel", path.join(artifactsDir, otelTar)); -} diff --git a/js/smoke/prepare-tests.sh b/js/smoke/prepare-tests.sh deleted file mode 100755 index 55558eac7..000000000 --- a/js/smoke/prepare-tests.sh +++ /dev/null @@ -1,228 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Script to prepare smoke tests by building SDK and installing into test directories -# This mimics what CI does -# Usage: ./prepare-tests.sh [test-name...] -# If no test names provided, prepares all tests - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -JS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -SDK_DIR="$(cd "$JS_DIR/.." && pwd)" -ARTIFACTS_DIR="$JS_DIR/artifacts" - -# Parse which tests to prepare -REQUESTED_TESTS=("$@") -PREPARE_ALL=false -if [ ${#REQUESTED_TESTS[@]} -eq 0 ]; then - PREPARE_ALL=true -fi - -# Helper to check if we should prepare a specific test -should_prepare() { - local test_name=$1 - if [ "$PREPARE_ALL" = true ]; then - return 0 - fi - for requested in "${REQUESTED_TESTS[@]}"; do - if [ "$requested" = "$test_name" ]; then - return 0 - fi - done - return 1 -} - -if [ "$PREPARE_ALL" = true ]; then - echo "============================================================" - echo "Preparing All Smoke Tests" - echo "============================================================" -else - echo "============================================================" - echo "Preparing Smoke Tests: ${REQUESTED_TESTS[*]}" - echo "============================================================" -fi -echo "" - -# Step 0: Restore test files to clean git state -echo "Step 0: Restoring test files to clean state..." -cd "$SCRIPT_DIR/tests" -# Only restore files that are tracked by git and modified -if git diff --quiet --exit-code 2>/dev/null; then - echo " ✓ Test files already clean" -else - git checkout -- . 2>/dev/null || true - echo " ✓ Restored test files from git" -fi -echo "" - -# Step 1: Build the SDK -echo "Step 1: Building SDK..." -cd "$JS_DIR" -if [ ! -d "node_modules" ]; then - echo "Installing dependencies..." - pnpm install --frozen-lockfile -fi -echo "Building SDK..." -pnpm run build -echo "✓ SDK built" -echo "" - -# Step 2: Pack SDK into artifacts -echo "Step 2: Packing SDK..." -mkdir -p "$ARTIFACTS_DIR" -cd "$JS_DIR" -PACKED_TARBALL=$(npm pack --pack-destination "$ARTIFACTS_DIR" 2>&1 | tail -1) -echo "✓ Packed: $PACKED_TARBALL" -echo "" - -# Step 3: Build and pack @braintrust/otel (needed for otel-v1 and nextjs tests) -NEEDS_OTEL=false -if should_prepare "otel-v1" || should_prepare "nextjs-instrumentation"; then - NEEDS_OTEL=true -fi - -if [ "$NEEDS_OTEL" = true ]; then - echo "Step 3: Building @braintrust/otel..." - OTEL_DIR="$SDK_DIR/integrations/otel-js" - if [ -d "$OTEL_DIR" ]; then - cd "$OTEL_DIR" - - # Install the built braintrust package as a dependency - BRAINTRUST_TARBALL=$(ls "$ARTIFACTS_DIR"/braintrust-*.tgz | head -n 1) - if [ -z "$BRAINTRUST_TARBALL" ]; then - echo "Error: braintrust tarball not found" - exit 1 - fi - - echo "Installing braintrust and OpenTelemetry dependencies..." - npm_config_save=false npm_config_lockfile=false pnpm add \ - "file:$BRAINTRUST_TARBALL" \ - "@opentelemetry/api@^1.9.0" \ - "@opentelemetry/core@^1.9.0" \ - "@opentelemetry/exporter-trace-otlp-http@^0.35.0" \ - "@opentelemetry/sdk-trace-base@^1.9.0" || true - - echo "Building @braintrust/otel..." - pnpm run build - - echo "Packing @braintrust/otel..." - OTEL_TARBALL=$(npm pack --pack-destination "$ARTIFACTS_DIR" 2>&1 | tail -1) - echo "✓ Packed: $OTEL_TARBALL" - else - echo "⚠ @braintrust/otel directory not found, skipping" - fi - echo "" -else - echo "Step 3: Skipping @braintrust/otel (not needed for requested tests)" - echo "" -fi - -# Step 4: Backup package.json files before modifications -echo "Step 4: Creating backups of package.json files..." -cd "$SCRIPT_DIR" - -# List of tests that need braintrust -TESTS_NEEDING_BRAINTRUST=( - "cloudflare-worker" - "nextjs-instrumentation" - "otel-v1" - "span" - "span-jest" - "browser" -) - -# Tests that also need @braintrust/otel -TESTS_NEEDING_OTEL=( - "otel-v1" - "nextjs-instrumentation" -) - -# Create backups only for tests we're preparing -for test_name in "${TESTS_NEEDING_BRAINTRUST[@]}"; do - if should_prepare "$test_name"; then - test_dir="$SCRIPT_DIR/tests/$test_name" - if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then - cd "$test_dir" - # Remove old backups first to ensure fresh backups - rm -f package.json.bak package-lock.json.bak - if grep -q '"backup"' package.json 2>/dev/null; then - npm run backup 2>/dev/null || true - echo " ✓ Backed up $test_name/package.json" - fi - fi - fi -done -echo "" - -# Step 5: Install built packages into test directories -echo "Step 5: Installing built packages into test directories..." -cd "$SCRIPT_DIR" - -for test_name in "${TESTS_NEEDING_BRAINTRUST[@]}"; do - if should_prepare "$test_name"; then - test_dir="$SCRIPT_DIR/tests/$test_name" - if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then - echo "Installing braintrust into $test_name..." - cd "$test_dir" - # Remove package-lock.json to avoid version conflicts - rm -f package-lock.json - npm install --legacy-peer-deps 2>/dev/null || npm install - npx tsx ../../install-build.ts ../../../artifacts braintrust - echo " ✓ $test_name" - fi - fi -done - -for test_name in "${TESTS_NEEDING_OTEL[@]}"; do - if should_prepare "$test_name"; then - test_dir="$SCRIPT_DIR/tests/$test_name" - if [ -d "$test_dir" ] && [ -f "$test_dir/package.json" ]; then - echo "Installing @braintrust/otel into $test_name..." - cd "$test_dir" - npx tsx ../../install-build.ts ../../../artifacts otel - echo " ✓ $test_name (otel)" - fi - fi -done - -# Special handling for Deno - extract tarball for file:// import -if should_prepare "deno"; then - echo "Setting up Deno test..." - DENO_DIR="$SCRIPT_DIR/tests/deno" - if [ -d "$DENO_DIR" ]; then - cd "$DENO_DIR" - TARBALL=$(ls "$ARTIFACTS_DIR"/braintrust-*.tgz | head -n 1) - if [ -n "$TARBALL" ]; then - echo "Extracting braintrust tarball for Deno..." - rm -rf build - mkdir -p build - tar -xzf "$TARBALL" -C build - [ -d build/package ] && mv build/package build/braintrust - echo " ✓ Deno build extracted" - - # Install Deno dependencies (npm packages in deno.json) - echo "Installing Deno dependencies..." - deno install - echo " ✓ Deno dependencies installed" - fi - fi - echo "" -fi - -# Step 6: Build shared test package -echo "Step 6: Building shared test package..." -cd "$SCRIPT_DIR/shared" -if [ ! -d "node_modules" ]; then - npm ci -fi -npm run build -echo "✓ Shared package built" -echo "" - -echo "============================================================" -echo "✓ Preparation complete!" -echo "============================================================" -echo "" -echo "You can now run tests with:" -echo " ./run-tests.sh" -echo "" diff --git a/js/smoke/run-tests.sh b/js/smoke/run-tests.sh deleted file mode 100755 index e3c25c075..000000000 --- a/js/smoke/run-tests.sh +++ /dev/null @@ -1,385 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Simplified smoke test runner for Braintrust JS SDK -# Convention: Any directory in tests/ with a package.json is a test -# Run with: npm test - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SHARED_DIR="$SCRIPT_DIR/shared" -TESTS_DIR="$SCRIPT_DIR/tests" - -# Color codes -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color - -# Track results -declare -a FAILED_TESTS -declare -a PASSED_TESTS - -# Logging functions -log_info() { - echo -e "${BLUE}ℹ${NC} $*" -} - -log_success() { - echo -e "${GREEN}✓${NC} $*" -} - -log_error() { - echo -e "${RED}✗${NC} $*" -} - -log_header() { - echo "" - echo "============================================================" - echo "$*" - echo "============================================================" -} - -# Show help -show_help() { - cat << EOF -Braintrust JS SDK Smoke Test Runner - -Usage: - ./run-tests.sh Run all tests - ./run-tests.sh TEST_NAME Run specific test(s) - ./run-tests.sh --list List all available tests - ./run-tests.sh --help Show this help - -Convention: - - Any directory in tests/ with package.json is a test - - Test name = directory name - - All tests run via: npm test - -Examples: - ./run-tests.sh # Run all tests - ./run-tests.sh cloudflare-worker # Run one test - ./run-tests.sh span deno # Run multiple tests - -EOF -} - -# Discover all tests -discover_tests() { - local -a tests - for dir in "$TESTS_DIR"/*/; do - [ -d "$dir" ] || continue - local dirname=$(basename "$dir") - # deno-node and deno-browser - if [ "$dirname" = "deno" ]; then - continue - fi - if [ -f "$dir/package.json" ]; then - tests+=("$dirname") - fi - done - # Add deno nested tests (deno-node, deno-browser, etc.) - for nested in node browser; do - if [ -d "$TESTS_DIR/deno/$nested" ] && [ -f "$TESTS_DIR/deno/$nested/package.json" ]; then - tests+=("deno-$nested") - fi - done - echo "${tests[@]}" -} - -# List all tests -list_tests() { - log_header "Available Smoke Tests" - echo "" - - local tests=($(discover_tests)) - - for test_name in "${tests[@]}"; do - echo -e "${GREEN}●${NC} ${CYAN}$test_name${NC}" - - # Show description from package.json if available - local pkg="$TESTS_DIR/$test_name/package.json" - # Handle nested deno tests (deno-node, deno-browser, etc.) - if [[ "$test_name" =~ ^deno- ]]; then - local nested="${test_name#deno-}" - pkg="$TESTS_DIR/deno/$nested/package.json" - fi - if [ -f "$pkg" ]; then - local desc=$(jq -r '.description // ""' "$pkg" 2>/dev/null || echo "") - if [ -n "$desc" ]; then - echo " $desc" - fi - fi - echo "" - done - - echo "Total: ${#tests[@]} tests" - echo "" - echo "Convention: Tests are auto-discovered from tests/*/" - echo "Add a test: Create tests/my-test/ with package.json" -} - -# Build shared package -build_shared_package() { - log_header "Building Shared Test Package" - echo "" - - cd "$SHARED_DIR" - - # Check if already built (e.g., in CI) - if [ -f "dist/index.js" ] && [ -f "dist/index.mjs" ]; then - log_info "Shared package already built, skipping build" - log_success "Using existing shared package" - echo "" - return - fi - - # Install dependencies if needed - if [ ! -d "node_modules" ] || [ "package-lock.json" -nt "node_modules/.package-lock.json" ]; then - log_info "Installing shared package dependencies..." - npm ci - touch node_modules/.package-lock.json - else - log_info "Dependencies up to date" - fi - - # Build - log_info "Building shared package..." - npm run build - - # Verify - if [ ! -f "dist/index.js" ] || [ ! -f "dist/index.mjs" ]; then - log_error "Shared package build failed" - exit 1 - fi - - log_success "Shared package built" - echo "" -} - -# Run a single test -run_test() { - local test_name=$1 - local test_dir="$TESTS_DIR/$test_name" - - # Handle nested deno tests (deno-node, deno-browser, etc.) - if [[ "$test_name" =~ ^deno- ]]; then - local nested="${test_name#deno-}" - test_dir="$TESTS_DIR/deno/$nested" - fi - - if [ ! -d "$test_dir" ]; then - log_error "Test directory not found: $test_name" - FAILED_TESTS+=("$test_name (not found)") - return 1 - fi - - if [ ! -f "$test_dir/package.json" ]; then - log_error "No package.json found: $test_name" - FAILED_TESTS+=("$test_name (no package.json)") - return 1 - fi - - cd "$test_dir" - - local npm_script="test" - - # Allow CI to run Cloudflare Worker variants as separate pipeline jobs - if [ "$test_name" = "cloudflare-worker" ] && [ -n "${CLOUDFLARE_WORKER_MODE:-}" ]; then - npm_script="test:${CLOUDFLARE_WORKER_MODE}" - fi - - log_info "Running: npm run $npm_script" - - # Ensure Deno has a local file:// module to import (deno.json maps `braintrust` to ./build/braintrust/dist/index.mjs) - # All deno tests (deno, deno-node, deno-browser, etc.) extract build to tests/deno/build/ (shared location) - if [ "$test_name" = "deno" ] || [[ "$test_name" =~ ^deno- ]]; then - local deno_dir="$TESTS_DIR/deno" - local deno_build_file="$deno_dir/build/braintrust/dist/index.mjs" - if [ ! -f "$deno_build_file" ]; then - log_info "Preparing Deno build directory from packed braintrust tarball..." - local artifacts_dir="$SCRIPT_DIR/../artifacts" - local tarball - tarball=$(ls "$artifacts_dir"/braintrust-*.tgz 2>/dev/null | grep -v "braintrust-otel-" | grep -v "braintrust-template-nunjucks-" | head -n 1 || true) - if [ -z "${tarball:-}" ]; then - log_error "No braintrust tarball found in $artifacts_dir" - FAILED_TESTS+=("$test_name (missing braintrust tarball)") - return 1 - fi - - rm -rf "$deno_dir/build" - mkdir -p "$deno_dir/build" - tar -xzf "$tarball" -C "$deno_dir/build" - if [ -d "$deno_dir/build/package" ]; then - mv "$deno_dir/build/package" "$deno_dir/build/braintrust" - fi - - if [ ! -f "$deno_build_file" ]; then - log_error "Deno build file not found after extraction: $deno_build_file" - FAILED_TESTS+=("$test_name (deno extraction failed)") - return 1 - fi - log_success "Deno build extracted" - fi - - # Convert to absolute path for any remaining file:// imports - local abs_dir="$(cd "$(dirname "$deno_build_file")" && pwd)" - export BRAINTRUST_BUILD_DIR="$abs_dir/$(basename "$deno_build_file")" - log_info "Set BRAINTRUST_BUILD_DIR=$BRAINTRUST_BUILD_DIR" - fi - - # Run test and capture output - local test_output - local test_exit_code - - if test_output=$(npm run "$npm_script" 2>&1); then - test_exit_code=0 - else - test_exit_code=$? - fi - - if [ $test_exit_code -eq 0 ]; then - log_success "$test_name passed" - PASSED_TESTS+=("$test_name") - return 0 - else - log_error "$test_name failed" - echo "" - echo "Output (last 30 lines):" - echo "----------------------------------------" - echo "$test_output" | tail -n 30 - echo "----------------------------------------" - FAILED_TESTS+=("$test_name") - return 1 - fi -} - -# Run tests -run_tests() { - local filter_tests=("$@") - local all_tests=($(discover_tests)) - - if [ ${#all_tests[@]} -eq 0 ]; then - log_error "No tests found in $TESTS_DIR" - exit 1 - fi - - # Determine which tests to run - local -a tests_to_run - - if [ ${#filter_tests[@]} -eq 0 ]; then - # Run all tests - tests_to_run=("${all_tests[@]}") - else - # Run filtered tests - for filter in "${filter_tests[@]}"; do - local found=false - for test in "${all_tests[@]}"; do - if [ "$test" = "$filter" ]; then - tests_to_run+=("$test") - found=true - break - fi - done - if [ "$found" = false ]; then - log_error "Unknown test: $filter" - log_info "Use --list to see available tests" - exit 1 - fi - done - fi - - log_header "Running ${#tests_to_run[@]} Test(s)" - echo "" - - local test_num=1 - for test_name in "${tests_to_run[@]}"; do - echo "Test $test_num/${#tests_to_run[@]}: $test_name" - echo "------------------------------------------------------------" - - # Run test and continue even if it fails - run_test "$test_name" || true - - echo "" - ((test_num++)) - done -} - -# Print summary -print_summary() { - log_header "Summary" - echo "" - - # Temporarily disable unbound variable check for safe array access - set +u - local passed_count=${#PASSED_TESTS[@]} - local failed_count=${#FAILED_TESTS[@]} - set -u - - local total=$((passed_count + failed_count)) - - echo "Total: $total tests" - echo -e "Passed: ${GREEN}${passed_count}${NC}" - echo -e "Failed: ${RED}${failed_count}${NC}" - echo "" - - if [ $passed_count -gt 0 ]; then - echo -e "${GREEN}Passed:${NC}" - for test in "${PASSED_TESTS[@]}"; do - echo " ✓ $test" - done - echo "" - fi - - if [ $failed_count -gt 0 ]; then - echo -e "${RED}Failed:${NC}" - for test in "${FAILED_TESTS[@]}"; do - echo " ✗ $test" - done - echo "" - return 1 - fi - - echo -e "${GREEN}✅ All tests passed!${NC}" - return 0 -} - -# Main -main() { - # Check for jq (optional, for listing descriptions) - if ! command -v jq &> /dev/null; then - # jq not required, just won't show descriptions - : - fi - - # Parse arguments - case "${1:-}" in - --list) - list_tests - exit 0 - ;; - --help|-h) - show_help - exit 0 - ;; - esac - - log_header "Braintrust JS SDK Smoke Tests" - echo "" - - # Build shared package - build_shared_package - - # Run tests - run_tests "$@" - - # Print summary - if print_summary; then - exit 0 - else - exit 1 - fi -} - -main "$@" diff --git a/js/smoke/scenarios/cloudflare-vite-hono/.gitignore b/js/smoke/scenarios/cloudflare-vite-hono/.gitignore new file mode 100644 index 000000000..04e14a1fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +.wrangler/ +.DS_Store +*.log +.vite/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-vite-hono/Makefile b/js/smoke/scenarios/cloudflare-vite-hono/Makefile new file mode 100644 index 000000000..f7f6a321d --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono/Makefile @@ -0,0 +1,33 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-vite-hono" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package if needed + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-vite-hono tests" + @echo "" + @npx tsx tests/worker.test.mjs || WORKER_FAILED=1; \ + echo ""; \ + npx tsx tests/vite-dev.test.mjs || true; \ + if [ "$$WORKER_FAILED" = "1" ]; then exit 1; fi diff --git a/js/smoke/scenarios/cloudflare-vite-hono/README.md b/js/smoke/scenarios/cloudflare-vite-hono/README.md new file mode 100644 index 000000000..2d9c8bc55 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono/README.md @@ -0,0 +1,51 @@ +# Cloudflare Vite + Hono Smoke Test + +Tests Braintrust SDK in a Cloudflare Workers environment with Vite bundling and Hono routing. + +## Design Decisions + +**Tarball installation:** Uses well-known tarball path (`braintrust-latest.tgz`) to avoid package.json changes. + +**Vite bundling:** Tests SDK through Vite's production bundler for Cloudflare Workers. + +**Hono framework:** Uses Hono for elegant routing instead of raw Worker API. + +**Browser build:** Uses `braintrust/browser` import since Cloudflare Workers don't support Node.js APIs. + +**Two-test approach:** Runs both Wrangler (production mode) and Vite dev server tests to validate different deployment scenarios. + +## Test Suite + +### Test 1: Wrangler (Production Mode) - `tests/worker.test.mjs` + +Tests the SDK via Wrangler dev server, which uses Vite to build the worker. + +**Expected results:** 19 tests total - 18 pass + 1 xfail (Nunjucks). Overall: **PASS**. + +**Expected failure handling:** Nunjucks templating is tested but expected to fail in browser builds. The test converts this failure to "xfail" (expected failure) status, so it doesn't cause the overall test run to fail. + +**Why test Nunjucks if it fails?** Testing both template engines ensures: + +- Mustache templating works correctly (browser-compatible) +- We detect if Nunjucks support changes in future Cloudflare Workers versions +- Consistent test coverage across all environments (Node.js scenarios pass both) + +### Test 2: Vite Dev Server - `tests/vite-dev.test.mjs` + +Tests whether the SDK can be loaded in Vite's dev server (with hot module reloading). + +**Expected result:** FAIL (expected to fail) - Vite's dependency pre-bundler cannot handle Nunjucks. + +**Known issue:** Nunjucks uses `Object.setPrototypeOf` in ways that fail in Vite's ESM bundler during dependency pre-bundling, causing: `TypeError: Object prototype may only be an Object or null: undefined` + +**This failure is expected and acceptable** - users should use Wrangler (production mode) for Cloudflare Workers development, not Vite dev server. The Wrangler test validates the production deployment path. + +**Note:** If you see a different error (not the Nunjucks error), that's unexpected and should be investigated. + +## Running Tests + +```bash +make test # Runs both tests sequentially +``` + +**Success criteria:** The Wrangler test must pass. The Vite dev test is expected to fail (exit code 1) and won't cause the overall `make test` to fail. diff --git a/js/smoke/scenarios/cloudflare-vite-hono/mise.toml b/js/smoke/scenarios/cloudflare-vite-hono/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-vite-hono/package.json b/js/smoke/scenarios/cloudflare-vite-hono/package.json new file mode 100644 index 000000000..180b94c26 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono/package.json @@ -0,0 +1,24 @@ +{ + "name": "smoke-cloudflare-vite-hono", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "hono": "^4.11.1", + "react": "^19.2.1", + "react-dom": "^19.2.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/vite-plugin": "^1.15.3", + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^24.10.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "tsx": "^4.19.2", + "typescript": "^5.8.3", + "vite": "^6.0.0", + "wrangler": "^4.56.0" + } +} diff --git a/js/smoke/tests/vite-react-hono/src/worker/index.ts b/js/smoke/scenarios/cloudflare-vite-hono/src/worker.ts similarity index 68% rename from js/smoke/tests/vite-react-hono/src/worker/index.ts rename to js/smoke/scenarios/cloudflare-vite-hono/src/worker.ts index 7667a90f1..dae2c847e 100644 --- a/js/smoke/tests/vite-react-hono/src/worker/index.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono/src/worker.ts @@ -1,8 +1,3 @@ -/** - * Vite + React + Hono + Cloudflare Worker smoke test using shared test suites - * This test demonstrates using the Braintrust SDK with Hono routing framework - */ - import { Hono } from "hono"; import { setupTestEnvironment, @@ -10,9 +5,10 @@ import { runBasicLoggingTests, runEvalSmokeTest, runImportVerificationTests, - runPromptTemplatingTests, + testMustacheTemplate, + testNunjucksTemplate, type TestResult, -} from "../../../../shared/dist/index.mjs"; +} from "../../../shared"; import * as braintrust from "braintrust/browser"; const { initLogger, _exportsForTestingOnly } = braintrust; @@ -31,9 +27,6 @@ interface TestResponse { failures?: TestResult[]; } -/** - * Run the shared test suites in Hono + Cloudflare Worker environment - */ async function runSharedTestSuites(): Promise { try { const adapters = await setupTestEnvironment({ @@ -41,28 +34,46 @@ async function runSharedTestSuites(): Promise { testingExports: _exportsForTestingOnly, canUseFileSystem: false, canUseCLI: false, - environment: "vite-react-hono", + environment: "cloudflare-vite-hono", }); try { const importResults = await runImportVerificationTests(braintrust); const functionalResults = await runBasicLoggingTests(adapters); const evalResult = await runEvalSmokeTest(adapters, braintrust); - const promptTemplatingResults = await runPromptTemplatingTests( - { - Prompt: braintrust.Prompt, - }, - adapters.environment, - ); + + // Test Mustache template (should always work) + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + // Test Nunjucks template - expected to fail in browser builds + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ? { + ...nunjucksResult, + status: "xfail" as const, + message: + "Expected failure: Nunjucks not supported in browser build", + } + : nunjucksResult; const results = [ ...importResults, ...functionalResults, evalResult, - ...promptTemplatingResults, + mustacheResult, + nunjucksResultHandled, ]; - const failures = results.filter((r) => !r.success); + // Filter out expected failures when counting actual failures + const failures = results.filter((r) => r.status === "fail"); if (failures.length > 0) { return { @@ -99,7 +110,7 @@ async function runSharedTestSuites(): Promise { } app.get("/", (c) => - c.text(`Braintrust Vite + React + Hono Smoke Test + c.text(`Braintrust Cloudflare Vite + Hono Smoke Test GET /api/ - Basic API endpoint GET /api/test - Run shared test suites @@ -111,7 +122,6 @@ app.get("/api/", (c) => c.json({ name: "Braintrust", framework: "Hono" })); app.get("/api/test", async (c) => { const result = await runSharedTestSuites(); - return c.json(result, result.success ? 200 : 500); }); diff --git a/js/smoke/tests/vite-react-hono/test-vite-dev.mjs b/js/smoke/scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs old mode 100644 new mode 100755 similarity index 64% rename from js/smoke/tests/vite-react-hono/test-vite-dev.mjs rename to js/smoke/scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs index 8991d8106..f49a5f3df --- a/js/smoke/tests/vite-react-hono/test-vite-dev.mjs +++ b/js/smoke/scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs @@ -12,8 +12,9 @@ * This is a known limitation when using the full Braintrust SDK in Vite dev mode. */ -import { spawn, execSync } from "node:child_process"; +import { spawn } from "node:child_process"; import { rmSync } from "node:fs"; +import { displayTestResults } from "../../../shared/dist/index.mjs"; const MAX_RETRIES = 20; const RETRY_DELAY_MS = 500; @@ -109,22 +110,17 @@ async function testViteDevServer() { }; } - // Print results - console.log("\n" + "=".repeat(60)); - console.log("VITE DEV SERVER TEST RESULTS"); - console.log("=".repeat(60) + "\n"); + // Convert to TestResult format and display + const results = []; if (testResult.success) { - console.log("✓ Status: PASS - Vite dev server started successfully"); - console.log("\n🎉 The Nunjucks issue may have been fixed!"); - console.log( - "Consider updating documentation if this is consistently passing.\n", - ); + results.push({ + status: "pass", + name: "viteDevServerStartup", + message: "Vite dev server started successfully", + }); } else if (testResult.issue === "vite-nunjucks-incompatibility") { - console.log("✗ Status: FAIL - Known Nunjucks incompatibility\n"); - console.log("Actual error from Vite:"); - console.log("-".repeat(60)); - // Show the actual error output + // Extract error details const errorLines = (output + errorOutput) .split("\n") .filter( @@ -133,46 +129,51 @@ async function testViteDevServer() { line.includes("Error") || line.includes("at "), ) - .slice(0, 15); // Show first 15 relevant lines - console.log(errorLines.join("\n")); - console.log("-".repeat(60)); - console.log( - "\nRoot cause: Nunjucks uses Object.setPrototypeOf in ways that", - ); - console.log("fail in Vite's ESM bundler during dependency pre-bundling.\n"); - console.log("Recommendation: Use 'braintrust/browser' import or configure"); - console.log("Vite to exclude Nunjucks from optimization.\n"); - console.log("Documented in: sdk/js/smoke/tests/vite-react-hono/README.md"); + .slice(0, 3); + + const errorStack = errorLines.join("\n"); + + results.push({ + status: "xfail", + name: "viteDevServerStartup", + message: + "Expected failure: Nunjucks incompatibility with Vite bundler. " + + "Root cause: Nunjucks uses Object.setPrototypeOf in ways incompatible with Vite's ESM bundler. " + + "Recommendation: Use 'braintrust/browser' import or exclude Nunjucks from Vite optimization", + error: errorStack + ? { + message: testResult.error, + stack: errorStack, + } + : undefined, + }); } else { - console.log("✗ Status: UNEXPECTED FAILURE"); - console.log(" Issue:", testResult.issue); - console.log(" Message:", testResult.message); - if (testResult.output) { - console.log("\nOutput:"); - console.log("-".repeat(60)); - console.log(testResult.output); - console.log("-".repeat(60)); - } + results.push({ + status: "fail", + name: "viteDevServerStartup", + message: testResult.message, + error: testResult.output + ? { + message: testResult.message, + stack: testResult.output, + } + : { message: testResult.message }, + }); } - console.log("\n" + "=".repeat(60) + "\n"); + // Use standardized display + displayTestResults({ + scenarioName: "Vite Dev Server Compatibility Test", + results, + }); // Return the actual test status - // CI should configure this as allowed-to-fail if desired if (testResult.issue === "vite-nunjucks-incompatibility") { - console.log("Test result: FAIL (Known issue - expected to fail)"); - console.log( - "\n💡 This is a known limitation. Configure CI to allow this failure.", - ); - return 1; // Actual failure + // Expected failure - return 1 but this is documented + return 1; } else if (testResult.success) { - console.log("Test result: PASS (Vite dev server started successfully!)"); - console.log( - "\n🎉 The Nunjucks issue may be fixed! Review and update documentation.", - ); return 0; } else { - console.log("Test result: FAIL (Unexpected behavior)"); return 1; } } diff --git a/js/smoke/tests/vite-react-hono/run-test.mjs b/js/smoke/scenarios/cloudflare-vite-hono/tests/worker.test.mjs similarity index 83% rename from js/smoke/tests/vite-react-hono/run-test.mjs rename to js/smoke/scenarios/cloudflare-vite-hono/tests/worker.test.mjs index 38008af47..bd6611948 100644 --- a/js/smoke/tests/vite-react-hono/run-test.mjs +++ b/js/smoke/scenarios/cloudflare-vite-hono/tests/worker.test.mjs @@ -1,4 +1,8 @@ import { spawn, execSync } from "node:child_process"; +import { + displayTestResults, + hasFailures, +} from "../../../shared/dist/index.mjs"; const PORT = 8800; const MAX_RETRIES = 20; @@ -65,7 +69,15 @@ async function runTest() { const response = await fetch(`http://localhost:${PORT}/api/test`); const result = await response.json(); - console.log(JSON.stringify(result, null, 2)); + if (result.results && result.results.length > 0) { + displayTestResults({ + scenarioName: "Cloudflare Vite Hono Test Results", + results: result.results, + }); + } else { + console.log(JSON.stringify(result, null, 2)); + } + exitCode = result.success ? 0 : 1; } catch (error) { console.error("Error:", error.message, "\n", output); diff --git a/js/smoke/tests/vite-react-hono/tsconfig.json b/js/smoke/scenarios/cloudflare-vite-hono/tsconfig.json similarity index 54% rename from js/smoke/tests/vite-react-hono/tsconfig.json rename to js/smoke/scenarios/cloudflare-vite-hono/tsconfig.json index 3dfdf73ff..601ba7734 100644 --- a/js/smoke/tests/vite-react-hono/tsconfig.json +++ b/js/smoke/scenarios/cloudflare-vite-hono/tsconfig.json @@ -1,19 +1,16 @@ { "compilerOptions": { "target": "ES2022", - "lib": ["ES2022"], "module": "ESNext", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, "moduleResolution": "bundler", - "allowImportingTsExtensions": true, "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, "types": ["@cloudflare/workers-types"] }, - "include": ["src/**/*"] + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules"] } diff --git a/js/smoke/tests/vite-react-hono/vite.config.ts b/js/smoke/scenarios/cloudflare-vite-hono/vite.config.ts similarity index 100% rename from js/smoke/tests/vite-react-hono/vite.config.ts rename to js/smoke/scenarios/cloudflare-vite-hono/vite.config.ts diff --git a/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml b/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml new file mode 100644 index 000000000..93f0b4dfa --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml @@ -0,0 +1,3 @@ +name = "smoke-cloudflare-vite-hono" +main = "src/worker.ts" +compatibility_date = "2025-01-15" diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/.gitignore b/js/smoke/scenarios/cloudflare-worker-browser-compat/.gitignore new file mode 100644 index 000000000..b1f90d523 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.wrangler/ +dist/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/Makefile b/js/smoke/scenarios/cloudflare-worker-browser-compat/Makefile new file mode 100644 index 000000000..fafcee6e8 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/Makefile @@ -0,0 +1,29 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-worker-browser-compat" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package if needed + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-worker-browser-compat tests" + npx tsx tests/worker.test.mjs diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/README.md b/js/smoke/scenarios/cloudflare-worker-browser-compat/README.md new file mode 100644 index 000000000..30c7fffd7 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/README.md @@ -0,0 +1,25 @@ +# Cloudflare Worker Browser Compat Scenario + +Tests Braintrust SDK in Cloudflare Workers with `braintrust/browser` entrypoint with `nodejs_compat_v2` enabled. + +## Design Decisions + +### Import Path + +Uses `braintrust/browser` (browser entrypoint) to test browser-compatible code with Node.js APIs available. + +### Compatibility Flags + +`nodejs_compat_v2` is enabled. While the browser entrypoint doesn't require Node.js APIs, this tests that the browser entrypoint works correctly when Node.js compatibility is present. This is useful for scenarios where other parts of the application need Node.js APIs. + +### Expected Outcome + +All tests should pass. The browser entrypoint should work correctly regardless of whether Node.js compatibility is enabled or not. + +### Test Pattern + +- Spawns wrangler dev server +- Makes HTTP request to worker +- Runs shared test suite inside worker runtime +- No mocks - real Cloudflare Workers environment with Node.js compatibility layer +- Tests that browser entrypoint is compatible with nodejs_compat_v2 flag diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/mise.toml b/js/smoke/scenarios/cloudflare-worker-browser-compat/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json b/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json new file mode 100644 index 000000000..c39db0404 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json @@ -0,0 +1,16 @@ +{ + "name": "smoke-cloudflare-worker-browser-compat", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^20", + "tsx": "^4.19.2", + "typescript": "^5.4.4", + "wrangler": "^4.28.1" + } +} diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts new file mode 100644 index 000000000..906b15adf --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts @@ -0,0 +1,157 @@ +import * as braintrust from "braintrust/browser"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + testMustacheTemplate, + testNunjucksTemplate, + type TestResult, +} from "../../../shared"; + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger: braintrust.initLogger, + testingExports: braintrust._exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "cloudflare-worker-browser-compat", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests( + adapters, + braintrust, + ); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + + // Test Mustache template (should always work) + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + // Test Nunjucks template - expected to fail in browser builds (even with nodejs_compat_v2) + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ? { + ...nunjucksResult, + status: "xfail" as const, + message: + "Expected failure: Nunjucks not supported in browser build", + } + : nunjucksResult; + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + mustacheResult, + nunjucksResultHandled, + ]; + + // Filter out expected failures when counting actual failures + const failures = results.filter((r) => r.status === "fail"); + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +export default { + async fetch(request: Request, _env: Env): Promise { + const url = new URL(request.url); + + if (url.pathname === "/test") { + const result = await runSharedTestSuites(); + + // Serialize errors properly (Error objects don't JSON.stringify well) + const serializedResult = { + ...result, + results: result.results?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + failures: result.failures?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + }; + + return new Response(JSON.stringify(serializedResult, null, 2), { + headers: { "Content-Type": "application/json" }, + status: result.success ? 200 : 500, + }); + } + + return new Response( + `Braintrust Cloudflare Worker Smoke Test (Browser + nodejs_compat_v2) + +GET /test - Run shared test suites + +This worker tests the Braintrust SDK in a Cloudflare Workers environment +using the browser entrypoint with nodejs_compat_v2 enabled.`, + { headers: { "Content-Type": "text/plain" } }, + ); + }, +}; diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/tests/worker.test.mjs b/js/smoke/scenarios/cloudflare-worker-browser-compat/tests/worker.test.mjs new file mode 100644 index 000000000..0f30c3341 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/tests/worker.test.mjs @@ -0,0 +1,98 @@ +import { spawn, execSync } from "node:child_process"; +import { + displayTestResults, + hasFailures, +} from "../../../shared/dist/index.mjs"; + +const PORT = 8801; +const MAX_RETRIES = 20; +const RETRY_DELAY_MS = 250; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +function killPort(port) { + try { + execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { + stdio: "ignore", + }); + } catch {} +} + +async function waitForServer() { + for (let i = 0; i < MAX_RETRIES; i++) { + try { + const res = await fetch(`http://localhost:${PORT}/`); + if (res.ok) return true; + } catch {} + await sleep(RETRY_DELAY_MS); + } + return false; +} + +function displayResults(testResult) { + if (testResult.results && testResult.results.length > 0) { + displayTestResults({ + scenarioName: "Cloudflare Worker Browser Compat Test Results", + results: testResult.results, + }); + } else { + console.log(JSON.stringify(testResult, null, 2)); + } +} + +async function main() { + killPort(PORT); + + const wrangler = spawn("npx", ["wrangler", "dev", "--port", String(PORT)], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let wranglerOutput = ""; + wrangler.stdout.on("data", (data) => (wranglerOutput += data)); + wrangler.stderr.on("data", (data) => (wranglerOutput += data)); + + const killWrangler = () => { + return new Promise((resolve) => { + if (wrangler.exitCode !== null) { + resolve(); + return; + } + wrangler.once("exit", resolve); + wrangler.kill("SIGTERM"); + setTimeout(() => { + if (wrangler.exitCode === null) { + wrangler.kill("SIGKILL"); + } + }, 1000); + }); + }; + + try { + const serverStartedSuccessfully = await waitForServer(); + + if (!serverStartedSuccessfully) { + console.error("Server failed to start:\n", wranglerOutput); + await killWrangler(); + process.exit(1); + } + + const testResponse = await fetch(`http://localhost:${PORT}/test`); + const testResult = await testResponse.json(); + + displayResults(testResult); + + const exitCode = testResult.success ? 0 : 1; + await killWrangler(); + process.exit(exitCode); + } catch (error) { + console.error("Error:", error.message, "\n", wranglerOutput); + await killWrangler(); + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/tsconfig.json b/js/smoke/scenarios/cloudflare-worker-browser-compat/tsconfig.json new file mode 100644 index 000000000..7b01869fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ES2022", + "moduleResolution": "bundler", + "types": ["@cloudflare/workers-types"], + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml new file mode 100644 index 000000000..94fa314a2 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml @@ -0,0 +1,4 @@ +name = "smoke-cloudflare-worker-browser-compat" +main = "src/worker.ts" +compatibility_date = "2024-09-23" +compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/.gitignore b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/.gitignore new file mode 100644 index 000000000..b1f90d523 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.wrangler/ +dist/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/Makefile b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/Makefile new file mode 100644 index 000000000..6191b7646 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/Makefile @@ -0,0 +1,29 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-worker-browser-no-compat" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package if needed + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-worker-browser-no-compat tests" + npx tsx tests/worker.test.mjs diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/README.md b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/README.md new file mode 100644 index 000000000..d2e30b6b0 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/README.md @@ -0,0 +1,25 @@ +# Cloudflare Worker Browser No Compat Scenario + +Tests Braintrust SDK in Cloudflare Workers with `braintrust/browser` entrypoint without Node.js compatibility flags. + +## Design Decisions + +### Import Path + +Uses `braintrust/browser` (browser entrypoint) to test the most lightweight configuration. The browser entrypoint is designed to work in environments without Node.js APIs. + +### Compatibility Flags + +No compatibility flags are enabled. This tests the pure Cloudflare Workers runtime without Node.js polyfills, representing the most minimal configuration. + +### Expected Outcome + +All tests should pass. The browser entrypoint is designed to work in standard Web API environments without requiring Node.js compatibility. + +### Test Pattern + +- Spawns wrangler dev server +- Makes HTTP request to worker +- Runs shared test suite inside worker runtime +- No mocks - real Cloudflare Workers environment without Node.js compatibility layer +- Most lightweight configuration - ideal for production use cases diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/mise.toml b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json new file mode 100644 index 000000000..5e8ae393f --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json @@ -0,0 +1,16 @@ +{ + "name": "smoke-cloudflare-worker-browser-no-compat", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^20", + "tsx": "^4.19.2", + "typescript": "^5.4.4", + "wrangler": "^4.28.1" + } +} diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts new file mode 100644 index 000000000..c8a6c9261 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts @@ -0,0 +1,157 @@ +import * as braintrust from "braintrust/browser"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + testMustacheTemplate, + testNunjucksTemplate, + type TestResult, +} from "../../../shared"; + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger: braintrust.initLogger, + testingExports: braintrust._exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "cloudflare-worker-browser-no-compat", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests( + adapters, + braintrust, + ); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + + // Test Mustache template (should always work) + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + // Test Nunjucks template - expected to fail in browser builds + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ? { + ...nunjucksResult, + status: "xfail" as const, + message: + "Expected failure: Nunjucks not supported in browser build", + } + : nunjucksResult; + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + mustacheResult, + nunjucksResultHandled, + ]; + + // Filter out expected failures when counting actual failures + const failures = results.filter((r) => r.status === "fail"); + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +export default { + async fetch(request: Request, _env: Env): Promise { + const url = new URL(request.url); + + if (url.pathname === "/test") { + const result = await runSharedTestSuites(); + + // Serialize errors properly (Error objects don't JSON.stringify well) + const serializedResult = { + ...result, + results: result.results?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + failures: result.failures?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + }; + + return new Response(JSON.stringify(serializedResult, null, 2), { + headers: { "Content-Type": "application/json" }, + status: result.success ? 200 : 500, + }); + } + + return new Response( + `Braintrust Cloudflare Worker Smoke Test (Browser + No Compat) + +GET /test - Run shared test suites + +This worker tests the Braintrust SDK in a Cloudflare Workers environment +using the browser entrypoint without nodejs_compat_v2.`, + { headers: { "Content-Type": "text/plain" } }, + ); + }, +}; diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/tests/worker.test.mjs b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/tests/worker.test.mjs new file mode 100644 index 000000000..3e2811b3b --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/tests/worker.test.mjs @@ -0,0 +1,98 @@ +import { spawn, execSync } from "node:child_process"; +import { + displayTestResults, + hasFailures, +} from "../../../shared/dist/index.mjs"; + +const PORT = 8800; +const MAX_RETRIES = 20; +const RETRY_DELAY_MS = 250; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +function killPort(port) { + try { + execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { + stdio: "ignore", + }); + } catch {} +} + +async function waitForServer() { + for (let i = 0; i < MAX_RETRIES; i++) { + try { + const res = await fetch(`http://localhost:${PORT}/`); + if (res.ok) return true; + } catch {} + await sleep(RETRY_DELAY_MS); + } + return false; +} + +function displayResults(testResult) { + if (testResult.results && testResult.results.length > 0) { + displayTestResults({ + scenarioName: "Cloudflare Worker Browser No Compat Test Results", + results: testResult.results, + }); + } else { + console.log(JSON.stringify(testResult, null, 2)); + } +} + +async function main() { + killPort(PORT); + + const wrangler = spawn("npx", ["wrangler", "dev", "--port", String(PORT)], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let wranglerOutput = ""; + wrangler.stdout.on("data", (data) => (wranglerOutput += data)); + wrangler.stderr.on("data", (data) => (wranglerOutput += data)); + + const killWrangler = () => { + return new Promise((resolve) => { + if (wrangler.exitCode !== null) { + resolve(); + return; + } + wrangler.once("exit", resolve); + wrangler.kill("SIGTERM"); + setTimeout(() => { + if (wrangler.exitCode === null) { + wrangler.kill("SIGKILL"); + } + }, 1000); + }); + }; + + try { + const serverStartedSuccessfully = await waitForServer(); + + if (!serverStartedSuccessfully) { + console.error("Server failed to start:\n", wranglerOutput); + await killWrangler(); + process.exit(1); + } + + const testResponse = await fetch(`http://localhost:${PORT}/test`); + const testResult = await testResponse.json(); + + displayResults(testResult); + + const exitCode = testResult.success ? 0 : 1; + await killWrangler(); + process.exit(exitCode); + } catch (error) { + console.error("Error:", error.message, "\n", wranglerOutput); + await killWrangler(); + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/tsconfig.json b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/tsconfig.json new file mode 100644 index 000000000..7b01869fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ES2022", + "moduleResolution": "bundler", + "types": ["@cloudflare/workers-types"], + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml new file mode 100644 index 000000000..ae058eb0b --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml @@ -0,0 +1,3 @@ +name = "smoke-cloudflare-worker-browser-no-compat" +main = "src/worker.ts" +compatibility_date = "2024-09-23" diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/.gitignore b/js/smoke/scenarios/cloudflare-worker-node-compat/.gitignore new file mode 100644 index 000000000..b1f90d523 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.wrangler/ +dist/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/Makefile b/js/smoke/scenarios/cloudflare-worker-node-compat/Makefile new file mode 100644 index 000000000..0c7ef605c --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/Makefile @@ -0,0 +1,29 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-worker-node-compat" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package if needed + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-worker-node-compat tests" + npx tsx tests/worker.test.mjs diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/README.md b/js/smoke/scenarios/cloudflare-worker-node-compat/README.md new file mode 100644 index 000000000..515a7e1c2 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/README.md @@ -0,0 +1,24 @@ +# Cloudflare Worker Node Compat Scenario + +Tests Braintrust SDK in Cloudflare Workers with `braintrust` (Node.js) entrypoint and `nodejs_compat_v2` enabled. + +## Design Decisions + +### Import Path + +Uses `braintrust` (Node.js entrypoint) to test Node.js-compatible APIs in Cloudflare Workers environment. + +### Compatibility Flags + +`nodejs_compat_v2` is enabled to provide Node.js API compatibility in the Cloudflare Workers runtime. This allows the Node.js entrypoint to access required Node.js APIs like `crypto`, `buffer`, etc. + +### Expected Outcome + +All tests should pass. The Node.js entrypoint requires `nodejs_compat_v2` to function properly in Cloudflare Workers. + +### Test Pattern + +- Spawns wrangler dev server +- Makes HTTP request to worker +- Runs shared test suite inside worker runtime +- No mocks - real Cloudflare Workers environment with Node.js compatibility layer diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/mise.toml b/js/smoke/scenarios/cloudflare-worker-node-compat/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/package.json b/js/smoke/scenarios/cloudflare-worker-node-compat/package.json new file mode 100644 index 000000000..4b2ac576e --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/package.json @@ -0,0 +1,16 @@ +{ + "name": "smoke-cloudflare-worker-node-compat", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^20", + "tsx": "^4.19.2", + "typescript": "^5.4.4", + "wrangler": "^4.28.1" + } +} diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts new file mode 100644 index 000000000..85d5a58cf --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts @@ -0,0 +1,157 @@ +import * as braintrust from "braintrust"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + testMustacheTemplate, + testNunjucksTemplate, + type TestResult, +} from "../../../shared"; + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger: braintrust.initLogger, + testingExports: braintrust._exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "cloudflare-worker-node-compat", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests( + adapters, + braintrust, + ); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + + // Test Mustache template (should always work) + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + // Test Nunjucks template - expected to fail due to code generation restrictions + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Disallowed in this environment for security reasons", + ) + ? { + ...nunjucksResult, + status: "xfail" as const, + message: + "Expected failure: Cloudflare Workers blocks dynamic code generation (eval/Function)", + } + : nunjucksResult; + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + mustacheResult, + nunjucksResultHandled, + ]; + + // Filter out expected failures when counting actual failures + const failures = results.filter((r) => r.status === "fail"); + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +export default { + async fetch(request: Request, _env: Env): Promise { + const url = new URL(request.url); + + if (url.pathname === "/test") { + const result = await runSharedTestSuites(); + + // Serialize errors properly (Error objects don't JSON.stringify well) + const serializedResult = { + ...result, + results: result.results?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + failures: result.failures?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + }; + + return new Response(JSON.stringify(serializedResult, null, 2), { + headers: { "Content-Type": "application/json" }, + status: result.success ? 200 : 500, + }); + } + + return new Response( + `Braintrust Cloudflare Worker Smoke Test (Node.js + nodejs_compat_v2) + +GET /test - Run shared test suites + +This worker tests the Braintrust SDK in a Cloudflare Workers environment +using the Node.js entrypoint with nodejs_compat_v2 enabled.`, + { headers: { "Content-Type": "text/plain" } }, + ); + }, +}; diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/tests/worker.test.mjs b/js/smoke/scenarios/cloudflare-worker-node-compat/tests/worker.test.mjs new file mode 100644 index 000000000..843596bb6 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/tests/worker.test.mjs @@ -0,0 +1,98 @@ +import { spawn, execSync } from "node:child_process"; +import { + displayTestResults, + hasFailures, +} from "../../../shared/dist/index.mjs"; + +const PORT = 8799; +const MAX_RETRIES = 20; +const RETRY_DELAY_MS = 250; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +function killPort(port) { + try { + execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { + stdio: "ignore", + }); + } catch {} +} + +async function waitForServer() { + for (let i = 0; i < MAX_RETRIES; i++) { + try { + const res = await fetch(`http://localhost:${PORT}/`); + if (res.ok) return true; + } catch {} + await sleep(RETRY_DELAY_MS); + } + return false; +} + +function displayResults(testResult) { + if (testResult.results && testResult.results.length > 0) { + displayTestResults({ + scenarioName: "Cloudflare Worker Node Compat Test Results", + results: testResult.results, + }); + } else { + console.log(JSON.stringify(testResult, null, 2)); + } +} + +async function main() { + killPort(PORT); + + const wrangler = spawn("npx", ["wrangler", "dev", "--port", String(PORT)], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let wranglerOutput = ""; + wrangler.stdout.on("data", (data) => (wranglerOutput += data)); + wrangler.stderr.on("data", (data) => (wranglerOutput += data)); + + const killWrangler = () => { + return new Promise((resolve) => { + if (wrangler.exitCode !== null) { + resolve(); + return; + } + wrangler.once("exit", resolve); + wrangler.kill("SIGTERM"); + setTimeout(() => { + if (wrangler.exitCode === null) { + wrangler.kill("SIGKILL"); + } + }, 1000); + }); + }; + + try { + const serverStartedSuccessfully = await waitForServer(); + + if (!serverStartedSuccessfully) { + console.error("Server failed to start:\n", wranglerOutput); + await killWrangler(); + process.exit(1); + } + + const testResponse = await fetch(`http://localhost:${PORT}/test`); + const testResult = await testResponse.json(); + + displayResults(testResult); + + const exitCode = testResult.success ? 0 : 1; + await killWrangler(); + process.exit(exitCode); + } catch (error) { + console.error("Error:", error.message, "\n", wranglerOutput); + await killWrangler(); + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/tsconfig.json b/js/smoke/scenarios/cloudflare-worker-node-compat/tsconfig.json new file mode 100644 index 000000000..7b01869fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ES2022", + "moduleResolution": "bundler", + "types": ["@cloudflare/workers-types"], + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/tests/cloudflare-worker/wrangler.node.toml b/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml similarity index 52% rename from js/smoke/tests/cloudflare-worker/wrangler.node.toml rename to js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml index 6e94cceb6..3f4e37af6 100644 --- a/js/smoke/tests/cloudflare-worker/wrangler.node.toml +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml @@ -1,4 +1,4 @@ -name = "braintrust-smoke-test-node" -main = "src/node-node-compat.ts" +name = "smoke-cloudflare-worker-node-compat" +main = "src/worker.ts" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/.gitignore b/js/smoke/scenarios/cloudflare-worker-node-no-compat/.gitignore new file mode 100644 index 000000000..b1f90d523 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.wrangler/ +dist/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/Makefile b/js/smoke/scenarios/cloudflare-worker-node-no-compat/Makefile new file mode 100644 index 000000000..9f41033a4 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/Makefile @@ -0,0 +1,29 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-worker-node-no-compat" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package if needed + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-worker-node-no-compat tests" + npx tsx tests/worker.test.mjs diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/README.md b/js/smoke/scenarios/cloudflare-worker-node-no-compat/README.md new file mode 100644 index 000000000..5eeaa082c --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/README.md @@ -0,0 +1,26 @@ +# Cloudflare Worker Node No Compat Scenario + +Tests Braintrust SDK in Cloudflare Workers with `braintrust` (Node.js) entrypoint without Node.js compatibility flags. + +## Design Decisions + +### Import Path + +Uses `braintrust` (Node.js entrypoint) which requires Node.js APIs. + +### Compatibility Flags + +No compatibility flags are enabled. This intentionally creates an invalid configuration to document the expected failure. + +### Expected Outcome + +**This scenario is expected to FAIL at startup.** The Node.js entrypoint requires `nodejs_compat_v2` to function in Cloudflare Workers because it relies on Node.js-specific APIs like `crypto`, `buffer`, and others that are not available in the standard Cloudflare Workers runtime. + +The test passes if wrangler fails to start the worker, documenting that this configuration is not supported. + +### Test Pattern + +- Spawns wrangler dev server +- Expects startup to fail +- Test passes if server fails to start +- Documents that Node.js entrypoint requires nodejs_compat_v2 diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/mise.toml b/js/smoke/scenarios/cloudflare-worker-node-no-compat/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/package.json b/js/smoke/scenarios/cloudflare-worker-node-no-compat/package.json new file mode 100644 index 000000000..49c42c830 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/package.json @@ -0,0 +1,16 @@ +{ + "name": "smoke-cloudflare-worker-node-no-compat", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^20", + "tsx": "^4.19.2", + "typescript": "^5.4.4", + "wrangler": "^4.28.1" + } +} diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts new file mode 100644 index 000000000..7e1cb045b --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts @@ -0,0 +1,135 @@ +import * as braintrust from "braintrust"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + runPromptTemplatingTests, + type TestResult, +} from "../../../shared"; + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger: braintrust.initLogger, + testingExports: braintrust._exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "cloudflare-worker-node-no-compat", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests( + adapters, + braintrust, + ); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + const promptTemplatingResults = await runPromptTemplatingTests({ + Prompt: braintrust.Prompt, + }); + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + ...promptTemplatingResults, + ]; + + const failures = results.filter((r) => r.status === "fail"); + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +export default { + async fetch(request: Request, _env: Env): Promise { + const url = new URL(request.url); + + if (url.pathname === "/test") { + const result = await runSharedTestSuites(); + + // Serialize errors properly (Error objects don't JSON.stringify well) + const serializedResult = { + ...result, + results: result.results?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + failures: result.failures?.map((r) => ({ + ...r, + error: r.error + ? { + message: r.error.message, + stack: r.error.stack, + name: r.error.name, + } + : undefined, + })), + }; + + return new Response(JSON.stringify(serializedResult, null, 2), { + headers: { "Content-Type": "application/json" }, + status: result.success ? 200 : 500, + }); + } + + return new Response( + `Braintrust Cloudflare Worker Smoke Test (Node.js + No Compat) + +GET /test - Run shared test suites + +This worker tests the Braintrust SDK in a Cloudflare Workers environment +using the Node.js entrypoint without nodejs_compat_v2. This is expected to fail.`, + { headers: { "Content-Type": "text/plain" } }, + ); + }, +}; diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/tests/worker.test.mjs b/js/smoke/scenarios/cloudflare-worker-node-no-compat/tests/worker.test.mjs new file mode 100644 index 000000000..b80cbd35a --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/tests/worker.test.mjs @@ -0,0 +1,106 @@ +import { spawn, execSync } from "node:child_process"; +import { + displayTestResults, + hasFailures, +} from "../../../shared/dist/index.mjs"; + +const PORT = 8802; +const MAX_RETRIES = 20; +const RETRY_DELAY_MS = 250; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +function killPort(port) { + try { + execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { + stdio: "ignore", + }); + } catch {} +} + +async function waitForServer() { + for (let i = 0; i < MAX_RETRIES; i++) { + try { + const res = await fetch(`http://localhost:${PORT}/`); + if (res.ok) return true; + } catch {} + await sleep(RETRY_DELAY_MS); + } + return false; +} + +async function main() { + killPort(PORT); + + const wrangler = spawn("npx", ["wrangler", "dev", "--port", String(PORT)], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let wranglerOutput = ""; + wrangler.stdout.on("data", (data) => (wranglerOutput += data)); + wrangler.stderr.on("data", (data) => (wranglerOutput += data)); + + const killWrangler = () => { + return new Promise((resolve) => { + if (wrangler.exitCode !== null) { + resolve(); + return; + } + wrangler.once("exit", resolve); + wrangler.kill("SIGTERM"); + setTimeout(() => { + if (wrangler.exitCode === null) { + wrangler.kill("SIGKILL"); + } + }, 1000); + }); + }; + + const results = []; + + try { + const serverStartedSuccessfully = await waitForServer(); + + if (!serverStartedSuccessfully) { + results.push({ + status: "xfail", + name: "Worker startup without nodejs_compat_v2", + message: + "Worker failed to start as expected (Node.js APIs require nodejs_compat_v2)", + }); + await killWrangler(); + } else { + results.push({ + status: "fail", + name: "Worker startup without nodejs_compat_v2", + error: { + message: + "Worker started successfully, but it should have failed! The Node.js entrypoint should not work without nodejs_compat_v2.", + }, + }); + await killWrangler(); + } + } catch (error) { + results.push({ + status: "xfail", + name: "Worker startup without nodejs_compat_v2", + message: `Worker failed as expected: ${error.message}`, + }); + await killWrangler(); + } + + displayTestResults({ + scenarioName: "Cloudflare Worker Node No Compat Test Results", + results, + }); + + if (hasFailures(results)) { + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/tsconfig.json b/js/smoke/scenarios/cloudflare-worker-node-no-compat/tsconfig.json new file mode 100644 index 000000000..7b01869fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ES2022", + "moduleResolution": "bundler", + "types": ["@cloudflare/workers-types"], + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml new file mode 100644 index 000000000..74b70da63 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml @@ -0,0 +1,3 @@ +name = "smoke-cloudflare-worker-node-no-compat" +main = "src/worker.ts" +compatibility_date = "2024-09-23" diff --git a/js/smoke/scenarios/deno-browser/.gitignore b/js/smoke/scenarios/deno-browser/.gitignore new file mode 100644 index 000000000..49103d242 --- /dev/null +++ b/js/smoke/scenarios/deno-browser/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +.DS_Store +package-lock.json diff --git a/js/smoke/scenarios/deno-browser/Makefile b/js/smoke/scenarios/deno-browser/Makefile new file mode 100644 index 000000000..09ab17ddf --- /dev/null +++ b/js/smoke/scenarios/deno-browser/Makefile @@ -0,0 +1,21 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up deno-browser scenario" + mise install + @# Deno uses workspace links - need SDK dist/ folder to exist + @if [ ! -d ../../../dist ]; then \ + if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Extracting SDK tarball for workspace link"; \ + TARBALL_PATH="$$(cd ../.. && pwd)/$(BRAINTRUST_TAR)"; \ + echo "==> Resolved tarball path: $$TARBALL_PATH"; \ + cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ + else \ + echo "==> Building SDK for workspace link"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust; \ + fi; \ + fi + deno install + +test: setup + deno test --sloppy-imports --allow-all tests/*.test.ts diff --git a/js/smoke/scenarios/deno-browser/README.md b/js/smoke/scenarios/deno-browser/README.md new file mode 100644 index 000000000..790322183 --- /dev/null +++ b/js/smoke/scenarios/deno-browser/README.md @@ -0,0 +1,35 @@ +# Deno Browser Build Test + +Tests the browser-specific build (`braintrust/browser` export) in Deno runtime. + +## Design Decisions + +### Local Package Linking + +Uses Deno's `links` feature in `deno.json` to test against local SDK builds: + +- `"links": ["../../..", "../../shared"]` ensures we use the workspace versions +- No need to publish or pack - Deno reads from `../../../dist/` directly + +### Sloppy Imports + +Requires `--sloppy-imports` flag because the shared test package uses extensionless imports: + +- Shared package: `import { foo } from "./helpers/types"` (no `.ts`) +- This is standard for TypeScript/Node.js but requires `--sloppy-imports` in Deno +- Alternative would be adding `.ts` extensions, but that may break Node.js tooling + +### npm Compatibility + +Uses `nodeModulesDir: "auto"` to enable Deno's npm package resolution: + +- Allows `npm:braintrust@^2.0.2/browser` imports +- Combined with `links`, resolves to local workspace packages + +### Browser vs Node Build + +Uses `braintrust/browser` export instead of main `braintrust`: + +- Browser-optimized bundle (no nunjucks, simple-git, etc.) +- Only mustache templates supported +- Platform-specific `.browser.ts` implementations diff --git a/js/smoke/scenarios/deno-browser/deno.json b/js/smoke/scenarios/deno-browser/deno.json new file mode 100644 index 000000000..6e1f5f0d4 --- /dev/null +++ b/js/smoke/scenarios/deno-browser/deno.json @@ -0,0 +1,12 @@ +{ + "imports": { + "@std/assert": "jsr:@std/assert@^1.0.14", + "@braintrust/smoke-test-shared": "jsr:@braintrust/smoke-test-shared", + "braintrust/browser": "npm:braintrust@^2.0.2/browser" + }, + "nodeModulesDir": "auto", + "links": [ + "../../..", + "../../shared" + ] +} diff --git a/js/smoke/scenarios/deno-browser/deno.lock b/js/smoke/scenarios/deno-browser/deno.lock new file mode 100644 index 000000000..d32c2672c --- /dev/null +++ b/js/smoke/scenarios/deno-browser/deno.lock @@ -0,0 +1,908 @@ +{ + "version": "5", + "specifiers": { + "jsr:@std/assert@^1.0.14": "1.0.16", + "jsr:@std/internal@^1.0.12": "1.0.12", + "npm:braintrust@^2.0.2": "2.0.2_zod@4.3.5" + }, + "jsr": { + "@std/assert@1.0.16": { + "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + } + }, + "npm": { + "@ai-sdk/provider@1.1.3": { + "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", + "dependencies": [ + "json-schema" + ] + }, + "@colors/colors@1.5.0": { + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" + }, + "@esbuild/aix-ppc64@0.27.2": { + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/android-arm64@0.27.2": { + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm@0.27.2": { + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-x64@0.27.2": { + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/darwin-arm64@0.27.2": { + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-x64@0.27.2": { + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-arm64@0.27.2": { + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-x64@0.27.2": { + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/linux-arm64@0.27.2": { + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm@0.27.2": { + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-ia32@0.27.2": { + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-loong64@0.27.2": { + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-mips64el@0.27.2": { + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-ppc64@0.27.2": { + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-riscv64@0.27.2": { + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-s390x@0.27.2": { + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-x64@0.27.2": { + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-arm64@0.27.2": { + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-x64@0.27.2": { + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-arm64@0.27.2": { + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-x64@0.27.2": { + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openharmony-arm64@0.27.2": { + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/sunos-x64@0.27.2": { + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/win32-arm64@0.27.2": { + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.27.2": { + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.27.2": { + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@kwsites/file-exists@1.1.1": { + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dependencies": [ + "debug@4.4.3" + ] + }, + "@kwsites/promise-deferred@1.1.1": { + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + }, + "@next/env@14.2.35": { + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==" + }, + "@types/nunjucks@3.2.6": { + "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==" + }, + "@vercel/functions@1.6.0": { + "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==" + }, + "a-sync-waterfall@1.0.1": { + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + }, + "accepts@1.3.8": { + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": [ + "mime-types", + "negotiator" + ] + }, + "ansi-align@3.0.1": { + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": [ + "string-width@4.2.3" + ] + }, + "ansi-regex@5.0.1": { + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-regex@6.2.2": { + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==" + }, + "ansi-styles@4.3.0": { + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": [ + "color-convert" + ] + }, + "ansi-styles@6.2.3": { + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" + }, + "argparse@2.0.1": { + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "array-flatten@1.1.1": { + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "asap@2.0.6": { + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "balanced-match@1.0.2": { + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "body-parser@1.20.4": { + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "dependencies": [ + "bytes", + "content-type", + "debug@2.6.9", + "depd", + "destroy", + "http-errors", + "iconv-lite", + "on-finished", + "qs", + "raw-body", + "type-is", + "unpipe" + ] + }, + "boxen@8.0.1": { + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "dependencies": [ + "ansi-align", + "camelcase", + "chalk@5.6.2", + "cli-boxes", + "string-width@7.2.0", + "type-fest", + "widest-line", + "wrap-ansi" + ] + }, + "brace-expansion@2.0.2": { + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": [ + "balanced-match" + ] + }, + "braintrust@2.0.2_zod@4.3.5": { + "dependencies": [ + "@ai-sdk/provider", + "@next/env", + "@types/nunjucks", + "@vercel/functions", + "argparse", + "boxen", + "chalk@4.1.2", + "cli-progress", + "cli-table3", + "cors", + "dotenv", + "esbuild", + "eventsource-parser", + "express", + "graceful-fs", + "http-errors", + "minimatch", + "mustache", + "nunjucks", + "pluralize", + "simple-git", + "source-map", + "termi-link", + "uuid", + "zod", + "zod-to-json-schema" + ], + "bin": true + }, + "bytes@3.1.2": { + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind-apply-helpers@1.0.2": { + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": [ + "es-errors", + "function-bind" + ] + }, + "call-bound@1.0.4": { + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": [ + "call-bind-apply-helpers", + "get-intrinsic" + ] + }, + "camelcase@8.0.0": { + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==" + }, + "chalk@4.1.2": { + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color" + ] + }, + "chalk@5.6.2": { + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==" + }, + "cli-boxes@3.0.0": { + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==" + }, + "cli-progress@3.12.0": { + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dependencies": [ + "string-width@4.2.3" + ] + }, + "cli-table3@0.6.5": { + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dependencies": [ + "string-width@4.2.3" + ], + "optionalDependencies": [ + "@colors/colors" + ] + }, + "color-convert@2.0.1": { + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": [ + "color-name" + ] + }, + "color-name@1.1.4": { + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "commander@5.1.0": { + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + }, + "content-disposition@0.5.4": { + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": [ + "safe-buffer" + ] + }, + "content-type@1.0.5": { + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie-signature@1.0.7": { + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "cookie@0.7.2": { + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + }, + "cors@2.8.5": { + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": [ + "object-assign", + "vary" + ] + }, + "debug@2.6.9": { + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": [ + "ms@2.0.0" + ] + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms@2.1.3" + ] + }, + "depd@2.0.0": { + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy@1.2.0": { + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "dotenv@16.6.1": { + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==" + }, + "dunder-proto@1.0.1": { + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": [ + "call-bind-apply-helpers", + "es-errors", + "gopd" + ] + }, + "ee-first@1.1.1": { + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "emoji-regex@10.6.0": { + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" + }, + "emoji-regex@8.0.0": { + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl@2.0.0": { + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" + }, + "es-define-property@1.0.1": { + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors@1.3.0": { + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms@1.1.1": { + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": [ + "es-errors" + ] + }, + "esbuild@0.27.2": { + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "optionalDependencies": [ + "@esbuild/aix-ppc64", + "@esbuild/android-arm", + "@esbuild/android-arm64", + "@esbuild/android-x64", + "@esbuild/darwin-arm64", + "@esbuild/darwin-x64", + "@esbuild/freebsd-arm64", + "@esbuild/freebsd-x64", + "@esbuild/linux-arm", + "@esbuild/linux-arm64", + "@esbuild/linux-ia32", + "@esbuild/linux-loong64", + "@esbuild/linux-mips64el", + "@esbuild/linux-ppc64", + "@esbuild/linux-riscv64", + "@esbuild/linux-s390x", + "@esbuild/linux-x64", + "@esbuild/netbsd-arm64", + "@esbuild/netbsd-x64", + "@esbuild/openbsd-arm64", + "@esbuild/openbsd-x64", + "@esbuild/openharmony-arm64", + "@esbuild/sunos-x64", + "@esbuild/win32-arm64", + "@esbuild/win32-ia32", + "@esbuild/win32-x64" + ], + "scripts": true, + "bin": true + }, + "escape-html@1.0.3": { + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag@1.8.1": { + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eventsource-parser@1.1.2": { + "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==" + }, + "express@4.22.1": { + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "dependencies": [ + "accepts", + "array-flatten", + "body-parser", + "content-disposition", + "content-type", + "cookie", + "cookie-signature", + "debug@2.6.9", + "depd", + "encodeurl", + "escape-html", + "etag", + "finalhandler", + "fresh", + "http-errors", + "merge-descriptors", + "methods", + "on-finished", + "parseurl", + "path-to-regexp", + "proxy-addr", + "qs", + "range-parser", + "safe-buffer", + "send", + "serve-static", + "setprototypeof", + "statuses", + "type-is", + "utils-merge", + "vary" + ] + }, + "finalhandler@1.3.2": { + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dependencies": [ + "debug@2.6.9", + "encodeurl", + "escape-html", + "on-finished", + "parseurl", + "statuses", + "unpipe" + ] + }, + "forwarded@0.2.0": { + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh@0.5.2": { + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "function-bind@1.1.2": { + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "get-east-asian-width@1.4.0": { + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==" + }, + "get-intrinsic@1.3.0": { + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": [ + "call-bind-apply-helpers", + "es-define-property", + "es-errors", + "es-object-atoms", + "function-bind", + "get-proto", + "gopd", + "has-symbols", + "hasown", + "math-intrinsics" + ] + }, + "get-proto@1.0.1": { + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": [ + "dunder-proto", + "es-object-atoms" + ] + }, + "gopd@1.2.0": { + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "graceful-fs@4.2.11": { + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "has-flag@4.0.0": { + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-symbols@1.1.0": { + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "hasown@2.0.2": { + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": [ + "function-bind" + ] + }, + "http-errors@2.0.1": { + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dependencies": [ + "depd", + "inherits", + "setprototypeof", + "statuses", + "toidentifier" + ] + }, + "iconv-lite@0.4.24": { + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": [ + "safer-buffer" + ] + }, + "inherits@2.0.4": { + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js@1.9.1": { + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-fullwidth-code-point@3.0.0": { + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "json-schema@0.4.0": { + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "math-intrinsics@1.1.0": { + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, + "media-typer@0.3.0": { + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors@1.0.3": { + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" + }, + "methods@1.1.2": { + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime-db@1.52.0": { + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types@2.1.35": { + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": [ + "mime-db" + ] + }, + "mime@1.6.0": { + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": true + }, + "minimatch@9.0.5": { + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": [ + "brace-expansion" + ] + }, + "ms@2.0.0": { + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "mustache@4.2.0": { + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": true + }, + "negotiator@0.6.3": { + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "nunjucks@3.2.4": { + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dependencies": [ + "a-sync-waterfall", + "asap", + "commander" + ], + "bin": true + }, + "object-assign@4.1.1": { + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect@1.13.4": { + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" + }, + "on-finished@2.4.1": { + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": [ + "ee-first" + ] + }, + "parseurl@1.3.3": { + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp@0.1.12": { + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "pluralize@8.0.0": { + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + }, + "proxy-addr@2.0.7": { + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": [ + "forwarded", + "ipaddr.js" + ] + }, + "qs@6.14.1": { + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "dependencies": [ + "side-channel" + ] + }, + "range-parser@1.2.1": { + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body@2.5.3": { + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dependencies": [ + "bytes", + "http-errors", + "iconv-lite", + "unpipe" + ] + }, + "safe-buffer@5.2.1": { + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer@2.1.2": { + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send@0.19.2": { + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dependencies": [ + "debug@2.6.9", + "depd", + "destroy", + "encodeurl", + "escape-html", + "etag", + "fresh", + "http-errors", + "mime", + "ms@2.1.3", + "on-finished", + "range-parser", + "statuses" + ] + }, + "serve-static@1.16.3": { + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dependencies": [ + "encodeurl", + "escape-html", + "parseurl", + "send" + ] + }, + "setprototypeof@1.2.0": { + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel-list@1.0.0": { + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": [ + "es-errors", + "object-inspect" + ] + }, + "side-channel-map@1.0.1": { + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": [ + "call-bound", + "es-errors", + "get-intrinsic", + "object-inspect" + ] + }, + "side-channel-weakmap@1.0.2": { + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": [ + "call-bound", + "es-errors", + "get-intrinsic", + "object-inspect", + "side-channel-map" + ] + }, + "side-channel@1.1.0": { + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": [ + "es-errors", + "object-inspect", + "side-channel-list", + "side-channel-map", + "side-channel-weakmap" + ] + }, + "simple-git@3.30.0": { + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "dependencies": [ + "@kwsites/file-exists", + "@kwsites/promise-deferred", + "debug@4.4.3" + ] + }, + "source-map@0.7.6": { + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" + }, + "statuses@2.0.2": { + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" + }, + "string-width@4.2.3": { + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": [ + "emoji-regex@8.0.0", + "is-fullwidth-code-point", + "strip-ansi@6.0.1" + ] + }, + "string-width@7.2.0": { + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dependencies": [ + "emoji-regex@10.6.0", + "get-east-asian-width", + "strip-ansi@7.1.2" + ] + }, + "strip-ansi@6.0.1": { + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": [ + "ansi-regex@5.0.1" + ] + }, + "strip-ansi@7.1.2": { + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": [ + "ansi-regex@6.2.2" + ] + }, + "supports-color@7.2.0": { + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": [ + "has-flag" + ] + }, + "termi-link@1.1.0": { + "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==" + }, + "toidentifier@1.0.1": { + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "type-fest@4.41.0": { + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==" + }, + "type-is@1.6.18": { + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": [ + "media-typer", + "mime-types" + ] + }, + "unpipe@1.0.0": { + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge@1.0.1": { + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid@9.0.1": { + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "bin": true + }, + "vary@1.1.2": { + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "widest-line@5.0.0": { + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "dependencies": [ + "string-width@7.2.0" + ] + }, + "wrap-ansi@9.0.2": { + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dependencies": [ + "ansi-styles@6.2.3", + "string-width@7.2.0", + "strip-ansi@7.1.2" + ] + }, + "zod-to-json-schema@3.25.1_zod@4.3.5": { + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "dependencies": [ + "zod" + ] + }, + "zod@4.3.5": { + "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==" + } + }, + "workspace": { + "dependencies": [ + "jsr:@braintrust/smoke-test-shared@*", + "jsr:@std/assert@^1.0.14", + "npm:braintrust@^2.0.2" + ], + "links": { + "jsr:@braintrust/smoke-test-shared": {}, + "npm:@braintrust/smoke-test-shared@1.0.0": {}, + "npm:braintrust-sdk-js@0.0.1": {}, + "npm:braintrust@2.0.2": { + "dependencies": [ + "npm:@ai-sdk/provider@^1.1.3", + "npm:@next/env@^14.2.3", + "npm:@types/nunjucks@^3.2.6", + "npm:@vercel/functions@^1.0.2", + "npm:argparse@^2.0.1", + "npm:boxen@^8.0.1", + "npm:chalk@^4.1.2", + "npm:cli-progress@^3.12.0", + "npm:cli-table3@~0.6.5", + "npm:cors@^2.8.5", + "npm:dotenv@^16.4.5", + "npm:esbuild@0.27", + "npm:eventsource-parser@^1.1.2", + "npm:express@^4.21.2", + "npm:graceful-fs@^4.2.11", + "npm:http-errors@2", + "npm:minimatch@^9.0.3", + "npm:mustache@^4.2.0", + "npm:nunjucks@^3.2.4", + "npm:pluralize@8", + "npm:simple-git@^3.21.0", + "npm:source-map@~0.7.4", + "npm:termi-link@^1.0.1", + "npm:uuid@^9.0.1", + "npm:zod-to-json-schema@^3.25.0" + ], + "peerDependencies": [ + "npm:zod@^3.25.34 || 4" + ] + } + } + } +} diff --git a/js/smoke/scenarios/deno-browser/mise.toml b/js/smoke/scenarios/deno-browser/mise.toml new file mode 100644 index 000000000..dd563ce6f --- /dev/null +++ b/js/smoke/scenarios/deno-browser/mise.toml @@ -0,0 +1,3 @@ +[tools] +deno = "latest" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts new file mode 100644 index 000000000..b98f2d261 --- /dev/null +++ b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts @@ -0,0 +1,87 @@ +// @ts-nocheck +/** + * Deno smoke test using shared test suites, but importing the browser build. + */ + +import { assertEquals } from "@std/assert"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + testMustacheTemplate, + testNunjucksTemplate, + displayTestResults, + hasFailures, + getFailureCount, + type TestResult, +} from "@braintrust/smoke-test-shared"; +import * as braintrust from "braintrust/browser"; + +export async function runSharedTestSuites(): Promise { + const { initLogger, _exportsForTestingOnly } = braintrust; + + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: true, + canUseCLI: false, + environment: "browser", + }); + + try { + // Run tests + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters, braintrust); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ? { + ...nunjucksResult, + status: "xfail" as const, + message: + "Expected failure: Nunjucks not supported in browser build", + } + : nunjucksResult; + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + mustacheResult, + nunjucksResultHandled, + ]; + + // Display results + displayTestResults({ + scenarioName: "Deno Browser Test Results", + results, + }); + + // Check for failures + if (hasFailures(results)) { + throw new Error(`${getFailureCount(results)} test(s) failed`); + } + + return results; + } finally { + await cleanupTestEnvironment(adapters); + } +} + +Deno.test("Run shared test suites (browser build)", async () => { + const results = await runSharedTestSuites(); + assertEquals(results.filter((r) => r.status === "fail").length, 0); +}); diff --git a/js/smoke/scenarios/deno-node/.gitignore b/js/smoke/scenarios/deno-node/.gitignore new file mode 100644 index 000000000..49103d242 --- /dev/null +++ b/js/smoke/scenarios/deno-node/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +.DS_Store +package-lock.json diff --git a/js/smoke/scenarios/deno-node/Makefile b/js/smoke/scenarios/deno-node/Makefile new file mode 100644 index 000000000..12ef36e31 --- /dev/null +++ b/js/smoke/scenarios/deno-node/Makefile @@ -0,0 +1,21 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up deno-node scenario" + mise install + @# Deno uses workspace links - need SDK dist/ folder to exist + @if [ ! -d ../../../dist ]; then \ + if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Extracting SDK tarball for workspace link"; \ + TARBALL_PATH="$$(cd ../.. && pwd)/$(BRAINTRUST_TAR)"; \ + echo "==> Resolved tarball path: $$TARBALL_PATH"; \ + cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ + else \ + echo "==> Building SDK for workspace link"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust; \ + fi; \ + fi + deno install + +test: setup + deno test --sloppy-imports --allow-all tests/*.test.ts diff --git a/js/smoke/scenarios/deno-node/README.md b/js/smoke/scenarios/deno-node/README.md new file mode 100644 index 000000000..5e369e395 --- /dev/null +++ b/js/smoke/scenarios/deno-node/README.md @@ -0,0 +1,27 @@ +# Deno Node Build Test + +Tests the main Node.js-compatible build (`braintrust` package) in Deno runtime. + +## Design Decisions + +### Local Package Linking + +Uses Deno's `links` feature in `deno.json` to test against local SDK builds: + +- `"links": ["../../..", "../../shared"]` ensures we use the workspace versions +- No need to publish or pack - Deno reads from `../../../dist/` directly + +### Sloppy Imports + +Requires `--sloppy-imports` flag because the shared test package uses extensionless imports: + +- Shared package: `import { foo } from "./helpers/types"` (no `.ts`) +- This is standard for TypeScript/Node.js but requires `--sloppy-imports` in Deno +- Alternative would be adding `.ts` extensions, but that may break Node.js tooling + +### npm Compatibility + +Uses `nodeModulesDir: "auto"` to enable Deno's npm package resolution: + +- Allows `npm:braintrust@^2.0.2` imports +- Combined with `links`, resolves to local workspace packages diff --git a/js/smoke/scenarios/deno-node/deno.json b/js/smoke/scenarios/deno-node/deno.json new file mode 100644 index 000000000..56d30fafa --- /dev/null +++ b/js/smoke/scenarios/deno-node/deno.json @@ -0,0 +1,12 @@ +{ + "imports": { + "@std/assert": "jsr:@std/assert@^1.0.14", + "@braintrust/smoke-test-shared": "jsr:@braintrust/smoke-test-shared", + "braintrust": "npm:braintrust@^2.0.2" + }, + "nodeModulesDir": "auto", + "links": [ + "../../..", + "../../shared" + ] +} diff --git a/js/smoke/scenarios/deno-node/deno.lock b/js/smoke/scenarios/deno-node/deno.lock new file mode 100644 index 000000000..d32c2672c --- /dev/null +++ b/js/smoke/scenarios/deno-node/deno.lock @@ -0,0 +1,908 @@ +{ + "version": "5", + "specifiers": { + "jsr:@std/assert@^1.0.14": "1.0.16", + "jsr:@std/internal@^1.0.12": "1.0.12", + "npm:braintrust@^2.0.2": "2.0.2_zod@4.3.5" + }, + "jsr": { + "@std/assert@1.0.16": { + "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + } + }, + "npm": { + "@ai-sdk/provider@1.1.3": { + "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", + "dependencies": [ + "json-schema" + ] + }, + "@colors/colors@1.5.0": { + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" + }, + "@esbuild/aix-ppc64@0.27.2": { + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/android-arm64@0.27.2": { + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm@0.27.2": { + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-x64@0.27.2": { + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/darwin-arm64@0.27.2": { + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-x64@0.27.2": { + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-arm64@0.27.2": { + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-x64@0.27.2": { + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/linux-arm64@0.27.2": { + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm@0.27.2": { + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-ia32@0.27.2": { + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-loong64@0.27.2": { + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-mips64el@0.27.2": { + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-ppc64@0.27.2": { + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-riscv64@0.27.2": { + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-s390x@0.27.2": { + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-x64@0.27.2": { + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-arm64@0.27.2": { + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-x64@0.27.2": { + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-arm64@0.27.2": { + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-x64@0.27.2": { + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openharmony-arm64@0.27.2": { + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/sunos-x64@0.27.2": { + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/win32-arm64@0.27.2": { + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.27.2": { + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.27.2": { + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@kwsites/file-exists@1.1.1": { + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dependencies": [ + "debug@4.4.3" + ] + }, + "@kwsites/promise-deferred@1.1.1": { + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + }, + "@next/env@14.2.35": { + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==" + }, + "@types/nunjucks@3.2.6": { + "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==" + }, + "@vercel/functions@1.6.0": { + "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==" + }, + "a-sync-waterfall@1.0.1": { + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + }, + "accepts@1.3.8": { + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": [ + "mime-types", + "negotiator" + ] + }, + "ansi-align@3.0.1": { + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": [ + "string-width@4.2.3" + ] + }, + "ansi-regex@5.0.1": { + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-regex@6.2.2": { + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==" + }, + "ansi-styles@4.3.0": { + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": [ + "color-convert" + ] + }, + "ansi-styles@6.2.3": { + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" + }, + "argparse@2.0.1": { + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "array-flatten@1.1.1": { + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "asap@2.0.6": { + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "balanced-match@1.0.2": { + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "body-parser@1.20.4": { + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "dependencies": [ + "bytes", + "content-type", + "debug@2.6.9", + "depd", + "destroy", + "http-errors", + "iconv-lite", + "on-finished", + "qs", + "raw-body", + "type-is", + "unpipe" + ] + }, + "boxen@8.0.1": { + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "dependencies": [ + "ansi-align", + "camelcase", + "chalk@5.6.2", + "cli-boxes", + "string-width@7.2.0", + "type-fest", + "widest-line", + "wrap-ansi" + ] + }, + "brace-expansion@2.0.2": { + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": [ + "balanced-match" + ] + }, + "braintrust@2.0.2_zod@4.3.5": { + "dependencies": [ + "@ai-sdk/provider", + "@next/env", + "@types/nunjucks", + "@vercel/functions", + "argparse", + "boxen", + "chalk@4.1.2", + "cli-progress", + "cli-table3", + "cors", + "dotenv", + "esbuild", + "eventsource-parser", + "express", + "graceful-fs", + "http-errors", + "minimatch", + "mustache", + "nunjucks", + "pluralize", + "simple-git", + "source-map", + "termi-link", + "uuid", + "zod", + "zod-to-json-schema" + ], + "bin": true + }, + "bytes@3.1.2": { + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind-apply-helpers@1.0.2": { + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": [ + "es-errors", + "function-bind" + ] + }, + "call-bound@1.0.4": { + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": [ + "call-bind-apply-helpers", + "get-intrinsic" + ] + }, + "camelcase@8.0.0": { + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==" + }, + "chalk@4.1.2": { + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color" + ] + }, + "chalk@5.6.2": { + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==" + }, + "cli-boxes@3.0.0": { + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==" + }, + "cli-progress@3.12.0": { + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dependencies": [ + "string-width@4.2.3" + ] + }, + "cli-table3@0.6.5": { + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dependencies": [ + "string-width@4.2.3" + ], + "optionalDependencies": [ + "@colors/colors" + ] + }, + "color-convert@2.0.1": { + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": [ + "color-name" + ] + }, + "color-name@1.1.4": { + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "commander@5.1.0": { + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + }, + "content-disposition@0.5.4": { + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": [ + "safe-buffer" + ] + }, + "content-type@1.0.5": { + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie-signature@1.0.7": { + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "cookie@0.7.2": { + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + }, + "cors@2.8.5": { + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": [ + "object-assign", + "vary" + ] + }, + "debug@2.6.9": { + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": [ + "ms@2.0.0" + ] + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms@2.1.3" + ] + }, + "depd@2.0.0": { + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy@1.2.0": { + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "dotenv@16.6.1": { + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==" + }, + "dunder-proto@1.0.1": { + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": [ + "call-bind-apply-helpers", + "es-errors", + "gopd" + ] + }, + "ee-first@1.1.1": { + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "emoji-regex@10.6.0": { + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" + }, + "emoji-regex@8.0.0": { + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl@2.0.0": { + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" + }, + "es-define-property@1.0.1": { + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors@1.3.0": { + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms@1.1.1": { + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": [ + "es-errors" + ] + }, + "esbuild@0.27.2": { + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "optionalDependencies": [ + "@esbuild/aix-ppc64", + "@esbuild/android-arm", + "@esbuild/android-arm64", + "@esbuild/android-x64", + "@esbuild/darwin-arm64", + "@esbuild/darwin-x64", + "@esbuild/freebsd-arm64", + "@esbuild/freebsd-x64", + "@esbuild/linux-arm", + "@esbuild/linux-arm64", + "@esbuild/linux-ia32", + "@esbuild/linux-loong64", + "@esbuild/linux-mips64el", + "@esbuild/linux-ppc64", + "@esbuild/linux-riscv64", + "@esbuild/linux-s390x", + "@esbuild/linux-x64", + "@esbuild/netbsd-arm64", + "@esbuild/netbsd-x64", + "@esbuild/openbsd-arm64", + "@esbuild/openbsd-x64", + "@esbuild/openharmony-arm64", + "@esbuild/sunos-x64", + "@esbuild/win32-arm64", + "@esbuild/win32-ia32", + "@esbuild/win32-x64" + ], + "scripts": true, + "bin": true + }, + "escape-html@1.0.3": { + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag@1.8.1": { + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eventsource-parser@1.1.2": { + "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==" + }, + "express@4.22.1": { + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "dependencies": [ + "accepts", + "array-flatten", + "body-parser", + "content-disposition", + "content-type", + "cookie", + "cookie-signature", + "debug@2.6.9", + "depd", + "encodeurl", + "escape-html", + "etag", + "finalhandler", + "fresh", + "http-errors", + "merge-descriptors", + "methods", + "on-finished", + "parseurl", + "path-to-regexp", + "proxy-addr", + "qs", + "range-parser", + "safe-buffer", + "send", + "serve-static", + "setprototypeof", + "statuses", + "type-is", + "utils-merge", + "vary" + ] + }, + "finalhandler@1.3.2": { + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dependencies": [ + "debug@2.6.9", + "encodeurl", + "escape-html", + "on-finished", + "parseurl", + "statuses", + "unpipe" + ] + }, + "forwarded@0.2.0": { + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh@0.5.2": { + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "function-bind@1.1.2": { + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "get-east-asian-width@1.4.0": { + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==" + }, + "get-intrinsic@1.3.0": { + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": [ + "call-bind-apply-helpers", + "es-define-property", + "es-errors", + "es-object-atoms", + "function-bind", + "get-proto", + "gopd", + "has-symbols", + "hasown", + "math-intrinsics" + ] + }, + "get-proto@1.0.1": { + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": [ + "dunder-proto", + "es-object-atoms" + ] + }, + "gopd@1.2.0": { + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "graceful-fs@4.2.11": { + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "has-flag@4.0.0": { + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-symbols@1.1.0": { + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "hasown@2.0.2": { + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": [ + "function-bind" + ] + }, + "http-errors@2.0.1": { + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dependencies": [ + "depd", + "inherits", + "setprototypeof", + "statuses", + "toidentifier" + ] + }, + "iconv-lite@0.4.24": { + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": [ + "safer-buffer" + ] + }, + "inherits@2.0.4": { + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js@1.9.1": { + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-fullwidth-code-point@3.0.0": { + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "json-schema@0.4.0": { + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "math-intrinsics@1.1.0": { + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, + "media-typer@0.3.0": { + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors@1.0.3": { + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" + }, + "methods@1.1.2": { + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime-db@1.52.0": { + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types@2.1.35": { + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": [ + "mime-db" + ] + }, + "mime@1.6.0": { + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": true + }, + "minimatch@9.0.5": { + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": [ + "brace-expansion" + ] + }, + "ms@2.0.0": { + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "mustache@4.2.0": { + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": true + }, + "negotiator@0.6.3": { + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "nunjucks@3.2.4": { + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dependencies": [ + "a-sync-waterfall", + "asap", + "commander" + ], + "bin": true + }, + "object-assign@4.1.1": { + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect@1.13.4": { + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" + }, + "on-finished@2.4.1": { + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": [ + "ee-first" + ] + }, + "parseurl@1.3.3": { + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp@0.1.12": { + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "pluralize@8.0.0": { + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + }, + "proxy-addr@2.0.7": { + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": [ + "forwarded", + "ipaddr.js" + ] + }, + "qs@6.14.1": { + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "dependencies": [ + "side-channel" + ] + }, + "range-parser@1.2.1": { + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body@2.5.3": { + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dependencies": [ + "bytes", + "http-errors", + "iconv-lite", + "unpipe" + ] + }, + "safe-buffer@5.2.1": { + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer@2.1.2": { + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send@0.19.2": { + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dependencies": [ + "debug@2.6.9", + "depd", + "destroy", + "encodeurl", + "escape-html", + "etag", + "fresh", + "http-errors", + "mime", + "ms@2.1.3", + "on-finished", + "range-parser", + "statuses" + ] + }, + "serve-static@1.16.3": { + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dependencies": [ + "encodeurl", + "escape-html", + "parseurl", + "send" + ] + }, + "setprototypeof@1.2.0": { + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel-list@1.0.0": { + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": [ + "es-errors", + "object-inspect" + ] + }, + "side-channel-map@1.0.1": { + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": [ + "call-bound", + "es-errors", + "get-intrinsic", + "object-inspect" + ] + }, + "side-channel-weakmap@1.0.2": { + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": [ + "call-bound", + "es-errors", + "get-intrinsic", + "object-inspect", + "side-channel-map" + ] + }, + "side-channel@1.1.0": { + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": [ + "es-errors", + "object-inspect", + "side-channel-list", + "side-channel-map", + "side-channel-weakmap" + ] + }, + "simple-git@3.30.0": { + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "dependencies": [ + "@kwsites/file-exists", + "@kwsites/promise-deferred", + "debug@4.4.3" + ] + }, + "source-map@0.7.6": { + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" + }, + "statuses@2.0.2": { + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" + }, + "string-width@4.2.3": { + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": [ + "emoji-regex@8.0.0", + "is-fullwidth-code-point", + "strip-ansi@6.0.1" + ] + }, + "string-width@7.2.0": { + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dependencies": [ + "emoji-regex@10.6.0", + "get-east-asian-width", + "strip-ansi@7.1.2" + ] + }, + "strip-ansi@6.0.1": { + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": [ + "ansi-regex@5.0.1" + ] + }, + "strip-ansi@7.1.2": { + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": [ + "ansi-regex@6.2.2" + ] + }, + "supports-color@7.2.0": { + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": [ + "has-flag" + ] + }, + "termi-link@1.1.0": { + "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==" + }, + "toidentifier@1.0.1": { + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "type-fest@4.41.0": { + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==" + }, + "type-is@1.6.18": { + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": [ + "media-typer", + "mime-types" + ] + }, + "unpipe@1.0.0": { + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge@1.0.1": { + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid@9.0.1": { + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "bin": true + }, + "vary@1.1.2": { + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "widest-line@5.0.0": { + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "dependencies": [ + "string-width@7.2.0" + ] + }, + "wrap-ansi@9.0.2": { + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dependencies": [ + "ansi-styles@6.2.3", + "string-width@7.2.0", + "strip-ansi@7.1.2" + ] + }, + "zod-to-json-schema@3.25.1_zod@4.3.5": { + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "dependencies": [ + "zod" + ] + }, + "zod@4.3.5": { + "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==" + } + }, + "workspace": { + "dependencies": [ + "jsr:@braintrust/smoke-test-shared@*", + "jsr:@std/assert@^1.0.14", + "npm:braintrust@^2.0.2" + ], + "links": { + "jsr:@braintrust/smoke-test-shared": {}, + "npm:@braintrust/smoke-test-shared@1.0.0": {}, + "npm:braintrust-sdk-js@0.0.1": {}, + "npm:braintrust@2.0.2": { + "dependencies": [ + "npm:@ai-sdk/provider@^1.1.3", + "npm:@next/env@^14.2.3", + "npm:@types/nunjucks@^3.2.6", + "npm:@vercel/functions@^1.0.2", + "npm:argparse@^2.0.1", + "npm:boxen@^8.0.1", + "npm:chalk@^4.1.2", + "npm:cli-progress@^3.12.0", + "npm:cli-table3@~0.6.5", + "npm:cors@^2.8.5", + "npm:dotenv@^16.4.5", + "npm:esbuild@0.27", + "npm:eventsource-parser@^1.1.2", + "npm:express@^4.21.2", + "npm:graceful-fs@^4.2.11", + "npm:http-errors@2", + "npm:minimatch@^9.0.3", + "npm:mustache@^4.2.0", + "npm:nunjucks@^3.2.4", + "npm:pluralize@8", + "npm:simple-git@^3.21.0", + "npm:source-map@~0.7.4", + "npm:termi-link@^1.0.1", + "npm:uuid@^9.0.1", + "npm:zod-to-json-schema@^3.25.0" + ], + "peerDependencies": [ + "npm:zod@^3.25.34 || 4" + ] + } + } + } +} diff --git a/js/smoke/scenarios/deno-node/mise.toml b/js/smoke/scenarios/deno-node/mise.toml new file mode 100644 index 000000000..dd563ce6f --- /dev/null +++ b/js/smoke/scenarios/deno-node/mise.toml @@ -0,0 +1,3 @@ +[tools] +deno = "latest" +pnpm = "10.26.2" diff --git a/js/smoke/tests/deno/node/shared_suite_test.ts b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts similarity index 52% rename from js/smoke/tests/deno/node/shared_suite_test.ts rename to js/smoke/scenarios/deno-node/tests/shared-suite.test.ts index d6bece4a4..93bb10da9 100644 --- a/js/smoke/tests/deno/node/shared_suite_test.ts +++ b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts @@ -4,7 +4,7 @@ * This test demonstrates using the shared test package across different runtimes */ -import { assertEquals } from "jsr:@std/assert@^1.0.14"; +import { assertEquals } from "@std/assert"; import { setupTestEnvironment, cleanupTestEnvironment, @@ -12,8 +12,11 @@ import { runEvalSmokeTest, runImportVerificationTests, runPromptTemplatingTests, + displayTestResults, + hasFailures, + getFailureCount, type TestResult, -} from "../../../shared/dist/index.mjs"; +} from "@braintrust/smoke-test-shared"; import * as braintrust from "braintrust"; /** @@ -32,22 +35,13 @@ export async function runSharedTestSuites() { }); try { - // Run import verification tests first (forces bundler to process all exports) + // Run tests const importResults = await runImportVerificationTests(braintrust); - - // Run functional tests - const functionalResults = await runBasicLoggingTests(adapters); - - // Run eval smoke test + const functionalResults = await runBasicLoggingTests(adapters, braintrust); const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests( - { - Prompt: braintrust.Prompt, - }, - adapters.environment, - ); + const promptTemplatingResults = await runPromptTemplatingTests({ + Prompt: braintrust.Prompt, + }); // Combine results const results = [ @@ -57,30 +51,15 @@ export async function runSharedTestSuites() { ...promptTemplatingResults, ]; - // Verify all tests passed - const failures = results.filter((r) => !r.success); - - if (failures.length > 0) { - console.error("Test failures:"); - for (const failure of failures) { - console.error(` ❌ ${failure.testName}: ${failure.error?.message}`); - } - throw new Error(`${failures.length} test(s) failed`); - } + // Display results + displayTestResults({ + scenarioName: "Deno Node Test Results", + results, + }); - // Log results by category - console.log("✅ All shared test suites passed:"); - console.log("\nImport Verification:"); - for (const result of importResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - console.log("\nFunctional Tests:"); - for (const result of functionalResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - console.log("\nPrompt Templating Tests:"); - for (const result of promptTemplatingResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); + // Check for failures + if (hasFailures(results)) { + throw new Error(`${getFailureCount(results)} test(s) failed`); } return results; @@ -95,11 +74,8 @@ Deno.test("Run shared test suites", async () => { // Assert all tests passed assertEquals( - results.filter((r) => !r.success).length, + results.filter((r) => r.status === "fail").length, 0, "All tests should pass", ); - - // Log test count for visibility - console.log(`\n✅ All ${results.length} tests passed`); }); diff --git a/js/smoke/scenarios/jest-node/.gitignore b/js/smoke/scenarios/jest-node/.gitignore new file mode 100644 index 000000000..995fc30ad --- /dev/null +++ b/js/smoke/scenarios/jest-node/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +dist/ +.DS_Store +*.log +coverage/ +package-lock.json diff --git a/js/smoke/scenarios/jest-node/Makefile b/js/smoke/scenarios/jest-node/Makefile new file mode 100644 index 000000000..22f859f8c --- /dev/null +++ b/js/smoke/scenarios/jest-node/Makefile @@ -0,0 +1,39 @@ +.PHONY: setup test + +# ============================================================================= +# Setup +# ============================================================================= + +setup: + @echo "==> Setting up jest-node scenario" + mise install + + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + + npm install --no-package-lock + +# ============================================================================= +# Test +# ============================================================================= + +test: setup + @echo "==> Running jest-node tests" + npx jest diff --git a/js/smoke/scenarios/jest-node/README.md b/js/smoke/scenarios/jest-node/README.md new file mode 100644 index 000000000..4cf00567d --- /dev/null +++ b/js/smoke/scenarios/jest-node/README.md @@ -0,0 +1,13 @@ +# Jest Node.js Smoke Test + +Tests Braintrust SDK in a Jest environment with Node.js runtime. + +## Design Decisions + +**Tarball installation:** Uses well-known tarball path (`braintrust-latest.tgz`) to avoid package.json changes on version bumps. + +**CommonJS mode:** Jest works best with CommonJS, so `type: "commonjs"` is used. + +**Shared test suites:** Leverages `../../shared` for consistent test coverage across all scenarios. + +**Test structure:** Both legacy simple span tests and modern shared suite tests are included to verify Jest compatibility. diff --git a/js/smoke/scenarios/jest-node/mise.toml b/js/smoke/scenarios/jest-node/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/jest-node/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/jest-node/package.json b/js/smoke/scenarios/jest-node/package.json new file mode 100644 index 000000000..580b9d38e --- /dev/null +++ b/js/smoke/scenarios/jest-node/package.json @@ -0,0 +1,15 @@ +{ + "name": "smoke-jest-node", + "private": true, + "type": "commonjs", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^3.25.76" + }, + "devDependencies": { + "@types/node": "^20", + "jest": "^29.7.0", + "tsx": "^4.19.2", + "typescript": "^5" + } +} diff --git a/js/smoke/scenarios/jest-node/tests/basic-span.test.js b/js/smoke/scenarios/jest-node/tests/basic-span.test.js new file mode 100644 index 000000000..7d806e105 --- /dev/null +++ b/js/smoke/scenarios/jest-node/tests/basic-span.test.js @@ -0,0 +1,117 @@ +const { + initLogger, + JSONAttachment, + _exportsForTestingOnly, +} = require("braintrust"); + +const { displayTestResults } = require("../../../shared/dist/index.js"); + +test("basic span logging works in Jest", async () => { + const results = []; + + _exportsForTestingOnly.setInitialTestState(); + await _exportsForTestingOnly.simulateLoginForTests(); + + const backgroundLogger = _exportsForTestingOnly.useTestBackgroundLogger(); + + const logger = initLogger({ + projectName: "jest-smoke-test", + projectId: "jest-smoke-test", + }); + + const testData = { + foo: "bar", + nested: { + array: [1, 2, 3], + bool: true, + }, + }; + + // Test 1: Logger has startSpan function + try { + expect(typeof logger.startSpan).toBe("function"); + results.push({ + status: "pass", + name: "Logger has startSpan function", + }); + } catch (error) { + results.push({ + status: "fail", + name: "Logger has startSpan function", + error: { message: error.message, stack: error.stack }, + }); + } + + // Test 2: Direct logging with JSONAttachment + try { + logger.log({ + input: { + type: "chat_completion", + transcript: new JSONAttachment(testData, { + filename: "conversation_transcript.json", + pretty: true, + }), + }, + }); + expect(testData.nested.array).toEqual([1, 2, 3]); + results.push({ + status: "pass", + name: "Direct logging with JSONAttachment", + }); + } catch (error) { + results.push({ + status: "fail", + name: "Direct logging with JSONAttachment", + error: { message: error.message, stack: error.stack }, + }); + } + + // Test 3: Span logging and capture + try { + const span = logger.startSpan({ name: "test-span" }); + span.log({ + input: "What is the capital of France?", + output: "Paris", + expected: "Paris", + metadata: { transport: "smoke-test" }, + }); + span.end(); + + await logger.flush(); + + const spans = await backgroundLogger.drain(); + + if (spans.length === 0) { + throw new Error("No spans were captured by the background logger"); + } + + const spanEvent = spans.slice(-1)[0]; + + expect(spanEvent.input).toEqual("What is the capital of France?"); + expect(spanEvent.output).toEqual("Paris"); + expect(spanEvent.expected).toEqual("Paris"); + + results.push({ + status: "pass", + name: "Span logging and capture", + }); + } catch (error) { + results.push({ + status: "fail", + name: "Span logging and capture", + error: { message: error.message, stack: error.stack }, + }); + } + + await _exportsForTestingOnly.clearTestBackgroundLogger(); + await _exportsForTestingOnly.simulateLogoutForTests(); + + displayTestResults({ + scenarioName: "Jest Basic Span Test Results", + results, + }); + + // Fail the Jest test if any results failed + const failures = results.filter((r) => r.status === "fail"); + expect(failures).toHaveLength(0); +}); diff --git a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js new file mode 100644 index 000000000..240e2a8af --- /dev/null +++ b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js @@ -0,0 +1,60 @@ +const { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runImportVerificationTests, + runPromptTemplatingTests, + displayTestResults, + hasFailures, + getFailureCount, +} = require("../../../shared/dist/index.js"); + +const braintrust = require("braintrust"); +const { initLogger, _exportsForTestingOnly } = braintrust; + +async function runSharedTestSuites() { + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: true, + canUseCLI: true, + environment: "jest", + }); + + try { + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters); + const promptTemplatingResults = await runPromptTemplatingTests({ + Prompt: braintrust.Prompt, + }); + + const results = [ + ...importResults, + ...functionalResults, + ...promptTemplatingResults, + ]; + + return { + all: results, + import: importResults, + functional: functionalResults, + templating: promptTemplatingResults, + }; + } finally { + await cleanupTestEnvironment(adapters); + } +} + +test("shared test suites pass in Jest", async () => { + const { all: results } = await runSharedTestSuites(); + + // Display results + displayTestResults({ + scenarioName: "Jest Node Test Results", + results, + }); + + // Check for failures + const failures = results.filter((r) => r.status === "fail"); + expect(failures).toHaveLength(0); +}); diff --git a/js/smoke/scenarios/jest-node/tsconfig.json b/js/smoke/scenarios/jest-node/tsconfig.json new file mode 100644 index 000000000..2cbbbdaf5 --- /dev/null +++ b/js/smoke/scenarios/jest-node/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true + }, + "include": ["tests/**/*", "src/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/scenarios/nextjs-instrumentation/.gitignore b/js/smoke/scenarios/nextjs-instrumentation/.gitignore new file mode 100644 index 000000000..611cdd9e5 --- /dev/null +++ b/js/smoke/scenarios/nextjs-instrumentation/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +.next/ +*.log +.env.local +package-lock.json diff --git a/js/smoke/scenarios/nextjs-instrumentation/Makefile b/js/smoke/scenarios/nextjs-instrumentation/Makefile new file mode 100644 index 000000000..0d379121f --- /dev/null +++ b/js/smoke/scenarios/nextjs-instrumentation/Makefile @@ -0,0 +1,48 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up nextjs-instrumentation scenario" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + + @# Check if BRAINTRUST_OTEL_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_OTEL_TAR)" ]; then \ + echo "==> Using BRAINTRUST_OTEL_TAR: $(BRAINTRUST_OTEL_TAR)"; \ + else \ + echo "==> Building @braintrust/otel package"; \ + cd ../../../../integrations/otel-js && pnpm exec turbo build --filter=@braintrust/otel && pnpm pack --pack-destination ../../js/artifacts; \ + \ + for f in ../../js/artifacts/braintrust-otel-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ + cp "$$f" ../../js/artifacts/braintrust-otel-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running Next.js build test (webpack bundling)" + npx next build + @echo "==> Running Next.js runtime tests (Edge + Node.js)" + node tests/api-routes.test.mjs diff --git a/js/smoke/scenarios/nextjs-instrumentation/README.md b/js/smoke/scenarios/nextjs-instrumentation/README.md new file mode 100644 index 000000000..05502add6 --- /dev/null +++ b/js/smoke/scenarios/nextjs-instrumentation/README.md @@ -0,0 +1,40 @@ +# Next.js Instrumentation Scenario + +Tests Braintrust SDK integration in Next.js with multiple runtimes. + +## Design Decisions + +### Tarball Installation + +Uses `file:` dependencies pointing to pre-built tarballs: + +- `"braintrust": "file:../../../artifacts/braintrust-latest.tgz"` +- `"@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz"` +- More realistic test of how Next.js bundles published packages +- Catches webpack bundling issues that local linking might miss + +### Build + Runtime Testing + +Tests at two stages: + +1. **Build-time** (`npx next build`) - Catches static issues (imports, exports, bundling) +2. **Runtime** (dev server + HTTP requests) - Catches execution issues in both runtimes + +Both needed because Next.js can build successfully but fail at runtime, or vice versa. + +### Multiple Runtime Testing + +Tests both Next.js runtimes in separate API routes: + +- **Edge Runtime** (`/api/smoke-test/edge`) - V8 isolates, no Node.js APIs (like Cloudflare Workers) +- **Node.js Runtime** (`/api/smoke-test/node`) - Full Node.js environment + +Different runtimes have different capabilities - Edge can't use nunjucks, filesystem, etc. + +### Shared Package Import + +Uses long relative path to shared package: + +- `from "../../../../../../../shared/dist/index.mjs"` +- Next.js webpack handles this correctly despite the deep nesting +- Alternative would be adding shared to dependencies, but relative import is simpler diff --git a/js/smoke/scenarios/nextjs-instrumentation/mise.toml b/js/smoke/scenarios/nextjs-instrumentation/mise.toml new file mode 100644 index 000000000..3fd2123a0 --- /dev/null +++ b/js/smoke/scenarios/nextjs-instrumentation/mise.toml @@ -0,0 +1,6 @@ +[tools] +node = "22" +pnpm = "10.26.2" + +[env] +_.file = ".env.local" diff --git a/js/smoke/scenarios/nextjs-instrumentation/next-env.d.ts b/js/smoke/scenarios/nextjs-instrumentation/next-env.d.ts new file mode 100644 index 000000000..40c3d6809 --- /dev/null +++ b/js/smoke/scenarios/nextjs-instrumentation/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/js/smoke/tests/nextjs-instrumentation/next.config.mjs b/js/smoke/scenarios/nextjs-instrumentation/next.config.mjs similarity index 100% rename from js/smoke/tests/nextjs-instrumentation/next.config.mjs rename to js/smoke/scenarios/nextjs-instrumentation/next.config.mjs diff --git a/js/smoke/tests/nextjs-instrumentation/package.json b/js/smoke/scenarios/nextjs-instrumentation/package.json similarity index 55% rename from js/smoke/tests/nextjs-instrumentation/package.json rename to js/smoke/scenarios/nextjs-instrumentation/package.json index 18761e503..e8faeef10 100644 --- a/js/smoke/tests/nextjs-instrumentation/package.json +++ b/js/smoke/scenarios/nextjs-instrumentation/package.json @@ -1,21 +1,14 @@ { - "name": "braintrust-nextjs-instrumentation-test", + "name": "smoke-nextjs-instrumentation", "version": "1.0.0", "description": "Smoke test for Braintrust + @braintrust/otel in Next.js instrumentation", "private": true, "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "test": "npm run test:build && npm run test:shared", - "test:build": "next build", - "test:shared": "node test-api-routes.mjs", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "enable-esm": "npx tsx ../../enable-esm.ts", - "install-build": "npm install --legacy-peer-deps && npx tsx ../../install-build.ts ../../../artifacts braintrust && npx tsx ../../install-build.ts ../../../artifacts otel" + "dev": "next dev" }, "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz", "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.200.0", "@opentelemetry/core": "^2.0.0", @@ -26,8 +19,6 @@ "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@vercel/otel": "^2.1.0", - "@braintrust/otel": "latest", - "braintrust": "latest", "next": "14.2.34", "react": "^18", "react-dom": "^18", diff --git a/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts similarity index 73% rename from js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts rename to js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts index ecf6b74f1..30f2fbfef 100644 --- a/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/edge/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts @@ -10,8 +10,9 @@ import { runBasicLoggingTests, runEvalSmokeTest, runImportVerificationTests, - runPromptTemplatingTests, -} from "../../../../../../shared/dist/index.mjs"; + testMustacheTemplate, + testNunjucksTemplate, +} from "../../../../../../../shared"; import * as braintrust from "braintrust"; const { initLogger, _exportsForTestingOnly } = braintrust; @@ -27,6 +28,12 @@ interface TestResponse { passedTests?: number; failedTests?: number; timestamp: string; + results?: Array<{ + name: string; + status: "pass" | "fail" | "xfail"; + error?: { message: string }; + message?: string; + }>; failures?: Array<{ testName: string; error?: string; @@ -54,29 +61,46 @@ export async function GET(): Promise> { const importResults = await runImportVerificationTests(braintrust); // Run functional tests - const functionalResults = await runBasicLoggingTests(adapters); + const functionalResults = await runBasicLoggingTests( + adapters, + braintrust, + ); // Run eval smoke test const evalResult = await runEvalSmokeTest(adapters, braintrust); // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests( - { - Prompt: braintrust.Prompt, - }, - adapters.environment, - ); + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ? { + ...nunjucksResult, + status: "pass" as const, + message: + "Expected failure: Nunjucks not supported in Edge Runtime", + } + : nunjucksResult; // Combine results const results = [ ...importResults, ...functionalResults, evalResult, - ...promptTemplatingResults, + mustacheResult, + nunjucksResultHandled, ]; // Check for failures - const failures = results.filter((r) => !r.success); + const failures = results.filter((r) => r.status === "fail"); if (failures.length > 0) { const response: TestResponse = { @@ -87,8 +111,9 @@ export async function GET(): Promise> { passedTests: results.length - failures.length, failedTests: failures.length, timestamp, + results, failures: failures.map((f) => ({ - testName: f.testName, + testName: f.name, error: f.error?.message || "Unknown error", })), }; @@ -105,6 +130,7 @@ export async function GET(): Promise> { passedTests: results.length, failedTests: 0, timestamp, + results, }; return NextResponse.json(response, { status: 200 }); diff --git a/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/node/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts similarity index 87% rename from js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/node/route.ts rename to js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts index 20b7cd17e..154964bac 100644 --- a/js/smoke/tests/nextjs-instrumentation/app/api/smoke-test/node/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts @@ -11,7 +11,7 @@ import { runEvalSmokeTest, runImportVerificationTests, runPromptTemplatingTests, -} from "../../../../../../shared/dist/index.mjs"; +} from "../../../../../../../shared"; import * as braintrust from "braintrust"; const { initLogger, _exportsForTestingOnly } = braintrust; @@ -27,6 +27,12 @@ interface TestResponse { passedTests?: number; failedTests?: number; timestamp: string; + results?: Array<{ + name: string; + status: "pass" | "fail" | "xfail"; + error?: { message: string }; + message?: string; + }>; failures?: Array<{ testName: string; error?: string; @@ -54,18 +60,18 @@ export async function GET(): Promise> { const importResults = await runImportVerificationTests(braintrust); // Run functional tests - const functionalResults = await runBasicLoggingTests(adapters); + const functionalResults = await runBasicLoggingTests( + adapters, + braintrust, + ); // Run eval smoke test const evalResult = await runEvalSmokeTest(adapters, braintrust); // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests( - { - Prompt: braintrust.Prompt, - }, - adapters.environment, - ); + const promptTemplatingResults = await runPromptTemplatingTests({ + Prompt: braintrust.Prompt, + }); // Combine results const results = [ @@ -76,7 +82,7 @@ export async function GET(): Promise> { ]; // Check for failures - const failures = results.filter((r) => !r.success); + const failures = results.filter((r) => r.status === "fail"); if (failures.length > 0) { const response: TestResponse = { @@ -87,8 +93,9 @@ export async function GET(): Promise> { passedTests: results.length - failures.length, failedTests: failures.length, timestamp, + results, failures: failures.map((f) => ({ - testName: f.testName, + testName: f.name, error: f.error?.message || "Unknown error", })), }; @@ -105,6 +112,7 @@ export async function GET(): Promise> { passedTests: results.length, failedTests: 0, timestamp, + results, }; return NextResponse.json(response, { status: 200 }); diff --git a/js/smoke/tests/nextjs-instrumentation/app/layout.tsx b/js/smoke/scenarios/nextjs-instrumentation/src/app/layout.tsx similarity index 100% rename from js/smoke/tests/nextjs-instrumentation/app/layout.tsx rename to js/smoke/scenarios/nextjs-instrumentation/src/app/layout.tsx diff --git a/js/smoke/tests/nextjs-instrumentation/app/page.tsx b/js/smoke/scenarios/nextjs-instrumentation/src/app/page.tsx similarity index 100% rename from js/smoke/tests/nextjs-instrumentation/app/page.tsx rename to js/smoke/scenarios/nextjs-instrumentation/src/app/page.tsx diff --git a/js/smoke/tests/nextjs-instrumentation/instrumentation.ts b/js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts similarity index 98% rename from js/smoke/tests/nextjs-instrumentation/instrumentation.ts rename to js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts index aeaa814da..5c7e8595d 100644 --- a/js/smoke/tests/nextjs-instrumentation/instrumentation.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts @@ -20,7 +20,7 @@ import { setupTestEnvironment, runBasicLoggingTests, runImportVerificationTests, -} from "../../shared/dist/index.mjs"; +} from "../../../shared"; export async function register() { // Log that imports succeeded (build-time verification passed) diff --git a/js/smoke/tests/nextjs-instrumentation/test-api-routes.mjs b/js/smoke/scenarios/nextjs-instrumentation/tests/api-routes.test.mjs similarity index 57% rename from js/smoke/tests/nextjs-instrumentation/test-api-routes.mjs rename to js/smoke/scenarios/nextjs-instrumentation/tests/api-routes.test.mjs index 3733f6021..e2f7ad84d 100644 --- a/js/smoke/tests/nextjs-instrumentation/test-api-routes.mjs +++ b/js/smoke/scenarios/nextjs-instrumentation/tests/api-routes.test.mjs @@ -6,6 +6,7 @@ import { spawn } from "child_process"; import { setTimeout as sleep } from "timers/promises"; +import { displayTestResults } from "../../../shared/dist/index.mjs"; const PORT = 5555; const BASE_URL = `http://localhost:${PORT}`; @@ -20,8 +21,6 @@ let devServer = null; * Start the Next.js dev server */ function startDevServer() { - console.log(`Starting Next.js dev server on port ${PORT}...\n`); - devServer = spawn("npm", ["run", "dev"], { stdio: ["ignore", "pipe", "pipe"], shell: true, @@ -29,11 +28,7 @@ function startDevServer() { }); devServer.stdout.on("data", (data) => { - const output = data.toString(); - process.stdout.write(output); - if (output.includes("Ready") || output.includes("started server")) { - console.log("✓ Dev server ready\n"); - } + process.stdout.write(data.toString()); }); devServer.stderr.on("data", (data) => { @@ -53,25 +48,19 @@ function startDevServer() { async function waitForServer(maxTime = MAX_STARTUP_TIME) { const startTime = Date.now(); - console.log("Waiting for server to be ready..."); - while (Date.now() - startTime < maxTime) { try { const response = await fetch(`${BASE_URL}/`, { method: "HEAD" }); if (response.ok || response.status === 404) { - console.log("✓ Server is responding\n"); await sleep(2000); // Buffer time return true; } } catch (error) { // Server not ready yet } - await sleep(POLL_INTERVAL); - process.stdout.write("."); } - console.error("\n✗ Server failed to start within timeout\n"); return false; } @@ -79,30 +68,15 @@ async function waitForServer(maxTime = MAX_STARTUP_TIME) { * Test an API endpoint */ async function testEndpoint(url, name) { - console.log(`Testing ${name}...`); - console.log(` URL: ${url}`); - try { const response = await fetch(url); const result = await response.json(); - console.log(` Status: ${response.status}`); - console.log(` Runtime: ${result.runtime}`); - console.log(` Message: ${result.message}`); - - if (result.totalTests !== undefined) { - console.log(` Tests: ${result.passedTests}/${result.totalTests} passed`); - } - - if (result.failures && result.failures.length > 0) { - console.log(` Failures:`); - for (const failure of result.failures) { - console.log(` - ${failure.testName}: ${failure.error}`); - } - } - - console.log(` Result: ${result.success ? "✅ PASS" : "❌ FAIL"}`); - console.log(); + // Display results using standardized format + displayTestResults({ + scenarioName: `${name} Test Results`, + results: result.results, + }); return { success: result.success, @@ -110,10 +84,7 @@ async function testEndpoint(url, name) { result, }; } catch (error) { - console.error(` Error: ${error.message}`); - console.log(` Result: ❌ FAIL`); - console.log(); - + console.error(`Error testing ${name}:`, error.message); return { success: false, status: null, @@ -127,9 +98,7 @@ async function testEndpoint(url, name) { */ function cleanup(exitCode = 0) { if (devServer) { - console.log("\nStopping dev server..."); devServer.kill("SIGTERM"); - setTimeout(() => { if (devServer && !devServer.killed) { devServer.kill("SIGKILL"); @@ -146,10 +115,6 @@ function cleanup(exitCode = 0) { * Main execution */ async function main() { - console.log("Next.js API Routes Test"); - console.log("=".repeat(60)); - console.log(); - // Handle cleanup on exit process.on("SIGINT", () => cleanup(1)); process.on("SIGTERM", () => cleanup(1)); @@ -161,48 +126,22 @@ async function main() { // Wait for server to be ready const serverReady = await waitForServer(); if (!serverReady) { - console.error("✗ Server startup failed\n"); + console.error("Server startup failed"); cleanup(1); return; } - console.log("=".repeat(60)); - console.log("Running Tests"); - console.log("=".repeat(60)); - console.log(); - // Test Edge Runtime const edgeResult = await testEndpoint(EDGE_URL, "Edge Runtime"); // Test Node.js Runtime const nodeResult = await testEndpoint(NODE_URL, "Node.js Runtime"); - // Summary - console.log("=".repeat(60)); - console.log("Summary"); - console.log("=".repeat(60)); - console.log(); - + // Exit based on results const allPassed = edgeResult.success && nodeResult.success; - - console.log( - `Edge Runtime: ${edgeResult.success ? "✅ PASS" : "❌ FAIL"}`, - ); - console.log( - `Node.js Runtime: ${nodeResult.success ? "✅ PASS" : "❌ FAIL"}`, - ); - console.log(); - - if (allPassed) { - console.log("✅ All tests passed!"); - cleanup(0); - } else { - console.log("❌ Some tests failed"); - cleanup(1); - } + cleanup(allPassed ? 0 : 1); } catch (error) { - console.error("\n❌ Unexpected error:"); - console.error(error); + console.error("Unexpected error:", error); cleanup(1); } } diff --git a/js/smoke/tests/nextjs-instrumentation/tsconfig.json b/js/smoke/scenarios/nextjs-instrumentation/tsconfig.json similarity index 100% rename from js/smoke/tests/nextjs-instrumentation/tsconfig.json rename to js/smoke/scenarios/nextjs-instrumentation/tsconfig.json diff --git a/js/smoke/scenarios/otel-v1/.gitignore b/js/smoke/scenarios/otel-v1/.gitignore new file mode 100644 index 000000000..cf4ae50aa --- /dev/null +++ b/js/smoke/scenarios/otel-v1/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +*.log +.env.local +package-lock.json diff --git a/js/smoke/scenarios/otel-v1/Makefile b/js/smoke/scenarios/otel-v1/Makefile new file mode 100644 index 000000000..0b72d0207 --- /dev/null +++ b/js/smoke/scenarios/otel-v1/Makefile @@ -0,0 +1,60 @@ +.PHONY: setup test + +# ============================================================================= +# Setup +# ============================================================================= + +setup: + @echo "==> Setting up otel-v1 scenario" + mise install + + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + + @# Check if BRAINTRUST_OTEL_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_OTEL_TAR)" ]; then \ + echo "==> Using BRAINTRUST_OTEL_TAR: $(BRAINTRUST_OTEL_TAR)"; \ + else \ + echo "==> Building @braintrust/otel package"; \ + cd ../../../../integrations/otel-js && pnpm exec turbo build --filter=@braintrust/otel && pnpm pack --pack-destination ../../js/artifacts; \ + \ + for f in ../../js/artifacts/braintrust-otel-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ + cp "$$f" ../../js/artifacts/braintrust-otel-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + npm install --no-package-lock + +# ============================================================================= +# Test +# ============================================================================= + +test: setup + @echo "==> Running otel-v1 tests" + @FAILED=0; \ + npx tsx tests/basic.test.ts || FAILED=1; \ + npx tsx tests/filtering.test.ts || FAILED=1; \ + npx tsx tests/shared-suite.test.ts || FAILED=1; \ + exit $$FAILED diff --git a/js/smoke/scenarios/otel-v1/README.md b/js/smoke/scenarios/otel-v1/README.md new file mode 100644 index 000000000..a2112c268 --- /dev/null +++ b/js/smoke/scenarios/otel-v1/README.md @@ -0,0 +1,32 @@ +# OTEL v1 Scenario + +Tests OpenTelemetry v1 integration with Braintrust SDK. + +## Design Decisions + +### Tarball Installation + +Uses `file:` dependencies pointing to pre-built tarballs instead of workspace linking: + +- `"braintrust": "file:../../../artifacts/braintrust-latest.tgz"` +- `"@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz"` +- Makefile builds both packages and creates tarballs in `artifacts/` directory +- More realistic test of published package structure + +### Multiple Package Build + +Requires building two separate packages: + +1. Main SDK: `cd ../../.. && pnpm build && npm pack` +2. OTEL integration: `cd ../../../../integrations/otel-js && pnpm build && pnpm pack` + +- Both tarballs copied to `artifacts/` with stable names (`-latest.tgz`) +- Ensures we test the OTEL integration package, not just the main SDK + +### Test Helper Pattern + +Uses shared mock OTLP collector (`src/test-helpers.ts`) across all tests: + +- Eliminates duplication while keeping tests realistic +- Real HTTP server captures OTLP exports for assertions +- No test frameworks - just Node.js built-ins (http, assert) diff --git a/js/smoke/scenarios/otel-v1/mise.toml b/js/smoke/scenarios/otel-v1/mise.toml new file mode 100644 index 000000000..3fd2123a0 --- /dev/null +++ b/js/smoke/scenarios/otel-v1/mise.toml @@ -0,0 +1,6 @@ +[tools] +node = "22" +pnpm = "10.26.2" + +[env] +_.file = ".env.local" diff --git a/js/smoke/scenarios/otel-v1/package.json b/js/smoke/scenarios/otel-v1/package.json new file mode 100644 index 000000000..335a0b33b --- /dev/null +++ b/js/smoke/scenarios/otel-v1/package.json @@ -0,0 +1,20 @@ +{ + "name": "smoke-otel-v1", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^1.9.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.53.0", + "@opentelemetry/sdk-node": "^0.53.0", + "@opentelemetry/sdk-trace-base": "^1.9.0", + "zod": "^3.25.76" + }, + "devDependencies": { + "@types/node": "^20.10.5", + "tsx": "^4.19.2", + "typescript": "^5.4.4" + } +} diff --git a/js/smoke/scenarios/otel-v1/src/test-helpers.ts b/js/smoke/scenarios/otel-v1/src/test-helpers.ts new file mode 100644 index 000000000..4f6e6e09b --- /dev/null +++ b/js/smoke/scenarios/otel-v1/src/test-helpers.ts @@ -0,0 +1,53 @@ +import { createServer } from "node:http"; +import type { AddressInfo } from "node:net"; + +export interface MockOtlpCollector { + url: string; + payloads: unknown[]; + cleanup: () => Promise; +} + +/** + * Sets up a mock OTLP collector HTTP server that captures trace payloads. + * Returns the server URL, captured payloads array, and cleanup function. + */ +export async function setupMockOtlpCollector(): Promise { + const payloads: unknown[] = []; + + const server = createServer((req, res) => { + if (req.method === "POST" && req.url === "/otel/v1/traces") { + const chunks: Buffer[] = []; + req.on("data", (chunk) => chunks.push(chunk)); + req.on("end", () => { + try { + const body = Buffer.concat(chunks).toString(); + if (body.length > 0) { + payloads.push(JSON.parse(body)); + } + } catch (error) { + res.writeHead(500).end(); + throw error; + } + res.writeHead(200).end(); + }); + return; + } + res.writeHead(404).end(); + }); + + const url = await new Promise((resolve) => { + server.listen(0, "127.0.0.1", () => { + const addressInfo = server.address() as AddressInfo; + resolve(`http://127.0.0.1:${addressInfo.port}/`); + }); + }); + + return { + url, + payloads, + cleanup: () => + new Promise((resolve, reject) => { + server.close((err) => (err ? reject(err) : resolve())); + }), + }; +} diff --git a/js/smoke/scenarios/otel-v1/tests/basic.test.ts b/js/smoke/scenarios/otel-v1/tests/basic.test.ts new file mode 100644 index 000000000..2031df34d --- /dev/null +++ b/js/smoke/scenarios/otel-v1/tests/basic.test.ts @@ -0,0 +1,80 @@ +import { setTimeout as delay } from "node:timers/promises"; +import { trace } from "@opentelemetry/api"; +import { NodeSDK } from "@opentelemetry/sdk-node"; +import type { SpanProcessor } from "@opentelemetry/sdk-trace-base"; +import { BraintrustSpanProcessor } from "@braintrust/otel"; +import { setupMockOtlpCollector } from "../src/test-helpers.js"; +import { + displayTestResults, + hasFailures, + type TestResult, +} from "../../../shared/dist/index.mjs"; + +async function main() { + const results: TestResult[] = []; + const collector = await setupMockOtlpCollector(); + + const previousApiUrl = process.env.BRAINTRUST_API_URL; + process.env.BRAINTRUST_API_URL = collector.url; + + try { + // Use real OpenTelemetry SDK with BraintrustSpanProcessor + const sdk = new NodeSDK({ + serviceName: "test-service", + spanProcessor: new BraintrustSpanProcessor() as unknown as SpanProcessor, + }); + + await sdk.start(); + + try { + const tracer = trace.getTracer("test-tracer"); + await tracer.startActiveSpan("test-span", async (span) => { + span.setAttributes({ "test.attr": "value" }); + span.end(); + }); + } finally { + await sdk.shutdown(); + } + + await delay(50); // Let exports flush + + if (collector.payloads.length > 0) { + results.push({ + status: "pass", + name: "Basic OTEL span export", + }); + } else { + results.push({ + status: "fail", + name: "Basic OTEL span export", + error: { message: "No spans exported" }, + }); + } + } catch (error) { + results.push({ + status: "fail", + name: "Basic OTEL span export", + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, + }); + } finally { + process.env.BRAINTRUST_API_URL = previousApiUrl; + await collector.cleanup(); + } + + displayTestResults({ + scenarioName: "OTEL v1 Basic Test Results", + results, + }); + + if (hasFailures(results)) { + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal error:", err); + process.exit(1); +}); diff --git a/js/smoke/scenarios/otel-v1/tests/filtering.test.ts b/js/smoke/scenarios/otel-v1/tests/filtering.test.ts new file mode 100644 index 000000000..3fdfab0a4 --- /dev/null +++ b/js/smoke/scenarios/otel-v1/tests/filtering.test.ts @@ -0,0 +1,144 @@ +import { setTimeout as delay } from "node:timers/promises"; +import { trace } from "@opentelemetry/api"; +import { NodeSDK } from "@opentelemetry/sdk-node"; +import type { SpanProcessor } from "@opentelemetry/sdk-trace-base"; +import { BraintrustSpanProcessor } from "@braintrust/otel"; +import { setupMockOtlpCollector } from "../src/test-helpers.js"; +import { + displayTestResults, + hasFailures, + type TestResult, +} from "../../../shared/dist/index.mjs"; + +type OtelPayload = { + resourceSpans?: Array<{ + scopeSpans?: Array<{ + spans?: Array<{ name?: string }>; + }>; + }>; +}; + +function flattenSpans(payloads: OtelPayload[]) { + return payloads.flatMap( + (p) => + p.resourceSpans?.flatMap( + (rs) => rs.scopeSpans?.flatMap((ss) => ss.spans ?? []) ?? [], + ) ?? [], + ); +} + +async function main() { + const results: TestResult[] = []; + const collector = await setupMockOtlpCollector(); + + const previousApiUrl = process.env.BRAINTRUST_API_URL; + process.env.BRAINTRUST_API_URL = collector.url; + + try { + // Test filterAISpans option + const sdk = new NodeSDK({ + serviceName: "filtering-test", + spanProcessor: new BraintrustSpanProcessor({ + filterAISpans: true, + }) as unknown as SpanProcessor, + }); + + await sdk.start(); + + try { + const tracer = trace.getTracer("test-tracer"); + + await tracer.startActiveSpan("root.span", async (rootSpan) => { + // This AI span should be exported + await tracer.startActiveSpan("ai.span", async (aiSpan) => { + aiSpan.setAttributes({ model: "gpt-4o-mini" }); + aiSpan.end(); + }); + + // This non-AI span should be filtered out + await tracer.startActiveSpan("logging.span", async (logSpan) => { + logSpan.end(); + }); + + rootSpan.end(); + }); + } finally { + await sdk.shutdown(); + } + + await delay(50); + + const exportedSpans = flattenSpans(collector.payloads as OtelPayload[]); + const names = exportedSpans + .map((s) => s.name) + .filter((n): n is string => !!n); + + // Test 1: Root span should be filtered + if (!names.includes("root.span")) { + results.push({ + status: "pass", + name: "Root span filtered correctly", + }); + } else { + results.push({ + status: "fail", + name: "Root span filtered correctly", + error: { message: "Root span should be filtered but was exported" }, + }); + } + + // Test 2: AI span should be exported + if (names.includes("ai.span")) { + results.push({ + status: "pass", + name: "AI span exported correctly", + }); + } else { + results.push({ + status: "fail", + name: "AI span exported correctly", + error: { message: "AI span should be exported but was filtered" }, + }); + } + + // Test 3: Non-AI span should be filtered + if (!names.includes("logging.span")) { + results.push({ + status: "pass", + name: "Non-AI span filtered correctly", + }); + } else { + results.push({ + status: "fail", + name: "Non-AI span filtered correctly", + error: { message: "Logging span should be filtered but was exported" }, + }); + } + } catch (error) { + results.push({ + status: "fail", + name: "AI span filtering test", + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, + }); + } finally { + process.env.BRAINTRUST_API_URL = previousApiUrl; + await collector.cleanup(); + } + + displayTestResults({ + scenarioName: "OTEL v1 Filtering Test Results", + results, + }); + + if (hasFailures(results)) { + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal error:", err); + process.exit(1); +}); diff --git a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts b/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts new file mode 100644 index 000000000..ffe72dc97 --- /dev/null +++ b/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts @@ -0,0 +1,63 @@ +/** + * Runs shared test suites to verify SDK exports and basic functionality + */ + +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runImportVerificationTests, + displayTestResults, + hasFailures, + getFailureCount, +} from "../../../shared/dist/index.js"; + +import { initLogger, _exportsForTestingOnly } from "braintrust"; + +async function runSharedTestSuites() { + // Import Braintrust module for import verification + const braintrust = await import("braintrust"); + + // Setup test environment + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: true, + canUseCLI: true, + environment: "otel-v1", + }); + + try { + // Run tests + const importResults = await runImportVerificationTests(braintrust); + const functionalResults = await runBasicLoggingTests(adapters, braintrust); + + // Combine results + const results = [...importResults, ...functionalResults]; + + // Display results + displayTestResults({ + scenarioName: "OTEL v1 Test Results", + results, + }); + + // Check for failures + if (hasFailures(results)) { + throw new Error(`${getFailureCount(results)} test(s) failed`); + } + + return results; + } finally { + // Clean up test environment + await cleanupTestEnvironment(adapters); + } +} + +runSharedTestSuites() + .then(() => { + process.exit(0); + }) + .catch((error) => { + console.error("\n❌ Test execution failed:", error.message); + process.exit(1); + }); diff --git a/js/smoke/tests/span-jest/tsconfig.json b/js/smoke/scenarios/otel-v1/tsconfig.json similarity index 66% rename from js/smoke/tests/span-jest/tsconfig.json rename to js/smoke/scenarios/otel-v1/tsconfig.json index 5a0373bdc..01117c670 100644 --- a/js/smoke/tests/span-jest/tsconfig.json +++ b/js/smoke/scenarios/otel-v1/tsconfig.json @@ -2,16 +2,16 @@ "compilerOptions": { "target": "ES2022", "module": "ESNext", - "moduleResolution": "Node", + "moduleResolution": "bundler", + "lib": ["ES2022"], "strict": true, "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "isolatedModules": true, - "types": ["node"] + "noEmit": true }, - "include": ["simple_span_example.jest.test.js"], + "include": ["src/**/*", "tests/**/*"], "exclude": ["node_modules"] } diff --git a/js/smoke/scenarios/playwright-browser/.gitignore b/js/smoke/scenarios/playwright-browser/.gitignore new file mode 100644 index 000000000..fd23753a2 --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/.gitignore @@ -0,0 +1,8 @@ +# Playwright test results +test-results/ +playwright-report/ +*.png + +# Build output +dist/ +package-lock.json diff --git a/js/smoke/scenarios/playwright-browser/Makefile b/js/smoke/scenarios/playwright-browser/Makefile new file mode 100644 index 000000000..68f23acac --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/Makefile @@ -0,0 +1,29 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up playwright-browser scenario" + mise install + @# Build shared test package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + npm install --no-package-lock + npx playwright install --with-deps chromium + node esbuild.config.mjs + +test: setup + npx playwright test diff --git a/js/smoke/scenarios/playwright-browser/README.md b/js/smoke/scenarios/playwright-browser/README.md new file mode 100644 index 000000000..d75cf2fbf --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/README.md @@ -0,0 +1,45 @@ +# Playwright Browser Test + +Tests the browser build of the Braintrust SDK in a real browser environment using Playwright. + +## Design Decisions + +### Playwright for Real Browser Testing + +Uses Playwright to execute tests in an actual Chromium browser: + +- Tests run in real browser context (not jsdom or simulated environment) +- Verifies browser-specific builds and browser APIs work correctly +- Uses esbuild to bundle tests for browser execution + +### ESBuild Bundling + +Uses esbuild to bundle test code for the browser: + +- Bundles the SDK and test code into a single browser-compatible file +- Eliminates need for import maps or module resolution in browser +- Target: ES2020, platform: browser + +### Tarball Installation + +Uses well-known tarball path for SDK installation: + +- `braintrust-latest.tgz` ensures package.json never changes +- Build happens before `npm install` to ensure tarball exists + +### Shared Test Suites + +Imports and executes all shared test suites from `@braintrust/smoke-test-shared`: + +- Import verification tests +- Basic logging tests +- Eval smoke tests +- Prompt templating tests + +### Test Communication + +Tests communicate results via `window.__btBrowserSmokeResults`: + +- Browser-side harness collects pass/fail results +- Playwright polls for completion and reads results +- Unhandled errors captured via window event listeners diff --git a/js/smoke/tests/browser/esbuild.config.js b/js/smoke/scenarios/playwright-browser/esbuild.config.mjs similarity index 77% rename from js/smoke/tests/browser/esbuild.config.js rename to js/smoke/scenarios/playwright-browser/esbuild.config.mjs index 05ce77a1a..43d838e5d 100644 --- a/js/smoke/tests/browser/esbuild.config.js +++ b/js/smoke/scenarios/playwright-browser/esbuild.config.mjs @@ -12,12 +12,9 @@ async function build() { target: "es2020", format: "esm", platform: "browser", - // Bundle everything including braintrust and all its dependencies - // This eliminates the need for import maps packages: "bundle", }; - // Build combined browser tests (includes both general tests and eval test) await esbuild.build({ ...baseConfig, entryPoints: [join(__dirname, "src/browser-tests.ts")], diff --git a/js/smoke/scenarios/playwright-browser/mise.toml b/js/smoke/scenarios/playwright-browser/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/playwright-browser/package.json b/js/smoke/scenarios/playwright-browser/package.json new file mode 100644 index 000000000..49818a121 --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/package.json @@ -0,0 +1,18 @@ +{ + "name": "smoke-playwright-browser", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Playwright browser smoke test for Braintrust SDK", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^4.3.5" + }, + "devDependencies": { + "@playwright/test": "^1.51.1", + "@types/node": "^20.10.5", + "esbuild": "^0.27.2", + "http-server": "^14.1.1", + "typescript": "^5.4.4" + } +} diff --git a/js/smoke/tests/browser/pages/browser-tests.html b/js/smoke/scenarios/playwright-browser/pages/browser-tests.html similarity index 100% rename from js/smoke/tests/browser/pages/browser-tests.html rename to js/smoke/scenarios/playwright-browser/pages/browser-tests.html diff --git a/js/smoke/tests/browser/playwright.config.ts b/js/smoke/scenarios/playwright-browser/playwright.config.ts similarity index 83% rename from js/smoke/tests/browser/playwright.config.ts rename to js/smoke/scenarios/playwright-browser/playwright.config.ts index fafd57c6f..7ea6343d5 100644 --- a/js/smoke/tests/browser/playwright.config.ts +++ b/js/smoke/scenarios/playwright-browser/playwright.config.ts @@ -22,9 +22,6 @@ export default defineConfig({ use: { ...devices["Desktop Chrome"] }, }, ], - // Build happens in globalSetup before tests run - globalSetup: "./global-setup.ts", - // Start web server after build (globalSetup runs first) webServer: { command: "npx http-server . -p 3001 -c-1 --cors", port: 3001, diff --git a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts new file mode 100644 index 000000000..33ff32c88 --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts @@ -0,0 +1,165 @@ +import * as braintrust from "braintrust/browser"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + testMustacheTemplate, + testNunjucksTemplate, +} from "../../../shared"; +import { createBrowserHarness, type BrowserSmokeResults } from "./harness"; + +declare global { + interface Window { + __btBrowserSmokeResults?: BrowserSmokeResults; + } +} + +const output = document.getElementById("output"); +if (!output) { + throw new Error("Missing #output element"); +} + +const harness = createBrowserHarness(output); +window.__btBrowserSmokeResults = harness.results; + +const SHARED_SECTION = "shared"; +const EVAL_SECTION = "eval"; +const PROMPT_SECTION = "prompt"; + +async function runAllTestSuites() { + if (!braintrust._exportsForTestingOnly) { + harness.fail( + "runtime", + "preflight", + new Error("_exportsForTestingOnly not available"), + ); + return; + } + + const adapters = await setupTestEnvironment({ + initLogger: braintrust.initLogger, + testingExports: braintrust._exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "browser", + }); + + try { + harness.log("=== Running shared suites ==="); + + const importResults = await runImportVerificationTests(braintrust); + for (const r of importResults) { + if (r.status === "pass") harness.pass(SHARED_SECTION, r.name, r.message); + else + harness.fail( + SHARED_SECTION, + r.name, + r.error || new Error("Test failed"), + r.message, + ); + } + + const loggingResults = await runBasicLoggingTests(adapters, braintrust); + for (const r of loggingResults) { + if (r.status === "pass") harness.pass(SHARED_SECTION, r.name, r.message); + else + harness.fail( + SHARED_SECTION, + r.name, + r.error || new Error("Test failed"), + r.message, + ); + } + + harness.completeSection(SHARED_SECTION); + + harness.log("\n=== Running eval suite ==="); + + const evalResult = await runEvalSmokeTest(adapters, braintrust); + if (evalResult.status === "pass") + harness.pass(EVAL_SECTION, evalResult.name, evalResult.message); + else + harness.fail( + EVAL_SECTION, + evalResult.name, + evalResult.error || new Error("Test failed"), + evalResult.message, + ); + + harness.completeSection(EVAL_SECTION); + + harness.log("\n=== Running prompt templating suite ==="); + + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + if (mustacheResult.status === "pass") + harness.pass(PROMPT_SECTION, mustacheResult.name, mustacheResult.message); + else + harness.fail( + PROMPT_SECTION, + mustacheResult.name, + mustacheResult.error || new Error("Test failed"), + mustacheResult.message, + ); + + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + if ( + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ) { + harness.pass( + PROMPT_SECTION, + nunjucksResult.name, + "Expected failure: Nunjucks not supported in browser build", + ); + } else if (nunjucksResult.status === "pass") { + harness.pass(PROMPT_SECTION, nunjucksResult.name, nunjucksResult.message); + } else { + harness.fail( + PROMPT_SECTION, + nunjucksResult.name, + nunjucksResult.error || new Error("Test failed"), + nunjucksResult.message, + ); + } + + harness.completeSection(PROMPT_SECTION); + } catch (err) { + harness.fail("runtime", "fatal", err); + } finally { + await cleanupTestEnvironment(adapters); + } +} + +async function main() { + const timeoutMs = 55_000; + const timeout = window.setTimeout(() => { + if (!harness.results.completed) { + harness.fail( + "runtime", + "timeout", + new Error("Timed out waiting for browser tests to finish"), + ); + harness.completeAll(); + } + }, timeoutMs); + + try { + await runAllTestSuites(); + } catch (err) { + harness.fail("runtime", "fatal", err); + } finally { + window.clearTimeout(timeout); + harness.log("\n=== All browser suites complete ==="); + harness.completeAll(); + } +} + +void main(); diff --git a/js/smoke/tests/browser/src/harness.ts b/js/smoke/scenarios/playwright-browser/src/harness.ts similarity index 96% rename from js/smoke/tests/browser/src/harness.ts rename to js/smoke/scenarios/playwright-browser/src/harness.ts index ac816bb50..0b9a35b1f 100644 --- a/js/smoke/tests/browser/src/harness.ts +++ b/js/smoke/scenarios/playwright-browser/src/harness.ts @@ -76,7 +76,6 @@ export function createBrowserHarness(outputEl: HTMLElement): BrowserHarness { }; const log = (line: string) => { - // Keep a bounded log buffer for Playwright timeout debugging. results.logs.push(line); if (results.logs.length > 200) results.logs.shift(); console.log(line); @@ -125,7 +124,6 @@ export function createBrowserHarness(outputEl: HTMLElement): BrowserHarness { ); }; - // Capture unhandled runtime errors so Playwright can surface them clearly. window.addEventListener("error", (event) => { const failure = toFailure( "window.error", diff --git a/js/smoke/scenarios/playwright-browser/tests/browser.test.ts b/js/smoke/scenarios/playwright-browser/tests/browser.test.ts new file mode 100644 index 000000000..c8f5cefde --- /dev/null +++ b/js/smoke/scenarios/playwright-browser/tests/browser.test.ts @@ -0,0 +1,181 @@ +import { test, expect } from "@playwright/test"; +import { + displayTestResults, + type TestResult, +} from "../../../shared/dist/index.mjs"; + +test.describe("Braintrust SDK Browser Tests", () => { + test("should run all browser tests (shared + eval + prompt)", async ({ + page, + baseURL, + }) => { + const results: TestResult[] = []; + + page.on("console", (msg) => { + const type = msg.type(); + const text = msg.text(); + if (type === "error") { + console.error(`[Browser Console Error] ${text}`); + } + }); + + page.on("pageerror", (error) => { + console.error("[Browser Page Error]", error.message); + }); + + page.on("requestfailed", (request) => { + console.error( + `[Request Failed] ${request.url()} - ${request.failure()?.errorText}`, + ); + }); + + const response = await page.goto(`${baseURL}/pages/browser-tests.html`, { + waitUntil: "domcontentloaded", + timeout: 30000, + }); + + if (!response || !response.ok()) { + throw new Error(`Failed to load page: ${response?.status()}`); + } + + try { + await page.waitForFunction( + () => { + return (window as any).__btBrowserSmokeResults?.completed === true; + }, + { timeout: 60000 }, + ); + } catch (error) { + const testState = await page.evaluate(() => { + return { + smoke: (window as any).__btBrowserSmokeResults, + documentReady: document.readyState, + bodyContent: document.body?.innerText?.substring(0, 500), + }; + }); + console.error( + "Test timeout - Current state:", + JSON.stringify(testState, null, 2), + ); + + await page.screenshot({ + path: "test-timeout-browser.png", + fullPage: true, + }); + throw error; + } + + const smoke = await page.evaluate( + () => (window as any).__btBrowserSmokeResults, + ); + + // Test 1: Overall completion + if (smoke && smoke.completed) { + results.push({ + status: "pass", + name: "Browser tests completed", + }); + } else { + results.push({ + status: "fail", + name: "Browser tests completed", + error: { message: "Tests did not complete" }, + }); + } + + // Test 2: No unhandled errors + if ((smoke.unhandledErrors?.length ?? 0) === 0) { + results.push({ + status: "pass", + name: "No unhandled errors", + }); + } else { + results.push({ + status: "fail", + name: "No unhandled errors", + error: { + message: `Found ${smoke.unhandledErrors.length} unhandled errors`, + }, + }); + } + + // Test 3: Shared suite + if ( + smoke.sections.shared.completed && + smoke.sections.shared.failed === 0 && + smoke.sections.shared.passed >= 17 + ) { + results.push({ + status: "pass", + name: `Shared suite (${smoke.sections.shared.passed} tests)`, + }); + } else { + results.push({ + status: "fail", + name: "Shared suite", + error: { + message: `Completed: ${smoke.sections.shared.completed}, Passed: ${smoke.sections.shared.passed}, Failed: ${smoke.sections.shared.failed}`, + }, + }); + } + + // Test 4: Eval suite + if ( + smoke.sections.eval.completed && + smoke.sections.eval.failed === 0 && + smoke.sections.eval.passed === 1 + ) { + results.push({ + status: "pass", + name: "Eval suite (1 test)", + }); + } else { + results.push({ + status: "fail", + name: "Eval suite", + error: { + message: `Completed: ${smoke.sections.eval.completed}, Passed: ${smoke.sections.eval.passed}, Failed: ${smoke.sections.eval.failed}`, + }, + }); + } + + // Test 5: Prompt suite + if ( + smoke.sections.prompt.completed && + smoke.sections.prompt.failed === 0 && + smoke.sections.prompt.passed === 2 + ) { + results.push({ + status: "pass", + name: "Prompt suite (2 tests)", + }); + } else { + results.push({ + status: "fail", + name: "Prompt suite", + error: { + message: `Completed: ${smoke.sections.prompt.completed}, Passed: ${smoke.sections.prompt.passed}, Failed: ${smoke.sections.prompt.failed}`, + }, + }); + } + + displayTestResults({ + scenarioName: "Playwright Browser Test Results", + results, + }); + + // Fail the Playwright test if any results failed + expect(smoke).toBeTruthy(); + expect(smoke.completed).toBe(true); + expect(smoke.unhandledErrors?.length ?? 0).toBe(0); + expect(smoke.sections.shared.completed).toBe(true); + expect(smoke.sections.shared.failed).toBe(0); + expect(smoke.sections.shared.passed).toBeGreaterThanOrEqual(17); + expect(smoke.sections.eval.completed).toBe(true); + expect(smoke.sections.eval.failed).toBe(0); + expect(smoke.sections.eval.passed).toBe(1); + expect(smoke.sections.prompt.completed).toBe(true); + expect(smoke.sections.prompt.failed).toBe(0); + expect(smoke.sections.prompt.passed).toBe(2); + }); +}); diff --git a/js/smoke/tests/browser/tsconfig.json b/js/smoke/scenarios/playwright-browser/tsconfig.json similarity index 85% rename from js/smoke/tests/browser/tsconfig.json rename to js/smoke/scenarios/playwright-browser/tsconfig.json index b1e97f000..d784430bc 100644 --- a/js/smoke/tests/browser/tsconfig.json +++ b/js/smoke/scenarios/playwright-browser/tsconfig.json @@ -11,6 +11,6 @@ "resolveJsonModule": true, "types": ["node", "@playwright/test"] }, - "include": ["src/**/*", "tests/**/*", "esbuild.config.js"], + "include": ["src/**/*", "tests/**/*", "esbuild.config.mjs"], "exclude": ["node_modules", "dist"] } diff --git a/js/smoke/shared/README.md b/js/smoke/shared/README.md index d8be806f6..bdd6f42a2 100644 --- a/js/smoke/shared/README.md +++ b/js/smoke/shared/README.md @@ -172,6 +172,48 @@ interface TestAdapters { Test suites check these flags and skip tests that aren't feasible in the current environment. +## Test Result Display + +### Standardized Output Format + +All scenarios now use a standardized display format via the `displayTestResults()` utility: + +```typescript +import { displayTestResults } from "../../shared/dist/index.mjs"; + +// Display test results +displayTestResults({ + scenarioName: "My Scenario Test Results", + results: testResults, + verbose: false, // Optional: show full stack traces +}); +``` + +This produces consistent output across all scenarios: + +``` +=== My Scenario Test Results === + +Tests: 18/20 passed +Expected failures: 2 + +✓ testCoreLoggingExports +✓ testDatasetExports +✗ testFailingFeature + Error: Feature not implemented + at Feature.test (feature.ts:42:11) + at runTest (test.ts:10:5) +⊘ testNunjucksTemplate + Expected failure: Nunjucks not supported in browser build +``` + +### Display Utilities + +- `displayTestResults(options)` - Display results in standardized format +- `hasFailures(results)` - Check if there are any real failures (excluding xfail) +- `getFailureCount(results)` - Get count of real failures +- `getTestStats(results)` - Get summary statistics (total, passed, failed, xfail) + ## Available Test Suites ### Basic Logging @@ -181,6 +223,7 @@ Tests core logging functionality: - `testBasicSpanLogging()` - Single span with input/output/expected - `testMultipleSpans()` - Multiple sequential spans - `testDirectLogging()` - Direct logger.log() if available +- `testJSONAttachment()` - JSON attachment logging - `runBasicLoggingTests()` - Runs all basic logging tests ### Adding New Test Suites diff --git a/js/smoke/shared/deno.json b/js/smoke/shared/deno.json new file mode 100644 index 000000000..fd4550289 --- /dev/null +++ b/js/smoke/shared/deno.json @@ -0,0 +1,6 @@ +{ + "name": "@braintrust/smoke-test-shared", + "exports": { + ".": "./src/index.ts" + } +} diff --git a/js/smoke/shared/package-lock.json b/js/smoke/shared/package-lock.json index 32ad0c26b..f67d631b2 100644 --- a/js/smoke/shared/package-lock.json +++ b/js/smoke/shared/package-lock.json @@ -933,7 +933,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -1126,7 +1125,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -1421,7 +1419,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/js/smoke/shared/src/helpers/display.ts b/js/smoke/shared/src/helpers/display.ts new file mode 100644 index 000000000..333669b39 --- /dev/null +++ b/js/smoke/shared/src/helpers/display.ts @@ -0,0 +1,101 @@ +/** + * Standardized test result display utilities + */ + +import type { TestResult } from "./types"; + +export interface DisplayTestResultsOptions { + scenarioName: string; + results: TestResult[]; + verbose?: boolean; +} + +/** + * Display test results in standardized format + */ +export function displayTestResults(options: DisplayTestResultsOptions): void { + const { scenarioName, results, verbose = false } = options; + + console.log(`\n=== ${scenarioName} ===\n`); + + const passedTests = results.filter((r) => r.status === "pass").length; + const xfailTests = results.filter((r) => r.status === "xfail").length; + const totalTests = results.length; + + console.log(`Tests: ${passedTests}/${totalTests} passed`); + if (xfailTests > 0) { + console.log(`Expected failures: ${xfailTests}`); + } + console.log(); + + for (const result of results) { + const statusSymbol = + result.status === "pass" ? "✓" : result.status === "xfail" ? "⊘" : "✗"; + const statusColor = + result.status === "pass" + ? "\x1b[32m" + : result.status === "xfail" + ? "\x1b[33m" + : "\x1b[31m"; + const resetColor = "\x1b[0m"; + + console.log(`${statusColor}${statusSymbol}${resetColor} ${result.name}`); + + if (result.status === "fail" && result.error) { + const errorMsg = result.error.message || String(result.error); + console.log(` Error: ${errorMsg}`); + + if (result.error.stack) { + const stackLines = result.error.stack.split("\n"); + if (verbose) { + console.log(` Stack trace:`); + for (const line of stackLines) { + console.log(` ${line}`); + } + } else { + const relevantLines = stackLines.slice(0, 3); + for (const line of relevantLines) { + console.log(` ${line}`); + } + } + } + } + + if (result.status === "xfail" && result.message) { + console.log(` ${result.message}`); + } + } + + console.log(); +} + +/** + * Check if there are any real failures (excluding xfail) + */ +export function hasFailures(results: TestResult[]): boolean { + return results.some((r) => r.status === "fail"); +} + +/** + * Get failure count (excluding xfail) + */ +export function getFailureCount(results: TestResult[]): number { + return results.filter((r) => r.status === "fail").length; +} + +/** + * Get summary statistics + */ +export function getTestStats(results: TestResult[]): { + total: number; + passed: number; + failed: number; + xfail: number; +} { + return { + total: results.length, + passed: results.filter((r) => r.status === "pass").length, + failed: results.filter((r) => r.status === "fail").length, + xfail: results.filter((r) => r.status === "xfail").length, + }; +} diff --git a/js/smoke/shared/src/helpers/types.ts b/js/smoke/shared/src/helpers/types.ts index bcf47c9b0..303515592 100644 --- a/js/smoke/shared/src/helpers/types.ts +++ b/js/smoke/shared/src/helpers/types.ts @@ -39,10 +39,13 @@ export interface TestAdapters { } export interface TestResult { - success: boolean; - testName: string; + status: "pass" | "fail" | "xfail"; // xfail = expected failure + name: string; message?: string; - error?: Error; + error?: { + message: string; + stack?: string; + }; } // ---- Braintrust module surface types ---- diff --git a/js/smoke/shared/src/index.ts b/js/smoke/shared/src/index.ts index d84810b26..386d5b4fc 100644 --- a/js/smoke/shared/src/index.ts +++ b/js/smoke/shared/src/index.ts @@ -37,11 +37,21 @@ export { assertHasProperty, } from "./helpers/assertions"; +// Export display utilities +export type { DisplayTestResultsOptions } from "./helpers/display"; +export { + displayTestResults, + hasFailures, + getFailureCount, + getTestStats, +} from "./helpers/display"; + // Export test suites export { testBasicSpanLogging, testMultipleSpans, testDirectLogging, + testJSONAttachment, runBasicLoggingTests, } from "./suites/basic-logging"; diff --git a/js/smoke/shared/src/suites/basic-logging.ts b/js/smoke/shared/src/suites/basic-logging.ts index 5620eedc7..a34b980fe 100644 --- a/js/smoke/shared/src/suites/basic-logging.ts +++ b/js/smoke/shared/src/suites/basic-logging.ts @@ -53,15 +53,18 @@ export async function testBasicSpanLogging( assertEqual(event.expected, "Paris"); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Basic span logging test passed", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -103,15 +106,18 @@ export async function testMultipleSpans( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: `Multiple spans test passed (${events.length} events captured)`, }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -145,22 +151,129 @@ export async function testDirectLogging( assertNotEmpty(events, "No events were captured from direct logging"); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Direct logging test passed", }; } else { return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Direct logging not supported, skipped", }; } } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, + }; + } +} + +/** + * Test JSONAttachment functionality + * Tests that JSONAttachment can be created and logged correctly + */ +export async function testJSONAttachment( + adapters: TestAdapters, + braintrust: { JSONAttachment?: unknown }, +): Promise { + const testName = "testJSONAttachment"; + + try { + const { initLogger, backgroundLogger } = adapters; + + const logger = initLogger({ + projectName: "json-attachment-test", + projectId: PROJECT_ID, + }); + + // Check if JSONAttachment is available + if (!braintrust.JSONAttachment) { + return { + status: "pass" as const, + name: testName, + message: "JSONAttachment not available, skipped", + }; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const JSONAttachment = braintrust.JSONAttachment as any; + + const testData = { + foo: "bar", + nested: { + array: [1, 2, 3], + bool: true, + }, + }; + + // Test logging with JSONAttachment + if (typeof logger.log === "function") { + logger.log({ + input: { + type: "chat_completion", + transcript: new JSONAttachment(testData, { + filename: "conversation_transcript.json", + pretty: true, + }), + }, + }); + } else { + // Fallback to span logging + const span = logger.startSpan({ name: "json-attachment-test" }); + span.log({ + input: { + type: "chat_completion", + transcript: new JSONAttachment(testData, { + filename: "conversation_transcript.json", + pretty: true, + }), + }, + }); + span.end(); + } + + await logger.flush(); + + const events = await backgroundLogger.drain(); + assertNotEmpty(events, "No events were captured with JSONAttachment"); + + // Verify the test data structure is preserved + assertEqual(testData.foo, "bar", "testData.foo should be 'bar'"); + assertEqual( + testData.nested.array.length, + 3, + "testData.nested.array should have 3 elements", + ); + assertEqual( + testData.nested.array[0], + 1, + "testData.nested.array[0] should be 1", + ); + assertEqual( + testData.nested.bool, + true, + "testData.nested.bool should be true", + ); + + return { + status: "pass" as const, + name: testName, + message: "JSONAttachment test passed", + }; + } catch (error) { + return { + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -170,6 +283,7 @@ export async function testDirectLogging( */ export async function runBasicLoggingTests( adapters: TestAdapters, + braintrust?: { JSONAttachment?: unknown }, ): Promise { const results: TestResult[] = []; @@ -177,5 +291,10 @@ export async function runBasicLoggingTests( results.push(await testMultipleSpans(adapters)); results.push(await testDirectLogging(adapters)); + // Only run JSONAttachment test if braintrust module is provided + if (braintrust) { + results.push(await testJSONAttachment(adapters, braintrust)); + } + return results; } diff --git a/js/smoke/shared/src/suites/eval-smoke.ts b/js/smoke/shared/src/suites/eval-smoke.ts index 7ed59df4e..ab533d1a8 100644 --- a/js/smoke/shared/src/suites/eval-smoke.ts +++ b/js/smoke/shared/src/suites/eval-smoke.ts @@ -115,15 +115,18 @@ export async function runEvalSmokeTest( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: `Eval smoke test passed (${evalData.length} cases)`, }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index 23c7b3043..2ad5561c6 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -141,15 +141,18 @@ export async function testCoreLoggingExports( assertType(module.flush, "function", "flush must be a function"); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Core logging exports verified (7 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -174,15 +177,18 @@ export async function testDatasetExports( assertType(module.Dataset, "function", "Dataset must be a function/class"); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Dataset exports verified (2 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -210,15 +216,18 @@ export async function testPromptExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Prompt exports verified (3 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -254,15 +263,18 @@ export async function testExperimentExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Experiment exports verified (3 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -324,15 +336,18 @@ export async function testEvalExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Eval exports verified (7 runtime exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -366,15 +381,18 @@ export async function testTracingExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Tracing exports verified (5 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -415,15 +433,18 @@ export async function testClientWrapperExports( } return { - success: true, - testName, + status: "pass" as const, + name: testName, message: `Client wrapper exports verified (1 required + ${optionalCount} optional)`, }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -458,15 +479,18 @@ export async function testUtilityExports( assertType(module.permalink, "function", "permalink must be a function"); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Utility exports verified (4 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -491,15 +515,18 @@ export async function testFunctionExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Function exports verified (2 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -527,15 +554,18 @@ export async function testFramework2Exports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Framework2 exports verified (3 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -557,15 +587,18 @@ export async function testIDGeneratorExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "ID generator exports verified (1 export)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -590,15 +623,18 @@ export async function testTestingExports( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Testing exports verified (1 export)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } @@ -623,15 +659,18 @@ export async function testStateManagementExports( assertType(module.login, "function", "login must be a function"); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "State management exports verified (2 exports)", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, }; } } diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index f2b14eb88..4dc43b9bd 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -71,15 +71,18 @@ export async function testMustacheTemplate( ); return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Mustache template test passed", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, message: `Test failed: ${error instanceof Error ? error.message : String(error)}`, }; } @@ -90,7 +93,6 @@ export async function testMustacheTemplate( */ export async function testNunjucksTemplate( module: PromptModule, - environment?: string, ): Promise { const testName = "testNunjucksTemplate"; @@ -124,9 +126,18 @@ export async function testNunjucksTemplate( ); } catch (constructorError) { return { - success: false, - testName, - error: constructorError as Error, + status: "fail" as const, + name: testName, + error: { + message: + constructorError instanceof Error + ? constructorError.message + : String(constructorError), + stack: + constructorError instanceof Error + ? constructorError.stack + : undefined, + }, message: `Failed to create Prompt: ${constructorError instanceof Error ? constructorError.message : String(constructorError)}`, }; } @@ -140,49 +151,17 @@ export async function testNunjucksTemplate( { templateFormat: "nunjucks" }, ); } catch (buildError) { - const errorMessage = - buildError instanceof Error ? buildError.message : String(buildError); - - const isUnsupported = errorMessage.includes( - "Nunjucks templating is not supported in this build", - ); - - if ( - (environment === "browser" || - environment === "cloudflare-worker-browser-no-compat" || - environment === "cloudflare-worker-browser-node-compat" || - environment === "nextjs-edge-runtime" || - environment === "vite-react-hono") && - isUnsupported - ) { - return { - success: true, - testName, - message: - "Nunjucks template test passed - threw expected unsupported error", - }; - } - - // In Cloudflare Workers (even with nodejs_compat), string-based template codegen is disallowed. - if ( - environment === "cloudflare-worker-node-node-compat" && - errorMessage.includes( - "String template rendering. Disallowed in this environment for security reasons", - ) - ) { - return { - success: true, - testName, - message: - "Nunjucks template test passed - threw expected codegen-disallowed error", - }; - } - return { - success: false, - testName, - error: buildError as Error, - message: `Failed to build prompt: ${errorMessage}`, + status: "fail" as const, + name: testName, + error: { + message: + buildError instanceof Error + ? buildError.message + : String(buildError), + stack: buildError instanceof Error ? buildError.stack : undefined, + }, + message: `Failed to build prompt: ${buildError instanceof Error ? buildError.message : String(buildError)}`, }; } @@ -196,23 +175,32 @@ export async function testNunjucksTemplate( ); } catch (assertError) { return { - success: false, - testName, - error: assertError as Error, + status: "fail" as const, + name: testName, + error: { + message: + assertError instanceof Error + ? assertError.message + : String(assertError), + stack: assertError instanceof Error ? assertError.stack : undefined, + }, message: `Assertion failed: ${assertError instanceof Error ? assertError.message : String(assertError)}`, }; } return { - success: true, - testName, + status: "pass" as const, + name: testName, message: "Nunjucks template test passed", }; } catch (error) { return { - success: false, - testName, - error: error as Error, + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, message: `Test failed: ${error instanceof Error ? error.message : String(error)}`, }; } @@ -223,12 +211,11 @@ export async function testNunjucksTemplate( */ export async function runPromptTemplatingTests( module: PromptModule, - environment?: string, ): Promise { const results: TestResult[] = []; results.push(await testMustacheTemplate(module)); - results.push(await testNunjucksTemplate(module, environment)); + results.push(await testNunjucksTemplate(module)); return results; } diff --git a/js/smoke/tests/browser/.gitignore b/js/smoke/tests/browser/.gitignore deleted file mode 100644 index 4ed917b39..000000000 --- a/js/smoke/tests/browser/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Playwright test results -test-results/ -playwright-report/ - -# Build output (already covered by root .gitignore, but explicit here) -dist/ diff --git a/js/smoke/tests/browser/README.md b/js/smoke/tests/browser/README.md deleted file mode 100644 index 1ad753b7a..000000000 --- a/js/smoke/tests/browser/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Braintrust SDK Browser Smoke Tests - -This package contains smoke tests for the Braintrust SDK running in a browser environment using Playwright. - -## What It Tests - -The browser tests run **all shared test suites** from `sdk/js/smoke/shared` to ensure full SDK compatibility in the browser. - -## Prerequisites - -- Node.js (v18+) -- npm - -## Setup - -```bash -npm install -``` - -This will automatically install Playwright browsers via the `postinstall` script. - -## Running Tests - -### Run all tests (builds automatically) - -```bash -npm test -``` - -This will: - -1. Build the test bundle using esbuild -2. Start a local web server -3. Run Playwright tests - -### Build only - -```bash -npm run build -``` - -### Run tests without rebuilding - -```bash -npx playwright test -``` - -## How It Works - -1. **Build Step**: `esbuild` bundles `src/browser-tests.ts` (which includes the Braintrust SDK and shared test suites) into `dist/browser-tests.js` -2. **Web Server**: Playwright's `webServer` starts `http-server` to serve the test files -3. **Test Execution**: Playwright loads `pages/browser-tests.html` which loads the bundled test script -4. **Test Results**: Tests communicate results via `window.testResults` and `window.evalTestResults` which Playwright reads - -## Test Environment - -- Uses `_exportsForTestingOnly.useTestBackgroundLogger()` to prevent real API calls -- Uses `noSendLogs: true` in Eval to prevent experiment registration -- All tests run locally without network requests to Braintrust API - -## Project Structure - -``` -browser/ -├── src/ -│ └── browser-tests.ts # Combined test file (general + eval) -├── tests/ -│ └── browser.test.ts # Playwright test runner -├── pages/ -│ └── browser-tests.html # HTML page that loads tests -├── dist/ # Built test bundle (gitignored) -├── playwright.config.ts # Playwright configuration -├── esbuild.config.js # Build configuration -└── package.json -``` - -## CI Integration - -The tests are designed to run in CI environments: - -- Automatically builds before running tests -- Uses test background logger (no real API calls) -- Retries on failure in CI mode -- Generates HTML reports diff --git a/js/smoke/tests/browser/global-setup.ts b/js/smoke/tests/browser/global-setup.ts deleted file mode 100644 index 5f0a1a994..000000000 --- a/js/smoke/tests/browser/global-setup.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { FullConfig } from "@playwright/test"; -import { execSync } from "child_process"; -import { dirname } from "path"; -import { fileURLToPath } from "url"; -import { join } from "path"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -async function globalSetup(config: FullConfig) { - void config; - - // Ensure the shared smoke-test package is built so browser bundle picks up latest exports. - const sharedDir = join(__dirname, "..", "..", "shared"); - console.log("🔨 Building shared smoke-test package..."); - execSync("npm run build", { - cwd: sharedDir, - stdio: "inherit", - }); - - console.log("🔨 Building browser tests..."); - try { - execSync("node esbuild.config.js", { - cwd: __dirname, - stdio: "inherit", - }); - console.log("✅ Build completed"); - } catch (error) { - console.error("❌ Build failed"); - throw error; - } -} - -export default globalSetup; diff --git a/js/smoke/tests/browser/package-lock.json b/js/smoke/tests/browser/package-lock.json deleted file mode 100644 index b665d9b86..000000000 --- a/js/smoke/tests/browser/package-lock.json +++ /dev/null @@ -1,2480 +0,0 @@ -{ - "name": "braintrust-browser-test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-browser-test", - "version": "1.0.0", - "hasInstallScript": true, - "dependencies": { - "braintrust": "latest", - "zod": "^4.3.5" - }, - "devDependencies": { - "@playwright/test": "^1.51.1", - "@types/node": "^20.10.5", - "esbuild": "^0.27.2", - "http-server": "^14.1.1", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", - "license": "MIT" - }, - "node_modules/@playwright/test": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", - "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright": "1.57.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@types/node": { - "version": "20.19.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.28.tgz", - "integrity": "sha512-VyKBr25BuFDzBFCK5sUM6ZXiWfqgCTwTAOK8qzGV/m9FCirXYDlmczJ+d5dXBAQALGCdRRdbteKYfJ84NGEusw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/nunjucks": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", - "license": "MIT" - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT" - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT" - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-2.0.2.tgz", - "integrity": "sha512-TOfdi2acpDnne3Pcew/shbwda0SKQvjTsGprr0gLWloaeYehhOPyrsWmwKsRNXOJa01D0czTGyetWpUbcH+euw==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@types/nunjucks": "^3.2.6", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "nunjucks": "^3.2.4", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "source-map": "^0.7.4", - "termi-link": "^1.0.1", - "uuid": "^9.0.1", - "zod-to-json-schema": "^3.25.0" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34 || ^4.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT" - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT" - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "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==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "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/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true, - "license": "MIT" - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "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==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-server": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", - "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "basic-auth": "^2.0.1", - "chalk": "^4.1.2", - "corser": "^2.0.1", - "he": "^1.2.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy": "^1.18.1", - "mime": "^1.6.0", - "minimist": "^1.2.6", - "opener": "^1.5.1", - "portfinder": "^1.0.28", - "secure-compare": "3.0.1", - "union": "~0.5.0", - "url-join": "^4.0.1" - }, - "bin": { - "http-server": "bin/http-server" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "license": "BSD-2-Clause", - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/playwright": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", - "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.57.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", - "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/portfinder": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz", - "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^3.2.6", - "debug": "^4.3.6" - }, - "engines": { - "node": ">= 10.12" - } - }, - "node_modules/portfinder/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/portfinder/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/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "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", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/secure-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", - "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", - "dev": true, - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/termi-link": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "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": { - "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/tsx/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/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "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, - "license": "MIT" - }, - "node_modules/union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", - "dev": true, - "dependencies": { - "qs": "^6.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true, - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "dev": true, - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/zod": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/browser/package.json b/js/smoke/tests/browser/package.json deleted file mode 100644 index 98f978d3c..000000000 --- a/js/smoke/tests/browser/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "braintrust-browser-test", - "version": "1.0.0", - "description": "Smoke test for Braintrust SDK in browser using Playwright", - "private": true, - "type": "module", - "scripts": { - "build": "node esbuild.config.js", - "test": "playwright test", - "test:ui": "playwright test --ui", - "test:debug": "playwright test --debug", - "postinstall": "npx playwright install --with-deps chromium", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "enable-esm": "npx tsx ../../enable-esm.ts", - "install-build": "npm install --legacy-peer-deps && npx tsx ../../install-build.ts ../../../artifacts braintrust" - }, - "dependencies": { - "braintrust": "latest", - "zod": "^4.3.5" - }, - "devDependencies": { - "@playwright/test": "^1.51.1", - "@types/node": "^20.10.5", - "esbuild": "^0.27.2", - "http-server": "^14.1.1", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } -} diff --git a/js/smoke/tests/browser/src/browser-tests.ts b/js/smoke/tests/browser/src/browser-tests.ts deleted file mode 100644 index b0d88c59f..000000000 --- a/js/smoke/tests/browser/src/browser-tests.ts +++ /dev/null @@ -1,127 +0,0 @@ -// Combined browser smoke tests. -// This file is the single entrypoint bundled by esbuild. - -import * as braintrust from "braintrust/browser"; -import { - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - withTestEnvironment, -} from "../../../shared/dist/index.mjs"; -import { createBrowserHarness, type BrowserSmokeResults } from "./harness"; - -declare global { - interface Window { - __btBrowserSmokeResults?: BrowserSmokeResults; - } -} - -const output = document.getElementById("output"); -if (!output) { - throw new Error("Missing #output element"); -} - -const harness = createBrowserHarness(output); -window.__btBrowserSmokeResults = harness.results; - -const SHARED_SECTION = "shared"; -const EVAL_SECTION = "eval"; -const PROMPT_SECTION = "prompt"; - -async function runAllTestSuites() { - if (!braintrust._exportsForTestingOnly) { - harness.fail( - "runtime", - "preflight", - new Error("_exportsForTestingOnly not available"), - ); - return; - } - - // Create a single test environment for all test suites - await withTestEnvironment( - { - initLogger: braintrust.initLogger, - testingExports: braintrust._exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "browser", - }, - async (adapters) => { - // Run shared suites (import verification + basic logging) - harness.log("=== Running shared suites ==="); - - const importResults = await runImportVerificationTests(braintrust); - for (const r of importResults) { - if (r.success) harness.pass(SHARED_SECTION, r.testName, r.message); - else harness.fail(SHARED_SECTION, r.testName, r.error, r.message); - } - - const loggingResults = await runBasicLoggingTests(adapters); - for (const r of loggingResults) { - if (r.success) harness.pass(SHARED_SECTION, r.testName, r.message); - else harness.fail(SHARED_SECTION, r.testName, r.error, r.message); - } - - harness.completeSection(SHARED_SECTION); - - // Run eval suite - harness.log("\n=== Running eval suite ==="); - - const evalResult = await runEvalSmokeTest(adapters, braintrust); - if (evalResult.success) - harness.pass(EVAL_SECTION, evalResult.testName, evalResult.message); - else - harness.fail( - EVAL_SECTION, - evalResult.testName, - evalResult.error, - evalResult.message, - ); - - harness.completeSection(EVAL_SECTION); - - // Run prompt templating suite - harness.log("\n=== Running prompt templating suite ==="); - - const promptResults = await runPromptTemplatingTests( - { Prompt: braintrust.Prompt }, - "browser", - ); - for (const r of promptResults) { - if (r.success) harness.pass(PROMPT_SECTION, r.testName, r.message); - else harness.fail(PROMPT_SECTION, r.testName, r.error, r.message); - } - - harness.completeSection(PROMPT_SECTION); - }, - ); -} - -async function main() { - // Hard timeout guard so Playwright never hangs indefinitely. - const timeoutMs = 55_000; - const timeout = window.setTimeout(() => { - if (!harness.results.completed) { - harness.fail( - "runtime", - "timeout", - new Error("Timed out waiting for browser tests to finish"), - ); - harness.completeAll(); - } - }, timeoutMs); - - try { - await runAllTestSuites(); - } catch (err) { - harness.fail("runtime", "fatal", err); - } finally { - window.clearTimeout(timeout); - harness.log("\n=== All browser suites complete ==="); - harness.completeAll(); - } -} - -void main(); diff --git a/js/smoke/tests/browser/tests/browser.test.ts b/js/smoke/tests/browser/tests/browser.test.ts deleted file mode 100644 index 7ddc30ec2..000000000 --- a/js/smoke/tests/browser/tests/browser.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { test, expect } from "@playwright/test"; - -test.describe("Braintrust SDK Browser Tests", () => { - test("should run all browser tests (general + eval)", async ({ - page, - baseURL, - }) => { - // Set up console logging - page.on("console", (msg) => { - const type = msg.type(); - const text = msg.text(); - if (type === "error") { - console.error(`[Browser Console Error] ${text}`); - } else { - console.log(`[Browser Console ${type}] ${text}`); - } - }); - - // Set up error handling - page.on("pageerror", (error) => { - console.error("[Browser Page Error]", error.message); - }); - - // Set up request/response logging for debugging - page.on("requestfailed", (request) => { - console.error( - `[Request Failed] ${request.url()} - ${request.failure()?.errorText}`, - ); - }); - - // Navigate to the HTML page via the test server - console.log(`Navigating to: ${baseURL}/pages/browser-tests.html`); - const response = await page.goto(`${baseURL}/pages/browser-tests.html`, { - waitUntil: "domcontentloaded", - timeout: 30000, - }); - - if (!response || !response.ok()) { - console.error( - `Page load failed: ${response?.status()} ${response?.statusText()}`, - ); - throw new Error(`Failed to load page: ${response?.status()}`); - } - - console.log("Page loaded, waiting for all tests to complete..."); - - // Wait for browser bundle to finish - try { - await page.waitForFunction( - () => { - return (window as any).__btBrowserSmokeResults?.completed === true; - }, - { timeout: 60000 }, - ); - } catch (error) { - // Get current state for debugging - const testState = await page.evaluate(() => { - return { - smoke: (window as any).__btBrowserSmokeResults, - documentReady: document.readyState, - bodyContent: document.body?.innerText?.substring(0, 500), - }; - }); - console.error( - "Test timeout - Current state:", - JSON.stringify(testState, null, 2), - ); - - // Take a screenshot for debugging - await page.screenshot({ - path: "test-timeout-browser.png", - fullPage: true, - }); - throw error; - } - - // Get smoke results from the page - const smoke = await page.evaluate( - () => (window as any).__btBrowserSmokeResults, - ); - - // Log test summary - console.log("\n=== Browser Test Results ==="); - console.log(`Overall completed: ${smoke.completed}`); - console.log(`Unhandled errors: ${smoke.unhandledErrors?.length ?? 0}`); - - // Verify all tests passed - expect(smoke).toBeTruthy(); - expect(smoke.completed).toBe(true); - expect(smoke.unhandledErrors?.length ?? 0).toBe(0); - - // Shared suite - expect(smoke.sections.shared.completed).toBe(true); - expect(smoke.sections.shared.failed).toBe(0); - expect(smoke.sections.shared.passed).toBe(16); - console.log( - `\nShared suite: ${smoke.sections.shared.passed} passed, ${smoke.sections.shared.failed} failed`, - ); - - // Eval suite - expect(smoke.sections.eval.completed).toBe(true); - expect(smoke.sections.eval.failed).toBe(0); - expect(smoke.sections.eval.passed).toBe(1); - console.log( - `Eval suite: ${smoke.sections.eval.passed} passed, ${smoke.sections.eval.failed} failed`, - ); - // Prompt suite - expect(smoke.sections.prompt.completed).toBe(true); - expect(smoke.sections.prompt.failed).toBe(0); - expect(smoke.sections.prompt.passed).toBe(2); - console.log( - `Prompt suite: ${smoke.sections.prompt.passed} passed, ${smoke.sections.prompt.failed} failed`, - ); - }); -}); diff --git a/js/smoke/tests/cloudflare-worker/package-lock.json b/js/smoke/tests/cloudflare-worker/package-lock.json deleted file mode 100644 index 8e428b02c..000000000 --- a/js/smoke/tests/cloudflare-worker/package-lock.json +++ /dev/null @@ -1,3748 +0,0 @@ -{ - "name": "braintrust-cloudflare-worker-smoke-test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-cloudflare-worker-smoke-test", - "version": "1.0.0", - "dependencies": { - "braintrust": "file:../../../artifacts/braintrust-2.0.2.tgz", - "zod": "^3.25.76" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20250810.0", - "tsx": "^4.19.2", - "typescript": "^5.4.4", - "wrangler": "^4.28.1" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.1.tgz", - "integrity": "sha512-Nu8ahitGFFJztxUml9oD/DLb7Z28C8cd8F46IVQ7y5Btz575pvMY8AqZsXkX7Gds29eCKdMgIHjIvzskHgPSFg==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "mime": "^3.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@cloudflare/kv-asset-handler/node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@cloudflare/unenv-preset": { - "version": "2.7.12", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.12.tgz", - "integrity": "sha512-SIBo+k58R9OyBsxF1jL6GdL7XHbzatT86c0be+UY5v5tg6TAuJ1/2QsRuC3pHgKVHile1HcJqEEORoS9hv8hNw==", - "dev": true, - "license": "MIT OR Apache-2.0", - "peerDependencies": { - "unenv": "2.0.0-rc.24", - "workerd": "^1.20251125.0" - }, - "peerDependenciesMeta": { - "workerd": { - "optional": true - } - } - }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251202.0.tgz", - "integrity": "sha512-/uvEAWEukTWb1geHhbjGUeZqcSSSyYzp0mvoPUBl+l0ont4NVGao3fgwM0q8wtKvgoKCHSG6zcG23wj9Opj3Nw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251202.0.tgz", - "integrity": "sha512-f52xRvcI9cWRd6400EZStRtXiRC5XKEud7K5aFIbbUv0VeINltujFQQ9nHWtsF6g1quIXWkjhh5u01gPAYNNXA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251202.0.tgz", - "integrity": "sha512-HYXinF5RBH7oXbsFUMmwKCj+WltpYbf5mRKUBG5v3EuPhUjSIFB84U+58pDyfBJjcynHdy3EtvTWcvh/+lcgow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251202.0.tgz", - "integrity": "sha512-++L02Jdoxz7hEA9qDaQjbVU1RzQS+S+eqIi22DkPe2Tgiq2M3UfNpeu+75k5L9DGRIkZPYvwMBMbcmKvQqdIIg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251202.0.tgz", - "integrity": "sha512-gzeU6eDydTi7ib+Q9DD/c0hpXtqPucnHk2tfGU03mljPObYxzMkkPGgB5qxpksFvub3y4K0ChjqYxGJB4F+j3g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251202.0.tgz", - "integrity": "sha512-Q7m1Ivu2fbKalOPm00KLpu6GfRaq4TlrPknqugvZgp/gDH96OYKINO4x7jvCIBvCz/aK9vVoOj8tlbSQBervVA==", - "dev": true, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "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": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "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/@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.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.33.tgz", - "integrity": "sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==", - "license": "MIT" - }, - "node_modules/@poppinss/colors": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", - "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", - "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/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.2", - "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", - "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sindresorhus/is": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.1.1.tgz", - "integrity": "sha512-rO92VvpgMc3kfiTjGT52LEtJ8Yc5kCWhZjLQ3LwlA4pSgPpQO7bVpYXParOD8Jwf+cVQECJo3yP/4I8aZtUQTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@speed-highlight/core": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.12.tgz", - "integrity": "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/@types/nunjucks": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", - "license": "MIT" - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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.4.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/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/boxen/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "2.0.2", - "resolved": "file:../../../artifacts/braintrust-2.0.2.tgz", - "integrity": "sha512-nU5mFGGJEzth094Hs1qiCRZ59s5PJjW35BgFjx2YBJg38HkMBflvf73NBLeYvgoqBfPFs1OyoGpyEyOB16YASw==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@types/nunjucks": "^3.2.6", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "nunjucks": "^3.2.4", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "source-map": "^0.7.4", - "termi-link": "^1.0.1", - "uuid": "^9.0.1", - "zod-to-json-schema": "^3.25.0" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34 || ^4.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "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==", - "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==", - "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": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "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/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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/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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "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/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "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/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "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/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/miniflare": { - "version": "4.20251202.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251202.0.tgz", - "integrity": "sha512-Pa5iBAVzzVT/yr7rcyr75ETm5IGCpdT61foGx+6jDj+vzISNfWZgEcSxWk1nlJboJumUJ10kC498hQudpdbDWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@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.20251202.0", - "ws": "8.18.0", - "youch": "4.1.0-beta.10", - "zod": "3.22.3" - }, - "bin": { - "miniflare": "bootstrap.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/miniflare/node_modules/zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "license": "BSD-2-Clause", - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "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": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", - "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/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==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "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": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" - }, - "engines": { - "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/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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "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": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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": ">=4", - "npm": ">=6" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/termi-link": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "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, - "license": "0BSD", - "optional": true - }, - "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": { - "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/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/unenv": { - "version": "2.0.0-rc.24", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", - "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pathe": "^2.0.3" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/workerd": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251202.0.tgz", - "integrity": "sha512-p08YfrUMHkjCECNdT36r+6DpJIZX4kixbZ4n6GMUcLR5Gh18fakSCsiQrh72iOm4M9QHv/rM7P8YvCrUPWT5sg==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "workerd": "bin/workerd" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20251202.0", - "@cloudflare/workerd-darwin-arm64": "1.20251202.0", - "@cloudflare/workerd-linux-64": "1.20251202.0", - "@cloudflare/workerd-linux-arm64": "1.20251202.0", - "@cloudflare/workerd-windows-64": "1.20251202.0" - } - }, - "node_modules/wrangler": { - "version": "4.52.1", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.52.1.tgz", - "integrity": "sha512-rIzDxzPnLAaqBF+SdHGd9Az0ELEWtIBwPp5diCR58p2F4C+KgNGGpPMFswMntuViQ2RKRgGbk4jIzStJoUUfjQ==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.1", - "@cloudflare/unenv-preset": "2.7.12", - "blake3-wasm": "2.1.5", - "esbuild": "0.27.0", - "miniflare": "4.20251202.0", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.24", - "workerd": "1.20251202.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=20.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20251202.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } - } - }, - "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" - } - }, - "node_modules/wrangler/node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "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/youch/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/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/cloudflare-worker/package.json b/js/smoke/tests/cloudflare-worker/package.json deleted file mode 100644 index b973f8d9e..000000000 --- a/js/smoke/tests/cloudflare-worker/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "braintrust-cloudflare-worker-smoke-test", - "version": "1.0.0", - "description": "Smoke test for Braintrust SDK in Cloudflare Workers", - "private": true, - "scripts": { - "test": "node run-test.mjs", - "test:braintrust-node-compat": "node run-test.mjs --config wrangler.node.toml", - "test:braintrust-browser-node-compat": "node run-test.mjs --config wrangler.browser-node-compat.toml", - "test:braintrust-browser-no-compat": "node run-test.mjs --config wrangler.browser.toml", - "test:braintrust-no-compat": "node run-test.mjs --config wrangler.node-no-compat.toml", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" - }, - "dependencies": { - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20250810.0", - "tsx": "^4.19.2", - "typescript": "^5.4.4", - "wrangler": "^4.28.1" - } -} diff --git a/js/smoke/tests/cloudflare-worker/run-test.mjs b/js/smoke/tests/cloudflare-worker/run-test.mjs deleted file mode 100644 index b03daa1fa..000000000 --- a/js/smoke/tests/cloudflare-worker/run-test.mjs +++ /dev/null @@ -1,215 +0,0 @@ -import { spawn, execSync } from "node:child_process"; -import { parseArgs } from "node:util"; - -const PORT = 8799; -const MAX_RETRIES = 20; -const RETRY_DELAY_MS = 250; - -const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - -const ENTRYPOINT = { - node: "braintrust", - browser: "braintrust/browser", -}; - -const COMPAT = { - enabled: "nodejs_compat_v2", - disabled: "no nodejs_compat", -}; - -const VARIANTS = { - "node-node-compat": { - config: "wrangler.node.toml", - entrypoint: ENTRYPOINT.node, - nodejsCompat: true, - }, - "browser-no-compat": { - config: "wrangler.browser.toml", - entrypoint: ENTRYPOINT.browser, - nodejsCompat: false, - }, - "browser-node-compat": { - config: "wrangler.browser-node-compat.toml", - entrypoint: ENTRYPOINT.browser, - nodejsCompat: true, - }, - "node-no-compat": { - config: "wrangler.node-no-compat.toml", - entrypoint: ENTRYPOINT.node, - nodejsCompat: false, - }, -}; - -function shouldExpectStartupFailure(variant) { - // Node entrypoint requires nodejs_compat to access Node.js APIs - return variant.entrypoint === ENTRYPOINT.node && !variant.nodejsCompat; -} - -function displayTestResults(testResult, testLabel) { - console.log(`\n=== ${testLabel} ===\n`); - - // Display individual test results if available - if (testResult.results && testResult.results.length > 0) { - console.log( - `Tests: ${testResult.passedTests}/${testResult.totalTests} passed\n`, - ); - - for (const result of testResult.results) { - const status = result.success ? "✓" : "✗"; - const statusColor = result.success ? "\x1b[32m" : "\x1b[31m"; - const resetColor = "\x1b[0m"; - - console.log(`${statusColor}${status}${resetColor} ${result.name}`); - - if (!result.success && result.error) { - console.log(` Error: ${result.error}`); - } - } - } else { - console.log(JSON.stringify(testResult, null, 2)); - } -} - -const VARIANTS_BY_CONFIG = Object.fromEntries( - Object.entries(VARIANTS).map(([id, v]) => [v.config, { id, ...v }]), -); - -function labelForVariant(variant) { - return `${variant.nodejsCompat ? COMPAT.enabled : COMPAT.disabled} + ${variant.entrypoint}`; -} - -function killPort(port) { - try { - execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { - stdio: "ignore", - }); - } catch {} -} - -async function waitForServer() { - for (let i = 0; i < MAX_RETRIES; i++) { - try { - const res = await fetch(`http://localhost:${PORT}/`); - if (res.ok) return true; - } catch {} - await sleep(RETRY_DELAY_MS); - } - return false; -} - -async function runVariant(variant) { - const testLabel = labelForVariant(variant); - const wranglerConfig = variant.config; - const startupShouldFail = shouldExpectStartupFailure(variant); - - killPort(PORT); - - const wrangler = spawn( - "npx", - ["wrangler", "dev", "--config", wranglerConfig, "--port", String(PORT)], - { - stdio: ["ignore", "pipe", "pipe"], - shell: true, - }, - ); - - let wranglerOutput = ""; - wrangler.stdout.on("data", (data) => (wranglerOutput += data)); - wrangler.stderr.on("data", (data) => (wranglerOutput += data)); - - const killWrangler = () => { - return new Promise((resolve) => { - if (wrangler.exitCode !== null) { - resolve(); - return; - } - wrangler.once("exit", resolve); - wrangler.kill("SIGTERM"); - setTimeout(() => { - if (wrangler.exitCode === null) { - wrangler.kill("SIGKILL"); - } - }, 1000); - }); - }; - - try { - const serverStartedSuccessfully = await waitForServer(); - - if (!serverStartedSuccessfully) { - if (startupShouldFail) { - console.log(`\n=== ${testLabel} (expected startup failure) ===\n`); - console.log(wranglerOutput.trim() || "(no output)"); - await killWrangler(); - return 0; - } - console.error(`[${testLabel}] Server failed to start:\n`, wranglerOutput); - await killWrangler(); - return 1; - } - - const testResponse = await fetch(`http://localhost:${PORT}/test`); - const testResult = await testResponse.json(); - - displayTestResults(testResult, testLabel); - - const exitCode = testResult.success ? 0 : 1; - await killWrangler(); - return exitCode; - } catch (error) { - console.error(`[${testLabel}] Error:`, error.message, "\n", wranglerOutput); - await killWrangler(); - return 1; - } -} - -async function main() { - const { values } = parseArgs({ - args: process.argv.slice(2), - options: { - config: { type: "string" }, - variant: { type: "string" }, - }, - allowPositionals: false, - }); - - const requestedConfig = values.config; - const requestedVariantId = values.variant; - - // If a specific variant/config was requested, run only that one - if (requestedConfig || requestedVariantId) { - const variant = requestedVariantId - ? VARIANTS[requestedVariantId] - : VARIANTS_BY_CONFIG[requestedConfig]; - - if (!variant) { - const availableVariants = Object.keys(VARIANTS).sort().join(", "); - throw new Error( - `Unknown variant/config. Use --variant <${availableVariants}> or --config .`, - ); - } - - const exitCode = await runVariant(variant); - process.exit(exitCode); - } - - // Run default test suite (both node and browser variants) - const defaultTestSuite = [ - VARIANTS["node-node-compat"], - VARIANTS["browser-no-compat"], - ]; - - for (const variant of defaultTestSuite) { - const exitCode = await runVariant(variant); - if (exitCode !== 0) { - process.exit(exitCode); - } - } - - process.exit(0); -} - -main().catch((err) => { - console.error("Fatal:", err); - process.exit(1); -}); diff --git a/js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts b/js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts deleted file mode 100644 index c594f3fe3..000000000 --- a/js/smoke/tests/cloudflare-worker/src/browser-no-compat.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as braintrust from "braintrust/browser"; -import { createWorker } from "./worker"; - -export default createWorker(braintrust, "cloudflare-worker-browser-no-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts b/js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts deleted file mode 100644 index 80f345d3d..000000000 --- a/js/smoke/tests/cloudflare-worker/src/browser-node-compat.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as braintrust from "braintrust/browser"; -import { createWorker } from "./worker"; - -export default createWorker( - braintrust, - "cloudflare-worker-browser-node-compat", -); diff --git a/js/smoke/tests/cloudflare-worker/src/browser.ts b/js/smoke/tests/cloudflare-worker/src/browser.ts deleted file mode 100644 index c594f3fe3..000000000 --- a/js/smoke/tests/cloudflare-worker/src/browser.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as braintrust from "braintrust/browser"; -import { createWorker } from "./worker"; - -export default createWorker(braintrust, "cloudflare-worker-browser-no-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/node-no-compat.ts b/js/smoke/tests/cloudflare-worker/src/node-no-compat.ts deleted file mode 100644 index 98a8e9e1d..000000000 --- a/js/smoke/tests/cloudflare-worker/src/node-no-compat.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as braintrust from "braintrust"; -import { createWorker } from "./worker"; - -export default createWorker(braintrust, "cloudflare-worker-node-no-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/node-node-compat.ts b/js/smoke/tests/cloudflare-worker/src/node-node-compat.ts deleted file mode 100644 index 9339aa6a8..000000000 --- a/js/smoke/tests/cloudflare-worker/src/node-node-compat.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as braintrust from "braintrust"; -import { createWorker } from "./worker"; - -export default createWorker(braintrust, "cloudflare-worker-node-node-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/node.ts b/js/smoke/tests/cloudflare-worker/src/node.ts deleted file mode 100644 index 9339aa6a8..000000000 --- a/js/smoke/tests/cloudflare-worker/src/node.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as braintrust from "braintrust"; -import { createWorker } from "./worker"; - -export default createWorker(braintrust, "cloudflare-worker-node-node-compat"); diff --git a/js/smoke/tests/cloudflare-worker/src/worker.ts b/js/smoke/tests/cloudflare-worker/src/worker.ts deleted file mode 100644 index f64fef263..000000000 --- a/js/smoke/tests/cloudflare-worker/src/worker.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - type TestResult, -} from "../../../shared/dist/index.mjs"; - -// Cloudflare Worker environment bindings (empty for this test) -interface Env {} - -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -export function createWorker( - braintrust: typeof import("braintrust") | typeof import("braintrust/browser"), - environment: string, -): { - fetch(request: Request, _env: Env): Promise; -} { - const { initLogger, _exportsForTestingOnly } = braintrust; - - async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment, - }); - - try { - const importResults = await runImportVerificationTests(braintrust); - const functionalResults = await runBasicLoggingTests(adapters); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - const promptTemplatingResults = await runPromptTemplatingTests( - { Prompt: braintrust.Prompt }, - adapters.environment, - ); - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - const failures = results.filter((r) => !r.success); - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } - } - - return { - async fetch(request: Request, _env: Env): Promise { - const url = new URL(request.url); - - if (url.pathname === "/test") { - const result = await runSharedTestSuites(); - return new Response(JSON.stringify(result, null, 2), { - headers: { "Content-Type": "application/json" }, - status: result.success ? 200 : 500, - }); - } - - return new Response( - `Braintrust Cloudflare Worker Smoke Test - -GET /test - Run shared test suites - -This worker tests the Braintrust SDK in a Cloudflare Workers environment -using shared test suites for consistency across runtime environments.`, - { headers: { "Content-Type": "text/plain" } }, - ); - }, - }; -} diff --git a/js/smoke/tests/cloudflare-worker/tsconfig.json b/js/smoke/tests/cloudflare-worker/tsconfig.json deleted file mode 100644 index 921234e40..000000000 --- a/js/smoke/tests/cloudflare-worker/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "target": "es2021", - "lib": ["es2021"], - "module": "es2022", - "moduleResolution": "node", - "types": ["@cloudflare/workers-types"], - "resolveJsonModule": true, - "allowJs": true, - "checkJs": false, - "noEmit": true, - "isolatedModules": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true - }, - "include": ["src/**/*"] -} diff --git a/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml b/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml deleted file mode 100644 index 508e049b1..000000000 --- a/js/smoke/tests/cloudflare-worker/wrangler.browser-node-compat.toml +++ /dev/null @@ -1,4 +0,0 @@ -name = "braintrust-smoke-test-browser-node-compat" -main = "src/browser-node-compat.ts" -compatibility_date = "2024-09-23" -compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/tests/cloudflare-worker/wrangler.browser.toml b/js/smoke/tests/cloudflare-worker/wrangler.browser.toml deleted file mode 100644 index 6048efa1d..000000000 --- a/js/smoke/tests/cloudflare-worker/wrangler.browser.toml +++ /dev/null @@ -1,3 +0,0 @@ -name = "braintrust-smoke-test-browser" -main = "src/browser-no-compat.ts" -compatibility_date = "2024-09-23" diff --git a/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml b/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml deleted file mode 100644 index 98528470d..000000000 --- a/js/smoke/tests/cloudflare-worker/wrangler.node-no-compat.toml +++ /dev/null @@ -1,3 +0,0 @@ -name = "braintrust-smoke-test-node-no-compat" -main = "src/node-no-compat.ts" -compatibility_date = "2024-09-23" diff --git a/js/smoke/tests/deno/.gitignore b/js/smoke/tests/deno/.gitignore deleted file mode 100644 index c8912c808..000000000 --- a/js/smoke/tests/deno/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Extracted Braintrust SDK package from build artifacts -# This is created by the install-build script and should not be committed -package/ - -# Deno cache and generated files -.deno/ diff --git a/js/smoke/tests/deno/browser/README.md b/js/smoke/tests/deno/browser/README.md deleted file mode 100644 index 541e193f4..000000000 --- a/js/smoke/tests/deno/browser/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Deno Browser Build Test - -This directory tests the browser build (`braintrust/browser`) in Deno. - -## Dependencies - -The browser build requires these npm packages (marked as `external` in tsup but still imported): - -### Required Dependencies - -- **`uuid`** - Used by `IDGenerator` for generating span and trace IDs - - Could potentially be replaced with `node:crypto.randomUUID()` but would require SDK code changes -- **`zod`** (v3 and v4) - Schema validation, used throughout the SDK - - Core dependency, cannot be removed -- **`mustache`** - Template rendering (default template engine for browser) - - Used by `Prompt` class for template rendering -- **`eventsource-parser`** - Streaming response parsing - - Used by OpenAI/Anthropic wrappers for streaming -- **`@vercel/functions`** - Vercel Edge Runtime utilities - - Used for `waitUntil` in serverless environments -- **`zod-to-json-schema`** - Convert Zod schemas to JSON Schema - - Used for schema serialization - -### Removed Dependencies - -- ~~**`nunjucks`**~~ - **REMOVED** by using `.browser.ts` variants - - The browser build now uses stub implementations that throw errors - - Browser users should use `templateFormat: 'mustache'` instead - -### Why Not Use `node:` Prefix? - -The `node:` prefix only works for **Node.js built-in modules** like `node:fs`, `node:crypto`, `node:path`, etc. - -It does **NOT** work for npm packages like `uuid`, `zod`, `mustache` - these must be resolved from npm via Deno's import map. - -## Build Configuration - -The browser build is configured in `sdk/js/tsup.config.ts` with: - -- `platform: "browser"` - Enables browser-specific optimizations -- `esbuildPlugins: [browserResolvePlugin]` - Resolves `.browser.ts` variants for platform-specific code -- `external: ["zod"]` - Marks zod as external (still needs to be in import map) - -### Browser Variants - -Files with `.browser.ts` extensions provide browser-specific implementations: - -- `src/template/nunjucks-env.browser.ts` - Throws error instead of using nunjucks -- `src/template/nunjucks-utils.browser.ts` - Throws error for nunjucks linting - -The `browserResolvePlugin` in tsup.config.ts automatically resolves these during the browser build. - -## Running Tests - -```bash -# Using deno task -deno task test:shared - -# Or directly -deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,./build --allow-net shared_suite_test.ts -``` - -Note: We use `--no-config` to avoid Deno's workspace detection which can cause issues with the parent pnpm workspace. - -## Updating Lock File - -```bash -deno cache --no-config --import-map=./deno.json --lock=deno.lock --frozen=false shared_suite_test.ts -``` diff --git a/js/smoke/tests/deno/browser/deno.json b/js/smoke/tests/deno/browser/deno.json deleted file mode 100644 index 5e7845d6e..000000000 --- a/js/smoke/tests/deno/browser/deno.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "imports": { - "braintrust/browser": "../build/braintrust/dist/browser.mjs", - "uuid": "npm:uuid@^13.0.0", - "zod/v3": "npm:zod@^3.24.1", - "zod/v4": "npm:zod@^4.1.12" - }, - "tasks": { - "test:shared": "deno test --no-config --import-map=./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts" - } -} diff --git a/js/smoke/tests/deno/browser/deno.lock b/js/smoke/tests/deno/browser/deno.lock deleted file mode 100644 index c66217d4f..000000000 --- a/js/smoke/tests/deno/browser/deno.lock +++ /dev/null @@ -1,59 +0,0 @@ -{ - "version": "5", - "specifiers": { - "jsr:@std/assert@^1.0.14": "1.0.15", - "jsr:@std/internal@^1.0.12": "1.0.12", - "npm:@vercel/functions@^3.3.0": "3.3.4", - "npm:eventsource-parser@^3.0.6": "3.0.6", - "npm:mustache@^4.2.0": "4.2.0", - "npm:uuid@13": "13.0.0", - "npm:zod-to-json-schema@^3.25.0": "3.25.0_zod@3.25.76", - "npm:zod@^3.24.1": "3.25.76", - "npm:zod@^4.1.12": "4.2.1" - }, - "jsr": { - "@std/assert@1.0.15": { - "integrity": "d64018e951dbdfab9777335ecdb000c0b4e3df036984083be219ce5941e4703b", - "dependencies": [ - "jsr:@std/internal" - ] - }, - "@std/internal@1.0.12": { - "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" - } - }, - "npm": { - "@vercel/functions@3.3.4": { - "integrity": "sha512-IoP8Xfr1QeCm+Dv5od3bfPiw/VgLKsA7IBd/88M/Wr421HdbH4b6bW5z8CTxiz1QRpalrPFZcLdMdxu+2hAjZg==", - "dependencies": [ - "@vercel/oidc" - ] - }, - "@vercel/oidc@3.0.5": { - "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==" - }, - "eventsource-parser@3.0.6": { - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==" - }, - "mustache@4.2.0": { - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": true - }, - "uuid@13.0.0": { - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", - "bin": true - }, - "zod-to-json-schema@3.25.0_zod@3.25.76": { - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "dependencies": [ - "zod@3.25.76" - ] - }, - "zod@3.25.76": { - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" - }, - "zod@4.2.1": { - "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==" - } - } -} diff --git a/js/smoke/tests/deno/browser/package.json b/js/smoke/tests/deno/browser/package.json deleted file mode 100644 index f8b400a12..000000000 --- a/js/smoke/tests/deno/browser/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "braintrust-deno-browser-smoke-test", - "version": "1.0.0", - "description": "Smoke test for Braintrust browser build in Deno runtime", - "private": true, - "scripts": { - "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts" - } -} diff --git a/js/smoke/tests/deno/browser/shared_suite_test.ts b/js/smoke/tests/deno/browser/shared_suite_test.ts deleted file mode 100644 index bf78eb8e0..000000000 --- a/js/smoke/tests/deno/browser/shared_suite_test.ts +++ /dev/null @@ -1,63 +0,0 @@ -// @ts-nocheck -/** - * Deno smoke test using shared test suites, but importing the browser build. - */ - -import { assertEquals } from "jsr:@std/assert@^1.0.14"; -import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - type TestResult, -} from "../../../shared/dist/index.mjs"; -import * as braintrust from "braintrust/browser"; - -export async function runSharedTestSuites(): Promise { - const { initLogger, _exportsForTestingOnly } = braintrust; - - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: false, - environment: "browser", - }); - - try { - const importResults = await runImportVerificationTests(braintrust); - const functionalResults = await runBasicLoggingTests(adapters); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - const promptTemplatingResults = await runPromptTemplatingTests( - { Prompt: braintrust.Prompt }, - adapters.environment, - ); - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - const failures = results.filter((r) => !r.success); - if (failures.length > 0) { - for (const failure of failures) { - console.error(` ❌ ${failure.testName}: ${failure.error?.message}`); - } - throw new Error(`${failures.length} test(s) failed`); - } - - return results; - } finally { - await cleanupTestEnvironment(adapters); - } -} - -Deno.test("Run shared test suites (browser build)", async () => { - const results = await runSharedTestSuites(); - assertEquals(results.filter((r) => !r.success).length, 0); - console.log(`\n✅ All ${results.length} tests passed`); -}); diff --git a/js/smoke/tests/deno/node/deno.json b/js/smoke/tests/deno/node/deno.json deleted file mode 100644 index 301391da6..000000000 --- a/js/smoke/tests/deno/node/deno.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "imports": { - "braintrust": "../build/braintrust/dist/index.mjs", - "uuid": "npm:uuid@^13.0.0", - "zod/v3": "npm:zod@^3.24.1", - "zod/v4": "npm:zod@^4.1.12", - "nunjucks": "npm:nunjucks@^3.2.4", - "simple-git": "npm:simple-git@^3.21.0" - }, - "tasks": { - "test:shared": "deno test --config ./deno.json --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts", - "test:legacy": "deno test --config ./deno.json --allow-env --allow-read=.,../build --allow-net span_test.ts" - } -} diff --git a/js/smoke/tests/deno/node/deno.lock b/js/smoke/tests/deno/node/deno.lock deleted file mode 100644 index f134d92a5..000000000 --- a/js/smoke/tests/deno/node/deno.lock +++ /dev/null @@ -1,89 +0,0 @@ -{ - "version": "5", - "specifiers": { - "jsr:@std/assert@^1.0.14": "1.0.15", - "jsr:@std/internal@^1.0.12": "1.0.12", - "npm:@types/node@*": "24.2.0", - "npm:nunjucks@^3.2.4": "3.2.4", - "npm:simple-git@^3.21.0": "3.30.0", - "npm:uuid@13": "13.0.0", - "npm:zod@^3.24.1": "3.25.76", - "npm:zod@^4.1.12": "4.2.1" - }, - "jsr": { - "@std/assert@1.0.15": { - "integrity": "d64018e951dbdfab9777335ecdb000c0b4e3df036984083be219ce5941e4703b", - "dependencies": [ - "jsr:@std/internal" - ] - }, - "@std/internal@1.0.12": { - "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" - } - }, - "npm": { - "@kwsites/file-exists@1.1.1": { - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dependencies": [ - "debug" - ] - }, - "@kwsites/promise-deferred@1.1.1": { - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" - }, - "@types/node@24.2.0": { - "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==", - "dependencies": [ - "undici-types" - ] - }, - "a-sync-waterfall@1.0.1": { - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" - }, - "asap@2.0.6": { - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "commander@5.1.0": { - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, - "debug@4.4.3": { - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": [ - "ms" - ] - }, - "ms@2.1.3": { - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "nunjucks@3.2.4": { - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "dependencies": [ - "a-sync-waterfall", - "asap", - "commander" - ], - "bin": true - }, - "simple-git@3.30.0": { - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "dependencies": [ - "@kwsites/file-exists", - "@kwsites/promise-deferred", - "debug" - ] - }, - "undici-types@7.10.0": { - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" - }, - "uuid@13.0.0": { - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", - "bin": true - }, - "zod@3.25.76": { - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" - }, - "zod@4.2.1": { - "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==" - } - } -} diff --git a/js/smoke/tests/deno/node/package.json b/js/smoke/tests/deno/node/package.json deleted file mode 100644 index c38349cbc..000000000 --- a/js/smoke/tests/deno/node/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "braintrust-deno-node-smoke-test", - "version": "1.0.0", - "description": "Smoke test for Braintrust Node build in Deno runtime", - "private": true, - "scripts": { - "test": "deno test --no-config --import-map=./deno.json --lock=deno.lock --allow-env --allow-read=.,../build --allow-net shared_suite_test.ts span_test.ts" - } -} diff --git a/js/smoke/tests/deno/node/span_test.ts b/js/smoke/tests/deno/node/span_test.ts deleted file mode 100644 index bf31deb82..000000000 --- a/js/smoke/tests/deno/node/span_test.ts +++ /dev/null @@ -1,59 +0,0 @@ -// @ts-nocheck -import { assertEquals } from "jsr:@std/assert@^1.0.14"; -import { - runSpanSmokeTest, - runMustacheTemplateTest, - runNunjucksTemplateTest, -} from "../../span/span_test_helper.ts"; - -/** - * This is a simple test to send a span to the braintrust API - * Uses BRAINTRUST_BUILD_DIR environment variable to import the braintrust package - * ie. BRAINTRUST_BUILD_DIR=./package/dist/index.mjs - */ -export async function runBrowserLoggerSmokeTest() { - const { initLogger, _exportsForTestingOnly, Prompt } = await import( - "braintrust" - ); - - const events = await runSpanSmokeTest({ - initLogger, - testingExports: _exportsForTestingOnly, - projectName: "deno-browser-logger", - }); - - assertEquals(events.length, 1, "Exactly one span should be captured"); - const event = events[0]; - - assertEquals(event.input, "What is the capital of France?"); - assertEquals(event.output, "Paris"); - assertEquals(event.expected, "Paris"); - - console.log("Deno smoke test passed"); - - // Test mustache template with simple variable - const mustacheResult = runMustacheTemplateTest(Prompt); - - assertEquals( - mustacheResult.messages[0]?.content, - "Hello, World!", - "Mustache template should render simple variable", - ); - - console.log("Mustache template test passed"); - - // Test nunjucks template with loop - const nunjucksResult = runNunjucksTemplateTest(Prompt); - - assertEquals( - nunjucksResult.messages[0]?.content, - "Items: apple, banana, cherry", - "Nunjucks template should render loop correctly", - ); - - console.log("Nunjucks template test passed"); -} - -Deno.test("Create a span", async () => { - await runBrowserLoggerSmokeTest(); -}); diff --git a/js/smoke/tests/deno/package-lock.json b/js/smoke/tests/deno/package-lock.json deleted file mode 100644 index 387929984..000000000 --- a/js/smoke/tests/deno/package-lock.json +++ /dev/null @@ -1,2069 +0,0 @@ -{ - "name": "braintrust-deno-smoke-test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-deno-smoke-test", - "version": "1.0.0", - "dependencies": { - "braintrust": "file:../../../artifacts/braintrust-1.1.3.tgz" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", - "license": "MIT" - }, - "node_modules/@types/nunjucks": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", - "license": "MIT" - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT" - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "1.1.3", - "resolved": "file:../../../artifacts/braintrust-1.1.3.tgz", - "integrity": "sha512-Wk60/ZGeMOmKF+8QpAxSGXVJoi1andEIdCXU8pqez8jYgbDtyK6H2+S1N6ww6rfmnzEDTHxbynA3rUnOWhEYJg==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@types/nunjucks": "^3.2.6", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "nunjucks": "^3.2.4", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "source-map": "^0.7.4", - "termi-link": "^1.0.1", - "uuid": "^9.0.1", - "zod": "^3.25.34", - "zod-to-json-schema": "^3.22.5" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT" - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT" - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "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==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "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/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "license": "BSD-2-Clause", - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/termi-link": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/deno/package.json b/js/smoke/tests/deno/package.json deleted file mode 100644 index 572a9f3fe..000000000 --- a/js/smoke/tests/deno/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "braintrust-deno-smoke-test", - "version": "1.0.0", - "description": "Smoke test for Braintrust SDK in Deno runtime", - "private": true, - "scripts": { - "test": "npm run test:node && npm run test:browser", - "test:node": "cd node && npm test", - "test:browser": "cd browser && npm test" - } -} diff --git a/js/smoke/tests/nextjs-instrumentation/.gitignore b/js/smoke/tests/nextjs-instrumentation/.gitignore deleted file mode 100644 index 7d88bbef8..000000000 --- a/js/smoke/tests/nextjs-instrumentation/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# dependencies -node_modules/ - -# next.js -.next/ -out/ - -# build -dist/ - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* - -# typescript -*.tsbuildinfo -next-env.d.ts - -# backup files from smoke test scripts -package.json.bak diff --git a/js/smoke/tests/nextjs-instrumentation/README.md b/js/smoke/tests/nextjs-instrumentation/README.md deleted file mode 100644 index 7ddee33e5..000000000 --- a/js/smoke/tests/nextjs-instrumentation/README.md +++ /dev/null @@ -1,176 +0,0 @@ -# Next.js Instrumentation Smoke Test - -This smoke test verifies that `braintrust` and `@braintrust/otel` work correctly -in a Next.js application. It includes two types of tests: - -1. **Build-time verification** - Tests webpack bundling and import resolution -2. **Runtime testing** - Tests actual SDK functionality in both Edge and Node.js runtimes - -## What This Tests - -### Build-Time Tests (`npm run build`) - -Next.js performs static analysis of imports during the build process. This can -catch export issues that runtime-only tests miss. Specifically, this test catches: - -- Missing exports from `braintrust` that `@braintrust/otel` depends on -- Module resolution issues in webpack/turbopack bundling -- ESM/CJS interoperability problems in the Next.js environment -- Tree-shaking issues with the shared test package - -### Runtime Tests (`npm run test:shared`) - -Tests the SDK in both Next.js runtime environments via API routes: - -**Edge Runtime** (`/api/smoke-test/edge`): - -- Runs in V8 isolates (same as Cloudflare Workers) -- No filesystem, no Node.js APIs -- Tests: 16+ (13 import verification + 3 functional) - -**Node.js Runtime** (`/api/smoke-test/node`): - -- Runs in full Node.js environment -- Standard Next.js API route runtime -- Tests: 16+ (13 import verification + 3 functional) - -Both runtimes verify all SDK exports are available and test basic functionality. - -## The Bug This Catches - -This test was created to catch an issue where Next.js reported: - -``` -Attempted import error: 'IDGenerator' is not exported from 'braintrust' (imported as 'IDGenerator'). -``` - -This error occurs because Next.js's webpack bundler performs static analysis of -the import/export graph, which can detect export mismatches that Node.js's runtime -resolution might not catch. The `@braintrust/otel` package imports `IDGenerator` -from `braintrust`, but Next.js's bundler cannot resolve this export. - -## How to Run - -### Build-Time Test (Quick) - -Tests webpack bundling and import resolution: - -```bash -# Clean install -rm -rf node_modules package-lock.json -npm install --legacy-peer-deps - -# Run build test -npm test -# or -npm run build -``` - -### Runtime Test (Comprehensive) - -Runs the full shared test suite in both Edge and Node.js runtimes: - -```bash -# Make sure shared package is built first -cd ../../shared && npm run build && cd - - -# Run runtime tests (tests both Edge and Node.js runtimes) -npm run test:shared -``` - -This will: - -1. Start the Next.js dev server -2. Wait for it to be ready -3. Call `GET /api/smoke-test/edge` endpoint (Edge Runtime) -4. Call `GET /api/smoke-test/node` endpoint (Node.js Runtime) -5. Display test results for both -6. Stop the server - -For CI with local build artifacts: - -```bash -npm run install-build -npm test # Build test -npm run test:shared # Runtime test -``` - -## Test Structure - -- `instrumentation.ts` - Next.js instrumentation file with import verification -- `app/api/smoke-test/edge/route.ts` - Edge Runtime API route (V8 isolates) -- `app/api/smoke-test/node/route.ts` - Node.js Runtime API route -- `test-api-routes.mjs` - Test runner script (starts server, calls both endpoints) -- `app/` - Minimal Next.js app router setup -- `next.config.mjs` - Enables the experimental instrumentation hook - -## Success Criteria - -### Build Test - -The test passes if `next build` completes without import/export errors. -Warnings about optional dependencies (like `@opentelemetry/exporter-jaeger`) are acceptable. - -### Runtime Test - -The test passes if: - -- Dev server starts successfully -- `/api/smoke-test/edge` endpoint returns HTTP 200 with all tests passing -- `/api/smoke-test/node` endpoint returns HTTP 200 with all tests passing -- Both runtimes run 16+ tests (13 import verification + 3 functional) -- Both responses show `"success": true` - -## Expected Output - -### Build Test - -``` -✓ Compiled successfully -✓ Linting and checking validity of types -✓ Creating an optimized production build -``` - -### Runtime Test - -``` -Next.js API Routes Test -============================================================ - -Starting Next.js dev server... - -✓ Dev server ready - -✓ Server is responding - -============================================================ -Running Tests -============================================================ - -Testing Edge Runtime... - URL: http://localhost:3000/api/smoke-test/edge - Status: 200 - Runtime: edge - Message: All 16 tests passed in Edge Runtime - Tests: 16/16 passed - Result: ✅ PASS - -Testing Node.js Runtime... - URL: http://localhost:3000/api/smoke-test/node - Status: 200 - Runtime: nodejs - Message: All 16 tests passed in Node.js Runtime - Tests: 16/16 passed - Result: ✅ PASS - -============================================================ -Summary -============================================================ - -Edge Runtime: ✅ PASS -Node.js Runtime: ✅ PASS - -✅ All tests passed! - -Stopping dev server... -``` diff --git a/js/smoke/tests/nextjs-instrumentation/package-lock.json b/js/smoke/tests/nextjs-instrumentation/package-lock.json deleted file mode 100644 index a78c1825e..000000000 --- a/js/smoke/tests/nextjs-instrumentation/package-lock.json +++ /dev/null @@ -1,3305 +0,0 @@ -{ - "name": "braintrust-nextjs-instrumentation-test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-nextjs-instrumentation-test", - "version": "1.0.0", - "dependencies": { - "@braintrust/otel": "latest", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/api-logs": "^0.200.0", - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.200.0", - "@opentelemetry/instrumentation": "^0.200.0", - "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/sdk-logs": "^0.200.0", - "@opentelemetry/sdk-metrics": "^2.0.0", - "@opentelemetry/sdk-trace-base": "^2.0.0", - "@vercel/otel": "^2.1.0", - "braintrust": "latest", - "next": "14.2.34", - "react": "^18", - "react-dom": "^18", - "zod": "^4.1.13" - }, - "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "tsx": "^4.19.2", - "typescript": "^5" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@braintrust/otel": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@braintrust/otel/-/otel-0.1.0.tgz", - "integrity": "sha512-lWsxgCNJibxhm2CauaboLcmro+4X6yA2GH6Jn7xpErYyLdAPE1svoIqkUwxOVcslQfHKi/o1+eoLW4qJ74Y9xQ==", - "license": "MIT", - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0", - "@opentelemetry/core": ">=1.9.0", - "@opentelemetry/exporter-trace-otlp-http": ">=0.35.0", - "@opentelemetry/sdk-trace-base": ">=1.9.0", - "braintrust": ">=1.0.0-0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": false - }, - "@opentelemetry/core": { - "optional": false - }, - "@opentelemetry/exporter-trace-otlp-http": { - "optional": false - }, - "@opentelemetry/sdk-trace-base": { - "optional": false - }, - "braintrust": { - "optional": false - } - } - }, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", - "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", - "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", - "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", - "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", - "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", - "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", - "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", - "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", - "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", - "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", - "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", - "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", - "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", - "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", - "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", - "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", - "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", - "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", - "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", - "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", - "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", - "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", - "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", - "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", - "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", - "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.34", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.34.tgz", - "integrity": "sha512-iuGW/UM+EZbn2dm+aLx+avo1rVap+ASoFr7oLpTBVW2G2DqhD5l8Fme9IsLZ6TTsp0ozVSFswidiHK1NGNO+pg==", - "license": "MIT" - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", - "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", - "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", - "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", - "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", - "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", - "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", - "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", - "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", - "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.200.0.tgz", - "integrity": "sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/core": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz", - "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.200.0.tgz", - "integrity": "sha512-Goi//m/7ZHeUedxTGVmEzH19NgqJY+Bzr6zXo1Rni1+hwqaksEyJ44gdlEMREu6dzX1DlAaH/qSykSVzdrdafA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/otlp-exporter-base": "0.200.0", - "@opentelemetry/otlp-transformer": "0.200.0", - "@opentelemetry/resources": "2.0.0", - "@opentelemetry/sdk-trace-base": "2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", - "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/resources": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", - "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.0.tgz", - "integrity": "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/resources": "2.0.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.200.0.tgz", - "integrity": "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.200.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "shimmer": "^1.2.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.200.0.tgz", - "integrity": "sha512-IxJgA3FD7q4V6gGq4bnmQM5nTIyMDkoGFGrBrrDjB6onEiq1pafma55V+bHvGYLWvcqbBbRfezr1GED88lacEQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/otlp-transformer": "0.200.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", - "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.200.0.tgz", - "integrity": "sha512-+9YDZbYybOnv7sWzebWOeK6gKyt2XE7iarSyBFkwwnP559pEevKOUD8NyDHhRjCSp13ybh9iVXlMfcj/DwF/yw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.200.0", - "@opentelemetry/core": "2.0.0", - "@opentelemetry/resources": "2.0.0", - "@opentelemetry/sdk-logs": "0.200.0", - "@opentelemetry/sdk-metrics": "2.0.0", - "@opentelemetry/sdk-trace-base": "2.0.0", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", - "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", - "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.0.tgz", - "integrity": "sha512-Bvy8QDjO05umd0+j+gDeWcTaVa1/R2lDj/eOvjzpm8VQj1K1vVZJuyjThpV5/lSHyYW2JaHF2IQ7Z8twJFAhjA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/resources": "2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.0.tgz", - "integrity": "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/resources": "2.0.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.200.0.tgz", - "integrity": "sha512-VZG870063NLfObmQQNtCVcdXXLzI3vOjjrRENmU37HYiPFa0ZXpXVDsTD02Nh3AT3xYJzQaWKl2X2lQ2l7TWJA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.200.0", - "@opentelemetry/core": "2.0.0", - "@opentelemetry/resources": "2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", - "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", - "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.0.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz", - "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", - "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz", - "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, - "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" - } - }, - "node_modules/@types/node": { - "version": "20.19.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", - "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", - "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", - "license": "MIT" - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/@vercel/otel": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vercel/otel/-/otel-2.1.0.tgz", - "integrity": "sha512-Zwu2Cu4t46DzBnY1DQSTxZ4MBLVfYsOjnlWuZuLRWnmVPX+SNrVHbs3ssiJ6uvY1J1JJswor4zSn8mHYxzYeBA==", - "license": "MIT", - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <2.0.0", - "@opentelemetry/api-logs": ">=0.200.0 <0.300.0", - "@opentelemetry/instrumentation": ">=0.200.0 <0.300.0", - "@opentelemetry/resources": ">=2.0.0 <3.0.0", - "@opentelemetry/sdk-logs": ">=0.200.0 <0.300.0", - "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", - "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/boxen/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-1.0.0.tgz", - "integrity": "sha512-YigO8F32F4l5RoaFlJE72VXWXPMSjqqmaum4BKI94TR7RaywQjirMAU4HtNE7+7NpUhTViLnY4RL2p/JMSH/pg==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "slugify": "^1.6.6", - "source-map": "^0.7.4", - "uuid": "^9.0.1", - "zod": "^3.25.34", - "zod-to-json-schema": "^3.22.5" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34" - } - }, - "node_modules/braintrust/node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001757", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", - "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", - "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==", - "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/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==", - "license": "MIT" - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "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==", - "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==", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", - "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.1", - "@esbuild/android-arm": "0.27.1", - "@esbuild/android-arm64": "0.27.1", - "@esbuild/android-x64": "0.27.1", - "@esbuild/darwin-arm64": "0.27.1", - "@esbuild/darwin-x64": "0.27.1", - "@esbuild/freebsd-arm64": "0.27.1", - "@esbuild/freebsd-x64": "0.27.1", - "@esbuild/linux-arm": "0.27.1", - "@esbuild/linux-arm64": "0.27.1", - "@esbuild/linux-ia32": "0.27.1", - "@esbuild/linux-loong64": "0.27.1", - "@esbuild/linux-mips64el": "0.27.1", - "@esbuild/linux-ppc64": "0.27.1", - "@esbuild/linux-riscv64": "0.27.1", - "@esbuild/linux-s390x": "0.27.1", - "@esbuild/linux-x64": "0.27.1", - "@esbuild/netbsd-arm64": "0.27.1", - "@esbuild/netbsd-x64": "0.27.1", - "@esbuild/openbsd-arm64": "0.27.1", - "@esbuild/openbsd-x64": "0.27.1", - "@esbuild/openharmony-arm64": "0.27.1", - "@esbuild/sunos-x64": "0.27.1", - "@esbuild/win32-arm64": "0.27.1", - "@esbuild/win32-ia32": "0.27.1", - "@esbuild/win32-x64": "0.27.1" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/import-in-the-middle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", - "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", - "license": "Apache-2.0", - "dependencies": { - "acorn": "^8.14.0", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next": { - "version": "14.2.34", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.34.tgz", - "integrity": "sha512-s7mRraWlkEVRLjHHdu5khn0bSnmUh+U+YtigBc+t2Ge7jJHFIVBZna+W9Jcx7b04HhM7eJWrNJ2A+sQs9gJ3eg==", - "license": "MIT", - "dependencies": { - "@next/env": "14.2.34", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", - "postcss": "8.4.31", - "styled-jsx": "5.1.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=18.17.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.33", - "@next/swc-darwin-x64": "14.2.33", - "@next/swc-linux-arm64-gnu": "14.2.33", - "@next/swc-linux-arm64-musl": "14.2.33", - "@next/swc-linux-x64-gnu": "14.2.33", - "@next/swc-linux-x64-musl": "14.2.33", - "@next/swc-win32-arm64-msvc": "14.2.33", - "@next/swc-win32-ia32-msvc": "14.2.33", - "@next/swc-win32-x64-msvc": "14.2.33" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "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==", - "license": "ISC" - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/require-in-the-middle/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/require-in-the-middle/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==", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/send": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", - "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/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==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "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==", - "license": "0BSD" - }, - "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": { - "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/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/zod": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/otel-v1/README.md b/js/smoke/tests/otel-v1/README.md deleted file mode 100644 index 33d152260..000000000 --- a/js/smoke/tests/otel-v1/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Running the OTEL v1 Integration Test Locally - -## Prerequisites - -1. Build and pack `braintrust`: - - ```bash - cd js - npm run build - mkdir -p artifacts - npm pack --pack-destination artifacts - ``` - -2. Build and pack `@braintrust/otel`: - ```bash - cd ../../integrations/otel-js - npm run build - npm pack --pack-destination ../../js/artifacts - ``` - -## Running the Test - -1. Navigate to the test directory: - - ```bash - cd js/smoke/tests/otel-v1 - ``` - -2. Install dependencies and local packages: - - ```bash - npm run install-build - ``` - - This will: - - - Install regular dependencies - - Install `braintrust` from `js/artifacts/` - - Install `@braintrust/otel` from `js/artifacts/` (or build it if not found) - -3. Run the test: - ```bash - npm start - ``` - -## Troubleshooting - -- If you get "Cannot find module '@braintrust/otel'", make sure you ran `npm run install-build` first -- If artifacts directory is empty, make sure you built and packed both packages (see Prerequisites) -- The `install-build` script will automatically build `@braintrust/otel` if it's not in artifacts diff --git a/js/smoke/tests/otel-v1/otel_example.ts b/js/smoke/tests/otel-v1/otel_example.ts deleted file mode 100644 index bb0eb9570..000000000 --- a/js/smoke/tests/otel-v1/otel_example.ts +++ /dev/null @@ -1,150 +0,0 @@ -/** -This test is a simple test to verify the braintrust otel and braintrust package can work be used to send spans using OpenTelemetry to the braintrust API. - -This test is not written as a vitest because it needs to be run as CommonJS and ESM. Vitest does not support running both modes. -**/ - -import assert from "node:assert/strict"; -import process from "node:process"; -import { setTimeout as delay } from "node:timers/promises"; -import { createServer } from "node:http"; -import type { AddressInfo } from "node:net"; - -import { trace } from "@opentelemetry/api"; -import { NodeSDK } from "@opentelemetry/sdk-node"; -import type { SpanProcessor } from "@opentelemetry/sdk-trace-base"; - -import { - TestBackgroundLogger, - initLogger, - _exportsForTestingOnly, -} from "braintrust"; -import { BraintrustSpanProcessor } from "@braintrust/otel"; - -type OtelExportPayload = { - resourceSpans?: Array<{ - scopeSpans?: Array<{ - spans?: Array<{ - name?: string; - attributes?: Array<{ key?: string; value?: { stringValue?: string } }>; - }>; - }>; - }>; -}; - -function flattenSpans(payloads: OtelExportPayload[]) { - return payloads.flatMap( - (payload) => - payload.resourceSpans?.flatMap( - (resourceSpan) => - resourceSpan.scopeSpans?.flatMap( - (scopeSpan) => scopeSpan.spans ?? [], - ) ?? [], - ) ?? [], - ); -} - -async function main() { - const receivedPayloads: OtelExportPayload[] = []; - - const otlpServer = createServer((req, res) => { - if (req.method === "POST" && req.url === "/otel/v1/traces") { - const chunks: Buffer[] = []; - req.on("data", (chunk) => chunks.push(chunk)); - req.on("end", () => { - try { - const body = Buffer.concat(chunks).toString(); - if (body.length > 0) { - receivedPayloads.push(JSON.parse(body)); - } - } catch (error) { - res.writeHead(500).end(); - throw error; - } - res.writeHead(200).end(); - }); - return; - } - - res.writeHead(404).end(); - }); - - const collectorUrl = await new Promise((resolve) => { - otlpServer.listen(0, "127.0.0.1", () => { - const addressInfo = otlpServer.address() as AddressInfo; - resolve(`http://127.0.0.1:${addressInfo.port}/`); - }); - }); - - const previousApiUrl = process.env.BRAINTRUST_API_URL; - process.env.BRAINTRUST_API_URL = collectorUrl; - - try { - const sdk = new NodeSDK({ - serviceName: "my-service", - spanProcessor: new BraintrustSpanProcessor({ - filterAISpans: true, - }) as unknown as SpanProcessor, - }); - - await sdk.start(); - - try { - const tracer = trace.getTracer("my-tracer", "1.0.0"); - await tracer.startActiveSpan("otel-v1.example", async (rootSpan) => { - rootSpan.setAttributes({ - "user.request": "my-request", - "request.timestamp": new Date( - "2025-01-01T00:00:00.000Z", - ).toISOString(), - }); - - await tracer.startActiveSpan("ai.span", async (aiSpan) => { - aiSpan.setAttributes({ model: "gpt-4o-mini" }); - aiSpan.end(); - }); - - await tracer.startActiveSpan("logging span", async (span) => { - span.end(); - }); - - rootSpan.end(); - }); - } finally { - await sdk.shutdown(); - } - - await delay(50); - - const exportedSpans = flattenSpans(receivedPayloads); - assert.ok( - exportedSpans.length > 0, - "No spans were exported to the collector", - ); - - const names = exportedSpans - .map((span) => span.name) - .filter((name): name is string => typeof name === "string"); - - assert.ok(!names.includes("otel-v1.example"), "root span included"); - assert.ok( - names.includes("ai.span"), - "AI span should exist in exported spans", - ); - assert.ok( - !names.includes("logging span"), - "Logging span should have been filtered", - ); - } finally { - process.env.BRAINTRUST_API_URL = previousApiUrl; - await new Promise((resolve, reject) => { - otlpServer.close((err) => (err ? reject(err) : resolve())); - }); - } - console.log("Otel v1 example passed"); -} - -main().catch((error) => { - console.log("Otel v1 example failed:", error); - process.exitCode = 1; -}); diff --git a/js/smoke/tests/otel-v1/package-lock.json b/js/smoke/tests/otel-v1/package-lock.json deleted file mode 100644 index e0cd55af4..000000000 --- a/js/smoke/tests/otel-v1/package-lock.json +++ /dev/null @@ -1,3253 +0,0 @@ -{ - "name": "braintrust-otel-v1-example", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-otel-v1-example", - "version": "1.0.0", - "dependencies": { - "@opentelemetry/api": "1.9.0", - "@opentelemetry/context-async-hooks": "1.9.0", - "@opentelemetry/core": "1.9.0", - "@opentelemetry/exporter-trace-otlp-http": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-node": "0.35.0", - "@opentelemetry/sdk-trace-base": "1.9.0", - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@types/node": "^20.10.5", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.1.tgz", - "integrity": "sha512-sPxgEWtPUR3EnRJCEtbGZG2iX8LQDUls2wUS3o27jg07KqJFMq6YDeWvMo1wfpmy3rqRdS0rivpLwhqQtEyCuQ==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.8.0", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.5.3", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.33.tgz", - "integrity": "sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==", - "license": "MIT" - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", - "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.9.0.tgz", - "integrity": "sha512-Ur+TgRmJgAEvg6VQuhkqzsWsqoOtr+QSZ8r8Yf6WrvlZpAl/sdRU+yUXWjA7r8JFS9VbBq7IEp7oMStFuJT2ow==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/core": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.9.0.tgz", - "integrity": "sha512-Koy1ApRUp5DB5KpOqhDk0JjO9x6QeEkmcePl8qQDsXZGF4MuHUBShXibd+J2tRNckTsvgEHi1uEuUckDgN+c/A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-jaeger": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-jaeger/-/exporter-jaeger-1.9.0.tgz", - "integrity": "sha512-XLsDLuTqQyw08s0n03zeqmz2ike/iQHiep819SJliJnJJKMbGta+JvaWWgrh/YUEYlbBLc/mQP1cndXtd8lbaA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0", - "jaeger-client": "^3.15.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.35.0.tgz", - "integrity": "sha512-T3g2u/GJ+mnRTEmKYivjnI4dEYZIqA+z85WovHzOxU2/Em8GJk1/NJ2U6ORJUYrgOlN12QZ/tCGrWsg3q9nyBA==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.9.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.35.0", - "@opentelemetry/otlp-transformer": "0.35.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.35.0.tgz", - "integrity": "sha512-XjxX6RLHYKadQNEVs7TT7YRwEhXzP8itLiu6en2P7HukSg0gTwOMhNzriBZBRC4q+HVsdnncWua1wCD1TBAfmg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-metrics": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.9.0.tgz", - "integrity": "sha512-fSlJWhp86kCan1zuxdH6LTyUBYlohQwDKnxep5qHMnRTNErkYmdjgsmjZvSMdAfUFtQqfZmTXe2Lap7a5AIf9Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "lodash.merge": "4.6.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.9.0.tgz", - "integrity": "sha512-zCyien0p3XWarU6zv72c/JZ6QlG5QW/hc61Nh5TSR1K9ndnljzAGrH55x4nfyQdubfoh9QxLNh9FXH0fWK6vcg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.57.2.tgz", - "integrity": "sha512-sB/gkSYFu+0w2dVQ0PWY9fAMl172PKMZ/JrHkkW8dmjCL0CYkmXeE+ssqIL/yBUTPOvpLIpenX5T9RwXRBW/3g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", - "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.35.0.tgz", - "integrity": "sha512-B2Evc3h8MopqwvljFDpTZyWe9PPVbYKxFEOpN5cls84GtYDsveHchCwiSG98liOqTQHORVNsz8lvLRNoK/J+Tw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/otlp-exporter-base": "0.35.0", - "@opentelemetry/otlp-proto-exporter-base": "0.35.0", - "@opentelemetry/otlp-transformer": "0.35.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.35.0.tgz", - "integrity": "sha512-ybXq1Dvg38ZwiNCtqRCRmJ93rP7jMhL8nHEYVXNKknPVplUoY9fsb8tCPi24iY1suAD98wAMy3hiHk4W8VqfSg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.35.0.tgz", - "integrity": "sha512-XjxX6RLHYKadQNEVs7TT7YRwEhXzP8itLiu6en2P7HukSg0gTwOMhNzriBZBRC4q+HVsdnncWua1wCD1TBAfmg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-metrics": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.9.0.tgz", - "integrity": "sha512-fSlJWhp86kCan1zuxdH6LTyUBYlohQwDKnxep5qHMnRTNErkYmdjgsmjZvSMdAfUFtQqfZmTXe2Lap7a5AIf9Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "lodash.merge": "4.6.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.9.0.tgz", - "integrity": "sha512-zCyien0p3XWarU6zv72c/JZ6QlG5QW/hc61Nh5TSR1K9ndnljzAGrH55x4nfyQdubfoh9QxLNh9FXH0fWK6vcg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.9.0.tgz", - "integrity": "sha512-+AghaRdhSritrXmB/zoreOheNVuDOWOy/LK/W4odCRtkM/WprpHCOVj5eN8/zqg0LVeE9AbVMODk//eR0lu2fA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.9.0.tgz", - "integrity": "sha512-zCyien0p3XWarU6zv72c/JZ6QlG5QW/hc61Nh5TSR1K9ndnljzAGrH55x4nfyQdubfoh9QxLNh9FXH0fWK6vcg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.35.0.tgz", - "integrity": "sha512-pQ5shVG53acTtq72DF7kx+4690ZKh3lATMRqf2JDMRvn0bcX/JaQ+NjPmt7oyT3h9brMA1rSFMVFS6yj8kd2OQ==", - "license": "Apache-2.0", - "dependencies": { - "require-in-the-middle": "^5.0.3", - "semver": "^7.3.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.57.2.tgz", - "integrity": "sha512-XdxEzL23Urhidyebg5E6jZoaiW5ygP/mRjxLHixogbqwDy2Faduzb5N0o/Oi+XTIJu+iyxXdVORjXax+Qgfxag==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-transformer": "0.57.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.35.0.tgz", - "integrity": "sha512-Tpk3+LC4eWbFO/QOwPcJAImQaG0hAVIhkLYo76RJCgxVSxbIcj6PzUwBEsCiw/M4dNFtx7886cy8+45FKZoJ1g==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@grpc/proto-loader": "^0.7.3", - "@opentelemetry/core": "1.9.0", - "@opentelemetry/otlp-exporter-base": "0.35.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.35.0.tgz", - "integrity": "sha512-ybXq1Dvg38ZwiNCtqRCRmJ93rP7jMhL8nHEYVXNKknPVplUoY9fsb8tCPi24iY1suAD98wAMy3hiHk4W8VqfSg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/otlp-proto-exporter-base": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-proto-exporter-base/-/otlp-proto-exporter-base-0.35.0.tgz", - "integrity": "sha512-yJhHeqh0tU/3vzPbFD0mVrlQe+ccrE9LShy5YlXk9RB9x/RXkSU5uNdKmOgmQU+6CSMZYporJYviUNE5knnYHQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/otlp-exporter-base": "0.35.0", - "protobufjs": "^7.1.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/otlp-proto-exporter-base/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.35.0.tgz", - "integrity": "sha512-ybXq1Dvg38ZwiNCtqRCRmJ93rP7jMhL8nHEYVXNKknPVplUoY9fsb8tCPi24iY1suAD98wAMy3hiHk4W8VqfSg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.57.2.tgz", - "integrity": "sha512-48IIRj49gbQVK52jYsw70+Jv+JbahT8BqT2Th7C4H7RCM9d0gZ5sgNPoMpWldmfjvIsSgiGJtjfk9MeZvjhoig==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-logs": "0.57.2", - "@opentelemetry/sdk-metrics": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", - "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", - "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.57.2.tgz", - "integrity": "sha512-TXFHJ5c+BKggWbdEQ/inpgIzEmS2BGQowLE9UhsMd7YYlUfBQJ4uax0VF/B5NYigdM/75OoJGhAV3upEhK+3gg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", - "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-node": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.35.0.tgz", - "integrity": "sha512-fascA8taT4CRCGLAjxiXlOcJmbSZxe5YN3PogmAZnm1sAxbR01ejWImyOx2YSmVjQXfyBkMKtKgsIqOENnh+KA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/exporter-jaeger": "1.9.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.35.0", - "@opentelemetry/exporter-trace-otlp-http": "0.35.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.35.0", - "@opentelemetry/exporter-zipkin": "1.9.0", - "@opentelemetry/instrumentation": "0.35.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-metrics": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0", - "@opentelemetry/sdk-trace-node": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.35.0.tgz", - "integrity": "sha512-wb5XqkTYq0uES65gIyjF5WZjUZooog/Dd2eP+AKOGJ9n5eewvvLjebC9qmFm0ZjHsTw7hzxnQVX/CvhD3NeVHw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/otlp-exporter-base": "0.35.0", - "@opentelemetry/otlp-transformer": "0.35.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.35.0.tgz", - "integrity": "sha512-XjxX6RLHYKadQNEVs7TT7YRwEhXzP8itLiu6en2P7HukSg0gTwOMhNzriBZBRC4q+HVsdnncWua1wCD1TBAfmg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/sdk-metrics": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.35.0.tgz", - "integrity": "sha512-ybXq1Dvg38ZwiNCtqRCRmJ93rP7jMhL8nHEYVXNKknPVplUoY9fsb8tCPi24iY1suAD98wAMy3hiHk4W8VqfSg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.9.0.tgz", - "integrity": "sha512-zCyien0p3XWarU6zv72c/JZ6QlG5QW/hc61Nh5TSR1K9ndnljzAGrH55x4nfyQdubfoh9QxLNh9FXH0fWK6vcg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-metrics": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.9.0.tgz", - "integrity": "sha512-fSlJWhp86kCan1zuxdH6LTyUBYlohQwDKnxep5qHMnRTNErkYmdjgsmjZvSMdAfUFtQqfZmTXe2Lap7a5AIf9Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "lodash.merge": "4.6.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.9.0.tgz", - "integrity": "sha512-VTpjiqGQ4s8f0/szgZmVrtNSSmXFNoHwC4PNVwXyNeEqQcqyAygHvobpUG6m7qCiBFh6ZtrCuLdhhqWE04Objw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/context-async-hooks": "1.9.0", - "@opentelemetry/core": "1.9.0", - "@opentelemetry/propagator-b3": "1.9.0", - "@opentelemetry/propagator-jaeger": "1.9.0", - "@opentelemetry/sdk-trace-base": "1.9.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/propagator-b3": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.9.0.tgz", - "integrity": "sha512-5M/NvJj7ZHZXEU8lkAFhrSrWaHmCCkFLstNbL8p16qpTn1AOZowuSjMOYRoJJBmL5PUobkZ3W8Gjov1UgldPBg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.9.0.tgz", - "integrity": "sha512-oo8RyuyzEbbXdIfeEG9iA5vmTH4Kld+dZMIZICd5G5SmeNcNes3sLrparpunIGms41wIP2mWiIlcOelDCmGceg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.9.0.tgz", - "integrity": "sha512-glNgtJjxAIrDku8DG5Xu3nBK25rT+hkyg7yuXh8RUurp/4BcsXjMyVqpyJvb2kg+lxAX73VJBhncRKGHn9t8QQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/resources": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.9.0.tgz", - "integrity": "sha512-zCyien0p3XWarU6zv72c/JZ6QlG5QW/hc61Nh5TSR1K9ndnljzAGrH55x4nfyQdubfoh9QxLNh9FXH0fWK6vcg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.9.0", - "@opentelemetry/semantic-conventions": "1.9.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.9.0.tgz", - "integrity": "sha512-po7penSfQ/Z8352lRVDpaBrd9znwA5mHGqXR7nDEiVnxkDFkBIhVf/tKeAJDIq/erFpcRowKFeCsr5eqqcSyFQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@types/node": { - "version": "20.19.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", - "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-color": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-color/-/ansi-color-0.2.1.tgz", - "integrity": "sha512-bF6xLaZBLpOQzgYUtYEhJx090nPSZk1BQ/q2oyBK9aMMcJHzx9uXGCjI2Y+LebsN4Jwoykr0V9whbPiogdyHoQ==", - "engines": { - "node": "*" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-0.4.9.tgz", - "integrity": "sha512-Gyd2Zp/KoWZ26DV/rl+j2TzVR3TCPMFwrUOwTqTt+GN+oqxO1v/SR9pUFovc7TuJdsLzPp0pw0svm7NN10XnDw==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.25.10", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "slugify": "^1.6.6", - "source-map": "^0.7.4", - "uuid": "^9.0.1", - "zod": "^3.25.34", - "zod-to-json-schema": "^3.22.5" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34" - } - }, - "node_modules/bufrw": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/bufrw/-/bufrw-1.4.0.tgz", - "integrity": "sha512-sWm8iPbqvL9+5SiYxXH73UOkyEbGQg7kyHQmReF89WJHQJw2eV4P/yZ0E+b71cczJ4pPobVhXxgQcmfSTgGHxQ==", - "dependencies": { - "ansi-color": "^0.2.1", - "error": "^7.0.0", - "hexer": "^1.5.0", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.10.x" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "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==", - "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==", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/error": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", - "integrity": "sha512-UtVv4l5MhijsYUxPJo4390gzfZvAnTHreNnDjnTZaKIiZ/SemXxAhBkYSKtWa5RtBXbLP8tMgn/n0RUa/H7jXw==", - "dependencies": { - "string-template": "~0.2.1", - "xtend": "~4.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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hexer": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/hexer/-/hexer-1.5.0.tgz", - "integrity": "sha512-dyrPC8KzBzUJ19QTIo1gXNqIISRXQ0NwteW6OeQHRN4ZuZeHkdODfj0zHBdOlHbRY8GqbqK57C9oWSvQZizFsg==", - "dependencies": { - "ansi-color": "^0.2.1", - "minimist": "^1.1.0", - "process": "^0.10.0", - "xtend": "^4.0.0" - }, - "bin": { - "hexer": "cli.js" - }, - "engines": { - "node": ">= 0.10.x" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jaeger-client": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/jaeger-client/-/jaeger-client-3.19.0.tgz", - "integrity": "sha512-M0c7cKHmdyEUtjemnJyx/y9uX16XHocL46yQvyqDlPdvAcwPDbHrIbKjQdBqtiE4apQ/9dmr+ZLJYYPGnurgpw==", - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0", - "opentracing": "^0.14.4", - "thriftrw": "^3.5.0", - "uuid": "^8.3.2", - "xorshift": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jaeger-client/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "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==", - "license": "MIT" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/opentracing": { - "version": "0.14.7", - "resolved": "https://registry.npmjs.org/opentracing/-/opentracing-0.14.7.tgz", - "integrity": "sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/process": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/process/-/process-0.10.1.tgz", - "integrity": "sha512-dyIett8dgGIZ/TXKUzeYExt7WA6ldDzys9vTDU/cCA9L17Ypme+KzS+NjQCjpn9xsvi/shbMC+yP/BcFMBz0NA==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-in-the-middle": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", - "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/require-in-the-middle/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/require-in-the-middle/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==", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==" - }, - "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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/thriftrw": { - "version": "3.11.4", - "resolved": "https://registry.npmjs.org/thriftrw/-/thriftrw-3.11.4.tgz", - "integrity": "sha512-UcuBd3eanB3T10nXWRRMwfwoaC6VMk7qe3/5YIWP2Jtw+EbHqJ0p1/K3x8ixiR5dozKSSfcg1W+0e33G1Di3XA==", - "dependencies": { - "bufrw": "^1.2.1", - "error": "7.0.2", - "long": "^2.4.0" - }, - "bin": { - "thrift2json": "thrift2json.js" - }, - "engines": { - "node": ">= 0.10.x" - } - }, - "node_modules/thriftrw/node_modules/long": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", - "integrity": "sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tsx": { - "version": "4.20.6", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", - "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "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/xorshift": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/xorshift/-/xorshift-1.2.0.tgz", - "integrity": "sha512-iYgNnGyeeJ4t6U11NpA/QiKy+PXn5Aa3Azg5qkwIFz1tBLllQrjjsk9yzD7IAK0naNU4JxdeDgqW9ov4u/hc4g==", - "license": "MIT" - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/otel-v1/package.json b/js/smoke/tests/otel-v1/package.json deleted file mode 100644 index c2ba0bc66..000000000 --- a/js/smoke/tests/otel-v1/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "braintrust-otel-v1-example", - "version": "1.0.0", - "description": "Integration tests for Braintrust with OpenTelemetry v1 NodeSDK", - "main": "otel_example.ts", - "scripts": { - "test": "tsx otel_example.ts", - "start": "tsx otel_example.ts", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "enable-esm": "npx tsx ../../enable-esm.ts", - "install-build": "npm install --legacy-peer-deps && npx tsx ../../install-build.ts ../../../artifacts otel" - }, - "dependencies": { - "@opentelemetry/api": "1.9.0", - "@opentelemetry/context-async-hooks": "1.9.0", - "@opentelemetry/core": "1.9.0", - "@opentelemetry/exporter-trace-otlp-http": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-node": "0.35.0", - "@opentelemetry/sdk-trace-base": "1.9.0", - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@types/node": "^20.10.5", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } -} diff --git a/js/smoke/tests/otel-v1/tsconfig.json b/js/smoke/tests/otel-v1/tsconfig.json deleted file mode 100644 index 1ad966779..000000000 --- a/js/smoke/tests/otel-v1/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "Node", - "strict": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "isolatedModules": true, - "types": ["node"] - }, - "include": ["otel_example.ts"], - "exclude": ["node_modules"] - } diff --git a/js/smoke/tests/span-jest/package-lock.json b/js/smoke/tests/span-jest/package-lock.json deleted file mode 100644 index eec1afc7e..000000000 --- a/js/smoke/tests/span-jest/package-lock.json +++ /dev/null @@ -1,5749 +0,0 @@ -{ - "name": "braintrust-span-jest-smoke-test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-span-jest-smoke-test", - "version": "1.0.0", - "dependencies": { - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@types/node": "^20.10.5", - "jest": "^29.7.0", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "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", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "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.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", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.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", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/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/@babel/core/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/@babel/generator": { - "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.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "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", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.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-module-imports": { - "version": "7.27.1", - "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" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "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", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.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-string-parser": { - "version": "7.27.1", - "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.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" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "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": { - "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.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.5" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "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==", - "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-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" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "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" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "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" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "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" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "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" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "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": { - "@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/@babel/traverse/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/@babel/traverse/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/@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": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.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, - "license": "MIT" - }, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", - "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", - "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", - "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", - "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", - "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", - "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", - "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", - "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", - "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", - "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", - "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", - "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", - "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", - "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", - "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", - "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", - "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", - "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", - "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", - "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", - "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", - "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", - "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", - "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", - "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", - "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "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/load-nyc-config/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/@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": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.34", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.34.tgz", - "integrity": "sha512-iuGW/UM+EZbn2dm+aLx+avo1rVap+ASoFr7oLpTBVW2G2DqhD5l8Fme9IsLZ6TTsp0ozVSFswidiHK1NGNO+pg==", - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "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": "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==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.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==", - "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/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "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/node": { - "version": "20.19.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.26.tgz", - "integrity": "sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg==", - "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/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT" - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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-escapes/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, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.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==", - "dev": true, - "license": "BSD-3-Clause", - "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" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "license": "BSD-3-Clause", - "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" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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": "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", - "integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "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==", - "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/braintrust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-1.0.2.tgz", - "integrity": "sha512-Zm8WbD18FLv5HN38TyUKw659vJdZALQ5VVVWTncMxZgPtFXeWoC7H0tInw/1EQ1pGq50v7WZtlaFBOXhUaf8DQ==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "slugify": "^1.6.6", - "source-map": "^0.7.4", - "termi-link": "^1.0.1", - "uuid": "^9.0.1", - "zod": "^3.25.34", - "zod-to-json-schema": "^3.22.5" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34" - } - }, - "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", - "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/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/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001760", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", - "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", - "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==", - "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": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "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-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT" - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT" - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/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/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/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-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==", - "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==", - "license": "MIT" - }, - "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/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "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": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "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/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "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": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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/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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", - "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.1", - "@esbuild/android-arm": "0.27.1", - "@esbuild/android-arm64": "0.27.1", - "@esbuild/android-x64": "0.27.1", - "@esbuild/darwin-arm64": "0.27.1", - "@esbuild/darwin-x64": "0.27.1", - "@esbuild/freebsd-arm64": "0.27.1", - "@esbuild/freebsd-x64": "0.27.1", - "@esbuild/linux-arm": "0.27.1", - "@esbuild/linux-arm64": "0.27.1", - "@esbuild/linux-ia32": "0.27.1", - "@esbuild/linux-loong64": "0.27.1", - "@esbuild/linux-mips64el": "0.27.1", - "@esbuild/linux-ppc64": "0.27.1", - "@esbuild/linux-riscv64": "0.27.1", - "@esbuild/linux-s390x": "0.27.1", - "@esbuild/linux-x64": "0.27.1", - "@esbuild/netbsd-arm64": "0.27.1", - "@esbuild/netbsd-x64": "0.27.1", - "@esbuild/openbsd-arm64": "0.27.1", - "@esbuild/openbsd-x64": "0.27.1", - "@esbuild/openharmony-arm64": "0.27.1", - "@esbuild/sunos-x64": "0.27.1", - "@esbuild/win32-arm64": "0.27.1", - "@esbuild/win32-ia32": "0.27.1", - "@esbuild/win32-x64": "0.27.1" - } - }, - "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-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "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": ">=8" - } - }, - "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/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "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/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "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/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/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/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.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/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "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": ">=6.9.0" - } - }, - "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, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "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": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/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/glob/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/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "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/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "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": { - "once": "^1.3.0", - "wrappy": "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==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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": ">=0.12.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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "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": { - "node": ">=8" - } - }, - "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": { - "@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": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/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": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "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==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/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/istanbul-lib-source-maps/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/istanbul-lib-source-maps/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/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": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", - "dev": true, - "license": "MIT", - "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" - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "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" - } - }, - "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" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "license": "MIT", - "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" - }, - "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, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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, - "license": "MIT", - "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/jest-snapshot/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": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?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, - "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": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js-yaml/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/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "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, - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "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_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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" - } - }, - "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": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/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" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/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": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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": { - "tmpl": "1.0.5" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "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/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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, - "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": ">=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==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.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==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "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": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "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==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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": ">=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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "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": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "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, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "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/send": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", - "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/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==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "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": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "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, - "license": "ISC" - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "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": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/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/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "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": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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/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, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/termi-link": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "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": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "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": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "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": { - "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/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": ">=4" - } - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "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, - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", - "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", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "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", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "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/which": { - "version": "2.0.2", - "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" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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, - "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==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "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", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "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/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/span-jest/package.json b/js/smoke/tests/span-jest/package.json deleted file mode 100644 index d3108476f..000000000 --- a/js/smoke/tests/span-jest/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "braintrust-span-jest-smoke-test", - "version": "1.0.0", - "description": "Jest smoke test for the Braintrust span simple_span_example script", - "main": "simple_span_example.jest.test.js", - "scripts": { - "test": "npm run test:shared && npm run test:legacy", - "test:shared": "jest shared_suite_test.jest.test.js", - "test:legacy": "jest simple_span_example.jest.test.js", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "enable-esm": "npx tsx ../../enable-esm.ts", - "install-build": "npx tsx ../../install-build.ts ../../../artifacts" - }, - "dependencies": { - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@types/node": "^20.10.5", - "jest": "^29.7.0", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } -} diff --git a/js/smoke/tests/span-jest/shared_suite_test.jest.test.js b/js/smoke/tests/span-jest/shared_suite_test.jest.test.js deleted file mode 100644 index 1d66c438f..000000000 --- a/js/smoke/tests/span-jest/shared_suite_test.jest.test.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Jest smoke test using shared test suites - * This test demonstrates using the shared test package with Jest - */ - -const { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runImportVerificationTests, - runPromptTemplatingTests, -} = require("../../shared/dist/index.js"); - -const braintrust = require("braintrust"); -const { initLogger, _exportsForTestingOnly } = braintrust; - -/** - * Run the shared test suites in Jest environment - */ -async function runSharedTestSuites() { - // Setup test environment - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, // Jest has filesystem access - canUseCLI: true, // Jest can invoke CLI - environment: "jest", - }); - - try { - // Run import verification tests first (forces all exports to be processed) - const importResults = await runImportVerificationTests(braintrust); - - // Run functional tests - const functionalResults = await runBasicLoggingTests(adapters); - - // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); - - // Combine results - const results = [ - ...importResults, - ...functionalResults, - ...promptTemplatingResults, - ]; - - return { - all: results, - import: importResults, - functional: functionalResults, - templating: promptTemplatingResults, - }; - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); - } -} - -test("shared test suites pass in Jest", async () => { - const { - all: results, - import: importResults, - functional: functionalResults, - templating: promptTemplatingResults, - } = await runSharedTestSuites(); - - // Verify all tests passed - const failures = results.filter((r) => !r.success); - - if (failures.length > 0) { - console.error("Test failures:"); - for (const failure of failures) { - console.error(` ❌ ${failure.testName}: ${failure.error?.message}`); - } - } - - // Jest assertions - expect(failures).toHaveLength(0); - - // Log success summary - console.log(`\n✅ All ${results.length} shared test suites passed!\n`); - console.log("Import Verification Tests:"); - for (const result of importResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - console.log("\nFunctional Tests:"); - for (const result of functionalResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - console.log("\nPrompt Templating Tests:"); - for (const result of promptTemplatingResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } -}); diff --git a/js/smoke/tests/span-jest/simple_span_example.jest.test.js b/js/smoke/tests/span-jest/simple_span_example.jest.test.js deleted file mode 100644 index 9d2b21ca3..000000000 --- a/js/smoke/tests/span-jest/simple_span_example.jest.test.js +++ /dev/null @@ -1,65 +0,0 @@ -const { - initLogger, - JSONAttachment, - _exportsForTestingOnly, -} = require("braintrust"); - -test("simple_span_example runs successfully via Jest", async () => { - _exportsForTestingOnly.setInitialTestState(); - await _exportsForTestingOnly.simulateLoginForTests(); - - const backgroundLogger = _exportsForTestingOnly.useTestBackgroundLogger(); - - const logger = initLogger({ - projectName: "otel-simple-example", - projectId: "otel-simple-example", - }); - - const testData = { - foo: "bar", - nested: { - array: [1, 2, 3], - bool: true, - }, - }; - - expect(typeof logger.startSpan).toBe("function"); - - logger.log({ - input: { - type: "chat_completion", - transcript: new JSONAttachment(testData, { - filename: "conversation_transcript.json", - pretty: true, - }), - }, - }); - - expect(testData.nested.array).toEqual([1, 2, 3]); - - const span = logger.startSpan({ name: "test-span" }); - span.log({ - input: "What is the capital of France?", - output: "Paris", - expected: "Paris", - metadata: { transport: "smoke-test" }, - }); - span.end(); - - await logger.flush(); - - const spans = await backgroundLogger.drain(); - - if (spans.length === 0) { - throw new Error("No spans were captured by the background logger"); - } - - const spanEvent = spans.slice(-1)[0]; - - expect(spanEvent.input).toEqual("What is the capital of France?"); - expect(spanEvent.output).toEqual("Paris"); - expect(spanEvent.expected).toEqual("Paris"); - - await _exportsForTestingOnly.clearTestBackgroundLogger(); - await _exportsForTestingOnly.simulateLogoutForTests(); -}); diff --git a/js/smoke/tests/span/package-lock.json b/js/smoke/tests/span/package-lock.json deleted file mode 100644 index ea52b9d68..000000000 --- a/js/smoke/tests/span/package-lock.json +++ /dev/null @@ -1,1855 +0,0 @@ -{ - "name": "braintrust-otel-example", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-otel-example", - "version": "1.0.0", - "dependencies": { - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@types/node": "^20.10.5", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/file-exists/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@kwsites/file-exists/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==", - "license": "MIT" - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.33.tgz", - "integrity": "sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", - "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT" - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-1.0.0.tgz", - "integrity": "sha512-YigO8F32F4l5RoaFlJE72VXWXPMSjqqmaum4BKI94TR7RaywQjirMAU4HtNE7+7NpUhTViLnY4RL2p/JMSH/pg==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "slugify": "^1.6.6", - "source-map": "^0.7.4", - "uuid": "^9.0.1", - "zod": "^3.25.34", - "zod-to-json-schema": "^3.22.5" - }, - "bin": { - "braintrust": "dist/cli.js" - } - }, - "node_modules/braintrust/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", - "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/braintrust/node_modules/esbuild": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", - "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.1", - "@esbuild/android-arm": "0.27.1", - "@esbuild/android-arm64": "0.27.1", - "@esbuild/android-x64": "0.27.1", - "@esbuild/darwin-arm64": "0.27.1", - "@esbuild/darwin-x64": "0.27.1", - "@esbuild/freebsd-arm64": "0.27.1", - "@esbuild/freebsd-x64": "0.27.1", - "@esbuild/linux-arm": "0.27.1", - "@esbuild/linux-arm64": "0.27.1", - "@esbuild/linux-ia32": "0.27.1", - "@esbuild/linux-loong64": "0.27.1", - "@esbuild/linux-mips64el": "0.27.1", - "@esbuild/linux-ppc64": "0.27.1", - "@esbuild/linux-riscv64": "0.27.1", - "@esbuild/linux-s390x": "0.27.1", - "@esbuild/linux-x64": "0.27.1", - "@esbuild/netbsd-arm64": "0.27.1", - "@esbuild/netbsd-x64": "0.27.1", - "@esbuild/openbsd-arm64": "0.27.1", - "@esbuild/openbsd-x64": "0.27.1", - "@esbuild/openharmony-arm64": "0.27.1", - "@esbuild/sunos-x64": "0.27.1", - "@esbuild/win32-arm64": "0.27.1", - "@esbuild/win32-ia32": "0.27.1", - "@esbuild/win32-x64": "0.27.1" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT" - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT" - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "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==", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", - "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/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==", - "license": "MIT" - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/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==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/simple-git/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/simple-git/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==", - "license": "MIT" - }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tsx": { - "version": "4.20.6", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", - "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "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, - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/span/package.json b/js/smoke/tests/span/package.json deleted file mode 100644 index 493ecd5d5..000000000 --- a/js/smoke/tests/span/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "braintrust-otel-example", - "version": "1.0.0", - "description": "Integration tests for Braintrust with OpenTelemetry NodeSDK", - "main": "simple_span_example.ts", - "scripts": { - "test": "npm run test:shared && npm run test:legacy", - "test:shared": "tsx shared_suite_test.ts", - "test:legacy": "tsx simple_span_example.ts", - "start": "tsx simple_span_example.ts", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "enable-esm": "npx tsx ../../enable-esm.ts", - "install-build": "npx tsx ../../install-build.ts ../../../artifacts" - }, - "dependencies": { - "braintrust": "latest", - "zod": "^3.25.76" - }, - "devDependencies": { - "@types/node": "^20.10.5", - "tsx": "^4.19.2", - "typescript": "^5.4.4" - } -} diff --git a/js/smoke/tests/span/shared_suite_test.ts b/js/smoke/tests/span/shared_suite_test.ts deleted file mode 100644 index 0d086b2ce..000000000 --- a/js/smoke/tests/span/shared_suite_test.ts +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Node.js CJS smoke test using shared test suites - * This test demonstrates using the shared test package in Node.js CommonJS mode - */ - -import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - type TestResult, -} from "../../shared/dist/index.js"; - -import { initLogger, _exportsForTestingOnly } from "braintrust"; - -/** - * Run the shared test suites in Node.js CJS environment - */ -async function runSharedTestSuites() { - console.log("Running shared test suites in Node.js CJS mode...\n"); - - // Import Braintrust module for import verification - const braintrust = await import("braintrust"); - - // Setup test environment - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, // Node.js has filesystem access - canUseCLI: true, // Node.js can invoke CLI - environment: "node-cjs", - }); - - try { - // Run import verification tests first (forces all exports to be processed) - console.log("Running import verification tests..."); - const importResults = await runImportVerificationTests(braintrust); - - // Run functional tests - console.log("\nRunning functional tests..."); - const functionalResults = await runBasicLoggingTests(adapters); - - // Run eval smoke test - console.log("\nRunning eval smoke test..."); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Run prompt templating tests - console.log("\nRunning prompt templating tests..."); - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); - - // Combine results - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - // Verify all tests passed - const failures = results.filter((r) => !r.success); - - if (failures.length > 0) { - console.error("\n❌ Test failures:"); - for (const failure of failures) { - console.error(` ${failure.testName}: ${failure.error?.message}`); - if (failure.error?.stack) { - console.error(` ${failure.error.stack}`); - } - } - throw new Error(`${failures.length} test(s) failed`); - } - - // Log results by category - console.log("\n✅ All shared test suites passed!\n"); - console.log("Import Verification Tests:"); - for (const result of importResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - console.log("\nFunctional Tests:"); - for (const result of functionalResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - console.log("\nPrompt Templating Tests:"); - for (const result of promptTemplatingResults) { - console.log(` ✓ ${result.testName}: ${result.message}`); - } - - console.log(`\nTotal: ${results.length} tests passed`); - - return results; - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); - } -} - -// Run tests if this file is executed directly -if (require.main === module) { - runSharedTestSuites() - .then(() => { - console.log("\n✅ Shared test suite execution completed successfully"); - process.exit(0); - }) - .catch((error) => { - console.error("\n❌ Shared test suite execution failed:", error); - process.exit(1); - }); -} - -export { runSharedTestSuites }; diff --git a/js/smoke/tests/span/simple_span_example.ts b/js/smoke/tests/span/simple_span_example.ts deleted file mode 100644 index 90abaee9a..000000000 --- a/js/smoke/tests/span/simple_span_example.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** -This test is a simple test to verify the braintrust package can be used to send spans to the braintrust API. - -This test is not written as a vitest because it needs to be run as CommonJS and ESM. Vitest does not support running both modes. -**/ -import assert from "node:assert/strict"; - -import { initLogger, _exportsForTestingOnly } from "braintrust"; -import { runSpanSmokeTest } from "./span_test_helper"; - -async function main() { - const spans = await runSpanSmokeTest({ - initLogger, - testingExports: _exportsForTestingOnly, - projectName: "otel-simple-example", - }); - - if (spans.length === 0) { - throw new Error("No spans were captured by the background logger"); - } - - const spanEvent = spans[0]!; - - assert.equal(spanEvent.input, "What is the capital of France?"); - assert.equal(spanEvent.output, "Paris"); - assert.equal(spanEvent.expected, "Paris"); - - console.log("Simple span example passed"); -} - -main().catch((error) => { - console.log("Simple span example failed:", error); - process.exitCode = 1; -}); diff --git a/js/smoke/tests/span/span_test_helper.ts b/js/smoke/tests/span/span_test_helper.ts deleted file mode 100644 index a2431238f..000000000 --- a/js/smoke/tests/span/span_test_helper.ts +++ /dev/null @@ -1,155 +0,0 @@ -interface LoggerSpan { - log: (payload: Record) => void; - end: () => void; -} - -interface LoggerInstance { - startSpan: (options: { name: string }) => LoggerSpan; - flush: () => Promise; -} - -interface BackgroundLogger { - drain: () => Promise; -} - -export interface TestingExports { - setInitialTestState: () => void; - simulateLoginForTests: () => Promise | unknown; - simulateLogoutForTests?: () => Promise | unknown; - useTestBackgroundLogger: () => BackgroundLogger; - clearTestBackgroundLogger: () => void; -} - -export interface RunSpanSmokeTestParams { - initLogger: (options: { - projectName: string; - projectId: string; - }) => LoggerInstance; - testingExports: TestingExports; - projectName: string; -} - -const PROJECT_ID = "test-project-id"; -const SPAN_NAME = "logger.smoke"; - -const SPAN_PAYLOAD = { - input: "What is the capital of France?", - output: "Paris", - expected: "Paris", - metadata: { transport: "smoke-test" }, -} satisfies Record; - -export async function runSpanSmokeTest( - params: RunSpanSmokeTestParams, -): Promise { - const { initLogger, testingExports, projectName } = params; - - testingExports.setInitialTestState(); - await testingExports.simulateLoginForTests(); - - const backgroundLogger = testingExports.useTestBackgroundLogger(); - - const logger = initLogger({ - projectName, - projectId: PROJECT_ID, - }); - - const span = logger.startSpan({ name: SPAN_NAME }); - span.log(SPAN_PAYLOAD); - span.end(); - - await logger.flush(); - - const events = await backgroundLogger.drain(); - - try { - return events; - } finally { - testingExports.clearTestBackgroundLogger(); - const { simulateLogoutForTests } = testingExports; - if (typeof simulateLogoutForTests === "function") { - await simulateLogoutForTests(); - } - } -} - -export interface MustacheTemplateTestResult { - messages: Array<{ content: string }>; -} - -export function runMustacheTemplateTest( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Prompt: any, -): MustacheTemplateTestResult { - const mustachePrompt = new Prompt( - { - name: "mustache-test", - slug: "mustache-test", - prompt_data: { - prompt: { - type: "chat", - messages: [ - { - role: "user", - content: "Hello, {{name}}!", - }, - ], - }, - options: { - model: "gpt-4", - }, - }, - }, - {}, - false, - ); - - const mustacheResult = mustachePrompt.build( - { name: "World" }, - { templateFormat: "mustache" }, - ); - - return mustacheResult; -} - -export interface NunjucksTemplateTestResult { - messages: Array<{ content: string }>; -} - -export function runNunjucksTemplateTest( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Prompt: any, -): NunjucksTemplateTestResult { - const nunjucksPrompt = new Prompt( - { - name: "nunjucks-test", - slug: "nunjucks-test", - prompt_data: { - prompt: { - type: "chat", - messages: [ - { - role: "user", - content: - "Items: {% for item in items %}{{ item.name }}{% if not loop.last %}, {% endif %}{% endfor %}", - }, - ], - }, - options: { - model: "gpt-4", - }, - }, - }, - {}, - false, - ); - - const nunjucksResult = nunjucksPrompt.build( - { - items: [{ name: "apple" }, { name: "banana" }, { name: "cherry" }], - }, - { templateFormat: "nunjucks" }, - ); - - return nunjucksResult; -} diff --git a/js/smoke/tests/span/tsconfig.json b/js/smoke/tests/span/tsconfig.json deleted file mode 100644 index 3aa5f582d..000000000 --- a/js/smoke/tests/span/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "Node", - "strict": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "isolatedModules": true, - "types": ["node"] - }, - "include": ["simple_span_example.ts", "span_test_helper.ts"], - "exclude": ["node_modules"] - } diff --git a/js/smoke/tests/vite-react-hono/.gitignore b/js/smoke/tests/vite-react-hono/.gitignore deleted file mode 100644 index 81cd1ebf9..000000000 --- a/js/smoke/tests/vite-react-hono/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -dist -.wrangler -.dev.vars -*.log diff --git a/js/smoke/tests/vite-react-hono/README.md b/js/smoke/tests/vite-react-hono/README.md deleted file mode 100644 index 6ce326070..000000000 --- a/js/smoke/tests/vite-react-hono/README.md +++ /dev/null @@ -1,195 +0,0 @@ -# Braintrust Vite + React + Hono Smoke Test - -Smoke test for the Braintrust SDK in a Vite + React + Hono + Cloudflare Workers environment. - -This test demonstrates: - -- Using Braintrust SDK with Hono routing framework -- Running shared test suites in a Cloudflare Worker -- Integration with Vite for both frontend and backend -- React frontend that can trigger smoke tests - -Based on the [Cloudflare Vite + React + Hono template](https://github.com/cloudflare/templates/tree/main/vite-react-template). - -📚 **See [TESTING.md](./TESTING.md) for detailed testing guide and issue documentation.** - -## Architecture - -- **Backend**: Hono app running in Cloudflare Worker (`src/worker/index.ts`) -- **Frontend**: React app built with Vite (`src/react-app/`) -- **Tests**: Shared test suites from `../../shared/` -- **Bundler**: Vite with Cloudflare plugin -- **Framework**: Hono for routing - -## Project Structure - -``` -vite-react-hono/ -├── src/ -│ ├── worker/ -│ │ └── index.ts # Hono worker with test endpoints -│ └── react-app/ -│ ├── App.tsx # React app with test UI -│ ├── main.tsx # React entry point -│ └── *.css # Styles -├── index.html # HTML entry point -├── vite.config.ts # Vite configuration -├── wrangler.json # Cloudflare Workers config -├── tsconfig.json # TypeScript config (worker) -├── tsconfig.app.json # TypeScript config (React) -├── tsconfig.worker.json # TypeScript config (worker) -└── run-test.mjs # Test runner script -``` - -## Running the Test - -```bash -# Install dependencies -npm install - -# Run the automated smoke test (CI mode) -npm test - -# Test Vite dev server compatibility (documents known issue) -npm run test:vite-dev - -# Build for production -npm run build -``` - -### Known Issue: Vite Dev Server - -**⚠️ The Vite dev server (`npm run dev`) currently fails** with the following error: - -``` -TypeError: Object prototype may only be an Object or null: undefined - at _inheritsLoose (node_modules/nunjucks/src/object.js:8:77) -``` - -**Root Cause**: When Vite tries to pre-bundle dependencies, it encounters Nunjucks (used by Braintrust for prompt templating). Nunjucks uses `Object.setPrototypeOf` with potentially undefined values, which fails in Vite's ESM bundler. - -**Workarounds**: - -1. Use `braintrust/browser` import instead of full `braintrust` package -2. Configure Vite to exclude Nunjucks from optimization: - ```js - // vite.config.ts - export default defineConfig({ - optimizeDeps: { - exclude: ["nunjucks"], - }, - }); - ``` - -**Testing**: Run `npm run test:vite-dev` to verify this known issue is reproducible. The test will fail (exit code 1), which is expected. CI is configured to allow this failure. - -## Test Endpoints - -When running (`npm run dev` or via `wrangler dev`): - -- `GET /` - Home page with test information (text response) -- `GET /api/` - Basic API endpoint returning JSON -- `GET /api/test` - Run shared test suites (returns JSON test results) - -## What's Tested - -This smoke test runs the full shared test suite: - -1. **Import Verification Tests** (~13 tests) - - - All Braintrust exports are accessible - - Core logging, Dataset, Prompt, Experiment, Eval exports - - Tracing, client wrappers, utilities - -2. **Functional Tests** (~3 tests) - - - Basic span logging - - Multiple sequential spans - - Direct logging operations - -3. **Eval Smoke Test** (1 test) - - - Evaluation functionality works - -4. **Prompt Templating Tests** (~2 tests) - - Prompt template rendering - -All tests use the shared test suite package for consistency across environments. - -## Development - -### Running with React Frontend (Optional) - -The React frontend provides a UI to trigger the smoke tests manually. To use it: - -1. Build the frontend: `npm run build` -2. Update `wrangler.json` to add assets configuration: - ```json - "assets": { - "directory": "./dist/client", - "not_found_handling": "single-page-application" - } - ``` -3. Start dev server: `npm run dev` -4. Visit http://localhost:5173 -5. Click "Run Smoke Tests" button - -**Note**: The automated smoke test (`npm test`) only needs the worker API endpoints and doesn't require building the React frontend. - -## CI Integration - -This test is automatically discovered and run by `../../run-tests.sh`: - -```bash -cd ../../ -./run-tests.sh vite-react-hono -``` - -The test runs in CI alongside other smoke tests: - -- Builds the SDK from source -- Installs the build artifact -- Runs the test via HTTP endpoint -- Verifies all shared test suites pass - -## Key Features - -1. **Hono Integration**: Uses Hono's elegant routing instead of raw Worker API -2. **Vite Bundling**: Tests the Braintrust SDK through Vite's bundler (production mode) -3. **Compatibility Testing**: Documents and tests Vite dev server limitations -4. **Cloudflare Workers**: Tests in actual Workers runtime environment -5. **Shared Test Suites**: Consistent test coverage across all environments - -## Test Coverage - -This smoke test suite includes: - -### 1. Production Worker Test (`npm test`) - -Tests the Braintrust SDK in a production-like Cloudflare Workers environment: - -- ✅ 18/19 tests pass -- ✅ All import verification tests -- ✅ All functional logging tests -- ✅ Eval smoke test -- ✅ Mustache prompt templating -- ❌ Nunjucks templating (expected failure - Cloudflare security policy) - -### 2. Vite Dev Server Compatibility Test (`npm run test:vite-dev`) - -Documents a known limitation with Vite's dev server: - -- ❌ Reproduces the Nunjucks bundling issue (exits with code 1) -- ✅ Provides clear error messages and workarounds -- ✅ Helps verify if the issue persists in new versions - -This test **reports honest failures**. CI is configured with `continue-on-error: true` to allow this expected failure without blocking the build. - -## Notes - -- The automated test (`npm test`) only exercises the `/api/test` endpoint via Wrangler -- The React frontend is optional and not used in CI -- Tests run in Cloudflare Workers environment (V8 isolates) -- Uses Wrangler dev server for local testing (not Vite) -- Port 8800 is used to avoid conflicts with other smoke tests -- The Vite dev server issue is documented and testable but not blocking diff --git a/js/smoke/tests/vite-react-hono/index.html b/js/smoke/tests/vite-react-hono/index.html deleted file mode 100644 index c99c0fe61..000000000 --- a/js/smoke/tests/vite-react-hono/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Braintrust Vite + React + Hono Smoke Test - - -
- - - diff --git a/js/smoke/tests/vite-react-hono/package-lock.json b/js/smoke/tests/vite-react-hono/package-lock.json deleted file mode 100644 index ff774c70f..000000000 --- a/js/smoke/tests/vite-react-hono/package-lock.json +++ /dev/null @@ -1,5419 +0,0 @@ -{ - "name": "braintrust-vite-react-hono-smoke-test", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "braintrust-vite-react-hono-smoke-test", - "dependencies": { - "braintrust": "latest", - "hono": "^4.11.1", - "react": "^19.2.1", - "react-dom": "^19.2.1", - "zod": "^3.25.76" - }, - "devDependencies": { - "@cloudflare/vite-plugin": "^1.15.3", - "@cloudflare/workers-types": "^4.20250810.0", - "@types/node": "^24.10.1", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "tsx": "^4.19.2", - "typescript": "^5.8.3", - "vite": "^6.0.0", - "wrangler": "^4.56.0" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.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-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "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.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" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "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": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.6" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "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-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "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/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", - "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", - "dev": true, - "license": "MIT OR Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@cloudflare/unenv-preset": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.10.0.tgz", - "integrity": "sha512-/uII4vLQXhzCAZzEVeYAjFLBNg2nqTJ1JGzd2lRF6ItYe6U2zVoYGfeKpGx/EkBF6euiU+cyBXgMdtJih+nQ6g==", - "dev": true, - "license": "MIT OR Apache-2.0", - "peerDependencies": { - "unenv": "2.0.0-rc.24", - "workerd": "^1.20251221.0" - }, - "peerDependenciesMeta": { - "workerd": { - "optional": true - } - } - }, - "node_modules/@cloudflare/vite-plugin": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@cloudflare/vite-plugin/-/vite-plugin-1.21.0.tgz", - "integrity": "sha512-3VXtkfjOQL+k3Plj+t0BHRyw8iIIRBQ8RJU6KJHJQKdYHA6rJE/WlSa/lRd0A8MMhvP8e8QiMLuDqveEN8gCZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cloudflare/unenv-preset": "2.10.0", - "miniflare": "4.20260114.0", - "unenv": "2.0.0-rc.24", - "wrangler": "4.59.2", - "ws": "8.18.0" - }, - "peerDependencies": { - "vite": "^6.1.0 || ^7.0.0", - "wrangler": "^4.59.2" - } - }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260114.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260114.0.tgz", - "integrity": "sha512-HNlsRkfNgardCig2P/5bp/dqDECsZ4+NU5XewqArWxMseqt3C5daSuptI620s4pn7Wr0ZKg7jVLH0PDEBkA+aA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260114.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260114.0.tgz", - "integrity": "sha512-qyE1UdFnAlxzb+uCfN/d9c8icch7XRiH49/DjoqEa+bCDihTuRS7GL1RmhVIqHJhb3pX3DzxmKgQZBDBL83Inw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260114.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260114.0.tgz", - "integrity": "sha512-Z0BLvAj/JPOabzads2ddDEfgExWTlD22pnwsuNbPwZAGTSZeQa3Y47eGUWyHk+rSGngknk++S7zHTGbKuG7RRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260114.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260114.0.tgz", - "integrity": "sha512-kPUmEtUxUWlr9PQ64kuhdK0qyo8idPe5IIXUgi7xCD7mDd6EOe5J7ugDpbfvfbYKEjx4DpLvN2t45izyI/Sodw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260114.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260114.0.tgz", - "integrity": "sha512-MJnKgm6i1jZGyt2ZHQYCnRlpFTEZcK2rv9y7asS3KdVEXaDgGF8kOns5u6YL6/+eMogfZuHRjfDS+UqRTUYIFA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20260115.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260115.0.tgz", - "integrity": "sha512-vi68ZODh6m9fH9wdBOzDsyWgrYRIZbzZEAGGkvFn4b1FQSukxaWS8NAtSd/h9mL4gVK9hG8FEYq/jipdOo4RJg==", - "dev": true, - "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==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "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": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "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": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "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/@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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "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" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "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.2.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "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.2.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "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-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "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.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "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.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "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.2.4" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "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.2.4" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "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-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "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-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "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.2.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "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.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "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.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "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.2.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "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-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "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.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "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/@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/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", - "license": "MIT" - }, - "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/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/@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/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "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/@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/@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/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/node": { - "version": "24.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz", - "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/nunjucks": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", - "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@vercel/functions": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vercel/functions/-/functions-1.6.0.tgz", - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@aws-sdk/credential-provider-web-identity": "*" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-web-identity": { - "optional": true - } - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz", - "integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.5", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.53", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT" - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.14", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", - "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braintrust": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/braintrust/-/braintrust-2.0.2.tgz", - "integrity": "sha512-TOfdi2acpDnne3Pcew/shbwda0SKQvjTsGprr0gLWloaeYehhOPyrsWmwKsRNXOJa01D0czTGyetWpUbcH+euw==", - "license": "MIT", - "dependencies": { - "@ai-sdk/provider": "^1.1.3", - "@next/env": "^14.2.3", - "@types/nunjucks": "^3.2.6", - "@vercel/functions": "^1.0.2", - "argparse": "^2.0.1", - "boxen": "^8.0.1", - "chalk": "^4.1.2", - "cli-progress": "^3.12.0", - "cli-table3": "^0.6.5", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "esbuild": "^0.27.0", - "eventsource-parser": "^1.1.2", - "express": "^4.21.2", - "graceful-fs": "^4.2.11", - "http-errors": "^2.0.0", - "minimatch": "^9.0.3", - "mustache": "^4.2.0", - "nunjucks": "^3.2.4", - "pluralize": "^8.0.0", - "simple-git": "^3.21.0", - "source-map": "^0.7.4", - "termi-link": "^1.0.1", - "uuid": "^9.0.1", - "zod-to-json-schema": "^3.25.0" - }, - "bin": { - "braintrust": "dist/cli.js" - }, - "peerDependencies": { - "zod": "^3.25.34 || ^4.0" - } - }, - "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", - "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/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001764", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", - "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==", - "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/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT" - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-progress/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT" - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "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==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "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/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "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/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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/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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "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-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource-parser": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "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": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "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": ">=6.9.0" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "ISC" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hono": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", - "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", - "license": "MIT", - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "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_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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/miniflare": { - "version": "4.20260114.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260114.0.tgz", - "integrity": "sha512-QwHT7S6XqGdQxIvql1uirH/7/i3zDEt0B/YBXTYzMfJtVCR4+ue3KPkU+Bl0zMxvpgkvjh9+eCHhJbKEqya70A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "0.8.1", - "sharp": "^0.34.5", - "undici": "7.14.0", - "workerd": "1.20260114.0", - "ws": "8.18.0", - "youch": "4.1.0-beta.10", - "zod": "^3.25.76" - }, - "bin": { - "miniflare": "bootstrap.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "license": "BSD-2-Clause", - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "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, - "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": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "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", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", - "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.3" - } - }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "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/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, - "node_modules/sharp/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": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "license": "MIT", - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-git": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/termi-link": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/termi-link/-/termi-link-1.1.0.tgz", - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "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, - "license": "0BSD", - "optional": true - }, - "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": { - "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/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unenv": { - "version": "2.0.0-rc.24", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", - "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pathe": "^2.0.3" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "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": [ - { - "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", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/workerd": { - "version": "1.20260114.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260114.0.tgz", - "integrity": "sha512-kTJ+jNdIllOzWuVA3NRQRvywP0T135zdCjAE2dAUY1BFbxM6fmMZV8BbskEoQ4hAODVQUfZQmyGctcwvVCKxFA==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "workerd": "bin/workerd" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260114.0", - "@cloudflare/workerd-darwin-arm64": "1.20260114.0", - "@cloudflare/workerd-linux-64": "1.20260114.0", - "@cloudflare/workerd-linux-arm64": "1.20260114.0", - "@cloudflare/workerd-windows-64": "1.20260114.0" - } - }, - "node_modules/wrangler": { - "version": "4.59.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.59.2.tgz", - "integrity": "sha512-Z4xn6jFZTaugcOKz42xvRAYKgkVUERHVbuCJ5+f+gK+R6k12L02unakPGOA0L0ejhUl16dqDjKe4tmL9sedHcw==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.2", - "@cloudflare/unenv-preset": "2.10.0", - "blake3-wasm": "2.1.5", - "esbuild": "0.27.0", - "miniflare": "4.20260114.0", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.24", - "workerd": "1.20260114.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=20.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20260114.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } - } - }, - "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/wrangler/node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" - } - }, - "node_modules/wrangler/node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "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/youch/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/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/js/smoke/tests/vite-react-hono/package.json b/js/smoke/tests/vite-react-hono/package.json deleted file mode 100644 index 3db0ef46e..000000000 --- a/js/smoke/tests/vite-react-hono/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "braintrust-vite-react-hono-smoke-test", - "description": "Smoke test for Braintrust SDK in Vite + React + Hono + Cloudflare Workers", - "private": true, - "type": "module", - "scripts": { - "test": "node run-test.mjs; TEST1=$?; node test-vite-dev.mjs; TEST2=$?; exit $((TEST1 || TEST2))", - "test:vite-dev": "node test-vite-dev.mjs", - "backup": "npx tsx ../../backup-and-restore.ts backup", - "restore": "npx tsx ../../backup-and-restore.ts restore", - "install-build": "npx tsx ../../install-build.ts ../../../artifacts braintrust" - }, - "dependencies": { - "braintrust": "latest", - "hono": "^4.11.1", - "react": "^19.2.1", - "react-dom": "^19.2.1", - "zod": "^3.25.76" - }, - "devDependencies": { - "@cloudflare/vite-plugin": "^1.15.3", - "@cloudflare/workers-types": "^4.20250810.0", - "@types/node": "^24.10.1", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "tsx": "^4.19.2", - "typescript": "^5.8.3", - "vite": "^6.0.0", - "wrangler": "^4.56.0" - } -} diff --git a/js/smoke/tests/vite-react-hono/src/react-app/App.css b/js/smoke/tests/vite-react-hono/src/react-app/App.css deleted file mode 100644 index 5d701319f..000000000 --- a/js/smoke/tests/vite-react-hono/src/react-app/App.css +++ /dev/null @@ -1,40 +0,0 @@ -.App { - max-width: 800px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.card { - padding: 2rem; - background: #f4f4f4; - border-radius: 8px; - margin: 1rem 0; -} - -button { - padding: 0.75rem 1.5rem; - font-size: 1rem; - border: none; - border-radius: 4px; - background: #0070f3; - color: white; - cursor: pointer; - margin-bottom: 1rem; -} - -button:hover:not(:disabled) { - background: #0051cc; -} - -button:disabled { - background: #ccc; - cursor: not-allowed; -} - -pre { - background: white; - padding: 1rem; - border-radius: 4px; - min-height: 100px; -} diff --git a/js/smoke/tests/vite-react-hono/src/react-app/App.tsx b/js/smoke/tests/vite-react-hono/src/react-app/App.tsx deleted file mode 100644 index a4106557b..000000000 --- a/js/smoke/tests/vite-react-hono/src/react-app/App.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useState } from "react"; -import "./App.css"; - -function App() { - const [testResult, setTestResult] = useState("Not run"); - const [isRunning, setIsRunning] = useState(false); - - const runSmokeTest = async () => { - setIsRunning(true); - setTestResult("Running tests..."); - - try { - const response = await fetch("/api/test"); - const result = await response.json(); - - if (result.success) { - setTestResult( - `✅ All ${result.totalTests} tests passed!\n${result.message}`, - ); - } else { - setTestResult( - `❌ ${result.failedTests}/${result.totalTests} tests failed\n${result.message}`, - ); - } - } catch (error) { - setTestResult( - `❌ Error: ${error instanceof Error ? error.message : String(error)}`, - ); - } finally { - setIsRunning(false); - } - }; - - return ( -
-

Braintrust Vite + React + Hono Smoke Test

-
- -
-          {testResult}
-        
-
-
- ); -} - -export default App; diff --git a/js/smoke/tests/vite-react-hono/src/react-app/index.css b/js/smoke/tests/vite-react-hono/src/react-app/index.css deleted file mode 100644 index 8b59f4df1..000000000 --- a/js/smoke/tests/vite-react-hono/src/react-app/index.css +++ /dev/null @@ -1,31 +0,0 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - color: #213547; - background-color: #ffffff; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -#root { - width: 100%; -} - -h1 { - font-size: 2.5em; - line-height: 1.1; -} - -@media (prefers-color-scheme: dark) { - :root { - color: #ffffff; - background-color: #242424; - } -} diff --git a/js/smoke/tests/vite-react-hono/src/react-app/main.tsx b/js/smoke/tests/vite-react-hono/src/react-app/main.tsx deleted file mode 100644 index ef474bf64..000000000 --- a/js/smoke/tests/vite-react-hono/src/react-app/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import App from "./App.tsx"; -import "./index.css"; - -createRoot(document.getElementById("root")!).render( - - - , -); diff --git a/js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts b/js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/js/smoke/tests/vite-react-hono/src/react-app/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/js/smoke/tests/vite-react-hono/tsconfig.app.json b/js/smoke/tests/vite-react-hono/tsconfig.app.json deleted file mode 100644 index 9393b4e33..000000000 --- a/js/smoke/tests/vite-react-hono/tsconfig.app.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src/react-app"] -} diff --git a/js/smoke/tests/vite-react-hono/tsconfig.node.json b/js/smoke/tests/vite-react-hono/tsconfig.node.json deleted file mode 100644 index 8e5b203b7..000000000 --- a/js/smoke/tests/vite-react-hono/tsconfig.node.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["vite.config.ts"] -} diff --git a/js/smoke/tests/vite-react-hono/tsconfig.worker.json b/js/smoke/tests/vite-react-hono/tsconfig.worker.json deleted file mode 100644 index 60579cdf0..000000000 --- a/js/smoke/tests/vite-react-hono/tsconfig.worker.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": true, - "types": ["@cloudflare/workers-types"] - }, - "include": ["src/worker"] -} diff --git a/js/smoke/tests/vite-react-hono/wrangler.json b/js/smoke/tests/vite-react-hono/wrangler.json deleted file mode 100644 index 0b750d0be..000000000 --- a/js/smoke/tests/vite-react-hono/wrangler.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "node_modules/wrangler/config-schema.json", - "name": "braintrust-vite-react-hono-smoke-test", - "main": "./src/worker/index.ts", - "compatibility_date": "2025-01-15", - "compatibility_flags": ["nodejs_compat"] -} diff --git a/package.json b/package.json index 298f7a1fe..61f1bf8c0 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { + "name": "braintrust-sdk-js", + "version": "0.0.1", "repository": "https://github.com/braintrustdata/braintrust-sdk", "license": "MIT", "private": true, "workspaces": [ - "js", - "core/js" + "js" ], "scripts": { "build": "turbo run build", diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6067e971f..aa39e5413 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,5 @@ packages: - js - - core/js - integrations/* - internal/golden - js/src/wrappers/* From 04ebd693f06529e0f88ebbb64a0bdf314c7c5cad Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 20 Jan 2026 15:57:32 -0800 Subject: [PATCH 32/57] add a recent compatibility date --- js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml | 2 +- .../scenarios/cloudflare-worker-browser-compat/wrangler.toml | 2 +- .../scenarios/cloudflare-worker-browser-no-compat/wrangler.toml | 2 +- js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml | 2 +- .../scenarios/cloudflare-worker-node-no-compat/wrangler.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml b/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml index 93f0b4dfa..d9f7bd166 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml @@ -1,3 +1,3 @@ name = "smoke-cloudflare-vite-hono" main = "src/worker.ts" -compatibility_date = "2025-01-15" +compatibility_date = "2026-01-15" diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml index 94fa314a2..0f979736b 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml @@ -1,4 +1,4 @@ name = "smoke-cloudflare-worker-browser-compat" main = "src/worker.ts" -compatibility_date = "2024-09-23" +compatibility_date = "2025-01-15" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml index ae058eb0b..8ec040f31 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml @@ -1,3 +1,3 @@ name = "smoke-cloudflare-worker-browser-no-compat" main = "src/worker.ts" -compatibility_date = "2024-09-23" +compatibility_date = "2025-01-15" diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml index 3f4e37af6..00dd2cd7b 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml @@ -1,4 +1,4 @@ name = "smoke-cloudflare-worker-node-compat" main = "src/worker.ts" -compatibility_date = "2024-09-23" +compatibility_date = "2026-01-15" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml index 74b70da63..30a7aed0d 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml @@ -1,3 +1,3 @@ name = "smoke-cloudflare-worker-node-no-compat" main = "src/worker.ts" -compatibility_date = "2024-09-23" +compatibility_date = "2026-01-15" From 51afb782fb8cdf1d13bdcd7e01bfd66fc0690d0b Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 20 Jan 2026 15:58:30 -0800 Subject: [PATCH 33/57] remove the additional no external --- js/tsup.config.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/js/tsup.config.ts b/js/tsup.config.ts index 9fe7424c0..f5100c6cb 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -24,13 +24,6 @@ export default defineConfig([ outDir: "dist", removeNodeProtocol: false, external: ["zod"], - noExternal: [ - "mustache", - "eventsource-parser", - "zod-to-json-schema", - "@vercel/functions", - ], - platform: "browser", dts: { // Split DTS generation to reduce memory usage compilerOptions: { From ea954795c9fcb6dcef5fe15e3118adc2780ff28f Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 20 Jan 2026 16:04:00 -0800 Subject: [PATCH 34/57] Revert "add a recent compatibility date" This reverts commit 04ebd693f06529e0f88ebbb64a0bdf314c7c5cad. --- js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml | 2 +- .../scenarios/cloudflare-worker-browser-compat/wrangler.toml | 2 +- .../scenarios/cloudflare-worker-browser-no-compat/wrangler.toml | 2 +- js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml | 2 +- .../scenarios/cloudflare-worker-node-no-compat/wrangler.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml b/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml index d9f7bd166..93f0b4dfa 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml @@ -1,3 +1,3 @@ name = "smoke-cloudflare-vite-hono" main = "src/worker.ts" -compatibility_date = "2026-01-15" +compatibility_date = "2025-01-15" diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml index 0f979736b..94fa314a2 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/wrangler.toml @@ -1,4 +1,4 @@ name = "smoke-cloudflare-worker-browser-compat" main = "src/worker.ts" -compatibility_date = "2025-01-15" +compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml index 8ec040f31..ae058eb0b 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/wrangler.toml @@ -1,3 +1,3 @@ name = "smoke-cloudflare-worker-browser-no-compat" main = "src/worker.ts" -compatibility_date = "2025-01-15" +compatibility_date = "2024-09-23" diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml index 00dd2cd7b..3f4e37af6 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/wrangler.toml @@ -1,4 +1,4 @@ name = "smoke-cloudflare-worker-node-compat" main = "src/worker.ts" -compatibility_date = "2026-01-15" +compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml b/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml index 30a7aed0d..74b70da63 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/wrangler.toml @@ -1,3 +1,3 @@ name = "smoke-cloudflare-worker-node-no-compat" main = "src/worker.ts" -compatibility_date = "2026-01-15" +compatibility_date = "2024-09-23" From 7180b69f41a6de5a7fc3afb1fd2f75c5f86c5de8 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 20 Jan 2026 16:40:18 -0800 Subject: [PATCH 35/57] try to fix deno --- js/smoke/scenarios/deno-node/Makefile | 20 +++++++++----------- js/smoke/scenarios/deno-node/deno.json | 2 +- js/smoke/scenarios/deno-node/deno.lock | 8 ++++---- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/js/smoke/scenarios/deno-node/Makefile b/js/smoke/scenarios/deno-node/Makefile index 12ef36e31..d9396568f 100644 --- a/js/smoke/scenarios/deno-node/Makefile +++ b/js/smoke/scenarios/deno-node/Makefile @@ -4,17 +4,15 @@ setup: @echo "==> Setting up deno-node scenario" mise install @# Deno uses workspace links - need SDK dist/ folder to exist - @if [ ! -d ../../../dist ]; then \ - if [ -n "$(BRAINTRUST_TAR)" ]; then \ - echo "==> Extracting SDK tarball for workspace link"; \ - TARBALL_PATH="$$(cd ../.. && pwd)/$(BRAINTRUST_TAR)"; \ - echo "==> Resolved tarball path: $$TARBALL_PATH"; \ - cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ - else \ - echo "==> Building SDK for workspace link"; \ - cd ../../.. && pnpm exec turbo build --filter=braintrust; \ - fi; \ - fi + if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Extracting SDK tarball for workspace link"; \ + TARBALL_PATH="$$(cd ../.. && pwd)/$(BRAINTRUST_TAR)"; \ + echo "==> Resolved tarball path: $$TARBALL_PATH"; \ + cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ + else \ + echo "==> Building SDK for workspace link"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust; \ + fi; \ deno install test: setup diff --git a/js/smoke/scenarios/deno-node/deno.json b/js/smoke/scenarios/deno-node/deno.json index 56d30fafa..2849e7456 100644 --- a/js/smoke/scenarios/deno-node/deno.json +++ b/js/smoke/scenarios/deno-node/deno.json @@ -2,7 +2,7 @@ "imports": { "@std/assert": "jsr:@std/assert@^1.0.14", "@braintrust/smoke-test-shared": "jsr:@braintrust/smoke-test-shared", - "braintrust": "npm:braintrust@^2.0.2" + "braintrust": "npm:braintrust" }, "nodeModulesDir": "auto", "links": [ diff --git a/js/smoke/scenarios/deno-node/deno.lock b/js/smoke/scenarios/deno-node/deno.lock index d32c2672c..390a833fa 100644 --- a/js/smoke/scenarios/deno-node/deno.lock +++ b/js/smoke/scenarios/deno-node/deno.lock @@ -3,7 +3,7 @@ "specifiers": { "jsr:@std/assert@^1.0.14": "1.0.16", "jsr:@std/internal@^1.0.12": "1.0.12", - "npm:braintrust@^2.0.2": "2.0.2_zod@4.3.5" + "npm:braintrust@*": "2.1.0_zod@4.3.5" }, "jsr": { "@std/assert@1.0.16": { @@ -253,7 +253,7 @@ "balanced-match" ] }, - "braintrust@2.0.2_zod@4.3.5": { + "braintrust@2.1.0_zod@4.3.5": { "dependencies": [ "@ai-sdk/provider", "@next/env", @@ -865,13 +865,13 @@ "dependencies": [ "jsr:@braintrust/smoke-test-shared@*", "jsr:@std/assert@^1.0.14", - "npm:braintrust@^2.0.2" + "npm:braintrust@*" ], "links": { "jsr:@braintrust/smoke-test-shared": {}, "npm:@braintrust/smoke-test-shared@1.0.0": {}, "npm:braintrust-sdk-js@0.0.1": {}, - "npm:braintrust@2.0.2": { + "npm:braintrust@2.1.0": { "dependencies": [ "npm:@ai-sdk/provider@^1.1.3", "npm:@next/env@^14.2.3", From 0247412226a6ee460199cf79793972b92150777c Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 20 Jan 2026 16:41:32 -0800 Subject: [PATCH 36/57] avoid deno install --- js/smoke/scenarios/deno-node/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/js/smoke/scenarios/deno-node/Makefile b/js/smoke/scenarios/deno-node/Makefile index d9396568f..3a7c730a7 100644 --- a/js/smoke/scenarios/deno-node/Makefile +++ b/js/smoke/scenarios/deno-node/Makefile @@ -13,7 +13,6 @@ setup: echo "==> Building SDK for workspace link"; \ cd ../../.. && pnpm exec turbo build --filter=braintrust; \ fi; \ - deno install test: setup deno test --sloppy-imports --allow-all tests/*.test.ts From 5f5dc16f2666d6e58cb13005a01ab78781e528b0 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 20 Jan 2026 16:52:51 -0800 Subject: [PATCH 37/57] try removing deno lock --- js/smoke/scenarios/deno-node/.gitignore | 1 + js/smoke/scenarios/deno-node/deno.lock | 908 ------------------------ 2 files changed, 1 insertion(+), 908 deletions(-) delete mode 100644 js/smoke/scenarios/deno-node/deno.lock diff --git a/js/smoke/scenarios/deno-node/.gitignore b/js/smoke/scenarios/deno-node/.gitignore index 49103d242..0203990b0 100644 --- a/js/smoke/scenarios/deno-node/.gitignore +++ b/js/smoke/scenarios/deno-node/.gitignore @@ -1,3 +1,4 @@ node_modules/ .DS_Store package-lock.json +deno.lock diff --git a/js/smoke/scenarios/deno-node/deno.lock b/js/smoke/scenarios/deno-node/deno.lock deleted file mode 100644 index 390a833fa..000000000 --- a/js/smoke/scenarios/deno-node/deno.lock +++ /dev/null @@ -1,908 +0,0 @@ -{ - "version": "5", - "specifiers": { - "jsr:@std/assert@^1.0.14": "1.0.16", - "jsr:@std/internal@^1.0.12": "1.0.12", - "npm:braintrust@*": "2.1.0_zod@4.3.5" - }, - "jsr": { - "@std/assert@1.0.16": { - "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", - "dependencies": [ - "jsr:@std/internal" - ] - }, - "@std/internal@1.0.12": { - "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" - } - }, - "npm": { - "@ai-sdk/provider@1.1.3": { - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "dependencies": [ - "json-schema" - ] - }, - "@colors/colors@1.5.0": { - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" - }, - "@esbuild/aix-ppc64@0.27.2": { - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "os": ["aix"], - "cpu": ["ppc64"] - }, - "@esbuild/android-arm64@0.27.2": { - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "os": ["android"], - "cpu": ["arm64"] - }, - "@esbuild/android-arm@0.27.2": { - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "os": ["android"], - "cpu": ["arm"] - }, - "@esbuild/android-x64@0.27.2": { - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "os": ["android"], - "cpu": ["x64"] - }, - "@esbuild/darwin-arm64@0.27.2": { - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "os": ["darwin"], - "cpu": ["arm64"] - }, - "@esbuild/darwin-x64@0.27.2": { - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "os": ["darwin"], - "cpu": ["x64"] - }, - "@esbuild/freebsd-arm64@0.27.2": { - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "os": ["freebsd"], - "cpu": ["arm64"] - }, - "@esbuild/freebsd-x64@0.27.2": { - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "os": ["freebsd"], - "cpu": ["x64"] - }, - "@esbuild/linux-arm64@0.27.2": { - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@esbuild/linux-arm@0.27.2": { - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "os": ["linux"], - "cpu": ["arm"] - }, - "@esbuild/linux-ia32@0.27.2": { - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "os": ["linux"], - "cpu": ["ia32"] - }, - "@esbuild/linux-loong64@0.27.2": { - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "os": ["linux"], - "cpu": ["loong64"] - }, - "@esbuild/linux-mips64el@0.27.2": { - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "os": ["linux"], - "cpu": ["mips64el"] - }, - "@esbuild/linux-ppc64@0.27.2": { - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "os": ["linux"], - "cpu": ["ppc64"] - }, - "@esbuild/linux-riscv64@0.27.2": { - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "os": ["linux"], - "cpu": ["riscv64"] - }, - "@esbuild/linux-s390x@0.27.2": { - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "os": ["linux"], - "cpu": ["s390x"] - }, - "@esbuild/linux-x64@0.27.2": { - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@esbuild/netbsd-arm64@0.27.2": { - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "os": ["netbsd"], - "cpu": ["arm64"] - }, - "@esbuild/netbsd-x64@0.27.2": { - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "os": ["netbsd"], - "cpu": ["x64"] - }, - "@esbuild/openbsd-arm64@0.27.2": { - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "os": ["openbsd"], - "cpu": ["arm64"] - }, - "@esbuild/openbsd-x64@0.27.2": { - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "os": ["openbsd"], - "cpu": ["x64"] - }, - "@esbuild/openharmony-arm64@0.27.2": { - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "os": ["openharmony"], - "cpu": ["arm64"] - }, - "@esbuild/sunos-x64@0.27.2": { - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "os": ["sunos"], - "cpu": ["x64"] - }, - "@esbuild/win32-arm64@0.27.2": { - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "os": ["win32"], - "cpu": ["arm64"] - }, - "@esbuild/win32-ia32@0.27.2": { - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "os": ["win32"], - "cpu": ["ia32"] - }, - "@esbuild/win32-x64@0.27.2": { - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "os": ["win32"], - "cpu": ["x64"] - }, - "@kwsites/file-exists@1.1.1": { - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dependencies": [ - "debug@4.4.3" - ] - }, - "@kwsites/promise-deferred@1.1.1": { - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" - }, - "@next/env@14.2.35": { - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==" - }, - "@types/nunjucks@3.2.6": { - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==" - }, - "@vercel/functions@1.6.0": { - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==" - }, - "a-sync-waterfall@1.0.1": { - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" - }, - "accepts@1.3.8": { - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": [ - "mime-types", - "negotiator" - ] - }, - "ansi-align@3.0.1": { - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dependencies": [ - "string-width@4.2.3" - ] - }, - "ansi-regex@5.0.1": { - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-regex@6.2.2": { - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==" - }, - "ansi-styles@4.3.0": { - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": [ - "color-convert" - ] - }, - "ansi-styles@6.2.3": { - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" - }, - "argparse@2.0.1": { - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "array-flatten@1.1.1": { - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "asap@2.0.6": { - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "balanced-match@1.0.2": { - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "body-parser@1.20.4": { - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "dependencies": [ - "bytes", - "content-type", - "debug@2.6.9", - "depd", - "destroy", - "http-errors", - "iconv-lite", - "on-finished", - "qs", - "raw-body", - "type-is", - "unpipe" - ] - }, - "boxen@8.0.1": { - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "dependencies": [ - "ansi-align", - "camelcase", - "chalk@5.6.2", - "cli-boxes", - "string-width@7.2.0", - "type-fest", - "widest-line", - "wrap-ansi" - ] - }, - "brace-expansion@2.0.2": { - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dependencies": [ - "balanced-match" - ] - }, - "braintrust@2.1.0_zod@4.3.5": { - "dependencies": [ - "@ai-sdk/provider", - "@next/env", - "@types/nunjucks", - "@vercel/functions", - "argparse", - "boxen", - "chalk@4.1.2", - "cli-progress", - "cli-table3", - "cors", - "dotenv", - "esbuild", - "eventsource-parser", - "express", - "graceful-fs", - "http-errors", - "minimatch", - "mustache", - "nunjucks", - "pluralize", - "simple-git", - "source-map", - "termi-link", - "uuid", - "zod", - "zod-to-json-schema" - ], - "bin": true - }, - "bytes@3.1.2": { - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind-apply-helpers@1.0.2": { - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": [ - "es-errors", - "function-bind" - ] - }, - "call-bound@1.0.4": { - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": [ - "call-bind-apply-helpers", - "get-intrinsic" - ] - }, - "camelcase@8.0.0": { - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==" - }, - "chalk@4.1.2": { - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": [ - "ansi-styles@4.3.0", - "supports-color" - ] - }, - "chalk@5.6.2": { - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==" - }, - "cli-boxes@3.0.0": { - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==" - }, - "cli-progress@3.12.0": { - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "dependencies": [ - "string-width@4.2.3" - ] - }, - "cli-table3@0.6.5": { - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dependencies": [ - "string-width@4.2.3" - ], - "optionalDependencies": [ - "@colors/colors" - ] - }, - "color-convert@2.0.1": { - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": [ - "color-name" - ] - }, - "color-name@1.1.4": { - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "commander@5.1.0": { - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, - "content-disposition@0.5.4": { - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": [ - "safe-buffer" - ] - }, - "content-type@1.0.5": { - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "cookie-signature@1.0.7": { - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" - }, - "cookie@0.7.2": { - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - }, - "cors@2.8.5": { - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": [ - "object-assign", - "vary" - ] - }, - "debug@2.6.9": { - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": [ - "ms@2.0.0" - ] - }, - "debug@4.4.3": { - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": [ - "ms@2.1.3" - ] - }, - "depd@2.0.0": { - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy@1.2.0": { - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "dotenv@16.6.1": { - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==" - }, - "dunder-proto@1.0.1": { - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": [ - "call-bind-apply-helpers", - "es-errors", - "gopd" - ] - }, - "ee-first@1.1.1": { - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "emoji-regex@10.6.0": { - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" - }, - "emoji-regex@8.0.0": { - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl@2.0.0": { - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, - "es-define-property@1.0.1": { - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" - }, - "es-errors@1.3.0": { - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-object-atoms@1.1.1": { - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": [ - "es-errors" - ] - }, - "esbuild@0.27.2": { - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "optionalDependencies": [ - "@esbuild/aix-ppc64", - "@esbuild/android-arm", - "@esbuild/android-arm64", - "@esbuild/android-x64", - "@esbuild/darwin-arm64", - "@esbuild/darwin-x64", - "@esbuild/freebsd-arm64", - "@esbuild/freebsd-x64", - "@esbuild/linux-arm", - "@esbuild/linux-arm64", - "@esbuild/linux-ia32", - "@esbuild/linux-loong64", - "@esbuild/linux-mips64el", - "@esbuild/linux-ppc64", - "@esbuild/linux-riscv64", - "@esbuild/linux-s390x", - "@esbuild/linux-x64", - "@esbuild/netbsd-arm64", - "@esbuild/netbsd-x64", - "@esbuild/openbsd-arm64", - "@esbuild/openbsd-x64", - "@esbuild/openharmony-arm64", - "@esbuild/sunos-x64", - "@esbuild/win32-arm64", - "@esbuild/win32-ia32", - "@esbuild/win32-x64" - ], - "scripts": true, - "bin": true - }, - "escape-html@1.0.3": { - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "etag@1.8.1": { - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "eventsource-parser@1.1.2": { - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==" - }, - "express@4.22.1": { - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "dependencies": [ - "accepts", - "array-flatten", - "body-parser", - "content-disposition", - "content-type", - "cookie", - "cookie-signature", - "debug@2.6.9", - "depd", - "encodeurl", - "escape-html", - "etag", - "finalhandler", - "fresh", - "http-errors", - "merge-descriptors", - "methods", - "on-finished", - "parseurl", - "path-to-regexp", - "proxy-addr", - "qs", - "range-parser", - "safe-buffer", - "send", - "serve-static", - "setprototypeof", - "statuses", - "type-is", - "utils-merge", - "vary" - ] - }, - "finalhandler@1.3.2": { - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "dependencies": [ - "debug@2.6.9", - "encodeurl", - "escape-html", - "on-finished", - "parseurl", - "statuses", - "unpipe" - ] - }, - "forwarded@0.2.0": { - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh@0.5.2": { - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "function-bind@1.1.2": { - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "get-east-asian-width@1.4.0": { - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==" - }, - "get-intrinsic@1.3.0": { - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": [ - "call-bind-apply-helpers", - "es-define-property", - "es-errors", - "es-object-atoms", - "function-bind", - "get-proto", - "gopd", - "has-symbols", - "hasown", - "math-intrinsics" - ] - }, - "get-proto@1.0.1": { - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": [ - "dunder-proto", - "es-object-atoms" - ] - }, - "gopd@1.2.0": { - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" - }, - "graceful-fs@4.2.11": { - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "has-flag@4.0.0": { - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-symbols@1.1.0": { - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" - }, - "hasown@2.0.2": { - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": [ - "function-bind" - ] - }, - "http-errors@2.0.1": { - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dependencies": [ - "depd", - "inherits", - "setprototypeof", - "statuses", - "toidentifier" - ] - }, - "iconv-lite@0.4.24": { - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": [ - "safer-buffer" - ] - }, - "inherits@2.0.4": { - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ipaddr.js@1.9.1": { - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-fullwidth-code-point@3.0.0": { - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "json-schema@0.4.0": { - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "math-intrinsics@1.1.0": { - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" - }, - "media-typer@0.3.0": { - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "merge-descriptors@1.0.3": { - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" - }, - "methods@1.1.2": { - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "mime-db@1.52.0": { - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types@2.1.35": { - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": [ - "mime-db" - ] - }, - "mime@1.6.0": { - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": true - }, - "minimatch@9.0.5": { - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": [ - "brace-expansion" - ] - }, - "ms@2.0.0": { - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "ms@2.1.3": { - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "mustache@4.2.0": { - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": true - }, - "negotiator@0.6.3": { - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "nunjucks@3.2.4": { - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "dependencies": [ - "a-sync-waterfall", - "asap", - "commander" - ], - "bin": true - }, - "object-assign@4.1.1": { - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect@1.13.4": { - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" - }, - "on-finished@2.4.1": { - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": [ - "ee-first" - ] - }, - "parseurl@1.3.3": { - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp@0.1.12": { - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" - }, - "pluralize@8.0.0": { - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" - }, - "proxy-addr@2.0.7": { - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": [ - "forwarded", - "ipaddr.js" - ] - }, - "qs@6.14.1": { - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", - "dependencies": [ - "side-channel" - ] - }, - "range-parser@1.2.1": { - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body@2.5.3": { - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "dependencies": [ - "bytes", - "http-errors", - "iconv-lite", - "unpipe" - ] - }, - "safe-buffer@5.2.1": { - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer@2.1.2": { - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send@0.19.2": { - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "dependencies": [ - "debug@2.6.9", - "depd", - "destroy", - "encodeurl", - "escape-html", - "etag", - "fresh", - "http-errors", - "mime", - "ms@2.1.3", - "on-finished", - "range-parser", - "statuses" - ] - }, - "serve-static@1.16.3": { - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "dependencies": [ - "encodeurl", - "escape-html", - "parseurl", - "send" - ] - }, - "setprototypeof@1.2.0": { - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "side-channel-list@1.0.0": { - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dependencies": [ - "es-errors", - "object-inspect" - ] - }, - "side-channel-map@1.0.1": { - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic", - "object-inspect" - ] - }, - "side-channel-weakmap@1.0.2": { - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic", - "object-inspect", - "side-channel-map" - ] - }, - "side-channel@1.1.0": { - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": [ - "es-errors", - "object-inspect", - "side-channel-list", - "side-channel-map", - "side-channel-weakmap" - ] - }, - "simple-git@3.30.0": { - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "dependencies": [ - "@kwsites/file-exists", - "@kwsites/promise-deferred", - "debug@4.4.3" - ] - }, - "source-map@0.7.6": { - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" - }, - "statuses@2.0.2": { - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" - }, - "string-width@4.2.3": { - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": [ - "emoji-regex@8.0.0", - "is-fullwidth-code-point", - "strip-ansi@6.0.1" - ] - }, - "string-width@7.2.0": { - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dependencies": [ - "emoji-regex@10.6.0", - "get-east-asian-width", - "strip-ansi@7.1.2" - ] - }, - "strip-ansi@6.0.1": { - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": [ - "ansi-regex@5.0.1" - ] - }, - "strip-ansi@7.1.2": { - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dependencies": [ - "ansi-regex@6.2.2" - ] - }, - "supports-color@7.2.0": { - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": [ - "has-flag" - ] - }, - "termi-link@1.1.0": { - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==" - }, - "toidentifier@1.0.1": { - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "type-fest@4.41.0": { - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==" - }, - "type-is@1.6.18": { - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": [ - "media-typer", - "mime-types" - ] - }, - "unpipe@1.0.0": { - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "utils-merge@1.0.1": { - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid@9.0.1": { - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "bin": true - }, - "vary@1.1.2": { - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "widest-line@5.0.0": { - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "dependencies": [ - "string-width@7.2.0" - ] - }, - "wrap-ansi@9.0.2": { - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dependencies": [ - "ansi-styles@6.2.3", - "string-width@7.2.0", - "strip-ansi@7.1.2" - ] - }, - "zod-to-json-schema@3.25.1_zod@4.3.5": { - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "dependencies": [ - "zod" - ] - }, - "zod@4.3.5": { - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==" - } - }, - "workspace": { - "dependencies": [ - "jsr:@braintrust/smoke-test-shared@*", - "jsr:@std/assert@^1.0.14", - "npm:braintrust@*" - ], - "links": { - "jsr:@braintrust/smoke-test-shared": {}, - "npm:@braintrust/smoke-test-shared@1.0.0": {}, - "npm:braintrust-sdk-js@0.0.1": {}, - "npm:braintrust@2.1.0": { - "dependencies": [ - "npm:@ai-sdk/provider@^1.1.3", - "npm:@next/env@^14.2.3", - "npm:@types/nunjucks@^3.2.6", - "npm:@vercel/functions@^1.0.2", - "npm:argparse@^2.0.1", - "npm:boxen@^8.0.1", - "npm:chalk@^4.1.2", - "npm:cli-progress@^3.12.0", - "npm:cli-table3@~0.6.5", - "npm:cors@^2.8.5", - "npm:dotenv@^16.4.5", - "npm:esbuild@0.27", - "npm:eventsource-parser@^1.1.2", - "npm:express@^4.21.2", - "npm:graceful-fs@^4.2.11", - "npm:http-errors@2", - "npm:minimatch@^9.0.3", - "npm:mustache@^4.2.0", - "npm:nunjucks@^3.2.4", - "npm:pluralize@8", - "npm:simple-git@^3.21.0", - "npm:source-map@~0.7.4", - "npm:termi-link@^1.0.1", - "npm:uuid@^9.0.1", - "npm:zod-to-json-schema@^3.25.0" - ], - "peerDependencies": [ - "npm:zod@^3.25.34 || 4" - ] - } - } - } -} From c42ed80bdb52a04dc13d7ed0da31df2a13ddb11d Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 20 Jan 2026 17:48:21 -0800 Subject: [PATCH 38/57] fix deno-browserg --- js/smoke/scenarios/deno-browser/.gitignore | 1 + js/smoke/scenarios/deno-browser/Makefile | 21 +- js/smoke/scenarios/deno-browser/deno.lock | 908 --------------------- 3 files changed, 10 insertions(+), 920 deletions(-) delete mode 100644 js/smoke/scenarios/deno-browser/deno.lock diff --git a/js/smoke/scenarios/deno-browser/.gitignore b/js/smoke/scenarios/deno-browser/.gitignore index 49103d242..0203990b0 100644 --- a/js/smoke/scenarios/deno-browser/.gitignore +++ b/js/smoke/scenarios/deno-browser/.gitignore @@ -1,3 +1,4 @@ node_modules/ .DS_Store package-lock.json +deno.lock diff --git a/js/smoke/scenarios/deno-browser/Makefile b/js/smoke/scenarios/deno-browser/Makefile index 09ab17ddf..09ad4910d 100644 --- a/js/smoke/scenarios/deno-browser/Makefile +++ b/js/smoke/scenarios/deno-browser/Makefile @@ -4,18 +4,15 @@ setup: @echo "==> Setting up deno-browser scenario" mise install @# Deno uses workspace links - need SDK dist/ folder to exist - @if [ ! -d ../../../dist ]; then \ - if [ -n "$(BRAINTRUST_TAR)" ]; then \ - echo "==> Extracting SDK tarball for workspace link"; \ - TARBALL_PATH="$$(cd ../.. && pwd)/$(BRAINTRUST_TAR)"; \ - echo "==> Resolved tarball path: $$TARBALL_PATH"; \ - cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ - else \ - echo "==> Building SDK for workspace link"; \ - cd ../../.. && pnpm exec turbo build --filter=braintrust; \ - fi; \ - fi - deno install + if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Extracting SDK tarball for workspace link"; \ + TARBALL_PATH="$$(cd ../.. && pwd)/$(BRAINTRUST_TAR)"; \ + echo "==> Resolved tarball path: $$TARBALL_PATH"; \ + cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ + else \ + echo "==> Building SDK for workspace link"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust; \ + fi; \ test: setup deno test --sloppy-imports --allow-all tests/*.test.ts diff --git a/js/smoke/scenarios/deno-browser/deno.lock b/js/smoke/scenarios/deno-browser/deno.lock deleted file mode 100644 index d32c2672c..000000000 --- a/js/smoke/scenarios/deno-browser/deno.lock +++ /dev/null @@ -1,908 +0,0 @@ -{ - "version": "5", - "specifiers": { - "jsr:@std/assert@^1.0.14": "1.0.16", - "jsr:@std/internal@^1.0.12": "1.0.12", - "npm:braintrust@^2.0.2": "2.0.2_zod@4.3.5" - }, - "jsr": { - "@std/assert@1.0.16": { - "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", - "dependencies": [ - "jsr:@std/internal" - ] - }, - "@std/internal@1.0.12": { - "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" - } - }, - "npm": { - "@ai-sdk/provider@1.1.3": { - "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", - "dependencies": [ - "json-schema" - ] - }, - "@colors/colors@1.5.0": { - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" - }, - "@esbuild/aix-ppc64@0.27.2": { - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "os": ["aix"], - "cpu": ["ppc64"] - }, - "@esbuild/android-arm64@0.27.2": { - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "os": ["android"], - "cpu": ["arm64"] - }, - "@esbuild/android-arm@0.27.2": { - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "os": ["android"], - "cpu": ["arm"] - }, - "@esbuild/android-x64@0.27.2": { - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "os": ["android"], - "cpu": ["x64"] - }, - "@esbuild/darwin-arm64@0.27.2": { - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "os": ["darwin"], - "cpu": ["arm64"] - }, - "@esbuild/darwin-x64@0.27.2": { - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "os": ["darwin"], - "cpu": ["x64"] - }, - "@esbuild/freebsd-arm64@0.27.2": { - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "os": ["freebsd"], - "cpu": ["arm64"] - }, - "@esbuild/freebsd-x64@0.27.2": { - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "os": ["freebsd"], - "cpu": ["x64"] - }, - "@esbuild/linux-arm64@0.27.2": { - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@esbuild/linux-arm@0.27.2": { - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "os": ["linux"], - "cpu": ["arm"] - }, - "@esbuild/linux-ia32@0.27.2": { - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "os": ["linux"], - "cpu": ["ia32"] - }, - "@esbuild/linux-loong64@0.27.2": { - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "os": ["linux"], - "cpu": ["loong64"] - }, - "@esbuild/linux-mips64el@0.27.2": { - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "os": ["linux"], - "cpu": ["mips64el"] - }, - "@esbuild/linux-ppc64@0.27.2": { - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "os": ["linux"], - "cpu": ["ppc64"] - }, - "@esbuild/linux-riscv64@0.27.2": { - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "os": ["linux"], - "cpu": ["riscv64"] - }, - "@esbuild/linux-s390x@0.27.2": { - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "os": ["linux"], - "cpu": ["s390x"] - }, - "@esbuild/linux-x64@0.27.2": { - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@esbuild/netbsd-arm64@0.27.2": { - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "os": ["netbsd"], - "cpu": ["arm64"] - }, - "@esbuild/netbsd-x64@0.27.2": { - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "os": ["netbsd"], - "cpu": ["x64"] - }, - "@esbuild/openbsd-arm64@0.27.2": { - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "os": ["openbsd"], - "cpu": ["arm64"] - }, - "@esbuild/openbsd-x64@0.27.2": { - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "os": ["openbsd"], - "cpu": ["x64"] - }, - "@esbuild/openharmony-arm64@0.27.2": { - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "os": ["openharmony"], - "cpu": ["arm64"] - }, - "@esbuild/sunos-x64@0.27.2": { - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "os": ["sunos"], - "cpu": ["x64"] - }, - "@esbuild/win32-arm64@0.27.2": { - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "os": ["win32"], - "cpu": ["arm64"] - }, - "@esbuild/win32-ia32@0.27.2": { - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "os": ["win32"], - "cpu": ["ia32"] - }, - "@esbuild/win32-x64@0.27.2": { - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "os": ["win32"], - "cpu": ["x64"] - }, - "@kwsites/file-exists@1.1.1": { - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dependencies": [ - "debug@4.4.3" - ] - }, - "@kwsites/promise-deferred@1.1.1": { - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" - }, - "@next/env@14.2.35": { - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==" - }, - "@types/nunjucks@3.2.6": { - "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==" - }, - "@vercel/functions@1.6.0": { - "integrity": "sha512-R6FKQrYT5MZs5IE1SqeCJWxMuBdHawFcCZboKKw8p7s+6/mcd55Gx6tWmyKnQTyrSEA04NH73Tc9CbqpEle8RA==" - }, - "a-sync-waterfall@1.0.1": { - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" - }, - "accepts@1.3.8": { - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": [ - "mime-types", - "negotiator" - ] - }, - "ansi-align@3.0.1": { - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dependencies": [ - "string-width@4.2.3" - ] - }, - "ansi-regex@5.0.1": { - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-regex@6.2.2": { - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==" - }, - "ansi-styles@4.3.0": { - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": [ - "color-convert" - ] - }, - "ansi-styles@6.2.3": { - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" - }, - "argparse@2.0.1": { - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "array-flatten@1.1.1": { - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "asap@2.0.6": { - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "balanced-match@1.0.2": { - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "body-parser@1.20.4": { - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "dependencies": [ - "bytes", - "content-type", - "debug@2.6.9", - "depd", - "destroy", - "http-errors", - "iconv-lite", - "on-finished", - "qs", - "raw-body", - "type-is", - "unpipe" - ] - }, - "boxen@8.0.1": { - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "dependencies": [ - "ansi-align", - "camelcase", - "chalk@5.6.2", - "cli-boxes", - "string-width@7.2.0", - "type-fest", - "widest-line", - "wrap-ansi" - ] - }, - "brace-expansion@2.0.2": { - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dependencies": [ - "balanced-match" - ] - }, - "braintrust@2.0.2_zod@4.3.5": { - "dependencies": [ - "@ai-sdk/provider", - "@next/env", - "@types/nunjucks", - "@vercel/functions", - "argparse", - "boxen", - "chalk@4.1.2", - "cli-progress", - "cli-table3", - "cors", - "dotenv", - "esbuild", - "eventsource-parser", - "express", - "graceful-fs", - "http-errors", - "minimatch", - "mustache", - "nunjucks", - "pluralize", - "simple-git", - "source-map", - "termi-link", - "uuid", - "zod", - "zod-to-json-schema" - ], - "bin": true - }, - "bytes@3.1.2": { - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind-apply-helpers@1.0.2": { - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": [ - "es-errors", - "function-bind" - ] - }, - "call-bound@1.0.4": { - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": [ - "call-bind-apply-helpers", - "get-intrinsic" - ] - }, - "camelcase@8.0.0": { - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==" - }, - "chalk@4.1.2": { - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": [ - "ansi-styles@4.3.0", - "supports-color" - ] - }, - "chalk@5.6.2": { - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==" - }, - "cli-boxes@3.0.0": { - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==" - }, - "cli-progress@3.12.0": { - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "dependencies": [ - "string-width@4.2.3" - ] - }, - "cli-table3@0.6.5": { - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dependencies": [ - "string-width@4.2.3" - ], - "optionalDependencies": [ - "@colors/colors" - ] - }, - "color-convert@2.0.1": { - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": [ - "color-name" - ] - }, - "color-name@1.1.4": { - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "commander@5.1.0": { - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, - "content-disposition@0.5.4": { - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": [ - "safe-buffer" - ] - }, - "content-type@1.0.5": { - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "cookie-signature@1.0.7": { - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" - }, - "cookie@0.7.2": { - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - }, - "cors@2.8.5": { - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": [ - "object-assign", - "vary" - ] - }, - "debug@2.6.9": { - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": [ - "ms@2.0.0" - ] - }, - "debug@4.4.3": { - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": [ - "ms@2.1.3" - ] - }, - "depd@2.0.0": { - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy@1.2.0": { - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "dotenv@16.6.1": { - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==" - }, - "dunder-proto@1.0.1": { - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": [ - "call-bind-apply-helpers", - "es-errors", - "gopd" - ] - }, - "ee-first@1.1.1": { - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "emoji-regex@10.6.0": { - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" - }, - "emoji-regex@8.0.0": { - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl@2.0.0": { - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, - "es-define-property@1.0.1": { - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" - }, - "es-errors@1.3.0": { - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-object-atoms@1.1.1": { - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": [ - "es-errors" - ] - }, - "esbuild@0.27.2": { - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "optionalDependencies": [ - "@esbuild/aix-ppc64", - "@esbuild/android-arm", - "@esbuild/android-arm64", - "@esbuild/android-x64", - "@esbuild/darwin-arm64", - "@esbuild/darwin-x64", - "@esbuild/freebsd-arm64", - "@esbuild/freebsd-x64", - "@esbuild/linux-arm", - "@esbuild/linux-arm64", - "@esbuild/linux-ia32", - "@esbuild/linux-loong64", - "@esbuild/linux-mips64el", - "@esbuild/linux-ppc64", - "@esbuild/linux-riscv64", - "@esbuild/linux-s390x", - "@esbuild/linux-x64", - "@esbuild/netbsd-arm64", - "@esbuild/netbsd-x64", - "@esbuild/openbsd-arm64", - "@esbuild/openbsd-x64", - "@esbuild/openharmony-arm64", - "@esbuild/sunos-x64", - "@esbuild/win32-arm64", - "@esbuild/win32-ia32", - "@esbuild/win32-x64" - ], - "scripts": true, - "bin": true - }, - "escape-html@1.0.3": { - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "etag@1.8.1": { - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "eventsource-parser@1.1.2": { - "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==" - }, - "express@4.22.1": { - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "dependencies": [ - "accepts", - "array-flatten", - "body-parser", - "content-disposition", - "content-type", - "cookie", - "cookie-signature", - "debug@2.6.9", - "depd", - "encodeurl", - "escape-html", - "etag", - "finalhandler", - "fresh", - "http-errors", - "merge-descriptors", - "methods", - "on-finished", - "parseurl", - "path-to-regexp", - "proxy-addr", - "qs", - "range-parser", - "safe-buffer", - "send", - "serve-static", - "setprototypeof", - "statuses", - "type-is", - "utils-merge", - "vary" - ] - }, - "finalhandler@1.3.2": { - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "dependencies": [ - "debug@2.6.9", - "encodeurl", - "escape-html", - "on-finished", - "parseurl", - "statuses", - "unpipe" - ] - }, - "forwarded@0.2.0": { - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh@0.5.2": { - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "function-bind@1.1.2": { - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "get-east-asian-width@1.4.0": { - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==" - }, - "get-intrinsic@1.3.0": { - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": [ - "call-bind-apply-helpers", - "es-define-property", - "es-errors", - "es-object-atoms", - "function-bind", - "get-proto", - "gopd", - "has-symbols", - "hasown", - "math-intrinsics" - ] - }, - "get-proto@1.0.1": { - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": [ - "dunder-proto", - "es-object-atoms" - ] - }, - "gopd@1.2.0": { - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" - }, - "graceful-fs@4.2.11": { - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "has-flag@4.0.0": { - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-symbols@1.1.0": { - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" - }, - "hasown@2.0.2": { - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": [ - "function-bind" - ] - }, - "http-errors@2.0.1": { - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dependencies": [ - "depd", - "inherits", - "setprototypeof", - "statuses", - "toidentifier" - ] - }, - "iconv-lite@0.4.24": { - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": [ - "safer-buffer" - ] - }, - "inherits@2.0.4": { - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ipaddr.js@1.9.1": { - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-fullwidth-code-point@3.0.0": { - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "json-schema@0.4.0": { - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "math-intrinsics@1.1.0": { - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" - }, - "media-typer@0.3.0": { - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "merge-descriptors@1.0.3": { - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" - }, - "methods@1.1.2": { - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "mime-db@1.52.0": { - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types@2.1.35": { - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": [ - "mime-db" - ] - }, - "mime@1.6.0": { - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": true - }, - "minimatch@9.0.5": { - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": [ - "brace-expansion" - ] - }, - "ms@2.0.0": { - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "ms@2.1.3": { - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "mustache@4.2.0": { - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": true - }, - "negotiator@0.6.3": { - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "nunjucks@3.2.4": { - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "dependencies": [ - "a-sync-waterfall", - "asap", - "commander" - ], - "bin": true - }, - "object-assign@4.1.1": { - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect@1.13.4": { - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" - }, - "on-finished@2.4.1": { - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": [ - "ee-first" - ] - }, - "parseurl@1.3.3": { - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp@0.1.12": { - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" - }, - "pluralize@8.0.0": { - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" - }, - "proxy-addr@2.0.7": { - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": [ - "forwarded", - "ipaddr.js" - ] - }, - "qs@6.14.1": { - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", - "dependencies": [ - "side-channel" - ] - }, - "range-parser@1.2.1": { - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body@2.5.3": { - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "dependencies": [ - "bytes", - "http-errors", - "iconv-lite", - "unpipe" - ] - }, - "safe-buffer@5.2.1": { - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer@2.1.2": { - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send@0.19.2": { - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "dependencies": [ - "debug@2.6.9", - "depd", - "destroy", - "encodeurl", - "escape-html", - "etag", - "fresh", - "http-errors", - "mime", - "ms@2.1.3", - "on-finished", - "range-parser", - "statuses" - ] - }, - "serve-static@1.16.3": { - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "dependencies": [ - "encodeurl", - "escape-html", - "parseurl", - "send" - ] - }, - "setprototypeof@1.2.0": { - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "side-channel-list@1.0.0": { - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dependencies": [ - "es-errors", - "object-inspect" - ] - }, - "side-channel-map@1.0.1": { - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic", - "object-inspect" - ] - }, - "side-channel-weakmap@1.0.2": { - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic", - "object-inspect", - "side-channel-map" - ] - }, - "side-channel@1.1.0": { - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": [ - "es-errors", - "object-inspect", - "side-channel-list", - "side-channel-map", - "side-channel-weakmap" - ] - }, - "simple-git@3.30.0": { - "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", - "dependencies": [ - "@kwsites/file-exists", - "@kwsites/promise-deferred", - "debug@4.4.3" - ] - }, - "source-map@0.7.6": { - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" - }, - "statuses@2.0.2": { - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" - }, - "string-width@4.2.3": { - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": [ - "emoji-regex@8.0.0", - "is-fullwidth-code-point", - "strip-ansi@6.0.1" - ] - }, - "string-width@7.2.0": { - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dependencies": [ - "emoji-regex@10.6.0", - "get-east-asian-width", - "strip-ansi@7.1.2" - ] - }, - "strip-ansi@6.0.1": { - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": [ - "ansi-regex@5.0.1" - ] - }, - "strip-ansi@7.1.2": { - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dependencies": [ - "ansi-regex@6.2.2" - ] - }, - "supports-color@7.2.0": { - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": [ - "has-flag" - ] - }, - "termi-link@1.1.0": { - "integrity": "sha512-2qSN6TnomHgVLtk+htSWbaYs4Rd2MH/RU7VpHTy6MBstyNyWbM4yKd1DCYpE3fDg8dmGWojXCngNi/MHCzGuAA==" - }, - "toidentifier@1.0.1": { - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "type-fest@4.41.0": { - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==" - }, - "type-is@1.6.18": { - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": [ - "media-typer", - "mime-types" - ] - }, - "unpipe@1.0.0": { - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "utils-merge@1.0.1": { - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid@9.0.1": { - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "bin": true - }, - "vary@1.1.2": { - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "widest-line@5.0.0": { - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "dependencies": [ - "string-width@7.2.0" - ] - }, - "wrap-ansi@9.0.2": { - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dependencies": [ - "ansi-styles@6.2.3", - "string-width@7.2.0", - "strip-ansi@7.1.2" - ] - }, - "zod-to-json-schema@3.25.1_zod@4.3.5": { - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "dependencies": [ - "zod" - ] - }, - "zod@4.3.5": { - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==" - } - }, - "workspace": { - "dependencies": [ - "jsr:@braintrust/smoke-test-shared@*", - "jsr:@std/assert@^1.0.14", - "npm:braintrust@^2.0.2" - ], - "links": { - "jsr:@braintrust/smoke-test-shared": {}, - "npm:@braintrust/smoke-test-shared@1.0.0": {}, - "npm:braintrust-sdk-js@0.0.1": {}, - "npm:braintrust@2.0.2": { - "dependencies": [ - "npm:@ai-sdk/provider@^1.1.3", - "npm:@next/env@^14.2.3", - "npm:@types/nunjucks@^3.2.6", - "npm:@vercel/functions@^1.0.2", - "npm:argparse@^2.0.1", - "npm:boxen@^8.0.1", - "npm:chalk@^4.1.2", - "npm:cli-progress@^3.12.0", - "npm:cli-table3@~0.6.5", - "npm:cors@^2.8.5", - "npm:dotenv@^16.4.5", - "npm:esbuild@0.27", - "npm:eventsource-parser@^1.1.2", - "npm:express@^4.21.2", - "npm:graceful-fs@^4.2.11", - "npm:http-errors@2", - "npm:minimatch@^9.0.3", - "npm:mustache@^4.2.0", - "npm:nunjucks@^3.2.4", - "npm:pluralize@8", - "npm:simple-git@^3.21.0", - "npm:source-map@~0.7.4", - "npm:termi-link@^1.0.1", - "npm:uuid@^9.0.1", - "npm:zod-to-json-schema@^3.25.0" - ], - "peerDependencies": [ - "npm:zod@^3.25.34 || 4" - ] - } - } - } -} From fa88223803dd4b6aee9e50a0c373c275b72f1fcd Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Wed, 21 Jan 2026 22:11:18 -0800 Subject: [PATCH 39/57] Modify package json exports for browser environments (#1295) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR updates default entrypoint selection so each runtime resolves the correct build. Node environments select the Node entrypoint, while browser and worker environments default to the browser build. Worker runtimes no longer implicitly resolve the Node build. Importing braintrust/node must be done explicitly and is expected to fail in workers (e.g. cloudflare-vite-hono-vite-dev-node-esm), rather than failing due to accidental default resolution. PR changes: The change uses Node’s conditional exports to ensure the correct build is selected based on runtime capabilities, instead of relying on ambiguous defaults. Each scenario now checks that the appropriate isomorphic build type (Node vs browser) is selected and that module resolution lands on the correct output files for that environment. --- js/package.json | 17 +- js/smoke/README.md | 5 +- .../.gitignore | 0 .../Makefile | 11 +- .../README.md | 37 +++ .../mise.toml | 0 .../package.json | 18 ++ .../src/worker-node-esm.ts | 75 ++++++ .../tests/node-esm-import.test.mjs} | 118 +++++---- .../tsconfig.json | 0 .../vite.config.ts | 10 + .../wrangler.toml | 4 + .../cloudflare-vite-hono-vite-dev/.gitignore | 7 + .../cloudflare-vite-hono-vite-dev/Makefile | 28 +++ .../cloudflare-vite-hono-vite-dev/README.md | 29 +++ .../cloudflare-vite-hono-vite-dev/mise.toml | 3 + .../package.json | 5 +- .../src/worker.ts | 11 +- .../tests/vite-dev.test.mjs | 104 ++++++++ .../tsconfig.json | 16 ++ .../vite.config.ts | 0 .../wrangler.toml | 0 .../.gitignore | 7 + .../Makefile | 28 +++ .../README.md | 37 +++ .../mise.toml | 3 + .../package.json | 17 ++ .../src/worker.ts | 133 ++++++++++ .../tests/worker.test.mjs | 0 .../tsconfig.json | 16 ++ .../wrangler.toml | 3 + .../scenarios/cloudflare-vite-hono/README.md | 51 ---- .../src/worker.ts | 12 +- .../src/worker.ts | 13 +- .../src/worker.ts | 14 +- .../src/worker.ts | 11 +- js/smoke/scenarios/deno-browser/deno.json | 2 +- .../deno-browser/tests/shared-suite.test.ts | 10 +- .../deno-node/tests/shared-suite.test.ts | 8 +- .../jest-node/tests/shared-suite.test.js | 5 +- .../src/app/api/smoke-test/edge/route.ts | 8 +- .../src/app/api/smoke-test/node/route.ts | 8 +- .../otel-v1/tests/shared-suite.test.ts | 8 +- .../playwright-browser/src/browser-tests.ts | 7 +- js/smoke/shared/src/index.ts | 1 + .../shared/src/suites/import-verification.ts | 235 ++++++++++++++++++ js/src/browser-config.ts | 4 + js/src/isomorph.ts | 3 + js/src/logger.ts | 1 + js/src/node.ts | 3 + .../api-compatibility.test.ts | 146 +++++++++-- 51 files changed, 1131 insertions(+), 161 deletions(-) rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev-node-esm}/.gitignore (100%) rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev-node-esm}/Makefile (72%) create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/README.md rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev-node-esm}/mise.toml (100%) create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/package.json create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts rename js/smoke/scenarios/{cloudflare-vite-hono/tests/vite-dev.test.mjs => cloudflare-vite-hono-vite-dev-node-esm/tests/node-esm-import.test.mjs} (55%) mode change 100755 => 100644 rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev-node-esm}/tsconfig.json (100%) create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/vite.config.ts create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/wrangler.toml create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev/Makefile create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev/README.md create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev/mise.toml rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev}/package.json (85%) rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev}/src/worker.ts (90%) create mode 100755 js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tsconfig.json rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev}/vite.config.ts (100%) rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-vite-dev}/wrangler.toml (100%) create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/.gitignore create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/Makefile create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/README.md create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/mise.toml create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts rename js/smoke/scenarios/{cloudflare-vite-hono => cloudflare-vite-hono-wrangler-dev}/tests/worker.test.mjs (100%) create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/tsconfig.json create mode 100644 js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/wrangler.toml delete mode 100644 js/smoke/scenarios/cloudflare-vite-hono/README.md diff --git a/js/package.json b/js/package.json index c62720945..b211d7cfb 100644 --- a/js/package.json +++ b/js/package.json @@ -24,15 +24,28 @@ "./package.json": "./package.json", ".": { "types": "./dist/index.d.ts", + "edge-light": "./dist/browser.mjs", + "workerd": "./dist/browser.mjs", + "node": { + "import": "./dist/index.mjs", + "require": "./dist/index.js" + }, + "browser": "./dist/browser.mjs", "import": "./dist/index.mjs", - "module": "./dist/index.mjs", - "require": "./dist/index.js" + "require": "./dist/index.js", + "default": "./dist/browser.mjs" }, "./browser": { "import": "./dist/browser.mjs", "module": "./dist/browser.mjs", "require": "./dist/browser.js" }, + "./node": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "module": "./dist/index.mjs", + "require": "./dist/index.js" + }, "./dev": { "types": "./dev/dist/index.d.ts", "import": "./dev/dist/index.mjs", diff --git a/js/smoke/README.md b/js/smoke/README.md index a483fef07..10d0ae2d7 100644 --- a/js/smoke/README.md +++ b/js/smoke/README.md @@ -85,7 +85,10 @@ async function runTests() { }); try { - const importResults = await runImportVerificationTests(braintrust); + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests(adapters, braintrust); const results = [...importResults, ...functionalResults]; diff --git a/js/smoke/scenarios/cloudflare-vite-hono/.gitignore b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/.gitignore similarity index 100% rename from js/smoke/scenarios/cloudflare-vite-hono/.gitignore rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/.gitignore diff --git a/js/smoke/scenarios/cloudflare-vite-hono/Makefile b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/Makefile similarity index 72% rename from js/smoke/scenarios/cloudflare-vite-hono/Makefile rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/Makefile index f7f6a321d..a4134fea1 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono/Makefile +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/Makefile @@ -1,7 +1,7 @@ .PHONY: setup test setup: - @echo "==> Setting up cloudflare-vite-hono" + @echo "==> Setting up cloudflare-vite-hono-vite-dev-node-esm" mise install @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build @if [ -n "$(BRAINTRUST_TAR)" ]; then \ @@ -16,7 +16,6 @@ setup: break; \ done; \ fi - @# Build shared package if needed @# Build shared package (if not running from parent) @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ echo "==> Building shared package"; \ @@ -25,9 +24,5 @@ setup: npm install --no-package-lock test: setup - @echo "==> Running cloudflare-vite-hono tests" - @echo "" - @npx tsx tests/worker.test.mjs || WORKER_FAILED=1; \ - echo ""; \ - npx tsx tests/vite-dev.test.mjs || true; \ - if [ "$$WORKER_FAILED" = "1" ]; then exit 1; fi + @echo "==> Running cloudflare-vite-hono-vite-dev-node-esm test" + @npx tsx tests/node-esm-import.test.mjs diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/README.md b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/README.md new file mode 100644 index 000000000..c365363a1 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/README.md @@ -0,0 +1,37 @@ +# Cloudflare Vite + Hono Vite Dev Server Test (Node ESM Build) + +Tests whether the Braintrust SDK (Node.js ESM build) can be loaded in Vite's dev server. + +## Design Decisions + +**Tarball installation:** Uses well-known tarball path (`braintrust-latest.tgz`) to avoid package.json changes. + +**Vite dev server:** Tests SDK through Vite's development server. + +**Hono framework:** Uses Hono for elegant routing instead of raw Worker API. + +**Node ESM build:** Uses `braintrust/node` import to test Node.js ESM build resolution. + +**nodejs_compat_v2:** Enables Node.js API compatibility in Cloudflare Workers runtime. + +## Test Suite + +Tests whether the SDK's Node.js ESM build can be loaded in Vite's dev server. + +**Expected result:** XFAIL (expected to fail) - Vite cannot load the Node.js ESM build. + +**Known issues:** + +- Nunjucks uses `Object.setPrototypeOf` in ways that fail in Vite's ESM bundler during dependency pre-bundling, causing: `TypeError: Object prototype may only be an Object or null: undefined` + +**This failure is expected and acceptable** - users should use Wrangler (production mode) for Cloudflare Workers development with the Node.js build, not Vite dev server. The wrangler-dev test validates the production deployment path. + +**Note:** If you see a different error (not the Nunjucks error), that's unexpected and should be investigated. + +## Running Tests + +```bash +make test # Runs the vite dev node esm test +``` + +**Success criteria:** The test should produce an expected failure (xfail) for Nunjucks incompatibility. The test itself should not fail (exit code 0). diff --git a/js/smoke/scenarios/cloudflare-vite-hono/mise.toml b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/mise.toml similarity index 100% rename from js/smoke/scenarios/cloudflare-vite-hono/mise.toml rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/mise.toml diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/package.json b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/package.json new file mode 100644 index 000000000..2d67e1a18 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/package.json @@ -0,0 +1,18 @@ +{ + "name": "smoke-cloudflare-vite-hono-vite-dev-node-esm", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "hono": "^4.11.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/vite-plugin": "^1.15.3", + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^24.10.1", + "tsx": "^4.19.2", + "typescript": "^5.8.3", + "vite": "^6.0.0" + } +} diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts new file mode 100644 index 000000000..2bc7dcc21 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts @@ -0,0 +1,75 @@ +import { Hono } from "hono"; +import { runImportVerificationTests, type TestResult } from "../../../shared"; + +// Explicitly import Node.js ESM build +import * as braintrustNode from "braintrust/node"; + +const app = new Hono<{ Bindings: Env }>(); + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +async function runNodeEsmImportTest(): Promise { + try { + // Vite bundler should resolve Node.js ESM build when importing from "braintrust/node" + // Note: This worker will not actually run via vite dev due to nunjucks bundling error, + // but we test import resolution to verify the export path works correctly. + const importResults = await runImportVerificationTests(braintrustNode, { + expectedBuild: "node", + expectedFormat: "esm", + }); + + const failures = importResults.filter((r) => r.status === "fail"); + + return { + success: failures.length === 0, + message: + failures.length === 0 + ? "Node.js ESM import resolution test passed" + : `${failures.length} test(s) failed`, + totalTests: importResults.length, + passedTests: importResults.length - failures.length, + failedTests: failures.length, + results: importResults, + failures: failures.length > 0 ? failures : undefined, + }; + } catch (error) { + return { + success: false, + message: `Error during Node.js ESM import test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +app.get("/", (c) => + c.text(`Braintrust Cloudflare Vite + Hono Smoke Test (Node.js ESM Build) + +GET /api/ - Basic API endpoint +GET /api/test - Run shared test suites + +This worker tests the Braintrust SDK (Node.js ESM build) in a Vite + Hono + Cloudflare Workers environment. +Explicitly imports "braintrust/node" to test Node.js ESM build resolution.`), +); + +app.get("/api/", (c) => + c.json({ name: "Braintrust", framework: "Hono", build: "node-esm" }), +); + +app.get("/api/test", async (c) => { + const result = await runNodeEsmImportTest(); + return c.json(result, result.success ? 200 : 500); +}); + +export default app; diff --git a/js/smoke/scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/tests/node-esm-import.test.mjs old mode 100755 new mode 100644 similarity index 55% rename from js/smoke/scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/tests/node-esm-import.test.mjs index f49a5f3df..20eb0d30c --- a/js/smoke/scenarios/cloudflare-vite-hono/tests/vite-dev.test.mjs +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/tests/node-esm-import.test.mjs @@ -1,71 +1,90 @@ #!/usr/bin/env node /** - * Test for Vite dev server compatibility with Braintrust SDK + * Test for Vite dev server compatibility with braintrust/node import * - * This test verifies a known issue: When Vite tries to pre-bundle the Braintrust SDK, - * it encounters Nunjucks (used for prompt templating) which doesn't work in Vite's - * ESM bundler due to its use of Object.setPrototypeOf with undefined values. + * This test verifies if Vite can pre-bundle braintrust/node (Node.js ESM build) + * without hitting the Nunjucks bundling error. The Node.js build includes Nunjucks + * (used for prompt templating) which doesn't work in Vite's ESM bundler due to + * its use of Object.setPrototypeOf with undefined values. * * Error: TypeError: Object prototype may only be an Object or null: undefined * at _inheritsLoose (node_modules/nunjucks/src/object.js:8:77) * - * This is a known limitation when using the full Braintrust SDK in Vite dev mode. + * This test uses the worker-node-esm.ts which explicitly imports "braintrust/node". */ import { spawn } from "node:child_process"; import { rmSync } from "node:fs"; -import { displayTestResults } from "../../../shared/dist/index.mjs"; - -const MAX_RETRIES = 20; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { + displayTestResults, + hasFailures, +} from "../../../shared/dist/index.mjs"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const scenarioDir = join(__dirname, ".."); +const viteConfig = join(scenarioDir, "vite.config.ts"); + +const MAX_RETRIES = 40; const RETRY_DELAY_MS = 500; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); -async function testViteDevServer() { - console.log("Testing Vite dev server compatibility with Braintrust SDK...\n"); - +async function testViteDevServerWithNodeEsm() { // Clear Vite cache to force fresh dependency pre-bundling - console.log("1. Clearing Vite cache..."); try { - rmSync("node_modules/.vite", { recursive: true, force: true }); - console.log(" ✓ Vite cache cleared\n"); - } catch (error) { - console.log(" ℹ No cache to clear\n"); - } - - // Try to start Vite dev server - console.log("2. Starting Vite dev server..."); + rmSync(join(scenarioDir, "node_modules/.vite"), { + recursive: true, + force: true, + }); + } catch {} - const vite = spawn("npx", ["vite"], { + // Try to start Vite dev server with node-esm config + const vite = spawn("npx", ["vite", "--config", viteConfig], { stdio: ["ignore", "pipe", "pipe"], shell: true, + cwd: scenarioDir, }); let output = ""; let errorOutput = ""; + let resolved = false; + let testResult = null; vite.stdout.on("data", (d) => (output += d.toString())); vite.stderr.on("data", (d) => (errorOutput += d.toString())); - - // Wait for either success or error - let resolved = false; - let testResult = null; + vite.on("exit", (code) => { + if (code !== 0 && !resolved) { + // Non-zero exit indicates an error - check output immediately + setTimeout(() => { + if (!resolved) { + checkOutput(); + } + }, 100); + } + }); const checkOutput = () => { const combined = output + errorOutput; - // Check for the Nunjucks error - if (combined.includes("Object prototype may only be an Object or null")) { + // Check for the ONE specific Nunjucks error + const hasNunjucksError = combined.includes( + "Object prototype may only be an Object or null", + ); + + if (hasNunjucksError) { resolved = true; testResult = { success: false, issue: "vite-nunjucks-incompatibility", message: - "Vite dev server fails to start due to Nunjucks incompatibility", + "Vite dev server fails to start due to Nunjucks incompatibility when bundling braintrust/node", error: "TypeError: Object prototype may only be an Object or null: undefined", details: - "Vite's dependency pre-bundler cannot handle Nunjucks' use of Object.setPrototypeOf", + "Vite's dependency pre-bundler cannot handle Nunjucks' use of Object.setPrototypeOf when pre-bundling braintrust/node", recommendation: "Use 'braintrust/browser' import or configure Vite to exclude Nunjucks from optimization", }; @@ -76,7 +95,8 @@ async function testViteDevServer() { resolved = true; testResult = { success: true, - message: "Vite dev server started successfully", + message: + "Vite dev server started successfully with braintrust/node import", }; } }; @@ -102,11 +122,13 @@ async function testViteDevServer() { } if (!testResult) { + // No Nunjucks error detected - this is unexpected + const combined = output + errorOutput; testResult = { success: false, - issue: "timeout", + issue: "unexpected", message: "Vite dev server did not start or error within timeout", - output: (output + errorOutput).slice(-500), + output: combined.slice(-500), }; } @@ -116,8 +138,9 @@ async function testViteDevServer() { if (testResult.success) { results.push({ status: "pass", - name: "viteDevServerStartup", - message: "Vite dev server started successfully", + name: "viteDevServerNodeEsmStartup", + message: + "Vite dev server started successfully with braintrust/node import", }); } else if (testResult.issue === "vite-nunjucks-incompatibility") { // Extract error details @@ -135,10 +158,11 @@ async function testViteDevServer() { results.push({ status: "xfail", - name: "viteDevServerStartup", + name: "viteDevServerNodeEsmStartup", message: - "Expected failure: Nunjucks incompatibility with Vite bundler. " + + "Expected failure: Nunjucks incompatibility with Vite bundler when using braintrust/node. " + "Root cause: Nunjucks uses Object.setPrototypeOf in ways incompatible with Vite's ESM bundler. " + + "The Node.js ESM build includes Nunjucks, which causes this error during Vite's dependency pre-bundling. " + "Recommendation: Use 'braintrust/browser' import or exclude Nunjucks from Vite optimization", error: errorStack ? { @@ -150,7 +174,7 @@ async function testViteDevServer() { } else { results.push({ status: "fail", - name: "viteDevServerStartup", + name: "viteDevServerNodeEsmStartup", message: testResult.message, error: testResult.output ? { @@ -163,19 +187,21 @@ async function testViteDevServer() { // Use standardized display displayTestResults({ - scenarioName: "Vite Dev Server Compatibility Test", + scenarioName: "Vite Dev Server - braintrust/node Import Test", results, }); - // Return the actual test status - if (testResult.issue === "vite-nunjucks-incompatibility") { - // Expected failure - return 1 but this is documented - return 1; - } else if (testResult.success) { - return 0; - } else { + // Check for failures (hasFailures excludes xfail) + // Note: This test expects xfail for nunjucks error, so it won't fail the suite + if (hasFailures(results)) { return 1; } + return 0; } -testViteDevServer().then((code) => process.exit(code)); +testViteDevServerWithNodeEsm() + .then((code) => process.exit(code)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/js/smoke/scenarios/cloudflare-vite-hono/tsconfig.json b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/tsconfig.json similarity index 100% rename from js/smoke/scenarios/cloudflare-vite-hono/tsconfig.json rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/tsconfig.json diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/vite.config.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/vite.config.ts new file mode 100644 index 000000000..c5392a2e3 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "vite"; +import { cloudflare } from "@cloudflare/vite-plugin"; + +export default defineConfig({ + plugins: [ + cloudflare({ + configPath: "./wrangler.toml", + }), + ], +}); diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/wrangler.toml b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/wrangler.toml new file mode 100644 index 000000000..26dc09ea1 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/wrangler.toml @@ -0,0 +1,4 @@ +name = "smoke-cloudflare-vite-hono-vite-dev-node-esm" +main = "src/worker-node-esm.ts" +compatibility_date = "2025-01-15" +compatibility_flags = ["nodejs_compat_v2"] diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/.gitignore b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/.gitignore new file mode 100644 index 000000000..04e14a1fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +.wrangler/ +.DS_Store +*.log +.vite/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/Makefile b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/Makefile new file mode 100644 index 000000000..d101af62c --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/Makefile @@ -0,0 +1,28 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-vite-hono-vite-dev" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-vite-hono-vite-dev test" + @npx tsx tests/vite-dev.test.mjs diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/README.md b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/README.md new file mode 100644 index 000000000..2485bd93a --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/README.md @@ -0,0 +1,29 @@ +# Cloudflare Vite + Hono Vite Dev Server Test + +Tests whether the Braintrust SDK (browser build) can be loaded in Vite's dev server with hot module reloading. + +## Design Decisions + +**Tarball installation:** Uses well-known tarball path (`braintrust-latest.tgz`) to avoid package.json changes. + +**Vite dev server:** Tests SDK through Vite's development server with hot module reloading. + +**Hono framework:** Uses Hono for elegant routing instead of raw Worker API. + +**Browser build:** Uses `braintrust/browser` import since Cloudflare Workers don't support Node.js APIs. + +## Test Suite + +Tests whether the SDK can be loaded in Vite's dev server (with hot module reloading). + +**Expected result:** PASS - The browser build should work correctly with Vite dev server. + +**Known issue (resolved):** Earlier versions had Nunjucks dependency issues in Vite's ESM bundler. The browser build does not include Nunjucks, so this should work correctly. + +## Running Tests + +```bash +make test # Runs the vite dev test +``` + +**Success criteria:** The test must pass (19 tests: 18 pass, 1 xfail for Nunjucks). diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/mise.toml b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-vite-hono/package.json b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json similarity index 85% rename from js/smoke/scenarios/cloudflare-vite-hono/package.json rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json index 180b94c26..272211cad 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono/package.json +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json @@ -1,5 +1,5 @@ { - "name": "smoke-cloudflare-vite-hono", + "name": "smoke-cloudflare-vite-hono-vite-dev", "private": true, "type": "module", "dependencies": { @@ -18,7 +18,6 @@ "@vitejs/plugin-react": "^5.1.1", "tsx": "^4.19.2", "typescript": "^5.8.3", - "vite": "^6.0.0", - "wrangler": "^4.56.0" + "vite": "^6.0.0" } } diff --git a/js/smoke/scenarios/cloudflare-vite-hono/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts similarity index 90% rename from js/smoke/scenarios/cloudflare-vite-hono/src/worker.ts rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts index dae2c847e..3849075e2 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts @@ -10,7 +10,7 @@ import { type TestResult, } from "../../../shared"; -import * as braintrust from "braintrust/browser"; +import * as braintrust from "braintrust"; const { initLogger, _exportsForTestingOnly } = braintrust; const app = new Hono<{ Bindings: Env }>(); @@ -38,7 +38,11 @@ async function runSharedTestSuites(): Promise { }); try { - const importResults = await runImportVerificationTests(braintrust); + // Vite bundler should automatically resolve browser build (ESM format) when importing from "braintrust" + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests(adapters); const evalResult = await runEvalSmokeTest(adapters, braintrust); @@ -115,7 +119,8 @@ app.get("/", (c) => GET /api/ - Basic API endpoint GET /api/test - Run shared test suites -This worker tests the Braintrust SDK in a Vite + Hono + Cloudflare Workers environment.`), +This worker tests the Braintrust SDK in a Vite + Hono + Cloudflare Workers environment. +Vite should automatically resolve the browser build from package.json exports.`), ); app.get("/api/", (c) => c.json({ name: "Braintrust", framework: "Hono" })); diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs new file mode 100755 index 000000000..2a4bd0ba4 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs @@ -0,0 +1,104 @@ +#!/usr/bin/env node +/** + * Test for Vite dev server compatibility with Braintrust SDK (browser build) + * + * This test verifies that Vite can successfully pre-bundle the browser build of Braintrust + * and that the worker runs correctly with all test suites via vite dev server. + * Should produce identical results to worker.test.mjs (19 pass, 1 xfail for nunjucks). + */ + +import { spawn, execSync } from "node:child_process"; +import { rmSync } from "node:fs"; +import { displayTestResults } from "../../../shared/dist/index.mjs"; + +const PORT = 5173; +const MAX_RETRIES = 40; +const RETRY_DELAY_MS = 250; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +function killPort(port) { + try { + execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { + stdio: "ignore", + }); + } catch {} +} + +async function waitForServer() { + for (let i = 0; i < MAX_RETRIES; i++) { + try { + const res = await fetch(`http://localhost:${PORT}/`); + if (res.ok) return true; + } catch {} + await sleep(RETRY_DELAY_MS); + } + return false; +} + +async function testViteDevServer() { + killPort(PORT); + + // Clear Vite cache to force fresh dependency pre-bundling + try { + rmSync("node_modules/.vite", { recursive: true, force: true }); + } catch {} + + const vite = spawn("npx", ["vite", "--port", String(PORT)], { + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let output = ""; + vite.stdout.on("data", (d) => (output += d)); + vite.stderr.on("data", (d) => (output += d)); + + const killVite = () => { + return new Promise((resolve) => { + if (vite.exitCode !== null) { + resolve(); + return; + } + vite.once("exit", resolve); + vite.kill("SIGTERM"); + setTimeout(() => { + if (vite.exitCode === null) { + vite.kill("SIGKILL"); + } + }, 1000); + }); + }; + + let exitCode = 1; + + try { + if (!(await waitForServer())) { + await killVite(); + return 1; + } + + const response = await fetch(`http://localhost:${PORT}/api/test`); + if (!response.ok) { + await killVite(); + return 1; + } + + const result = await response.json(); + + if (result.results && result.results.length > 0) { + displayTestResults({ + scenarioName: "Vite Dev Server - Browser Build Test", + results: result.results, + }); + } + + exitCode = result.success ? 0 : 1; + } catch (error) { + exitCode = 1; + } + + await killVite(); + return exitCode; +} + +testViteDevServer().then((code) => process.exit(code)); diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tsconfig.json b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tsconfig.json new file mode 100644 index 000000000..601ba7734 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "bundler", + "resolveJsonModule": true, + "types": ["@cloudflare/workers-types"] + }, + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/scenarios/cloudflare-vite-hono/vite.config.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/vite.config.ts similarity index 100% rename from js/smoke/scenarios/cloudflare-vite-hono/vite.config.ts rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev/vite.config.ts diff --git a/js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/wrangler.toml similarity index 100% rename from js/smoke/scenarios/cloudflare-vite-hono/wrangler.toml rename to js/smoke/scenarios/cloudflare-vite-hono-vite-dev/wrangler.toml diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/.gitignore b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/.gitignore new file mode 100644 index 000000000..04e14a1fe --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +.wrangler/ +.DS_Store +*.log +.vite/ +package-lock.json diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/Makefile b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/Makefile new file mode 100644 index 000000000..46371d813 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/Makefile @@ -0,0 +1,28 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up cloudflare-vite-hono-wrangler-dev" + mise install + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + \ + for f in artifacts/braintrust-*.tgz; do \ + [ "$$(basename $$f)" = "braintrust-latest.tgz" ] && continue; \ + cp "$$f" artifacts/braintrust-latest.tgz; \ + break; \ + done; \ + fi + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../shared && npm ci && npm run build; \ + fi + npm install --no-package-lock + +test: setup + @echo "==> Running cloudflare-vite-hono-wrangler-dev test" + @npx tsx tests/worker.test.mjs diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/README.md b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/README.md new file mode 100644 index 000000000..77b51ac01 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/README.md @@ -0,0 +1,37 @@ +# Cloudflare Vite + Hono Wrangler Dev Test + +Tests Braintrust SDK in a Cloudflare Workers environment with Vite bundling via Wrangler dev server. + +## Design Decisions + +**Tarball installation:** Uses well-known tarball path (`braintrust-latest.tgz`) to avoid package.json changes. + +**Vite bundling:** Tests SDK through Vite's production bundler for Cloudflare Workers via Wrangler. + +**Hono framework:** Uses Hono for elegant routing instead of raw Worker API. + +**Browser build:** Uses `braintrust/browser` import since Cloudflare Workers don't support Node.js APIs. + +**Wrangler dev:** Tests via Wrangler dev server, which uses Vite to build the worker. + +## Test Suite + +Tests the SDK via Wrangler dev server, which uses Vite to build the worker. + +**Expected results:** 19 tests total - 18 pass + 1 xfail (Nunjucks). Overall: **PASS**. + +**Expected failure handling:** Nunjucks templating is tested but expected to fail in browser builds. The test converts this failure to "xfail" (expected failure) status, so it doesn't cause the overall test run to fail. + +**Why test Nunjucks if it fails?** Testing both template engines ensures: + +- Mustache templating works correctly (browser-compatible) +- We detect if Nunjucks support changes in future Cloudflare Workers versions +- Consistent test coverage across all environments (Node.js scenarios pass both) + +## Running Tests + +```bash +make test # Runs the wrangler dev test +``` + +**Success criteria:** The test must pass (18 pass, 1 xfail). diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/mise.toml b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/mise.toml new file mode 100644 index 000000000..abf7452af --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22" +pnpm = "10.26.2" diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json new file mode 100644 index 000000000..c0edc8625 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json @@ -0,0 +1,17 @@ +{ + "name": "smoke-cloudflare-vite-hono-wrangler-dev", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "hono": "^4.11.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250810.0", + "@types/node": "^24.10.1", + "tsx": "^4.19.2", + "typescript": "^5.8.3", + "wrangler": "^4.56.0" + } +} diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts new file mode 100644 index 000000000..3849075e2 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts @@ -0,0 +1,133 @@ +import { Hono } from "hono"; +import { + setupTestEnvironment, + cleanupTestEnvironment, + runBasicLoggingTests, + runEvalSmokeTest, + runImportVerificationTests, + testMustacheTemplate, + testNunjucksTemplate, + type TestResult, +} from "../../../shared"; + +import * as braintrust from "braintrust"; +const { initLogger, _exportsForTestingOnly } = braintrust; + +const app = new Hono<{ Bindings: Env }>(); + +interface Env {} + +interface TestResponse { + success: boolean; + message: string; + totalTests?: number; + passedTests?: number; + failedTests?: number; + results?: TestResult[]; + failures?: TestResult[]; +} + +async function runSharedTestSuites(): Promise { + try { + const adapters = await setupTestEnvironment({ + initLogger, + testingExports: _exportsForTestingOnly, + canUseFileSystem: false, + canUseCLI: false, + environment: "cloudflare-vite-hono", + }); + + try { + // Vite bundler should automatically resolve browser build (ESM format) when importing from "braintrust" + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); + const functionalResults = await runBasicLoggingTests(adapters); + const evalResult = await runEvalSmokeTest(adapters, braintrust); + + // Test Mustache template (should always work) + const mustacheResult = await testMustacheTemplate({ + Prompt: braintrust.Prompt, + }); + + // Test Nunjucks template - expected to fail in browser builds + const nunjucksResult = await testNunjucksTemplate({ + Prompt: braintrust.Prompt, + }); + const nunjucksResultHandled = + nunjucksResult.status === "fail" && + nunjucksResult.error?.message.includes( + "Nunjucks templating is not supported", + ) + ? { + ...nunjucksResult, + status: "xfail" as const, + message: + "Expected failure: Nunjucks not supported in browser build", + } + : nunjucksResult; + + const results = [ + ...importResults, + ...functionalResults, + evalResult, + mustacheResult, + nunjucksResultHandled, + ]; + + // Filter out expected failures when counting actual failures + const failures = results.filter((r) => r.status === "fail"); + + if (failures.length > 0) { + return { + success: false, + message: `${failures.length} test(s) failed`, + totalTests: results.length, + passedTests: results.length - failures.length, + failedTests: failures.length, + results, + failures, + }; + } + + return { + success: true, + message: "All shared test suites passed in Vite + Hono environment", + totalTests: results.length, + passedTests: results.length, + failedTests: 0, + results, + }; + } finally { + await cleanupTestEnvironment(adapters); + } + } catch (error) { + return { + success: false, + message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, + totalTests: 0, + passedTests: 0, + failedTests: 0, + }; + } +} + +app.get("/", (c) => + c.text(`Braintrust Cloudflare Vite + Hono Smoke Test + +GET /api/ - Basic API endpoint +GET /api/test - Run shared test suites + +This worker tests the Braintrust SDK in a Vite + Hono + Cloudflare Workers environment. +Vite should automatically resolve the browser build from package.json exports.`), +); + +app.get("/api/", (c) => c.json({ name: "Braintrust", framework: "Hono" })); + +app.get("/api/test", async (c) => { + const result = await runSharedTestSuites(); + return c.json(result, result.success ? 200 : 500); +}); + +export default app; diff --git a/js/smoke/scenarios/cloudflare-vite-hono/tests/worker.test.mjs b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/tests/worker.test.mjs similarity index 100% rename from js/smoke/scenarios/cloudflare-vite-hono/tests/worker.test.mjs rename to js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/tests/worker.test.mjs diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/tsconfig.json b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/tsconfig.json new file mode 100644 index 000000000..601ba7734 --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "bundler", + "resolveJsonModule": true, + "types": ["@cloudflare/workers-types"] + }, + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules"] +} diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/wrangler.toml b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/wrangler.toml new file mode 100644 index 000000000..93f0b4dfa --- /dev/null +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/wrangler.toml @@ -0,0 +1,3 @@ +name = "smoke-cloudflare-vite-hono" +main = "src/worker.ts" +compatibility_date = "2025-01-15" diff --git a/js/smoke/scenarios/cloudflare-vite-hono/README.md b/js/smoke/scenarios/cloudflare-vite-hono/README.md deleted file mode 100644 index 2d9c8bc55..000000000 --- a/js/smoke/scenarios/cloudflare-vite-hono/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Cloudflare Vite + Hono Smoke Test - -Tests Braintrust SDK in a Cloudflare Workers environment with Vite bundling and Hono routing. - -## Design Decisions - -**Tarball installation:** Uses well-known tarball path (`braintrust-latest.tgz`) to avoid package.json changes. - -**Vite bundling:** Tests SDK through Vite's production bundler for Cloudflare Workers. - -**Hono framework:** Uses Hono for elegant routing instead of raw Worker API. - -**Browser build:** Uses `braintrust/browser` import since Cloudflare Workers don't support Node.js APIs. - -**Two-test approach:** Runs both Wrangler (production mode) and Vite dev server tests to validate different deployment scenarios. - -## Test Suite - -### Test 1: Wrangler (Production Mode) - `tests/worker.test.mjs` - -Tests the SDK via Wrangler dev server, which uses Vite to build the worker. - -**Expected results:** 19 tests total - 18 pass + 1 xfail (Nunjucks). Overall: **PASS**. - -**Expected failure handling:** Nunjucks templating is tested but expected to fail in browser builds. The test converts this failure to "xfail" (expected failure) status, so it doesn't cause the overall test run to fail. - -**Why test Nunjucks if it fails?** Testing both template engines ensures: - -- Mustache templating works correctly (browser-compatible) -- We detect if Nunjucks support changes in future Cloudflare Workers versions -- Consistent test coverage across all environments (Node.js scenarios pass both) - -### Test 2: Vite Dev Server - `tests/vite-dev.test.mjs` - -Tests whether the SDK can be loaded in Vite's dev server (with hot module reloading). - -**Expected result:** FAIL (expected to fail) - Vite's dependency pre-bundler cannot handle Nunjucks. - -**Known issue:** Nunjucks uses `Object.setPrototypeOf` in ways that fail in Vite's ESM bundler during dependency pre-bundling, causing: `TypeError: Object prototype may only be an Object or null: undefined` - -**This failure is expected and acceptable** - users should use Wrangler (production mode) for Cloudflare Workers development, not Vite dev server. The Wrangler test validates the production deployment path. - -**Note:** If you see a different error (not the Nunjucks error), that's unexpected and should be investigated. - -## Running Tests - -```bash -make test # Runs both tests sequentially -``` - -**Success criteria:** The Wrangler test must pass. The Vite dev test is expected to fail (exit code 1) and won't cause the overall `make test` to fail. diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts index 906b15adf..4b111497f 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust/browser"; +import * as braintrust from "braintrust"; import { setupTestEnvironment, cleanupTestEnvironment, @@ -33,7 +33,11 @@ async function runSharedTestSuites(): Promise { }); try { - const importResults = await runImportVerificationTests(braintrust); + // Test import verification including build resolution check + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests( adapters, braintrust, @@ -149,8 +153,8 @@ export default { GET /test - Run shared test suites -This worker tests the Braintrust SDK in a Cloudflare Workers environment -using the browser entrypoint with nodejs_compat_v2 enabled.`, +This worker tests the Braintrust SDK in a Cloudflare Workers environment. +The bundler should automatically resolve the browser build from package.json exports.`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts index c8a6c9261..4a6b42d8e 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust/browser"; +import * as braintrust from "braintrust"; import { setupTestEnvironment, cleanupTestEnvironment, @@ -33,7 +33,12 @@ async function runSharedTestSuites(): Promise { }); try { - const importResults = await runImportVerificationTests(braintrust); + // Test import verification including build resolution check + // Bundler should automatically resolve browser build (ESM format) when importing from "braintrust" + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests( adapters, braintrust, @@ -149,8 +154,8 @@ export default { GET /test - Run shared test suites -This worker tests the Braintrust SDK in a Cloudflare Workers environment -using the browser entrypoint without nodejs_compat_v2.`, +This worker tests the Braintrust SDK in a Cloudflare Workers environment. +The bundler should automatically resolve the browser build from package.json exports.`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts index 85d5a58cf..0e476bf49 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts @@ -1,4 +1,6 @@ -import * as braintrust from "braintrust"; +// Workers with nodejs_compat can use Node.js build +// Explicitly import from "braintrust/node" to ensure Node.js build is used +import * as braintrust from "braintrust/node"; import { setupTestEnvironment, cleanupTestEnvironment, @@ -33,7 +35,11 @@ async function runSharedTestSuites(): Promise { }); try { - const importResults = await runImportVerificationTests(braintrust); + // Node.js build (ESM format) should be used in Cloudflare Workers with nodejs_compat_v2 + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests( adapters, braintrust, @@ -149,8 +155,8 @@ export default { GET /test - Run shared test suites -This worker tests the Braintrust SDK in a Cloudflare Workers environment -using the Node.js entrypoint with nodejs_compat_v2 enabled.`, +This worker tests the Braintrust SDK in a Cloudflare Workers environment. +Should use Node.js build from package.json exports.`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts index 7e1cb045b..a88f7beb6 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust"; +import * as braintrust from "braintrust/node"; import { setupTestEnvironment, cleanupTestEnvironment, @@ -32,7 +32,10 @@ async function runSharedTestSuites(): Promise { }); try { - const importResults = await runImportVerificationTests(braintrust); + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests( adapters, braintrust, @@ -127,8 +130,8 @@ export default { GET /test - Run shared test suites -This worker tests the Braintrust SDK in a Cloudflare Workers environment -using the Node.js entrypoint without nodejs_compat_v2. This is expected to fail.`, +This worker tests the Braintrust SDK in a Cloudflare Workers environment. +Should use Node.js build from package.json exports (may fail without nodejs_compat_v2).`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/deno-browser/deno.json b/js/smoke/scenarios/deno-browser/deno.json index 6e1f5f0d4..ab612b4d0 100644 --- a/js/smoke/scenarios/deno-browser/deno.json +++ b/js/smoke/scenarios/deno-browser/deno.json @@ -2,7 +2,7 @@ "imports": { "@std/assert": "jsr:@std/assert@^1.0.14", "@braintrust/smoke-test-shared": "jsr:@braintrust/smoke-test-shared", - "braintrust/browser": "npm:braintrust@^2.0.2/browser" + "braintrust": "npm:braintrust/browser" }, "nodeModulesDir": "auto", "links": [ diff --git a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts index b98f2d261..515692c06 100644 --- a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts @@ -17,7 +17,7 @@ import { getFailureCount, type TestResult, } from "@braintrust/smoke-test-shared"; -import * as braintrust from "braintrust/browser"; +import * as braintrust from "braintrust"; export async function runSharedTestSuites(): Promise { const { initLogger, _exportsForTestingOnly } = braintrust; @@ -31,8 +31,12 @@ export async function runSharedTestSuites(): Promise { }); try { - // Run tests - const importResults = await runImportVerificationTests(braintrust); + // Run tests including build resolution check + // Bundler should automatically resolve browser build (ESM format) when importing from "braintrust" + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests(adapters, braintrust); const evalResult = await runEvalSmokeTest(adapters, braintrust); diff --git a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts index 93bb10da9..471976531 100644 --- a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts @@ -35,8 +35,12 @@ export async function runSharedTestSuites() { }); try { - // Run tests - const importResults = await runImportVerificationTests(braintrust); + // Run tests including build resolution check + // Deno Node should resolve to Node build (ESM format) when using import + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests(adapters, braintrust); const evalResult = await runEvalSmokeTest(adapters, braintrust); const promptTemplatingResults = await runPromptTemplatingTests({ diff --git a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js index 240e2a8af..b37d5f7d3 100644 --- a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js +++ b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js @@ -22,7 +22,10 @@ async function runSharedTestSuites() { }); try { - const importResults = await runImportVerificationTests(braintrust); + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "cjs", + }); const functionalResults = await runBasicLoggingTests(adapters); const promptTemplatingResults = await runPromptTemplatingTests({ Prompt: braintrust.Prompt, diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts index 30f2fbfef..6a300ffd2 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts @@ -57,8 +57,12 @@ export async function GET(): Promise> { }); try { - // Run import verification tests (forces all exports to be processed) - const importResults = await runImportVerificationTests(braintrust); + // Run import verification tests including build resolution check + // Next.js Edge runtime should resolve to browser build (ESM format) + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); // Run functional tests const functionalResults = await runBasicLoggingTests( diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts index 154964bac..5e50e4b38 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts @@ -56,8 +56,12 @@ export async function GET(): Promise> { }); try { - // Run import verification tests (forces all exports to be processed) - const importResults = await runImportVerificationTests(braintrust); + // Run import verification tests including build resolution check + // Next.js Node.js runtime should resolve to Node build (CJS format) + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "cjs", + }); // Run functional tests const functionalResults = await runBasicLoggingTests( diff --git a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts b/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts index ffe72dc97..2bf19c768 100644 --- a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts @@ -28,8 +28,12 @@ async function runSharedTestSuites() { }); try { - // Run tests - const importResults = await runImportVerificationTests(braintrust); + // Run tests including build resolution check + // Node.js should resolve to Node build (ESM format) when using import + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "node", + expectedFormat: "esm", + }); const functionalResults = await runBasicLoggingTests(adapters, braintrust); // Combine results diff --git a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts index 33ff32c88..75c831525 100644 --- a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts +++ b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust/browser"; +import * as braintrust from "braintrust"; import { setupTestEnvironment, cleanupTestEnvironment, @@ -49,7 +49,10 @@ async function runAllTestSuites() { try { harness.log("=== Running shared suites ==="); - const importResults = await runImportVerificationTests(braintrust); + const importResults = await runImportVerificationTests(braintrust, { + expectedBuild: "browser", + expectedFormat: "esm", + }); for (const r of importResults) { if (r.status === "pass") harness.pass(SHARED_SECTION, r.name, r.message); else diff --git a/js/smoke/shared/src/index.ts b/js/smoke/shared/src/index.ts index 386d5b4fc..fd2abc9e9 100644 --- a/js/smoke/shared/src/index.ts +++ b/js/smoke/shared/src/index.ts @@ -70,6 +70,7 @@ export { testIDGeneratorExports, testTestingExports, testStateManagementExports, + testBuildResolution, runImportVerificationTests, } from "./suites/import-verification"; diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index 2ad5561c6..0f01acc2e 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -675,6 +675,229 @@ export async function testStateManagementExports( } } +/** + * Test which build variant was resolved (browser vs Node.js) and module format (CJS vs ESM) + * + * This test checks which export path was used by reading the buildType property + * from the isomorph object and by resolving the module specifier. + * + * @param module - The Braintrust module to test + * @param expectedBuild - Expected build type: "browser" or "node" (optional, for validation) + * @param expectedFormat - Expected module format: "cjs" or "esm" (optional, for validation) + */ +export async function testBuildResolution( + module: BraintrustModule, + expectedBuild?: "browser" | "node", + expectedFormat?: "cjs" | "esm", +): Promise { + const testName = "testBuildResolution"; + + try { + // Detect build type from isomorph.buildType + const { buildType: detectedBuild, buildDetails } = detectBuildType(module); + + // Detect module format (CJS vs ESM) + const detectedFormat = detectModuleFormat(); + + const errors = validateBuildResolution( + detectedBuild, + detectedFormat, + expectedBuild, + expectedFormat, + buildDetails, + ); + + if (errors.length > 0) { + return { + status: "fail" as const, + name: testName, + error: { message: errors.join(" ") }, + }; + } + + // Build success message + const message = buildSuccessMessage( + detectedBuild, + detectedFormat, + expectedBuild, + expectedFormat, + ); + + return { + status: "pass" as const, + name: testName, + message, + }; + } catch (error) { + return { + status: "fail" as const, + name: testName, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, + }; + } +} + +function detectBuildType(module: BraintrustModule): { + buildType: "browser" | "node" | "unknown"; + buildDetails: string; +} { + if (!module._exportsForTestingOnly) { + return { + buildType: "unknown", + buildDetails: "_exportsForTestingOnly not available", + }; + } + + const testing = module._exportsForTestingOnly as any; + const iso = testing.isomorph; + + if (!iso || typeof iso !== "object") { + return { + buildType: "unknown", + buildDetails: "isomorph not available in testing exports", + }; + } + + const buildType = iso.buildType; + if ( + buildType === "browser" || + buildType === "node" || + buildType === "unknown" + ) { + return { + buildType, + buildDetails: `Build type from isomorph.buildType: ${buildType}`, + }; + } + + return { + buildType: "unknown", + buildDetails: `isomorph.buildType has unexpected value: ${buildType}`, + }; +} + +/** + * Detect module format (CJS vs ESM) by resolving the actual file path + */ +function detectModuleFormat(): "cjs" | "esm" | "unknown" { + const packageSpec = "braintrust"; + // Try ESM resolution first + try { + if ( + typeof import.meta !== "undefined" && + typeof import.meta.resolve === "function" + ) { + const resolved = import.meta.resolve(packageSpec); + let resolvedPath: string; + try { + const url = new URL(resolved); + resolvedPath = url.pathname; + } catch { + resolvedPath = resolved; + } + if (resolvedPath.endsWith(".mjs")) { + return "esm"; + } + // If resolved but not .mjs, check if it's .js (CJS) + if (resolvedPath.endsWith(".js") && !resolvedPath.endsWith(".mjs")) { + return "cjs"; + } + } + } catch { + // import.meta.resolve might not be available or might throw + // Continue to try CJS resolution + } + + // Try CJS resolution + try { + if (typeof require !== "undefined" && require.resolve) { + const resolved = require.resolve(packageSpec); + // CJS files end with .js (not .mjs) + if (resolved.endsWith(".js") && !resolved.endsWith(".mjs")) { + return "cjs"; + } + // If resolved to .mjs, it's ESM + if (resolved.endsWith(".mjs")) { + return "esm"; + } + } + } catch { + // require.resolve might not be available or might throw + } + + return "unknown"; +} + +/** + * Validate detected build type and format against expectations + */ +function validateBuildResolution( + detectedBuild: "browser" | "node" | "unknown", + detectedFormat: "cjs" | "esm" | "unknown", + expectedBuild?: "browser" | "node", + expectedFormat?: "cjs" | "esm", + buildDetails?: string, +): string[] { + const errors: string[] = []; + + // Always error if build type is unknown (not configured) + if (detectedBuild === "unknown") { + errors.push( + `Build type is unknown - configureBrowser() or configureNode() was not called. ${buildDetails || ""}`, + ); + return errors; + } + + // Validate build type matches expectation + if (expectedBuild && detectedBuild !== expectedBuild) { + errors.push( + `Expected ${expectedBuild} build but detected ${detectedBuild} build. ${buildDetails || ""}`, + ); + } + + // Validate module format matches expectation + if ( + expectedFormat && + detectedFormat !== expectedFormat && + detectedFormat !== "unknown" + ) { + errors.push( + `Expected ${expectedFormat} format but detected ${detectedFormat} format.`, + ); + } + + return errors; +} + +/** + * Build success message for test result + */ +function buildSuccessMessage( + detectedBuild: "browser" | "node" | "unknown", + detectedFormat: "cjs" | "esm" | "unknown", + expectedBuild?: "browser" | "node", + expectedFormat?: "cjs" | "esm", +): string { + const parts: string[] = []; + + if (detectedBuild !== "unknown") { + const buildMsg = `Detected ${detectedBuild} build`; + const expectedMsg = expectedBuild ? ` (expected ${expectedBuild})` : ""; + parts.push(`${buildMsg}${expectedMsg}`); + } + + if (detectedFormat !== "unknown") { + const formatMsg = `${detectedFormat} format`; + const expectedMsg = expectedFormat ? ` (expected ${expectedFormat})` : ""; + parts.push(`${formatMsg}${expectedMsg}`); + } + + return parts.join(", ") || "Build resolution check passed"; +} + /** * Run all import verification tests * @@ -685,9 +908,14 @@ export async function testStateManagementExports( * TypeScript type-only exports are not tested as they don't exist at runtime. * * @param module - The Braintrust module to test + * @param options - Optional test configuration */ export async function runImportVerificationTests( module: BraintrustModule, + options: { + expectedBuild: "browser" | "node"; + expectedFormat: "cjs" | "esm"; + }, ): Promise { const results: TestResult[] = []; @@ -705,6 +933,13 @@ export async function runImportVerificationTests( results.push(await testStateManagementExports(module)); results.push(await testExperimentExports(module)); results.push(await testEvalExports(module)); + results.push( + await testBuildResolution( + module, + options.expectedBuild, + options.expectedFormat, + ), + ); return results; } diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts index 3b69e2588..2607a4ec1 100644 --- a/js/src/browser-config.ts +++ b/js/src/browser-config.ts @@ -15,6 +15,10 @@ export function configureBrowser() { if (browserConfigured) { return; } + + // Set build type indicator + iso.buildType = "browser"; + try { if (typeof AsyncLocalStorage !== "undefined") { iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); diff --git a/js/src/isomorph.ts b/js/src/isomorph.ts index 37857593f..690fdcb38 100644 --- a/js/src/isomorph.ts +++ b/js/src/isomorph.ts @@ -30,6 +30,8 @@ class DefaultAsyncLocalStorage implements IsoAsyncLocalStorage { } export interface Common { + buildType: "browser" | "node" | "unknown"; + getRepoInfo: ( settings?: GitMetadataSettings, ) => Promise; @@ -83,6 +85,7 @@ export interface Common { } const iso: Common = { + buildType: "unknown", // Will be set by configureBrowser() or configureNode() getRepoInfo: async (_settings) => undefined, getPastNAncestors: async () => [], getEnv: (_name) => undefined, diff --git a/js/src/logger.ts b/js/src/logger.ts index b8c348742..9d1838dde 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -7135,4 +7135,5 @@ export const _exportsForTestingOnly = { isGeneratorFunction, isAsyncGeneratorFunction, resetIdGenStateForTests, + isomorph: iso, // Expose isomorph for build type detection }; diff --git a/js/src/node.ts b/js/src/node.ts index 1a575ffe7..df453a3a8 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -15,6 +15,9 @@ import { promisify } from "node:util"; import * as zlib from "node:zlib"; export function configureNode() { + // Set build type indicator + iso.buildType = "node"; + iso.getRepoInfo = getRepoInfo; iso.getPastNAncestors = getPastNAncestors; iso.getEnv = (name) => process.env[name]; diff --git a/js/tests/api-compatibility/api-compatibility.test.ts b/js/tests/api-compatibility/api-compatibility.test.ts index fc9610089..44366e575 100644 --- a/js/tests/api-compatibility/api-compatibility.test.ts +++ b/js/tests/api-compatibility/api-compatibility.test.ts @@ -387,8 +387,16 @@ function compareExports( kind: string; }> = []; + // Internal testing exports that can change without breaking compatibility + const internalExports = new Set(["_exportsForTestingOnly"]); + // Check for removed or modified exports for (const [name, publishedSymbol] of publishedExports) { + // Skip internal exports - they can change without being breaking changes + if (internalExports.has(name)) { + continue; + } + const currentSymbol = currentExports.get(name); if (!currentSymbol) { removed.push(publishedSymbol); @@ -410,6 +418,11 @@ function compareExports( // Check for added exports for (const [name, currentSymbol] of currentExports) { + // Skip internal exports - their additions don't count as public API additions + if (internalExports.has(name)) { + continue; + } + if (!publishedExports.has(name)) { added.push(currentSymbol); } @@ -743,17 +756,42 @@ function areFunctionSignaturesCompatible( } /** - * Compares type alias signatures to determine if changes are backwards compatible. - * Widening union types or adding optional properties to objects is compatible. + * Normalizes type references to handle equivalent forms: + * - z.infer -> TypeType + * - z.infer -> TypeType (handles TypeScript disambiguation suffixes) + * - Type$1, Type$2, etc. -> Type (removes TypeScript disambiguation suffixes) */ +function normalizeTypeReference(type: string): string { + // First normalize z.infer patterns - handle both with and without $N suffix + // This handles: z.infer -> ObjectReferenceType + // And: z.infer -> ObjectReferenceType + // Match the full identifier (which may include $ suffix) and extract just the base name + type = type.replace( + /z\.infer/g, + (match, fullIdentifier) => { + // Extract base name by removing $ suffix if present + // Simply remove any $ followed by digits from the end + const baseName = fullIdentifier.replace(/\$\d+$/, ""); + return `${baseName}Type`; + }, + ); + + // Then remove any remaining TypeScript disambiguation suffixes + // This handles cases like: ObjectReferenceType$1 -> ObjectReferenceType + type = type.replace(/(\w+)\$\d+/g, "$1"); + + return type; +} + function areTypeAliasSignaturesCompatible( oldType: string, newType: string, ): boolean { // Extract type name and definition const parseTypeSig = (sig: string) => { - // Match: export type Name = Definition - const match = sig.match(/export\s+type\s+(\w+)\s*=\s*(.+)$/); + // Match: export type Name = Definition (handle multiline) + // Use [\s\S] instead of . to match newlines, and make it non-greedy + const match = sig.match(/export\s+type\s+(\w+)\s*=\s*([\s\S]+)$/); if (!match) return null; return { @@ -894,7 +932,13 @@ function areTypeAliasSignaturesCompatible( return false; } - if (oldProp.type !== newProp.type) { + // Normalize type references before comparing + // This handles cases where TypeScript generates different names (e.g., ObjectReference$1 vs ObjectReference) + // that are semantically equivalent + const oldTypeNorm = normalizeTypeReference(oldProp.type); + const newTypeNorm = normalizeTypeReference(newProp.type); + + if (oldTypeNorm !== newTypeNorm) { // Property type changed - breaking change return false; } @@ -919,8 +963,11 @@ function areTypeAliasSignaturesCompatible( return true; } - // For other types, they must match exactly - return oldDef === newDef; + // For other types, normalize and compare + // This handles cases where TypeScript generates different names that are semantically equivalent + const oldDefNorm = normalizeTypeReference(oldDef); + const newDefNorm = normalizeTypeReference(newDef); + return oldDefNorm === newDefNorm; } /** @@ -1113,8 +1160,9 @@ function areInterfaceSignaturesCompatible( return false; } - // Normalize field types for comparison (remove whitespace differences) - const normalizeType = (type: string) => type.replace(/\s+/g, " ").trim(); + // Normalize field types for comparison (remove whitespace differences and normalize type references) + const normalizeType = (type: string) => + normalizeTypeReference(type.replace(/\s+/g, " ").trim()); const oldTypeNorm = normalizeType(oldField.type); const newTypeNorm = normalizeType(newField.type); @@ -1631,6 +1679,16 @@ describe("areTypeAliasSignaturesCompatible", () => { const newType = `export type Foo = { value: string }`; expect(areTypeAliasSignaturesCompatible(oldType, newType)).toBe(false); }); + + test("should treat ObjectReference$1 and ObjectReference as compatible", () => { + const oldType = `export type OtherExperimentLogFields = { + origin: z.infer; +};`; + const newType = `export type OtherExperimentLogFields = { + origin: z.infer; +};`; + expect(areTypeAliasSignaturesCompatible(oldType, newType)).toBe(true); + }); }); describe("areEnumSignaturesCompatible", () => { @@ -1771,6 +1829,8 @@ interface BreakingChanges { function findNewBreakingChanges( baselineChanges: BreakingChanges, currentChanges: BreakingChanges, + baselineExports?: Map, + currentExports?: Map, ): BreakingChanges { // Find removed exports in current that don't exist in baseline const newRemoved = currentChanges.removed.filter( @@ -1778,9 +1838,52 @@ function findNewBreakingChanges( ); // Find modified exports in current that don't exist in baseline - const newModified = currentChanges.modified.filter( - (exp) => !baselineChanges.modified.some((b) => b.name === exp.name), - ); + // Also exclude exports that normalize to the same signature (not actually breaking) + const newModified = currentChanges.modified.filter((exp) => { + // Check if this export exists in baseline with same name + const baselineMod = baselineChanges.modified.find( + (b) => b.name === exp.name, + ); + + if (baselineMod) { + // It exists in baseline modified - check if the "after" signatures normalize to the same thing + // If they do, it's the same breaking change that's already in main, not a new one + const baselineAfterNorm = normalizeTypeReference( + baselineMod.after.replace(/\s+/g, " ").trim(), + ); + const currentAfterNorm = normalizeTypeReference( + exp.after.replace(/\s+/g, " ").trim(), + ); + + // Only consider it "new" if normalized "after" signatures are different + return baselineAfterNorm !== currentAfterNorm; + } + + // Not in baseline modified list - check if it exists in baseline exports + // If it does and normalized signatures match, it's not a new breaking change + if (baselineExports && currentExports) { + const baselineExp = baselineExports.get(exp.name); + const currentExp = currentExports.get(exp.name); + + if (baselineExp && currentExp) { + // Both exist - check if normalized signatures match + const baselineNorm = normalizeTypeReference( + baselineExp.signature.replace(/\s+/g, " ").trim(), + ); + const currentNorm = normalizeTypeReference( + currentExp.signature.replace(/\s+/g, " ").trim(), + ); + + // If they normalize to the same, it's not a new breaking change + if (baselineNorm === currentNorm) { + return false; + } + } + } + + // Not in baseline at all, or signatures don't match - it's new + return true; + }); return { removed: newRemoved, modified: newModified }; } @@ -1962,9 +2065,12 @@ describe("API Compatibility", () => { }; // Find NEW breaking changes (not in baseline) + // Also pass exports so we can check normalized signatures even if not in modified list const newBreaking = findNewBreakingChanges( baselineBreaking, currentBreaking, + mainExports, + currentExports, ); // Log baseline info (informational only) @@ -1998,8 +2104,12 @@ describe("API Compatibility", () => { `NEW modified exports (${newBreaking.modified.length}):\n` + newBreaking.modified .map((m) => { - const beforeNorm = m.before.replace(/\s+/g, " ").trim(); - const afterNorm = m.after.replace(/\s+/g, " ").trim(); + const beforeNorm = normalizeTypeReference( + m.before.replace(/\s+/g, " ").trim(), + ); + const afterNorm = normalizeTypeReference( + m.after.replace(/\s+/g, " ").trim(), + ); if (beforeNorm === afterNorm) { return ` - ${m.name} (${m.kind})\n Note: Signatures appear identical after normalization`; @@ -2063,8 +2173,12 @@ describe("API Compatibility", () => { `Modified exports (${comparison.modified.length}):\n` + comparison.modified .map((m) => { - const beforeNorm = m.before.replace(/\s+/g, " ").trim(); - const afterNorm = m.after.replace(/\s+/g, " ").trim(); + const beforeNorm = normalizeTypeReference( + m.before.replace(/\s+/g, " ").trim(), + ); + const afterNorm = normalizeTypeReference( + m.after.replace(/\s+/g, " ").trim(), + ); if (beforeNorm === afterNorm) { return ` - ${m.name} (${m.kind})\n Note: Signatures appear identical after normalization`; From a8072d6ccd7a336afa2dbd0c3ebd6ef2576a6ffc Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 22 Jan 2026 16:39:47 -0800 Subject: [PATCH 40/57] Robust-er smoke tests (#1299) Simpler testing/expecting and ensure all scenarios are running all the things. Currently CI shows failing because of ALS not working in /browser. Expected for now. --- .pre-commit-config.yaml | 2 +- js/smoke/Makefile | 12 +- js/smoke/README.md | 194 +++-- .../src/worker-node-esm.ts | 129 ++-- .../src/worker.ts | 184 ++--- .../tests/vite-dev.test.mjs | 5 - .../src/worker.ts | 184 ++--- .../src/worker.ts | 201 ++--- .../src/worker.ts | 202 ++---- .../src/worker.ts | 203 ++---- .../src/worker.ts | 177 ++--- .../deno-browser/tests/shared-suite.test.ts | 138 ++-- .../deno-node/tests/shared-suite.test.ts | 128 ++-- .../jest-node/tests/shared-suite.test.js | 107 ++- .../src/app/api/smoke-test/edge/route.ts | 221 ++---- .../src/app/api/smoke-test/node/route.ts | 202 ++---- .../src/instrumentation.ts | 12 +- .../otel-v1/tests/shared-suite.test.ts | 94 +-- .../playwright-browser/playwright.config.ts | 2 +- .../playwright-browser/src/browser-tests.ts | 194 ++--- .../playwright-browser/tests/browser.test.ts | 66 +- js/smoke/shared/README.md | 531 ++++++++++---- js/smoke/shared/src/helpers/register.ts | 199 +++++ js/smoke/shared/src/helpers/test-state.ts | 76 -- js/smoke/shared/src/helpers/types.ts | 12 - js/smoke/shared/src/index.ts | 37 +- js/smoke/shared/src/suites/basic-logging.ts | 436 ++++++----- js/smoke/shared/src/suites/eval-smoke.ts | 161 ++-- .../shared/src/suites/import-verification.ts | 685 ++++-------------- .../shared/src/suites/prompt-templating.ts | 219 ++---- js/smoke/tests/otel-v1/tsconfig.json | 17 - js/smoke/tests/span/tsconfig.json | 17 - 32 files changed, 2255 insertions(+), 2792 deletions(-) create mode 100644 js/smoke/shared/src/helpers/register.ts delete mode 100644 js/smoke/shared/src/helpers/test-state.ts delete mode 100644 js/smoke/tests/otel-v1/tsconfig.json delete mode 100644 js/smoke/tests/span/tsconfig.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 35cb1aedb..af83981d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: )$ args: - "-L" - - "rouge,coo,couldn,unsecure,ontext,afterall" + - "rouge,coo,couldn,unsecure,ontext,afterall,als" - repo: https://github.com/rbubley/mirrors-prettier rev: v3.3.2 hooks: diff --git a/js/smoke/Makefile b/js/smoke/Makefile index 7fa08d910..effaa15e5 100644 --- a/js/smoke/Makefile +++ b/js/smoke/Makefile @@ -104,14 +104,22 @@ test: : $${SMOKE_V2_SHARED_DIST:=shared/dist}; \ export BRAINTRUST_TAR BRAINTRUST_OTEL_TAR SMOKE_V2_SHARED_DIST; \ \ + FAILED_SCENARIOS=""; \ for scenario in $$SCENARIOS_TO_RUN; do \ echo ""; \ echo "=== Testing $$scenario ==="; \ - $(MAKE) -C scenarios/$$scenario test || exit 1; \ + if ! $(MAKE) -C scenarios/$$scenario test; then \ + FAILED_SCENARIOS="$$FAILED_SCENARIOS $$scenario"; \ + fi; \ done; \ \ echo ""; \ - echo "✓ All requested scenarios passed" + if [ -n "$$FAILED_SCENARIOS" ]; then \ + echo "✗ Failed scenarios:$$FAILED_SCENARIOS"; \ + exit 1; \ + else \ + echo "✓ All requested scenarios passed"; \ + fi # ============================================================================= # List - Show discovered scenarios diff --git a/js/smoke/README.md b/js/smoke/README.md index 10d0ae2d7..f0b52cec5 100644 --- a/js/smoke/README.md +++ b/js/smoke/README.md @@ -5,7 +5,7 @@ Smoke test infrastructure verifying SDK installation across different runtimes a ## Quick Reference ```bash -make test # Run all scenarios +make test # Run all scenarios (doesn't exit early on failures) make test otel-v1 # Run specific scenario make list # List available scenarios ``` @@ -16,27 +16,42 @@ make list # List available scenarios ```typescript import { - displayTestResults, - hasFailures, - getFailureCount, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + // ... other test functions } from "../../shared/dist/index.mjs"; -// Run your tests -const results = [...importResults, ...functionalResults]; - -// Display with standardized format -displayTestResults({ - scenarioName: "My Scenario Test Results", - results, +import * as braintrust from "braintrust"; + +// Run tests with the new runTests helper +const { all, passed, failed, xfail } = await runTests({ + name: "My Scenario Test Results", + braintrust, + tests: [ + testBasicSpanLogging, + testMultipleSpans, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("not supported"), + "Nunjucks not supported in browser build", + ), + ], }); // Check for failures -if (hasFailures(results)) { +if (failed.length > 0) { process.exit(1); } ``` -**Keep logging minimal:** No status messages, banners, or summaries. Let `displayTestResults()` do the talking. +**Key features:** + +- `runTests()` automatically displays results, validates coverage, and returns structured results +- `expectFailure()` wraps tests expected to fail with error predicate validation +- No manual `try/catch` blocks needed around `runTests()` +- No manual coverage validation needed ## Creating a New Scenario @@ -47,7 +62,7 @@ if (hasFailures(results)) { - [ ] Dependencies declared (package.json, deno.json, etc.) - [ ] README.md explaining design decisions (15-25 lines) - [ ] .gitignore (ignore artifacts, track lock files) -- [ ] **Tests use `displayTestResults()`** +- [ ] **Tests use `runTests()` and individual test functions** - [ ] **Minimal logging** (errors only) - [ ] **POSIX shell syntax** (`[ ]` not `[[ ]]`) @@ -63,54 +78,94 @@ if (hasFailures(results)) { ```typescript import { - setupTestEnvironment, - cleanupTestEnvironment, - runImportVerificationTests, - runBasicLoggingTests, - displayTestResults, - hasFailures, -} from "../../shared/dist/index.mjs"; - -import { initLogger, _exportsForTestingOnly } from "braintrust"; - -async function runTests() { - const braintrust = await import("braintrust"); - - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: true, - environment: "my-scenario", + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testCoreLoggingExports, + testBuildResolution, + testNunjucksTemplate, +} from "../../shared"; + +import * as braintrust from "braintrust"; + +async function main() { + const { all, passed, failed, xfail } = await runTests({ + name: "My Scenario Test Results", + braintrust, + tests: [ + // Import verification tests + testCoreLoggingExports, + testBuildResolution, + + // Functional tests + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + + // Expected failures with error validation + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("not supported"), + "Nunjucks not supported in browser build", + ), + ], }); - try { - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests(adapters, braintrust); - const results = [...importResults, ...functionalResults]; - - displayTestResults({ - scenarioName: "My Scenario Test Results", - results, - }); - - if (hasFailures(results)) { - process.exit(1); - } - } finally { - await cleanupTestEnvironment(adapters); + if (failed.length > 0) { + process.exit(1); } } -runTests().catch((error) => { +main().catch((error) => { console.error(error); process.exit(1); }); ``` +### Example HTTP Endpoint (Cloudflare Workers, Next.js) + +```typescript +import { + runTests, + expectFailure /* ... test functions */, +} from "../../../shared"; +import * as braintrust from "braintrust"; + +app.get("/api/test", async (c) => { + const { all, passed, failed, xfail } = await runTests({ + name: "My Worker Test Results", + braintrust, + tests: [ + testBasicSpanLogging, + testMultipleSpans, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Disallowed"), + "Cloudflare Workers blocks dynamic code generation", + ), + ], + }); + + return c.json( + { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All tests passed", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all, + }, + failed.length === 0 ? 200 : 500, + ); +}); +``` + ### Example Makefile (Multiple Tests) **IMPORTANT:** Run all tests even if one fails. Don't exit early. @@ -137,6 +192,30 @@ Use version-agnostic paths: `braintrust-latest.tgz` not `braintrust-2.0.2.tgz`. Never use `--legacy-peer-deps`, `--no-check`, `--ignore-errors`, or mocks. Smoke tests must expose issues users will encounter. +### No Defensive Checks in Tests + +Don't conditionally check if functions exist before calling them. Let natural JavaScript errors occur and get caught by the test framework. This provides: + +- **Better error messages**: Stack traces show exactly where/what failed +- **Cleaner test code**: No redundant existence checks +- **Real-world behavior**: Tests fail the same way user code would fail + +```typescript +// ❌ Bad - defensive checks hide the real error +if (!braintrust.traced) { + return { status: "fail", error: { message: "traced missing" } }; +} + +// ✓ Good - let it throw naturally (register() wraps this) +const traced = braintrust.traced as TracedFn; +await traced( + () => { + /* ... */ + }, + { name: "test" }, +); +``` + ### Build Before Install Build all artifacts BEFORE installing dependencies that reference them. Prevents "ENOENT" errors. @@ -194,6 +273,17 @@ SCENARIOS := $(shell find scenarios -mindepth 1 -maxdepth 1 -type d -exec test - Any folder in `scenarios/` with a `Makefile` is automatically discovered. No registration needed. +## Shared Test Suites + +The `shared/` package provides reusable test suites that run across all scenarios: + +- **Import Verification** - Verifies SDK exports exist, prevents tree-shaking issues +- **Basic Logging** - Core logging functionality including Async Local Storage (ALS) tests +- **Prompt Templating** - Mustache (all environments) and Nunjucks (Node.js) +- **Eval Smoke Test** - Basic eval functionality + +See `shared/README.md` for complete test suite documentation, individual test functions, and implementation details. + ## Reference Scenarios - **Node.js + OTEL:** `scenarios/otel-v1/` diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts index 2bc7dcc21..90f59075c 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts @@ -1,58 +1,39 @@ import { Hono } from "hono"; -import { runImportVerificationTests, type TestResult } from "../../../shared"; +import { + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testMustacheTemplate, + testNunjucksTemplate, + testEvalSmoke, +} from "../../../shared"; -// Explicitly import Node.js ESM build -import * as braintrustNode from "braintrust/node"; +import * as braintrust from "braintrust/node"; const app = new Hono<{ Bindings: Env }>(); interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runNodeEsmImportTest(): Promise { - try { - // Vite bundler should resolve Node.js ESM build when importing from "braintrust/node" - // Note: This worker will not actually run via vite dev due to nunjucks bundling error, - // but we test import resolution to verify the export path works correctly. - const importResults = await runImportVerificationTests(braintrustNode, { - expectedBuild: "node", - expectedFormat: "esm", - }); - - const failures = importResults.filter((r) => r.status === "fail"); - - return { - success: failures.length === 0, - message: - failures.length === 0 - ? "Node.js ESM import resolution test passed" - : `${failures.length} test(s) failed`, - totalTests: importResults.length, - passedTests: importResults.length - failures.length, - failedTests: failures.length, - results: importResults, - failures: failures.length > 0 ? failures : undefined, - }; - } catch (error) { - return { - success: false, - message: `Error during Node.js ESM import test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - app.get("/", (c) => c.text(`Braintrust Cloudflare Vite + Hono Smoke Test (Node.js ESM Build) @@ -68,8 +49,56 @@ app.get("/api/", (c) => ); app.get("/api/test", async (c) => { - const result = await runNodeEsmImportTest(); - return c.json(result, result.success ? 200 : 500); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-vite-hono-vite-dev-node-esm", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Disallowed in this environment"), + "Cloudflare Workers blocks dynamic code generation (eval/Function)", + ), + ], + }); + + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed in Vite + Hono environment (Node.js ESM build)", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all, + failures: failed, + }; + + return c.json(response, response.success ? 200 : 500); }); export default app; diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts index 3849075e2..29fbbbd41 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts @@ -1,133 +1,99 @@ import { Hono } from "hono"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, - type TestResult, + testEvalSmoke, } from "../../../shared"; import * as braintrust from "braintrust"; -const { initLogger, _exportsForTestingOnly } = braintrust; const app = new Hono<{ Bindings: Env }>(); interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "cloudflare-vite-hono", - }); - - try { - // Vite bundler should automatically resolve browser build (ESM format) when importing from "braintrust" - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests(adapters); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Test Mustache template (should always work) - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - // Test Nunjucks template - expected to fail in browser builds - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ? { - ...nunjucksResult, - status: "xfail" as const, - message: - "Expected failure: Nunjucks not supported in browser build", - } - : nunjucksResult; - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Filter out expected failures when counting actual failures - const failures = results.filter((r) => r.status === "fail"); - - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed in Vite + Hono environment", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - app.get("/", (c) => c.text(`Braintrust Cloudflare Vite + Hono Smoke Test GET /api/ - Basic API endpoint -GET /api/test - Run shared test suites - -This worker tests the Braintrust SDK in a Vite + Hono + Cloudflare Workers environment. -Vite should automatically resolve the browser build from package.json exports.`), +GET /api/test - Run shared test suites`), ); app.get("/api/", (c) => c.json({ name: "Braintrust", framework: "Hono" })); app.get("/api/test", async (c) => { - const result = await runSharedTestSuites(); - return c.json(result, result.success ? 200 : 500); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-vite-hono-vite-dev", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Nunjucks templating is not supported"), + "Nunjucks not supported in browser build", + ), + ], + }); + + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed in Vite + Hono environment", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all, + failures: failed, + }; + + return c.json(response, response.success ? 200 : 500); }); export default app; diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs index 2a4bd0ba4..2d67ff8c3 100755 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/tests/vite-dev.test.mjs @@ -78,11 +78,6 @@ async function testViteDevServer() { } const response = await fetch(`http://localhost:${PORT}/api/test`); - if (!response.ok) { - await killVite(); - return 1; - } - const result = await response.json(); if (result.results && result.results.length > 0) { diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts index 3849075e2..c440196ba 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts @@ -1,133 +1,99 @@ import { Hono } from "hono"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, - type TestResult, + testEvalSmoke, } from "../../../shared"; import * as braintrust from "braintrust"; -const { initLogger, _exportsForTestingOnly } = braintrust; const app = new Hono<{ Bindings: Env }>(); interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "cloudflare-vite-hono", - }); - - try { - // Vite bundler should automatically resolve browser build (ESM format) when importing from "braintrust" - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests(adapters); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Test Mustache template (should always work) - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - // Test Nunjucks template - expected to fail in browser builds - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ? { - ...nunjucksResult, - status: "xfail" as const, - message: - "Expected failure: Nunjucks not supported in browser build", - } - : nunjucksResult; - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Filter out expected failures when counting actual failures - const failures = results.filter((r) => r.status === "fail"); - - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed in Vite + Hono environment", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - app.get("/", (c) => c.text(`Braintrust Cloudflare Vite + Hono Smoke Test GET /api/ - Basic API endpoint -GET /api/test - Run shared test suites - -This worker tests the Braintrust SDK in a Vite + Hono + Cloudflare Workers environment. -Vite should automatically resolve the browser build from package.json exports.`), +GET /api/test - Run shared test suites`), ); app.get("/api/", (c) => c.json({ name: "Braintrust", framework: "Hono" })); app.get("/api/test", async (c) => { - const result = await runSharedTestSuites(); - return c.json(result, result.success ? 200 : 500); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-vite-hono-wrangler-dev", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Nunjucks templating is not supported"), + "Nunjucks not supported in browser build", + ), + ], + }); + + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed in Vite + Hono environment", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all, + failures: failed, + }; + + return c.json(response, response.success ? 200 : 500); }); export default app; diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts index 4b111497f..a80533a28 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts @@ -1,160 +1,109 @@ import * as braintrust from "braintrust"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, - type TestResult, + testEvalSmoke, } from "../../../shared"; interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger: braintrust.initLogger, - testingExports: braintrust._exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "cloudflare-worker-browser-compat", - }); - - try { - // Test import verification including build resolution check - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests( - adapters, - braintrust, - ); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Test Mustache template (should always work) - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - // Test Nunjucks template - expected to fail in browser builds (even with nodejs_compat_v2) - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ? { - ...nunjucksResult, - status: "xfail" as const, - message: - "Expected failure: Nunjucks not supported in browser build", - } - : nunjucksResult; - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Filter out expected failures when counting actual failures - const failures = results.filter((r) => r.status === "fail"); - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - export default { async fetch(request: Request, _env: Env): Promise { const url = new URL(request.url); if (url.pathname === "/test") { - const result = await runSharedTestSuites(); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-worker-browser-compat", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("String template rendering. Disallowed"), + "Nunjucks evals not supported", + ), + ], + }); - // Serialize errors properly (Error objects don't JSON.stringify well) - const serializedResult = { - ...result, - results: result.results?.map((r) => ({ + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), - failures: result.failures?.map((r) => ({ + failures: failed.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), }; - return new Response(JSON.stringify(serializedResult, null, 2), { + return new Response(JSON.stringify(response, null, 2), { headers: { "Content-Type": "application/json" }, - status: result.success ? 200 : 500, + status: response.success ? 200 : 500, }); } return new Response( `Braintrust Cloudflare Worker Smoke Test (Browser + nodejs_compat_v2) -GET /test - Run shared test suites - -This worker tests the Braintrust SDK in a Cloudflare Workers environment. -The bundler should automatically resolve the browser build from package.json exports.`, +GET /test - Run shared test suites`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts index 4a6b42d8e..56e8c1cc1 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts @@ -1,161 +1,109 @@ import * as braintrust from "braintrust"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, - type TestResult, + testEvalSmoke, } from "../../../shared"; interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger: braintrust.initLogger, - testingExports: braintrust._exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "cloudflare-worker-browser-no-compat", - }); - - try { - // Test import verification including build resolution check - // Bundler should automatically resolve browser build (ESM format) when importing from "braintrust" - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests( - adapters, - braintrust, - ); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Test Mustache template (should always work) - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - // Test Nunjucks template - expected to fail in browser builds - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ? { - ...nunjucksResult, - status: "xfail" as const, - message: - "Expected failure: Nunjucks not supported in browser build", - } - : nunjucksResult; - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Filter out expected failures when counting actual failures - const failures = results.filter((r) => r.status === "fail"); - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - export default { async fetch(request: Request, _env: Env): Promise { const url = new URL(request.url); if (url.pathname === "/test") { - const result = await runSharedTestSuites(); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-worker-browser-no-compat", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Nunjucks templating is not supported"), + "Nunjucks not supported in browser build", + ), + ], + }); - // Serialize errors properly (Error objects don't JSON.stringify well) - const serializedResult = { - ...result, - results: result.results?.map((r) => ({ + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), - failures: result.failures?.map((r) => ({ + failures: failed.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), }; - return new Response(JSON.stringify(serializedResult, null, 2), { + return new Response(JSON.stringify(response, null, 2), { headers: { "Content-Type": "application/json" }, - status: result.success ? 200 : 500, + status: response.success ? 200 : 500, }); } return new Response( `Braintrust Cloudflare Worker Smoke Test (Browser + No Compat) -GET /test - Run shared test suites - -This worker tests the Braintrust SDK in a Cloudflare Workers environment. -The bundler should automatically resolve the browser build from package.json exports.`, +GET /test - Run shared test suites`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts index 0e476bf49..17c8e186e 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts @@ -1,162 +1,109 @@ -// Workers with nodejs_compat can use Node.js build -// Explicitly import from "braintrust/node" to ensure Node.js build is used import * as braintrust from "braintrust/node"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, - type TestResult, + testEvalSmoke, } from "../../../shared"; interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger: braintrust.initLogger, - testingExports: braintrust._exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "cloudflare-worker-node-compat", - }); - - try { - // Node.js build (ESM format) should be used in Cloudflare Workers with nodejs_compat_v2 - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests( - adapters, - braintrust, - ); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Test Mustache template (should always work) - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - // Test Nunjucks template - expected to fail due to code generation restrictions - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Disallowed in this environment for security reasons", - ) - ? { - ...nunjucksResult, - status: "xfail" as const, - message: - "Expected failure: Cloudflare Workers blocks dynamic code generation (eval/Function)", - } - : nunjucksResult; - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Filter out expected failures when counting actual failures - const failures = results.filter((r) => r.status === "fail"); - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - export default { async fetch(request: Request, _env: Env): Promise { const url = new URL(request.url); if (url.pathname === "/test") { - const result = await runSharedTestSuites(); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-worker-node-compat", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Disallowed in this environment"), + "Cloudflare Workers blocks dynamic code generation (eval/Function)", + ), + ], + }); - // Serialize errors properly (Error objects don't JSON.stringify well) - const serializedResult = { - ...result, - results: result.results?.map((r) => ({ + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), - failures: result.failures?.map((r) => ({ + failures: failed.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), }; - return new Response(JSON.stringify(serializedResult, null, 2), { + return new Response(JSON.stringify(response, null, 2), { headers: { "Content-Type": "application/json" }, - status: result.success ? 200 : 500, + status: response.success ? 200 : 500, }); } return new Response( `Braintrust Cloudflare Worker Smoke Test (Node.js + nodejs_compat_v2) -GET /test - Run shared test suites - -This worker tests the Braintrust SDK in a Cloudflare Workers environment. -Should use Node.js build from package.json exports.`, +GET /test - Run shared test suites`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts index a88f7beb6..8090a2fce 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts @@ -1,137 +1,104 @@ import * as braintrust from "braintrust/node"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - type TestResult, + runTests, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testMustacheTemplate, + testNunjucksTemplate, + testEvalSmoke, } from "../../../shared"; interface Env {} -interface TestResponse { - success: boolean; - message: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - results?: TestResult[]; - failures?: TestResult[]; -} - -async function runSharedTestSuites(): Promise { - try { - const adapters = await setupTestEnvironment({ - initLogger: braintrust.initLogger, - testingExports: braintrust._exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "cloudflare-worker-node-no-compat", - }); - - try { - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests( - adapters, - braintrust, - ); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - const failures = results.filter((r) => r.status === "fail"); - if (failures.length > 0) { - return { - success: false, - message: `${failures.length} test(s) failed`, - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - results, - failures, - }; - } - - return { - success: true, - message: "All shared test suites passed", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - results, - }; - } finally { - await cleanupTestEnvironment(adapters); - } - } catch (error) { - return { - success: false, - message: `Error during smoke test: ${error instanceof Error ? error.message : String(error)}`, - totalTests: 0, - passedTests: 0, - failedTests: 0, - }; - } -} - export default { async fetch(request: Request, _env: Env): Promise { const url = new URL(request.url); if (url.pathname === "/test") { - const result = await runSharedTestSuites(); + const { all, passed, failed, xfail } = await runTests({ + name: "cloudflare-worker-node-no-compat", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + testNunjucksTemplate, + ], + }); - // Serialize errors properly (Error objects don't JSON.stringify well) - const serializedResult = { - ...result, - results: result.results?.map((r) => ({ + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed` + : "All shared test suites passed", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), - failures: result.failures?.map((r) => ({ + failures: failed.map((r) => ({ ...r, error: r.error - ? { - message: r.error.message, - stack: r.error.stack, - name: r.error.name, - } + ? { message: r.error.message, stack: r.error.stack } : undefined, })), }; - return new Response(JSON.stringify(serializedResult, null, 2), { + return new Response(JSON.stringify(response, null, 2), { headers: { "Content-Type": "application/json" }, - status: result.success ? 200 : 500, + status: response.success ? 200 : 500, }); } return new Response( `Braintrust Cloudflare Worker Smoke Test (Node.js + No Compat) -GET /test - Run shared test suites - -This worker tests the Braintrust SDK in a Cloudflare Workers environment. -Should use Node.js build from package.json exports (may fail without nodejs_compat_v2).`, +GET /test - Run shared test suites`, { headers: { "Content-Type": "text/plain" } }, ); }, diff --git a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts index 515692c06..2c37b4f98 100644 --- a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts @@ -1,91 +1,75 @@ // @ts-nocheck /** - * Deno smoke test using shared test suites, but importing the browser build. + * Deno smoke test using shared test suites (browser build) */ import { assertEquals } from "@std/assert"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, - displayTestResults, - hasFailures, - getFailureCount, - type TestResult, + testEvalSmoke, } from "@braintrust/smoke-test-shared"; import * as braintrust from "braintrust"; -export async function runSharedTestSuites(): Promise { - const { initLogger, _exportsForTestingOnly } = braintrust; - - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: false, - environment: "browser", +Deno.test("Run shared test suites (browser build)", async () => { + const { failed } = await runTests({ + name: "deno-browser", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e: { message: string }) => + e.message.includes("Nunjucks templating is not supported"), + "Nunjucks not supported in browser build", + ), + ], }); - try { - // Run tests including build resolution check - // Bundler should automatically resolve browser build (ESM format) when importing from "braintrust" - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests(adapters, braintrust); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ? { - ...nunjucksResult, - status: "xfail" as const, - message: - "Expected failure: Nunjucks not supported in browser build", - } - : nunjucksResult; - - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Display results - displayTestResults({ - scenarioName: "Deno Browser Test Results", - results, - }); - - // Check for failures - if (hasFailures(results)) { - throw new Error(`${getFailureCount(results)} test(s) failed`); - } - - return results; - } finally { - await cleanupTestEnvironment(adapters); - } -} - -Deno.test("Run shared test suites (browser build)", async () => { - const results = await runSharedTestSuites(); - assertEquals(results.filter((r) => r.status === "fail").length, 0); + assertEquals(failed.length, 0, "All tests should pass"); }); diff --git a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts index 471976531..543312576 100644 --- a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts @@ -1,85 +1,69 @@ // @ts-nocheck /** * Deno smoke test using shared test suites - * This test demonstrates using the shared test package across different runtimes */ import { assertEquals } from "@std/assert"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, - displayTestResults, - hasFailures, - getFailureCount, - type TestResult, + runTests, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testMustacheTemplate, + testNunjucksTemplate, + testEvalSmoke, } from "@braintrust/smoke-test-shared"; import * as braintrust from "braintrust"; -/** - * Run the shared test suites in Deno environment - */ -export async function runSharedTestSuites() { - const { initLogger, _exportsForTestingOnly } = braintrust; - - // Setup test environment - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, // Deno has filesystem access - canUseCLI: false, // No CLI in Deno tests - environment: "deno", - }); - - try { - // Run tests including build resolution check - // Deno Node should resolve to Node build (ESM format) when using import - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests(adapters, braintrust); - const evalResult = await runEvalSmokeTest(adapters, braintrust); - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); - - // Combine results - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - // Display results - displayTestResults({ - scenarioName: "Deno Node Test Results", - results, - }); - - // Check for failures - if (hasFailures(results)) { - throw new Error(`${getFailureCount(results)} test(s) failed`); - } - - return results; - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); - } -} - Deno.test("Run shared test suites", async () => { - const results = await runSharedTestSuites(); + const { failed } = await runTests({ + name: "deno-node", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + testNunjucksTemplate, + ], + }); - // Assert all tests passed - assertEquals( - results.filter((r) => r.status === "fail").length, - 0, - "All tests should pass", - ); + assertEquals(failed.length, 0, "All tests should pass"); }); diff --git a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js index b37d5f7d3..33c2d24a4 100644 --- a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js +++ b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js @@ -1,63 +1,62 @@ const { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runImportVerificationTests, - runPromptTemplatingTests, - displayTestResults, - hasFailures, - getFailureCount, + runTests, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testMustacheTemplate, + testNunjucksTemplate, } = require("../../../shared/dist/index.js"); const braintrust = require("braintrust"); -const { initLogger, _exportsForTestingOnly } = braintrust; - -async function runSharedTestSuites() { - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: true, - environment: "jest", - }); - - try { - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "cjs", - }); - const functionalResults = await runBasicLoggingTests(adapters); - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); - - const results = [ - ...importResults, - ...functionalResults, - ...promptTemplatingResults, - ]; - - return { - all: results, - import: importResults, - functional: functionalResults, - templating: promptTemplatingResults, - }; - } finally { - await cleanupTestEnvironment(adapters); - } -} test("shared test suites pass in Jest", async () => { - const { all: results } = await runSharedTestSuites(); - - // Display results - displayTestResults({ - scenarioName: "Jest Node Test Results", - results, + const { failed } = await runTests({ + name: "jest-node", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testMustacheTemplate, + testNunjucksTemplate, + ], }); - // Check for failures - const failures = results.filter((r) => r.status === "fail"); - expect(failures).toHaveLength(0); + expect(failed).toHaveLength(0); }); diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts index 6a300ffd2..c0bf8769c 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts @@ -1,158 +1,97 @@ /** * Next.js Edge Runtime API route for running shared test suites - * Tests the Braintrust SDK in Next.js Edge Runtime (V8 isolates) */ import { NextResponse } from "next/server"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, + testEvalSmoke, } from "../../../../../../../shared"; import * as braintrust from "braintrust"; -const { initLogger, _exportsForTestingOnly } = braintrust; -// Force Edge Runtime export const runtime = "edge"; -interface TestResponse { - success: boolean; - message: string; - runtime: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - timestamp: string; - results?: Array<{ - name: string; - status: "pass" | "fail" | "xfail"; - error?: { message: string }; - message?: string; - }>; - failures?: Array<{ - testName: string; - error?: string; - }>; -} - -/** - * GET /api/smoke-test/edge - Run shared test suites in Edge Runtime - */ -export async function GET(): Promise> { +export async function GET() { const timestamp = new Date().toISOString(); - try { - // Setup test environment with Edge Runtime constraints - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, // No filesystem in Edge Runtime - canUseCLI: false, // No CLI in Edge Runtime - environment: "nextjs-edge-runtime", - }); - - try { - // Run import verification tests including build resolution check - // Next.js Edge runtime should resolve to browser build (ESM format) - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - - // Run functional tests - const functionalResults = await runBasicLoggingTests( - adapters, - braintrust, - ); - - // Run eval smoke test - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Run prompt templating tests - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - const nunjucksResultHandled = - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ? { - ...nunjucksResult, - status: "pass" as const, - message: - "Expected failure: Nunjucks not supported in Edge Runtime", - } - : nunjucksResult; - - // Combine results - const results = [ - ...importResults, - ...functionalResults, - evalResult, - mustacheResult, - nunjucksResultHandled, - ]; - - // Check for failures - const failures = results.filter((r) => r.status === "fail"); - - if (failures.length > 0) { - const response: TestResponse = { - success: false, - message: `${failures.length} test(s) failed in Edge Runtime`, - runtime: "edge", - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - timestamp, - results, - failures: failures.map((f) => ({ - testName: f.name, - error: f.error?.message || "Unknown error", - })), - }; - - return NextResponse.json(response, { status: 500 }); - } - - // All tests passed - const response: TestResponse = { - success: true, - message: `All ${results.length} tests passed in Edge Runtime`, - runtime: "edge", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - timestamp, - results, - }; - - return NextResponse.json(response, { status: 200 }); - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); - } - } catch (error) { - const response: TestResponse = { - success: false, - message: `Edge Runtime test error: ${error instanceof Error ? error.message : String(error)}`, - runtime: "edge", - totalTests: 0, - passedTests: 0, - failedTests: 0, - timestamp, - }; - - return NextResponse.json(response, { status: 500 }); - } + const { all, passed, failed, xfail } = await runTests({ + name: "nextjs-edge", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Nunjucks templating is not supported"), + "Nunjucks not supported in Edge Runtime", + ), + ], + }); + + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed in Edge Runtime` + : `All ${all.length} tests passed in Edge Runtime`, + runtime: "edge", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + timestamp, + results: all, + failures: failed.map((f) => ({ + testName: f.name, + error: f.error?.message || "Unknown error", + })), + }; + + return NextResponse.json(response, { status: response.success ? 200 : 500 }); } diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts index 5e50e4b38..1730617da 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts @@ -1,140 +1,92 @@ /** * Next.js Node.js Runtime API route for running shared test suites - * Tests the Braintrust SDK in Next.js Node.js Runtime */ import { NextResponse } from "next/server"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, - runPromptTemplatingTests, + runTests, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testMustacheTemplate, + testNunjucksTemplate, + testEvalSmoke, } from "../../../../../../../shared"; import * as braintrust from "braintrust"; -const { initLogger, _exportsForTestingOnly } = braintrust; -// Force Node.js Runtime export const runtime = "nodejs"; -interface TestResponse { - success: boolean; - message: string; - runtime: string; - totalTests?: number; - passedTests?: number; - failedTests?: number; - timestamp: string; - results?: Array<{ - name: string; - status: "pass" | "fail" | "xfail"; - error?: { message: string }; - message?: string; - }>; - failures?: Array<{ - testName: string; - error?: string; - }>; -} - -/** - * GET /api/smoke-test/node - Run shared test suites in Node.js Runtime - */ -export async function GET(): Promise> { +export async function GET() { const timestamp = new Date().toISOString(); - try { - // Setup test environment with Node.js Runtime constraints - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, // API routes shouldn't rely on filesystem - canUseCLI: false, // No CLI in API routes - environment: "nextjs-nodejs-runtime", - }); - - try { - // Run import verification tests including build resolution check - // Next.js Node.js runtime should resolve to Node build (CJS format) - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "cjs", - }); - - // Run functional tests - const functionalResults = await runBasicLoggingTests( - adapters, - braintrust, - ); - - // Run eval smoke test - const evalResult = await runEvalSmokeTest(adapters, braintrust); - - // Run prompt templating tests - const promptTemplatingResults = await runPromptTemplatingTests({ - Prompt: braintrust.Prompt, - }); - - // Combine results - const results = [ - ...importResults, - ...functionalResults, - evalResult, - ...promptTemplatingResults, - ]; - - // Check for failures - const failures = results.filter((r) => r.status === "fail"); - - if (failures.length > 0) { - const response: TestResponse = { - success: false, - message: `${failures.length} test(s) failed in Node.js Runtime`, - runtime: "nodejs", - totalTests: results.length, - passedTests: results.length - failures.length, - failedTests: failures.length, - timestamp, - results, - failures: failures.map((f) => ({ - testName: f.name, - error: f.error?.message || "Unknown error", - })), - }; - - return NextResponse.json(response, { status: 500 }); - } - - // All tests passed - const response: TestResponse = { - success: true, - message: `All ${results.length} tests passed in Node.js Runtime`, - runtime: "nodejs", - totalTests: results.length, - passedTests: results.length, - failedTests: 0, - timestamp, - results, - }; - - return NextResponse.json(response, { status: 200 }); - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); - } - } catch (error) { - const response: TestResponse = { - success: false, - message: `Node.js Runtime test error: ${error instanceof Error ? error.message : String(error)}`, - runtime: "nodejs", - totalTests: 0, - passedTests: 0, - failedTests: 0, - timestamp, - }; - - return NextResponse.json(response, { status: 500 }); - } + const { all, passed, failed, xfail } = await runTests({ + name: "nextjs-node", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + testNunjucksTemplate, + ], + }); + + const response = { + success: failed.length === 0, + message: + failed.length > 0 + ? `${failed.length} test(s) failed in Node.js Runtime` + : `All ${all.length} tests passed in Node.js Runtime`, + runtime: "nodejs", + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + timestamp, + results: all, + failures: failed.map((f) => ({ + testName: f.name, + error: f.error?.message || "Unknown error", + })), + }; + + return NextResponse.json(response, { status: response.success ? 200 : 500 }); } diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts b/js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts index 5c7e8595d..50a2433b3 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/instrumentation.ts @@ -17,9 +17,9 @@ import { registerOTel } from "@vercel/otel"; // Import verification: webpack will fail the build if this import doesn't work // This tests tree-shaking and module resolution import { - setupTestEnvironment, - runBasicLoggingTests, - runImportVerificationTests, + runTests, + testBasicSpanLogging, + testCoreLoggingExports, } from "../../../shared"; export async function register() { @@ -48,7 +48,7 @@ export async function register() { // (They need to be referenced somewhere for webpack to include them) if (process.env.NODE_ENV === "test") { // This code never runs in production, but ensures webpack includes the imports - void setupTestEnvironment; - void runBasicLoggingTests; - void runImportVerificationTests; + void runTests; + void testBasicSpanLogging; + void testCoreLoggingExports; } diff --git a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts b/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts index 2bf19c768..5559e89ac 100644 --- a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts @@ -3,57 +3,63 @@ */ import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runImportVerificationTests, - displayTestResults, - hasFailures, - getFailureCount, + runTests, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, } from "../../../shared/dist/index.js"; -import { initLogger, _exportsForTestingOnly } from "braintrust"; - async function runSharedTestSuites() { - // Import Braintrust module for import verification const braintrust = await import("braintrust"); - // Setup test environment - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: true, - environment: "otel-v1", + const { failed } = await runTests({ + name: "otel-v1", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + ], }); - try { - // Run tests including build resolution check - // Node.js should resolve to Node build (ESM format) when using import - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "node", - expectedFormat: "esm", - }); - const functionalResults = await runBasicLoggingTests(adapters, braintrust); - - // Combine results - const results = [...importResults, ...functionalResults]; - - // Display results - displayTestResults({ - scenarioName: "OTEL v1 Test Results", - results, - }); - - // Check for failures - if (hasFailures(results)) { - throw new Error(`${getFailureCount(results)} test(s) failed`); - } - - return results; - } finally { - // Clean up test environment - await cleanupTestEnvironment(adapters); + if (failed.length > 0) { + throw new Error(`${failed.length} test(s) failed`); } } diff --git a/js/smoke/scenarios/playwright-browser/playwright.config.ts b/js/smoke/scenarios/playwright-browser/playwright.config.ts index 7ea6343d5..bcf5b1896 100644 --- a/js/smoke/scenarios/playwright-browser/playwright.config.ts +++ b/js/smoke/scenarios/playwright-browser/playwright.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, - reporter: "html", + reporter: "list", use: { trace: "on-first-retry", baseURL: "http://localhost:3001", diff --git a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts index 75c831525..e56a78d0a 100644 --- a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts +++ b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts @@ -1,12 +1,31 @@ import * as braintrust from "braintrust"; import { - setupTestEnvironment, - cleanupTestEnvironment, - runBasicLoggingTests, - runEvalSmokeTest, - runImportVerificationTests, + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, testMustacheTemplate, testNunjucksTemplate, + testEvalSmoke, } from "../../../shared"; import { createBrowserHarness, type BrowserSmokeResults } from "./harness"; @@ -24,10 +43,6 @@ if (!output) { const harness = createBrowserHarness(output); window.__btBrowserSmokeResults = harness.results; -const SHARED_SECTION = "shared"; -const EVAL_SECTION = "eval"; -const PROMPT_SECTION = "prompt"; - async function runAllTestSuites() { if (!braintrust._exportsForTestingOnly) { harness.fail( @@ -38,107 +53,59 @@ async function runAllTestSuites() { return; } - const adapters = await setupTestEnvironment({ - initLogger: braintrust.initLogger, - testingExports: braintrust._exportsForTestingOnly, - canUseFileSystem: false, - canUseCLI: false, - environment: "browser", + harness.log("=== Running test suites ==="); + + const { passed, failed, xfail } = await runTests({ + name: "playwright-browser", + braintrust, + tests: [ + testCoreLoggingExports, + testDatasetExports, + testPromptExports, + testExperimentExports, + testEvalExports, + testTracingExports, + testClientWrapperExports, + testUtilityExports, + testFunctionExports, + testFramework2Exports, + testIDGeneratorExports, + testTestingExports, + testStateManagementExports, + testBuildResolution, + testBasicSpanLogging, + testMultipleSpans, + testDirectLogging, + testJSONAttachment, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Nunjucks templating is not supported"), + "Nunjucks not supported in browser build", + ), + ], }); - try { - harness.log("=== Running shared suites ==="); - - const importResults = await runImportVerificationTests(braintrust, { - expectedBuild: "browser", - expectedFormat: "esm", - }); - for (const r of importResults) { - if (r.status === "pass") harness.pass(SHARED_SECTION, r.name, r.message); - else - harness.fail( - SHARED_SECTION, - r.name, - r.error || new Error("Test failed"), - r.message, - ); - } - - const loggingResults = await runBasicLoggingTests(adapters, braintrust); - for (const r of loggingResults) { - if (r.status === "pass") harness.pass(SHARED_SECTION, r.name, r.message); - else - harness.fail( - SHARED_SECTION, - r.name, - r.error || new Error("Test failed"), - r.message, - ); - } - - harness.completeSection(SHARED_SECTION); - - harness.log("\n=== Running eval suite ==="); - - const evalResult = await runEvalSmokeTest(adapters, braintrust); - if (evalResult.status === "pass") - harness.pass(EVAL_SECTION, evalResult.name, evalResult.message); - else - harness.fail( - EVAL_SECTION, - evalResult.name, - evalResult.error || new Error("Test failed"), - evalResult.message, - ); - - harness.completeSection(EVAL_SECTION); - - harness.log("\n=== Running prompt templating suite ==="); - - const mustacheResult = await testMustacheTemplate({ - Prompt: braintrust.Prompt, - }); - if (mustacheResult.status === "pass") - harness.pass(PROMPT_SECTION, mustacheResult.name, mustacheResult.message); - else - harness.fail( - PROMPT_SECTION, - mustacheResult.name, - mustacheResult.error || new Error("Test failed"), - mustacheResult.message, - ); - - const nunjucksResult = await testNunjucksTemplate({ - Prompt: braintrust.Prompt, - }); - if ( - nunjucksResult.status === "fail" && - nunjucksResult.error?.message.includes( - "Nunjucks templating is not supported", - ) - ) { - harness.pass( - PROMPT_SECTION, - nunjucksResult.name, - "Expected failure: Nunjucks not supported in browser build", - ); - } else if (nunjucksResult.status === "pass") { - harness.pass(PROMPT_SECTION, nunjucksResult.name, nunjucksResult.message); - } else { - harness.fail( - PROMPT_SECTION, - nunjucksResult.name, - nunjucksResult.error || new Error("Test failed"), - nunjucksResult.message, - ); - } - - harness.completeSection(PROMPT_SECTION); - } catch (err) { - harness.fail("runtime", "fatal", err); - } finally { - await cleanupTestEnvironment(adapters); + for (const r of passed) { + harness.pass("tests", r.name, r.message); } + for (const r of xfail) { + harness.pass("tests", r.name, `[xfail] ${r.message}`); + } + for (const r of failed) { + harness.fail( + "tests", + r.name, + r.error || new Error("Test failed"), + r.message, + ); + } + + harness.completeSection("tests"); } async function main() { @@ -154,15 +121,10 @@ async function main() { } }, timeoutMs); - try { - await runAllTestSuites(); - } catch (err) { - harness.fail("runtime", "fatal", err); - } finally { - window.clearTimeout(timeout); - harness.log("\n=== All browser suites complete ==="); - harness.completeAll(); - } + await runAllTestSuites(); + window.clearTimeout(timeout); + harness.log("\n=== All browser suites complete ==="); + harness.completeAll(); } void main(); diff --git a/js/smoke/scenarios/playwright-browser/tests/browser.test.ts b/js/smoke/scenarios/playwright-browser/tests/browser.test.ts index c8f5cefde..fec302726 100644 --- a/js/smoke/scenarios/playwright-browser/tests/browser.test.ts +++ b/js/smoke/scenarios/playwright-browser/tests/browser.test.ts @@ -99,62 +99,22 @@ test.describe("Braintrust SDK Browser Tests", () => { }); } - // Test 3: Shared suite + // Test 3: All tests passed if ( - smoke.sections.shared.completed && - smoke.sections.shared.failed === 0 && - smoke.sections.shared.passed >= 17 + smoke.sections.tests.completed && + smoke.sections.tests.failed === 0 && + smoke.sections.tests.passed >= 20 ) { results.push({ status: "pass", - name: `Shared suite (${smoke.sections.shared.passed} tests)`, + name: `All tests (${smoke.sections.tests.passed} passed)`, }); } else { results.push({ status: "fail", - name: "Shared suite", + name: "All tests", error: { - message: `Completed: ${smoke.sections.shared.completed}, Passed: ${smoke.sections.shared.passed}, Failed: ${smoke.sections.shared.failed}`, - }, - }); - } - - // Test 4: Eval suite - if ( - smoke.sections.eval.completed && - smoke.sections.eval.failed === 0 && - smoke.sections.eval.passed === 1 - ) { - results.push({ - status: "pass", - name: "Eval suite (1 test)", - }); - } else { - results.push({ - status: "fail", - name: "Eval suite", - error: { - message: `Completed: ${smoke.sections.eval.completed}, Passed: ${smoke.sections.eval.passed}, Failed: ${smoke.sections.eval.failed}`, - }, - }); - } - - // Test 5: Prompt suite - if ( - smoke.sections.prompt.completed && - smoke.sections.prompt.failed === 0 && - smoke.sections.prompt.passed === 2 - ) { - results.push({ - status: "pass", - name: "Prompt suite (2 tests)", - }); - } else { - results.push({ - status: "fail", - name: "Prompt suite", - error: { - message: `Completed: ${smoke.sections.prompt.completed}, Passed: ${smoke.sections.prompt.passed}, Failed: ${smoke.sections.prompt.failed}`, + message: `Completed: ${smoke.sections.tests.completed}, Passed: ${smoke.sections.tests.passed}, Failed: ${smoke.sections.tests.failed}`, }, }); } @@ -168,14 +128,8 @@ test.describe("Braintrust SDK Browser Tests", () => { expect(smoke).toBeTruthy(); expect(smoke.completed).toBe(true); expect(smoke.unhandledErrors?.length ?? 0).toBe(0); - expect(smoke.sections.shared.completed).toBe(true); - expect(smoke.sections.shared.failed).toBe(0); - expect(smoke.sections.shared.passed).toBeGreaterThanOrEqual(17); - expect(smoke.sections.eval.completed).toBe(true); - expect(smoke.sections.eval.failed).toBe(0); - expect(smoke.sections.eval.passed).toBe(1); - expect(smoke.sections.prompt.completed).toBe(true); - expect(smoke.sections.prompt.failed).toBe(0); - expect(smoke.sections.prompt.passed).toBe(2); + expect(smoke.sections.tests.completed).toBe(true); + expect(smoke.sections.tests.failed).toBe(0); + expect(smoke.sections.tests.passed).toBeGreaterThanOrEqual(20); }); }); diff --git a/js/smoke/shared/README.md b/js/smoke/shared/README.md index bdd6f42a2..1cac4d920 100644 --- a/js/smoke/shared/README.md +++ b/js/smoke/shared/README.md @@ -30,11 +30,14 @@ shared/ ├── src/ │ ├── helpers/ │ │ ├── types.ts # Shared type definitions -│ │ ├── test-state.ts # Test environment setup/teardown -│ │ └── assertions.ts # Assertion utilities +│ │ ├── register.ts # Test registration and runner +│ │ ├── assertions.ts # Assertion utilities +│ │ └── display.ts # Result display utilities │ ├── suites/ -│ │ ├── basic-logging.ts # Basic logging test suite -│ │ └── ... # Additional test suites +│ │ ├── basic-logging.ts # Basic logging test suite +│ │ ├── import-verification.ts # Import/export verification +│ │ ├── prompt-templating.ts # Prompt templating tests +│ │ └── eval-smoke.ts # Eval functionality tests │ └── index.ts # Main exports ├── dist/ # Build output (gitignored) ├── package.json @@ -54,134 +57,366 @@ This produces both CJS and ESM builds in the `dist/` directory. ## Usage -### In Node.js (CJS) +### Basic Pattern ```typescript -// CommonJS environment +import { + runTests, + expectFailure, + testBasicSpanLogging, + testMultipleSpans, + testNunjucksTemplate, +} from "../../shared/dist/index.mjs"; + +import * as braintrust from "braintrust"; + +async function main() { + const { all, passed, failed, xfail } = await runTests({ + name: "My Test Suite", + braintrust, + tests: [ + testBasicSpanLogging, + testMultipleSpans, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("not supported"), + "Nunjucks not supported in browser build", + ), + ], + }); + + if (failed.length > 0) { + process.exit(1); + } +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); +``` + +### In Node.js (CJS) + +```javascript const { - setupTestEnvironment, - runBasicLoggingTests, -} = require("../../shared/dist/index.js"); + runTests, + testBasicSpanLogging, + testMultipleSpans, +} = require("../../shared"); + +const braintrust = require("braintrust"); async function main() { - const { initLogger, _exportsForTestingOnly } = require("braintrust"); - - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: true, - environment: "node", + const { all, passed, failed, xfail } = await runTests({ + name: "Node.js CJS Tests", + braintrust, + tests: [testBasicSpanLogging, testMultipleSpans], }); - const results = await runBasicLoggingTests(adapters); - // Handle results... + if (failed.length > 0) { + process.exit(1); + } } ``` ### In Node.js (ESM) ```typescript -// ESM environment (after enable-esm) import { - setupTestEnvironment, - runBasicLoggingTests, -} from "../../shared/dist/index.mjs"; + runTests, + testBasicSpanLogging, + testMultipleSpans, +} from "../../shared"; -async function main() { - const { initLogger, _exportsForTestingOnly } = await import("braintrust"); - - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: true, - environment: "node-esm", - }); +import * as braintrust from "braintrust"; - const results = await runBasicLoggingTests(adapters); - // Handle results... +const { all, passed, failed, xfail } = await runTests({ + name: "Node.js ESM Tests", + braintrust, + tests: [testBasicSpanLogging, testMultipleSpans], +}); + +if (failed.length > 0) { + process.exit(1); } ``` ### In Deno ```typescript -// Deno always uses ESM import { - setupTestEnvironment, - runBasicLoggingTests, -} from "../../shared/dist/index.mjs"; + runTests, + testBasicSpanLogging, + testMultipleSpans, +} from "../../shared"; -const { initLogger, _exportsForTestingOnly } = await import( - `file://${Deno.env.get("BRAINTRUST_BUILD_DIR")}` -); +import * as braintrust from "braintrust"; -const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: true, - canUseCLI: false, - environment: "deno", +const { all, passed, failed, xfail } = await runTests({ + name: "Deno Tests", + braintrust, + tests: [testBasicSpanLogging, testMultipleSpans], }); -const results = await runBasicLoggingTests(adapters); +if (failed.length > 0) { + Deno.exit(1); +} ``` ### In Cloudflare Workers ```typescript -// Workers use ESM import { - setupTestEnvironment, - runBasicLoggingTests, -} from "../../../shared/dist/index.mjs"; + runTests, + expectFailure, + testBasicSpanLogging, + testNunjucksTemplate, +} from "../../../shared"; -import { initLogger, _exportsForTestingOnly } from "braintrust"; +import * as braintrust from "braintrust"; export default { async fetch(request: Request): Promise { - const adapters = await setupTestEnvironment({ - initLogger, - testingExports: _exportsForTestingOnly, - canUseFileSystem: false, // No fs in Workers - canUseCLI: false, - environment: "cloudflare-worker", + const { all, passed, failed, xfail } = await runTests({ + name: "Cloudflare Worker Tests", + braintrust, + tests: [ + testBasicSpanLogging, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("Disallowed"), + "Cloudflare Workers blocks dynamic code generation", + ), + ], }); - const results = await runBasicLoggingTests(adapters); - return new Response(JSON.stringify(results)); + return new Response( + JSON.stringify({ + success: failed.length === 0, + totalTests: all.length, + passedTests: passed.length, + failedTests: failed.length, + xfailTests: xfail.length, + results: all, + }), + { + status: failed.length === 0 ? 200 : 500, + headers: { "Content-Type": "application/json" }, + }, + ); }, }; ``` -## Test Adapters +## Core Concepts + +### Test Registration Pattern + +Tests are defined using the `register()` function which: + +- Adds tests to a global registry for coverage validation +- Normalizes test output to `TestResult` format +- Handles setup/teardown automatically using `_exportsForTestingOnly` +- Wraps tests in try/catch blocks + +```typescript +import { register } from "../helpers/register"; + +export const testMyFeature = register( + "testMyFeature", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; + const logger = initLogger({ projectName: "test-project" }); + + // Test logic here + + return "Test passed successfully"; + }, +); +``` + +### Test Runner: `runTests()` + +The `runTests()` helper: + +- Executes all provided tests +- Validates coverage (ensures all registered tests are called) +- Displays results automatically +- Returns structured results + +**API:** + +```typescript +interface RunTestsOptions { + name: string; // Scenario name for display + braintrust: BraintrustModule; // Braintrust SDK module + tests: TestFn[]; // Array of test functions +} + +interface TestRunResults { + all: TestResult[]; // All test results + passed: TestResult[]; // Only passed tests + failed: TestResult[]; // Only failed tests + xfail: TestResult[]; // Only expected failures +} + +function runTests(options: RunTestsOptions): Promise; +``` + +**Example:** + +```typescript +const { all, passed, failed, xfail } = await runTests({ + name: "My Test Suite", + braintrust, + tests: [testOne, testTwo, testThree], +}); + +// Access specific result categories +console.log(`Passed: ${passed.length}`); +console.log(`Failed: ${failed.length}`); +console.log(`Expected failures: ${xfail.length}`); +``` + +### Expected Failures: `expectFailure()` + +Use `expectFailure()` to mark tests that are expected to fail in certain environments: + +```typescript +expectFailure( + testFunction, // The test function + errorPredicate, // Function to validate the error + reason, // Human-readable explanation +); +``` + +**Error Predicate:** +The `errorPredicate` function receives an error object and must return `true` if the error matches expectations: + +```typescript +type ErrorPredicate = (error: { message: string; stack?: string }) => boolean; +``` + +**Examples:** -The `TestAdapters` interface allows test suites to adapt to different environment capabilities: +```typescript +// Simple message check +expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("not supported"), + "Nunjucks not supported in browser build", +); + +// Multiple conditions +expectFailure( + testAsyncLocalStorage, + (e) => + e.message.includes("AsyncLocalStorage") || + e.message.includes("not available"), + "ALS not available in this environment", +); + +// Always expect failure (use sparingly) +expectFailure( + testExperimentalFeature, + () => true, + "Feature not yet implemented", +); +``` + +**Why Error Predicates Matter:** + +- Prevents masking unexpected errors +- Ensures the test fails for the expected reason +- If predicate returns `false`, the test remains a `fail` instead of converting to `xfail` + +### Test Context + +Tests receive a `TestContext` object with additional utilities: ```typescript -interface TestAdapters { - initLogger: Function; // Braintrust initLogger function - testingExports: TestingExports; // _exportsForTestingOnly - backgroundLogger: BackgroundLogger; - canUseFileSystem: boolean; // Can tests read/write files? - canUseCLI: boolean; // Can tests invoke CLI commands? - environment: string; // Environment name for logging +interface TestContext { + backgroundLogger: BackgroundLogger; // Logger for capturing/draining logs } ``` -Test suites check these flags and skip tests that aren't feasible in the current environment. +The `backgroundLogger` provides: + +- `drain()` - Get and clear all captured events +- Access to logged events for verification + +## Available Test Suites + +### Import Verification + +Tests that verify SDK exports are correctly exposed and not tree-shaken: + +- `testCoreLoggingExports` - initLogger, Logger, Span, etc. +- `testDatasetExports` - Dataset class and methods +- `testPromptExports` - Prompt class and methods +- `testExperimentExports` - Experiment class and methods +- `testEvalExports` - Eval, Evaluator, Score, etc. +- `testTracingExports` - traced, startSpan, currentSpan, etc. +- `testClientWrapperExports` - wrapOpenAI, wrapAnthropic, etc. +- `testUtilityExports` - Utility functions +- `testFunctionExports` - Function class and methods +- `testFramework2Exports` - Framework exports +- `testIDGeneratorExports` - ID generation utilities +- `testTestingExports` - \_exportsForTestingOnly +- `testStateManagementExports` - State management utilities +- `testBuildResolution` - Verifies correct build (browser vs node) and format (cjs vs esm) + +### Basic Logging + +Tests core logging functionality: + +- `testBasicSpanLogging` - Single span with input/output/expected +- `testMultipleSpans` - Multiple sequential spans +- `testDirectLogging` - Direct logger.log() if available +- `testJSONAttachment` - JSON attachment logging +- `testAsyncLocalStorageTraced` - ALS: traced() + startSpan() parent-child relationship +- `testNestedTraced` - ALS: Nested traced() calls (3-level hierarchy) +- `testCurrentSpan` - ALS: currentSpan() returns active span + +**Async Local Storage (ALS) tests**: Verify parent-child span relationships work correctly. + +- **Node.js/Deno**: Full ALS → verifies `span_parents` relationships +- **Browser/Workers**: May have limited or no ALS support +- **Edge**: May have ALS → tests check if relationships work + +**Error handling**: Tests don't pre-check if functions exist. If `traced`, `startSpan`, or `currentSpan` are undefined, the code naturally throws and the error is caught by the `register()` wrapper, resulting in a test failure with the full stack trace. + +### Prompt Templating + +Tests prompt templating functionality: + +- `testMustacheTemplate` - Mustache templating (works everywhere) +- `testNunjucksTemplate` - Nunjucks templating (Node.js only, uses eval/Function) + +**Note**: Nunjucks tests typically fail in browser/Workers environments due to: + +- Browser build doesn't include Nunjucks +- Cloudflare Workers blocks dynamic code generation (eval/Function) + +Use `expectFailure()` for these tests in browser/Workers scenarios. + +### Eval Smoke Test + +Tests basic eval functionality: + +- `testEvalSmoke` - Creates eval, runs test cases, verifies output structure ## Test Result Display ### Standardized Output Format -All scenarios now use a standardized display format via the `displayTestResults()` utility: +All scenarios use `displayTestResults()` for consistent output: ```typescript import { displayTestResults } from "../../shared/dist/index.mjs"; -// Display test results +// Called automatically by runTests(), but can also be used standalone displayTestResults({ scenarioName: "My Scenario Test Results", results: testResults, @@ -189,7 +424,7 @@ displayTestResults({ }); ``` -This produces consistent output across all scenarios: +Output format: ``` === My Scenario Test Results === @@ -202,7 +437,6 @@ Expected failures: 2 ✗ testFailingFeature Error: Feature not implemented at Feature.test (feature.ts:42:11) - at runTest (test.ts:10:5) ⊘ testNunjucksTemplate Expected failure: Nunjucks not supported in browser build ``` @@ -214,85 +448,73 @@ Expected failures: 2 - `getFailureCount(results)` - Get count of real failures - `getTestStats(results)` - Get summary statistics (total, passed, failed, xfail) -## Available Test Suites +## Adding New Tests -### Basic Logging - -Tests core logging functionality: +1. **Create test function in a suite file:** -- `testBasicSpanLogging()` - Single span with input/output/expected -- `testMultipleSpans()` - Multiple sequential spans -- `testDirectLogging()` - Direct logger.log() if available -- `testJSONAttachment()` - JSON attachment logging -- `runBasicLoggingTests()` - Runs all basic logging tests +```typescript +// src/suites/my-suite.ts +import { register } from "../helpers/register"; -### Adding New Test Suites +export const testMyFeature = register( + "testMyFeature", + async (braintrust, { backgroundLogger }) => { + const MyClass = braintrust.MyClass as typeof MyClassType; -1. Create a new file in `src/suites/`: + const instance = new MyClass(); + const result = await instance.doSomething(); -```typescript -// src/suites/my-new-suite.ts -import type { TestAdapters, TestResult } from "../helpers/types"; - -export async function testMyFeature( - adapters: TestAdapters, -): Promise { - try { - // Your test logic here - return { success: true, testName: "testMyFeature" }; - } catch (error) { - return { success: false, testName: "testMyFeature", error }; - } -} + assertEqual(result, expectedValue); -export async function runMyNewSuiteTests( - adapters: TestAdapters, -): Promise { - return [ - await testMyFeature(adapters), - // ... more tests - ]; -} + return "Test passed successfully"; + }, +); ``` -2. Export from `src/index.ts`: +2. **Export from `src/index.ts`:** ```typescript -export { testMyFeature, runMyNewSuiteTests } from "./suites/my-new-suite"; +export { testMyFeature } from "./suites/my-suite"; ``` -3. Rebuild: +3. **Rebuild:** ```bash npm run build ``` -4. Use in any test environment: +4. **Use in scenarios:** ```typescript -import { runMyNewSuiteTests } from "../../shared/dist/index.mjs"; +import { runTests, testMyFeature } from "../../shared"; + +const { failed } = await runTests({ + name: "My Scenario", + braintrust, + tests: [testMyFeature], +}); ``` ## Best Practices ### Write Environment-Agnostic Tests -Check adapter flags before using environment-specific features: +Let tests fail naturally when features aren't available: ```typescript -export async function testDatasets( - adapters: TestAdapters, -): Promise { - if (!adapters.canUseFileSystem) { - return { - success: true, - testName: "testDatasets", - message: "Skipped (no filesystem access)", - }; - } +// ✓ Good - let it throw naturally +export const testDatasets = register("testDatasets", async (braintrust) => { + const Dataset = braintrust.Dataset as typeof DatasetClass; + const dataset = new Dataset(); + // ... test logic +}); - // Test logic that needs filesystem... -} +// In scenarios where Dataset isn't available, wrap with expectFailure: +expectFailure( + testDatasets, + (e) => e.message.includes("Dataset is not defined"), + "Datasets not available in browser build", +); ``` ### Use Provided Assertions @@ -302,25 +524,39 @@ Use the provided assertion helpers instead of environment-specific ones: ```typescript import { assert, assertEqual, assertNotEmpty } from "../helpers/assertions"; -// Good - works everywhere +// ✓ Good - works everywhere assertEqual(actual, expected); -// Bad - only works in specific environments +// ✗ Bad - only works in specific environments expect(actual).toBe(expected); // Jest-specific assertEquals(actual, expected); // Deno-specific ``` -### Return TestResult +### Return Success Messages -Always return a `TestResult` object with consistent structure: +Test functions should return a descriptive success message: ```typescript -interface TestResult { - success: boolean; - testName: string; - message?: string; - error?: Error; -} +export const testMyFeature = register("testMyFeature", async (braintrust) => { + // ... test logic + + return "MyFeature works correctly with X and Y"; +}); +``` + +### Type Assertions + +Since `BraintrustModule` properties are typed as `unknown`, explicitly cast them: + +```typescript +export const testSomething = register("testSomething", async (braintrust) => { + const initLogger = braintrust.initLogger as InitLoggerFn; + const MyClass = braintrust.MyClass as typeof MyClassType; + + // Now use with proper types + const logger = initLogger({ projectName: "test" }); + const instance = new MyClass(); +}); ``` ## Development Workflow @@ -329,14 +565,27 @@ interface TestResult { 2. Run `npm run build` to rebuild 3. Test in target environment (e.g., Deno): ```bash - cd ../tests/deno - deno task test:shared + cd ../scenarios/deno-node + make test ``` 4. Verify tests pass in multiple environments +## Coverage Validation + +The test framework automatically validates that all registered tests are run in each scenario. If a scenario forgets to include a test, `validateCoverage()` (called automatically by `runTests()`) will add a failure to the results: + +``` +✗ Test coverage validation + Missing tests: testForgottenTest, testAnotherMissing +``` + +This ensures scenarios don't accidentally skip tests. + ## Notes - Tests use `_exportsForTestingOnly` to avoid hitting real APIs -- Each test suite should be independent and idempotent -- Clean up test state in `finally` blocks using `cleanupTestEnvironment()` +- Each test suite is independent and idempotent +- The `register()` wrapper handles setup/cleanup automatically - The package is marked `private: true` - it's only for internal smoke tests +- No manual `try/catch` blocks needed - `register()` handles this +- No manual coverage validation needed - `runTests()` handles this diff --git a/js/smoke/shared/src/helpers/register.ts b/js/smoke/shared/src/helpers/register.ts new file mode 100644 index 000000000..663481b5e --- /dev/null +++ b/js/smoke/shared/src/helpers/register.ts @@ -0,0 +1,199 @@ +/** + * Test registration and execution helpers + * + * This module provides: + * - register(): Define tests with automatic setup/cleanup fixtures + * - runTests(): Execute tests and validate coverage + * - expectFailure(): Wrap tests with expected failure handling + * - validateCoverage(): Check all registered tests were executed + */ + +import type { TestResult, BackgroundLogger } from "./types"; +import type { BraintrustModule } from "../suites/import-verification"; +import { displayTestResults } from "./display"; + +const registeredTests = new Set(); + +export interface TestContext { + backgroundLogger: BackgroundLogger; +} + +export type TestFn = (braintrust: BraintrustModule) => Promise; + +type RegisteredTestFn = ( + braintrust: BraintrustModule, + ctx: TestContext, +) => Promise>; + +/** + * Register a test with automatic setup/cleanup fixtures. + * + * The test function receives the braintrust module and a context with backgroundLogger. + * Tests can: + * - Return nothing (void) -> pass + * - Return a string -> pass with message + * - Return a partial TestResult -> merged with pass status + * - Throw an error -> fail with error details + */ +export function register(name: string, fn: RegisteredTestFn): TestFn { + registeredTests.add(name); + + return async (braintrust: BraintrustModule): Promise => { + const testing = braintrust._exportsForTestingOnly as { + setInitialTestState: () => void; + simulateLoginForTests: () => Promise | unknown; + simulateLogoutForTests?: () => Promise | unknown; + useTestBackgroundLogger: () => BackgroundLogger; + clearTestBackgroundLogger: () => void; + }; + + testing.setInitialTestState(); + await testing.simulateLoginForTests(); + const backgroundLogger = testing.useTestBackgroundLogger(); + + try { + const result = await fn(braintrust, { backgroundLogger }); + + if (typeof result === "string") { + return { status: "pass", name, message: result }; + } + if (result && typeof result === "object") { + return { status: "pass", name, ...result }; + } + return { status: "pass", name }; + } catch (error) { + return { + status: "fail", + name, + error: { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + }, + }; + } finally { + testing.clearTestBackgroundLogger(); + if (typeof testing.simulateLogoutForTests === "function") { + await testing.simulateLogoutForTests(); + } + } + }; +} + +/** + * Validate that all registered tests were executed. + * Returns a TestResult indicating coverage status. + */ +export function validateCoverage(results: TestResult[]): TestResult { + const expected = Array.from(registeredTests); + const ran = new Set(results.map((r) => r.name)); + const missing = expected.filter((t) => !ran.has(t)); + + if (missing.length > 0) { + return { + status: "fail", + name: "test-coverage", + message: `Missing tests: ${missing.join(", ")}`, + }; + } + return { + status: "pass", + name: "test-coverage", + message: `All ${expected.length} registered tests ran`, + }; +} + +/** + * Get all registered test names (useful for debugging). + */ +export function getRegisteredTests(): string[] { + return Array.from(registeredTests); +} + +/** + * Clear the test registry (useful for testing the test framework itself). + */ +export function clearRegistry(): void { + registeredTests.clear(); +} + +export interface RunTestsOptions { + name: string; + braintrust: BraintrustModule; + tests: TestFn[]; +} + +export interface TestRunResults { + all: TestResult[]; + passed: TestResult[]; + failed: TestResult[]; + xfail: TestResult[]; +} + +/** + * Run a set of tests and validate coverage. + * + * This function: + * 1. Executes all provided tests sequentially + * 2. Validates that all registered tests were run + * 3. Displays results in standardized format + * 4. Returns categorized results + */ +export async function runTests({ + name, + braintrust, + tests, +}: RunTestsOptions): Promise { + const results: TestResult[] = []; + + for (const test of tests) { + results.push(await test(braintrust)); + } + + results.push(validateCoverage(results)); + + displayTestResults({ scenarioName: name, results }); + + return { + all: results, + passed: results.filter((r) => r.status === "pass"), + failed: results.filter((r) => r.status === "fail"), + xfail: results.filter((r) => r.status === "xfail"), + }; +} + +export type ErrorPredicate = (error: { + message: string; + stack?: string; +}) => boolean; + +/** + * Wrap a test to convert expected failures to xfail status. + * + * The predicate function receives the error and returns true if the failure + * is expected. If the predicate throws or returns false, the failure is + * treated as a real failure (not masked). + * + * @param test - The test function to wrap + * @param predicate - Function that returns true if the error is expected + * @param reason - Human-readable explanation of why failure is expected + */ +export function expectFailure( + test: TestFn, + predicate: ErrorPredicate, + reason: string, +): TestFn { + return async (braintrust: BraintrustModule): Promise => { + const result = await test(braintrust); + + if (result.status === "fail" && result.error) { + try { + if (predicate(result.error)) { + return { ...result, status: "xfail", message: reason }; + } + } catch { + // Predicate threw - this is unexpected, treat as real failure + } + } + return result; + }; +} diff --git a/js/smoke/shared/src/helpers/test-state.ts b/js/smoke/shared/src/helpers/test-state.ts deleted file mode 100644 index 82a8dd2c2..000000000 --- a/js/smoke/shared/src/helpers/test-state.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Helper functions for setting up and tearing down test state - */ - -import type { TestAdapters, TestingExports } from "./types"; - -export interface SetupTestEnvironmentOptions { - initLogger: TestAdapters["initLogger"]; - testingExports: TestingExports; - projectName?: string; - canUseFileSystem?: boolean; - canUseCLI?: boolean; - environment?: string; -} - -/** - * Set up the test environment with proper state initialization - */ -export async function setupTestEnvironment( - options: SetupTestEnvironmentOptions, -): Promise { - const { - initLogger, - testingExports, - canUseFileSystem = true, - canUseCLI = true, - environment = "node", - } = options; - - // Initialize test state - testingExports.setInitialTestState(); - await testingExports.simulateLoginForTests(); - - // Get the background logger for capturing events - const backgroundLogger = testingExports.useTestBackgroundLogger(); - - return { - initLogger, - testingExports, - backgroundLogger, - canUseFileSystem, - canUseCLI, - environment, - }; -} - -/** - * Clean up the test environment - */ -export async function cleanupTestEnvironment( - adapters: TestAdapters, -): Promise { - const { testingExports } = adapters; - - testingExports.clearTestBackgroundLogger(); - - if (typeof testingExports.simulateLogoutForTests === "function") { - await testingExports.simulateLogoutForTests(); - } -} - -/** - * Run a test with automatic setup and cleanup - */ -export async function withTestEnvironment( - options: SetupTestEnvironmentOptions, - testFn: (adapters: TestAdapters) => Promise, -): Promise { - const adapters = await setupTestEnvironment(options); - - try { - return await testFn(adapters); - } finally { - await cleanupTestEnvironment(adapters); - } -} diff --git a/js/smoke/shared/src/helpers/types.ts b/js/smoke/shared/src/helpers/types.ts index 303515592..13ab6d7ba 100644 --- a/js/smoke/shared/src/helpers/types.ts +++ b/js/smoke/shared/src/helpers/types.ts @@ -26,18 +26,6 @@ export interface TestingExports { clearTestBackgroundLogger: () => void; } -export interface TestAdapters { - initLogger: (options: { - projectName: string; - projectId?: string; - }) => LoggerInstance; - testingExports: TestingExports; - backgroundLogger: BackgroundLogger; - canUseFileSystem: boolean; - canUseCLI: boolean; - environment: string; -} - export interface TestResult { status: "pass" | "fail" | "xfail"; // xfail = expected failure name: string; diff --git a/js/smoke/shared/src/index.ts b/js/smoke/shared/src/index.ts index fd2abc9e9..3af0b80af 100644 --- a/js/smoke/shared/src/index.ts +++ b/js/smoke/shared/src/index.ts @@ -11,17 +11,25 @@ export type { LoggerInstance, BackgroundLogger, TestingExports, - TestAdapters, TestResult, } from "./helpers/types"; -// Export test state helpers +// Export register helpers (new pattern) export { - setupTestEnvironment, - cleanupTestEnvironment, - withTestEnvironment, -} from "./helpers/test-state"; -export type { SetupTestEnvironmentOptions } from "./helpers/test-state"; + register, + runTests, + validateCoverage, + expectFailure, + getRegisteredTests, + clearRegistry, +} from "./helpers/register"; +export type { + TestFn, + TestContext, + RunTestsOptions, + TestRunResults, + ErrorPredicate, +} from "./helpers/register"; // Export assertions export { @@ -46,15 +54,18 @@ export { getTestStats, } from "./helpers/display"; -// Export test suites +// Export test suites - basic logging export { testBasicSpanLogging, testMultipleSpans, testDirectLogging, testJSONAttachment, - runBasicLoggingTests, + testAsyncLocalStorageTraced, + testNestedTraced, + testCurrentSpan, } from "./suites/basic-logging"; +// Export test suites - import verification export type { BraintrustModule } from "./suites/import-verification"; export { testCoreLoggingExports, @@ -71,15 +82,13 @@ export { testTestingExports, testStateManagementExports, testBuildResolution, - runImportVerificationTests, } from "./suites/import-verification"; -export type { PromptModule } from "./suites/prompt-templating"; +// Export test suites - prompt templating export { testMustacheTemplate, testNunjucksTemplate, - runPromptTemplatingTests, } from "./suites/prompt-templating"; -// Eval smoke test suite -export { runEvalSmokeTest } from "./suites/eval-smoke"; +// Export test suites - eval smoke +export { testEvalSmoke } from "./suites/eval-smoke"; diff --git a/js/smoke/shared/src/suites/basic-logging.ts b/js/smoke/shared/src/suites/basic-logging.ts index a34b980fe..9bd174022 100644 --- a/js/smoke/shared/src/suites/basic-logging.ts +++ b/js/smoke/shared/src/suites/basic-logging.ts @@ -3,31 +3,28 @@ * Tests core logging functionality: initLogger, spans, flush */ -import type { TestAdapters, TestResult } from "../helpers/types"; +import type { LoggerInstance } from "../helpers/types"; import { assert, assertEqual, assertNotEmpty } from "../helpers/assertions"; +import { register } from "../helpers/register"; const PROJECT_ID = "test-project-id"; -/** - * Test basic span logging - */ -export async function testBasicSpanLogging( - adapters: TestAdapters, -): Promise { - const testName = "testBasicSpanLogging"; - - try { - const { initLogger, backgroundLogger } = adapters; +type InitLoggerFn = (options: { + projectName: string; + projectId?: string; +}) => LoggerInstance; +export const testBasicSpanLogging = register( + "testBasicSpanLogging", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; const logger = initLogger({ projectName: "basic-logging-test", projectId: PROJECT_ID, }); - // Create a span const span = logger.startSpan({ name: "basic.span" }); - // Log some data span.log({ input: "What is the capital of France?", output: "Paris", @@ -35,13 +32,9 @@ export async function testBasicSpanLogging( metadata: { transport: "smoke-test" }, }); - // End the span span.end(); - - // Flush the logger await logger.flush(); - // Verify events were captured const events = await backgroundLogger.drain(); assertNotEmpty(events, "No events were captured by the background logger"); @@ -52,40 +45,19 @@ export async function testBasicSpanLogging( assertEqual(event.output, "Paris"); assertEqual(event.expected, "Paris"); - return { - status: "pass" as const, - name: testName, - message: "Basic span logging test passed", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test multiple spans in sequence - */ -export async function testMultipleSpans( - adapters: TestAdapters, -): Promise { - const testName = "testMultipleSpans"; - - try { - const { initLogger, backgroundLogger } = adapters; + return "Basic span logging test passed"; + }, +); +export const testMultipleSpans = register( + "testMultipleSpans", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; const logger = initLogger({ projectName: "multi-span-test", projectId: PROJECT_ID, }); - // Create multiple spans const span1 = logger.startSpan({ name: "span.1" }); span1.log({ input: "test1", output: "result1" }); span1.end(); @@ -96,7 +68,6 @@ export async function testMultipleSpans( await logger.flush(); - // Verify events const events = await backgroundLogger.drain(); assertNotEmpty(events, "No events were captured"); @@ -105,104 +76,45 @@ export async function testMultipleSpans( `Expected at least 2 events, got ${events.length}`, ); - return { - status: "pass" as const, - name: testName, - message: `Multiple spans test passed (${events.length} events captured)`, - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test logger.log() if available (direct logging without explicit span) - */ -export async function testDirectLogging( - adapters: TestAdapters, -): Promise { - const testName = "testDirectLogging"; - - try { - const { initLogger, backgroundLogger } = adapters; + return `Multiple spans test passed (${events.length} events captured)`; + }, +); +export const testDirectLogging = register( + "testDirectLogging", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; const logger = initLogger({ projectName: "direct-logging-test", projectId: PROJECT_ID, }); - // Some logger implementations support direct logging - if (typeof logger.log === "function") { - logger.log({ - input: "direct test", - output: "direct result", - }); - - await logger.flush(); - - const events = await backgroundLogger.drain(); - assertNotEmpty(events, "No events were captured from direct logging"); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logger.log!({ + input: "direct test", + output: "direct result", + }); - return { - status: "pass" as const, - name: testName, - message: "Direct logging test passed", - }; - } else { - return { - status: "pass" as const, - name: testName, - message: "Direct logging not supported, skipped", - }; - } - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} + await logger.flush(); -/** - * Test JSONAttachment functionality - * Tests that JSONAttachment can be created and logged correctly - */ -export async function testJSONAttachment( - adapters: TestAdapters, - braintrust: { JSONAttachment?: unknown }, -): Promise { - const testName = "testJSONAttachment"; + const events = await backgroundLogger.drain(); + assertNotEmpty(events, "No events were captured from direct logging"); - try { - const { initLogger, backgroundLogger } = adapters; + return "Direct logging test passed"; + }, +); +export const testJSONAttachment = register( + "testJSONAttachment", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; const logger = initLogger({ projectName: "json-attachment-test", projectId: PROJECT_ID, }); - // Check if JSONAttachment is available - if (!braintrust.JSONAttachment) { - return { - status: "pass" as const, - name: testName, - message: "JSONAttachment not available, skipped", - }; - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const JSONAttachment = braintrust.JSONAttachment as any; + const Attachment = braintrust.JSONAttachment as any; const testData = { foo: "bar", @@ -212,38 +124,22 @@ export async function testJSONAttachment( }, }; - // Test logging with JSONAttachment - if (typeof logger.log === "function") { - logger.log({ - input: { - type: "chat_completion", - transcript: new JSONAttachment(testData, { - filename: "conversation_transcript.json", - pretty: true, - }), - }, - }); - } else { - // Fallback to span logging - const span = logger.startSpan({ name: "json-attachment-test" }); - span.log({ - input: { - type: "chat_completion", - transcript: new JSONAttachment(testData, { - filename: "conversation_transcript.json", - pretty: true, - }), - }, - }); - span.end(); - } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logger.log!({ + input: { + type: "chat_completion", + transcript: new Attachment(testData, { + filename: "conversation_transcript.json", + pretty: true, + }), + }, + }); await logger.flush(); const events = await backgroundLogger.drain(); assertNotEmpty(events, "No events were captured with JSONAttachment"); - // Verify the test data structure is preserved assertEqual(testData.foo, "bar", "testData.foo should be 'bar'"); assertEqual( testData.nested.array.length, @@ -261,40 +157,202 @@ export async function testJSONAttachment( "testData.nested.bool should be true", ); - return { - status: "pass" as const, - name: testName, - message: "JSONAttachment test passed", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, + return "JSONAttachment test passed"; + }, +); + +export const testAsyncLocalStorageTraced = register( + "testAsyncLocalStorageTraced", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const tracedFn = braintrust.traced as any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const startSpanFn = braintrust.startSpan as any; + + initLogger({ + projectName: "als-traced-test", + projectId: PROJECT_ID, + }); + + await tracedFn( + () => { + const child = startSpanFn({ name: "child-span" }); + child.log({ input: "child input", output: "child output" }); + child.end(); }, - }; - } -} + { name: "parent-span" }, + ); -/** - * Run all basic logging tests - */ -export async function runBasicLoggingTests( - adapters: TestAdapters, - braintrust?: { JSONAttachment?: unknown }, -): Promise { - const results: TestResult[] = []; - - results.push(await testBasicSpanLogging(adapters)); - results.push(await testMultipleSpans(adapters)); - results.push(await testDirectLogging(adapters)); - - // Only run JSONAttachment test if braintrust module is provided - if (braintrust) { - results.push(await testJSONAttachment(adapters, braintrust)); - } - - return results; -} + const events = (await backgroundLogger.drain()) as Array< + Record + >; + + assertNotEmpty(events, "No events captured for ALS traced test"); + + const parentSpan = events.find( + (e) => + typeof e.span_attributes === "object" && + e.span_attributes !== null && + (e.span_attributes as Record).name === "parent-span", + ); + const childSpan = events.find( + (e) => + typeof e.span_attributes === "object" && + e.span_attributes !== null && + (e.span_attributes as Record).name === "child-span", + ); + + if (parentSpan && childSpan) { + const parentId = parentSpan.span_id as string; + const childParents = (childSpan.span_parents as string[]) || []; + + assert( + childParents.includes(parentId), + `Child span should have parent span ID in span_parents. Parent ID: ${parentId}, Child parents: ${JSON.stringify(childParents)}`, + ); + + return "ALS traced test passed (parent-child relationship verified)"; + } else if (!parentSpan && !childSpan) { + return "ALS not available in this environment, test skipped"; + } else { + throw new Error( + `Expected both parent and child spans, but found: parent=${!!parentSpan}, child=${!!childSpan}`, + ); + } + }, +); + +export const testNestedTraced = register( + "testNestedTraced", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const tracedFn = braintrust.traced as any; + + initLogger({ + projectName: "nested-traced-test", + projectId: PROJECT_ID, + }); + + await tracedFn( + async () => { + await tracedFn( + async () => { + await tracedFn( + () => { + // innermost span + }, + { name: "grandchild-span" }, + ); + }, + { name: "child-span" }, + ); + }, + { name: "parent-span" }, + ); + + const events = (await backgroundLogger.drain()) as Array< + Record + >; + + if (events.length === 0) { + return "ALS not available in this environment, test skipped"; + } + + const parentSpan = events.find( + (e) => + typeof e.span_attributes === "object" && + e.span_attributes !== null && + (e.span_attributes as Record).name === "parent-span", + ); + const childSpan = events.find( + (e) => + typeof e.span_attributes === "object" && + e.span_attributes !== null && + (e.span_attributes as Record).name === "child-span", + ); + const grandchildSpan = events.find( + (e) => + typeof e.span_attributes === "object" && + e.span_attributes !== null && + (e.span_attributes as Record).name === + "grandchild-span", + ); + + if (parentSpan && childSpan && grandchildSpan) { + const parentId = parentSpan.span_id as string; + const childId = childSpan.span_id as string; + const childParents = (childSpan.span_parents as string[]) || []; + const grandchildParents = (grandchildSpan.span_parents as string[]) || []; + + assert( + childParents.includes(parentId), + "Child should have parent in span_parents", + ); + + assert( + grandchildParents.includes(childId), + "Grandchild should have child in span_parents", + ); + + return "Nested traced test passed (3-level hierarchy verified)"; + } else { + return "ALS not available in this environment, test skipped"; + } + }, +); + +export const testCurrentSpan = register( + "testCurrentSpan", + async (braintrust, { backgroundLogger }) => { + const initLogger = braintrust.initLogger as InitLoggerFn; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const tracedFn = braintrust.traced as any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const currentSpanFn = braintrust.currentSpan as any; + + initLogger({ + projectName: "current-span-test", + projectId: PROJECT_ID, + }); + + let capturedSpanId: string | undefined; + + await tracedFn( + () => { + const current = currentSpanFn(); + if (current && typeof current === "object" && "spanId" in current) { + capturedSpanId = (current as { spanId: string }).spanId; + } + }, + { name: "test-current-span" }, + ); + + const events = (await backgroundLogger.drain()) as Array< + Record + >; + + if (events.length === 0 || !capturedSpanId) { + return "ALS not available in this environment, test skipped"; + } + + const span = events.find((e) => e.span_id === capturedSpanId); + + if (span) { + assertEqual( + ( + (span.span_attributes as Record) || { + name: undefined, + } + ).name, + "test-current-span", + "currentSpan() should return the active span", + ); + + return "currentSpan test passed"; + } else { + throw new Error("currentSpan() returned a span ID that was not logged"); + } + }, +); diff --git a/js/smoke/shared/src/suites/eval-smoke.ts b/js/smoke/shared/src/suites/eval-smoke.ts index ab533d1a8..ae9e89dcd 100644 --- a/js/smoke/shared/src/suites/eval-smoke.ts +++ b/js/smoke/shared/src/suites/eval-smoke.ts @@ -3,20 +3,14 @@ * Tests that Eval can run end-to-end in the current runtime without making real API calls. */ -import type { EvalFn, TestAdapters, TestResult } from "../helpers/types"; import { assertDefined, assertEqual, assertHasProperty, assertType, } from "../helpers/assertions"; +import { register } from "../helpers/register"; -type BraintrustEvalModule = { - Eval?: EvalFn; -}; - -// Incredibly simple scorer for smoke tests: exact string match. -// Deterministic, no dependencies, no network/LLM calls. function exactMatchScore({ output, expected, @@ -27,106 +21,77 @@ function exactMatchScore({ return { name: "exact_match", score: output === expected ? 1 : 0 }; } -/** - * Run a minimal eval and ensure it completes successfully. - * - * Notes: - * - Uses `noSendLogs: true` to avoid experiment registration / API calls. - * - Assumes the caller has already set up test state (via setupTestEnvironment / withTestEnvironment). - */ -export async function runEvalSmokeTest( - _adapters: TestAdapters, - braintrust: BraintrustEvalModule, -): Promise { - const testName = "runEvalSmokeTest"; - - try { - assertDefined(braintrust.Eval, "Eval must exist"); - assertType(braintrust.Eval, "function", "Eval must be a function"); - - const evalData = [ - { input: "Alice", expected: "Hi Alice" }, - { input: "Bob", expected: "Hi Bob" }, - { input: "Charlie", expected: "Hi Charlie" }, - ]; +export const testEvalSmoke = register("testEvalSmoke", async (braintrust) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const Eval = braintrust.Eval as any; - // Call signature in the JS SDK is: Eval(name, config, options) - const result = await braintrust.Eval( - "smoke-eval-test", - { - data: evalData, - task: async (input: string) => `Hi ${input}`, - scores: [exactMatchScore], - }, - { - noSendLogs: true, - returnResults: true, - }, - ); + assertDefined(Eval, "Eval must exist"); + assertType(Eval, "function", "Eval must be a function"); - // Verify result shape + content (similar to js/src/framework.test.ts expectations) - assertDefined(result, "Eval should return a result"); - const r = result as unknown as Record; + const evalData = [ + { input: "Alice", expected: "Hi Alice" }, + { input: "Bob", expected: "Hi Bob" }, + { input: "Charlie", expected: "Hi Charlie" }, + ]; - assertHasProperty(r, "summary", "Eval result missing summary"); - assertHasProperty(r, "results", "Eval result missing results"); + const result = await Eval( + "smoke-eval-test", + { + data: evalData, + task: async (input: string) => `Hi ${input}`, + scores: [exactMatchScore], + }, + { + noSendLogs: true, + returnResults: true, + }, + ); - const summary = r.summary as Record; - const results = r.results as Array>; + assertDefined(result, "Eval should return a result"); + const r = result as Record; - // Per-example results should be retained when returnResults=true - assertEqual( - results.length, - evalData.length, - `Expected ${evalData.length} eval results`, - ); + assertHasProperty(r, "summary", "Eval result missing summary"); + assertHasProperty(r, "results", "Eval result missing results"); - // Validate each result matches expected and has exact_match score = 1 - for (const row of results) { - assertDefined(row.input, "Eval result missing input"); - assertDefined(row.expected, "Eval result missing expected"); - assertDefined(row.output, "Eval result missing output"); - assertEqual( - row.output as string, - row.expected as string, - "Output should equal expected", - ); + const summary = r.summary as Record; + const results = r.results as Array>; - assertHasProperty(row, "scores", "Eval result missing scores"); - const scores = row.scores as Record; - assertDefined(scores.exact_match, "Missing exact_match score"); - assertEqual(scores.exact_match as number, 1, "exact_match should be 1"); - } + assertEqual( + results.length, + evalData.length, + `Expected ${evalData.length} eval results`, + ); - // Validate aggregate score in summary: summary.scores.exact_match.score === 1 - assertHasProperty(summary, "scores", "Summary missing scores"); - const summaryScores = summary.scores as Record; - assertHasProperty( - summaryScores, - "exact_match", - "Summary missing exact_match scorer", - ); - const exact = summaryScores.exact_match as Record; - assertDefined(exact.score, "Summary exact_match missing score"); + for (const row of results) { + assertDefined(row.input, "Eval result missing input"); + assertDefined(row.expected, "Eval result missing expected"); + assertDefined(row.output, "Eval result missing output"); assertEqual( - exact.score as number, - 1, - "Summary exact_match.score should be 1", + row.output as string, + row.expected as string, + "Output should equal expected", ); - return { - status: "pass" as const, - name: testName, - message: `Eval smoke test passed (${evalData.length} cases)`, - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; + assertHasProperty(row, "scores", "Eval result missing scores"); + const scores = row.scores as Record; + assertDefined(scores.exact_match, "Missing exact_match score"); + assertEqual(scores.exact_match as number, 1, "exact_match should be 1"); } -} + + assertHasProperty(summary, "scores", "Summary missing scores"); + const summaryScores = summary.scores as Record; + assertHasProperty( + summaryScores, + "exact_match", + "Summary missing exact_match scorer", + ); + const exact = summaryScores.exact_match as Record; + assertDefined(exact.score, "Summary exact_match missing score"); + assertEqual( + exact.score as number, + 1, + "Summary exact_match.score should be 1", + ); + + return `Eval smoke test passed (${evalData.length} cases)`; +}); diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index 0f01acc2e..e276c5aaa 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -17,8 +17,8 @@ * - Optional: May not exist depending on build configuration */ -import type { TestResult } from "../helpers/types"; import { assertType, assertDefined } from "../helpers/assertions"; +import { register } from "../helpers/register"; /** * Interface for the Braintrust module based on exports.ts @@ -102,15 +102,9 @@ export interface BraintrustModule { [key: string]: unknown; } -/** - * Test required core logging exports - */ -export async function testCoreLoggingExports( - module: BraintrustModule, -): Promise { - const testName = "testCoreLoggingExports"; - - try { +export const testCoreLoggingExports = register( + "testCoreLoggingExports", + async (module) => { assertDefined(module.initLogger, "initLogger must exist"); assertType(module.initLogger, "function", "initLogger must be a function"); @@ -140,32 +134,13 @@ export async function testCoreLoggingExports( assertDefined(module.flush, "flush must exist"); assertType(module.flush, "function", "flush must be a function"); - return { - status: "pass" as const, - name: testName, - message: "Core logging exports verified (7 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required dataset exports - */ -export async function testDatasetExports( - module: BraintrustModule, -): Promise { - const testName = "testDatasetExports"; + return "Core logging exports verified (7 exports)"; + }, +); - try { +export const testDatasetExports = register( + "testDatasetExports", + async (module) => { assertDefined(module.initDataset, "initDataset must exist"); assertType( module.initDataset, @@ -176,32 +151,13 @@ export async function testDatasetExports( assertDefined(module.Dataset, "Dataset must exist"); assertType(module.Dataset, "function", "Dataset must be a function/class"); - return { - status: "pass" as const, - name: testName, - message: "Dataset exports verified (2 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required prompt exports - */ -export async function testPromptExports( - module: BraintrustModule, -): Promise { - const testName = "testPromptExports"; + return "Dataset exports verified (2 exports)"; + }, +); - try { +export const testPromptExports = register( + "testPromptExports", + async (module) => { assertDefined(module.loadPrompt, "loadPrompt must exist"); assertType(module.loadPrompt, "function", "loadPrompt must be a function"); @@ -215,32 +171,13 @@ export async function testPromptExports( "getPromptVersions must be a function", ); - return { - status: "pass" as const, - name: testName, - message: "Prompt exports verified (3 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test experiment exports (all browser-compatible now) - */ -export async function testExperimentExports( - module: BraintrustModule, -): Promise { - const testName = "testExperimentExports"; + return "Prompt exports verified (3 exports)"; + }, +); - try { +export const testExperimentExports = register( + "testExperimentExports", + async (module) => { assertDefined(module.initExperiment, "initExperiment must exist"); assertType( module.initExperiment, @@ -262,105 +199,64 @@ export async function testExperimentExports( "currentExperiment must be a function", ); - return { - status: "pass" as const, - name: testName, - message: "Experiment exports verified (3 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test evaluation exports (runtime values only - types like Evaluator, BaseExperiment, EvalTask are type-only) - */ -export async function testEvalExports( - module: BraintrustModule, -): Promise { - const testName = "testEvalExports"; + return "Experiment exports verified (3 exports)"; + }, +); - try { - assertDefined(module.Eval, "Eval must exist"); - assertType(module.Eval, "function", "Eval must be a function"); +export const testEvalExports = register("testEvalExports", async (module) => { + assertDefined(module.Eval, "Eval must exist"); + assertType(module.Eval, "function", "Eval must be a function"); - assertDefined( - module.EvalResultWithSummary, - "EvalResultWithSummary must exist", - ); - assertType( - module.EvalResultWithSummary, - "function", - "EvalResultWithSummary must be a function/class", - ); + assertDefined( + module.EvalResultWithSummary, + "EvalResultWithSummary must exist", + ); + assertType( + module.EvalResultWithSummary, + "function", + "EvalResultWithSummary must be a function/class", + ); - assertDefined(module.Reporter, "Reporter must exist"); - assertType(module.Reporter, "function", "Reporter must be a function"); + assertDefined(module.Reporter, "Reporter must exist"); + assertType(module.Reporter, "function", "Reporter must be a function"); - assertDefined(module.runEvaluator, "runEvaluator must exist"); - assertType( - module.runEvaluator, - "function", - "runEvaluator must be a function", - ); - - assertDefined(module.buildLocalSummary, "buildLocalSummary must exist"); - assertType( - module.buildLocalSummary, - "function", - "buildLocalSummary must be a function", - ); + assertDefined(module.runEvaluator, "runEvaluator must exist"); + assertType( + module.runEvaluator, + "function", + "runEvaluator must be a function", + ); - assertDefined(module.reportFailures, "reportFailures must exist"); - assertType( - module.reportFailures, - "function", - "reportFailures must be a function", - ); + assertDefined(module.buildLocalSummary, "buildLocalSummary must exist"); + assertType( + module.buildLocalSummary, + "function", + "buildLocalSummary must be a function", + ); - assertDefined( - module.defaultErrorScoreHandler, - "defaultErrorScoreHandler must exist", - ); - assertType( - module.defaultErrorScoreHandler, - "function", - "defaultErrorScoreHandler must be a function", - ); + assertDefined(module.reportFailures, "reportFailures must exist"); + assertType( + module.reportFailures, + "function", + "reportFailures must be a function", + ); - return { - status: "pass" as const, - name: testName, - message: "Eval exports verified (7 runtime exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} + assertDefined( + module.defaultErrorScoreHandler, + "defaultErrorScoreHandler must exist", + ); + assertType( + module.defaultErrorScoreHandler, + "function", + "defaultErrorScoreHandler must be a function", + ); -/** - * Test required tracing exports - */ -export async function testTracingExports( - module: BraintrustModule, -): Promise { - const testName = "testTracingExports"; + return "Eval exports verified (7 runtime exports)"; +}); - try { +export const testTracingExports = register( + "testTracingExports", + async (module) => { assertDefined(module.traced, "traced must exist"); assertType(module.traced, "function", "traced must be a function"); @@ -380,38 +276,16 @@ export async function testTracingExports( "withCurrent must be a function", ); - return { - status: "pass" as const, - name: testName, - message: "Tracing exports verified (5 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test client wrapper exports - * wrapOpenAI is required, others are optional - */ -export async function testClientWrapperExports( - module: BraintrustModule, -): Promise { - const testName = "testClientWrapperExports"; + return "Tracing exports verified (5 exports)"; + }, +); - try { - // wrapOpenAI is required +export const testClientWrapperExports = register( + "testClientWrapperExports", + async (module) => { assertDefined(module.wrapOpenAI, "wrapOpenAI must exist"); assertType(module.wrapOpenAI, "function", "wrapOpenAI must be a function"); - // Count optional wrappers that exist let optionalCount = 0; const optionalWrappers = [ "wrapAnthropic", @@ -432,32 +306,13 @@ export async function testClientWrapperExports( } } - return { - status: "pass" as const, - name: testName, - message: `Client wrapper exports verified (1 required + ${optionalCount} optional)`, - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required utility exports - */ -export async function testUtilityExports( - module: BraintrustModule, -): Promise { - const testName = "testUtilityExports"; + return `Client wrapper exports verified (1 required + ${optionalCount} optional)`; + }, +); - try { +export const testUtilityExports = register( + "testUtilityExports", + async (module) => { assertDefined(module.JSONAttachment, "JSONAttachment must exist"); assertType( module.JSONAttachment, @@ -478,32 +333,13 @@ export async function testUtilityExports( assertDefined(module.permalink, "permalink must exist"); assertType(module.permalink, "function", "permalink must be a function"); - return { - status: "pass" as const, - name: testName, - message: "Utility exports verified (4 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required function exports - */ -export async function testFunctionExports( - module: BraintrustModule, -): Promise { - const testName = "testFunctionExports"; + return "Utility exports verified (4 exports)"; + }, +); - try { +export const testFunctionExports = register( + "testFunctionExports", + async (module) => { assertDefined(module.invoke, "invoke must exist"); assertType(module.invoke, "function", "invoke must be a function"); @@ -514,32 +350,13 @@ export async function testFunctionExports( "initFunction must be a function", ); - return { - status: "pass" as const, - name: testName, - message: "Function exports verified (2 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test framework2 exports (programmatic prompt/function creation) - */ -export async function testFramework2Exports( - module: BraintrustModule, -): Promise { - const testName = "testFramework2Exports"; + return "Function exports verified (2 exports)"; + }, +); - try { +export const testFramework2Exports = register( + "testFramework2Exports", + async (module) => { assertDefined(module.Project, "Project must exist"); assertType(module.Project, "function", "Project must be a function/class"); @@ -553,32 +370,13 @@ export async function testFramework2Exports( "PromptBuilder must be a function/class", ); - return { - status: "pass" as const, - name: testName, - message: "Framework2 exports verified (3 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required ID generation exports - */ -export async function testIDGeneratorExports( - module: BraintrustModule, -): Promise { - const testName = "testIDGeneratorExports"; + return "Framework2 exports verified (3 exports)"; + }, +); - try { +export const testIDGeneratorExports = register( + "testIDGeneratorExports", + async (module) => { assertDefined(module.IDGenerator, "IDGenerator must exist"); assertType( module.IDGenerator, @@ -586,32 +384,13 @@ export async function testIDGeneratorExports( "IDGenerator must be a function/class", ); - return { - status: "pass" as const, - name: testName, - message: "ID generator exports verified (1 export)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required testing exports - */ -export async function testTestingExports( - module: BraintrustModule, -): Promise { - const testName = "testTestingExports"; + return "ID generator exports verified (1 export)"; + }, +); - try { +export const testTestingExports = register( + "testTestingExports", + async (module) => { assertDefined( module._exportsForTestingOnly, "_exportsForTestingOnly must exist", @@ -622,32 +401,13 @@ export async function testTestingExports( "_exportsForTestingOnly must be an object", ); - return { - status: "pass" as const, - name: testName, - message: "Testing exports verified (1 export)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test required state management exports - */ -export async function testStateManagementExports( - module: BraintrustModule, -): Promise { - const testName = "testStateManagementExports"; + return "Testing exports verified (1 export)"; + }, +); - try { +export const testStateManagementExports = register( + "testStateManagementExports", + async (module) => { assertDefined(module.BraintrustState, "BraintrustState must exist"); assertType( module.BraintrustState, @@ -658,87 +418,31 @@ export async function testStateManagementExports( assertDefined(module.login, "login must exist"); assertType(module.login, "function", "login must be a function"); - return { - status: "pass" as const, - name: testName, - message: "State management exports verified (2 exports)", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} - -/** - * Test which build variant was resolved (browser vs Node.js) and module format (CJS vs ESM) - * - * This test checks which export path was used by reading the buildType property - * from the isomorph object and by resolving the module specifier. - * - * @param module - The Braintrust module to test - * @param expectedBuild - Expected build type: "browser" or "node" (optional, for validation) - * @param expectedFormat - Expected module format: "cjs" or "esm" (optional, for validation) - */ -export async function testBuildResolution( - module: BraintrustModule, - expectedBuild?: "browser" | "node", - expectedFormat?: "cjs" | "esm", -): Promise { - const testName = "testBuildResolution"; + return "State management exports verified (2 exports)"; + }, +); - try { - // Detect build type from isomorph.buildType +export const testBuildResolution = register( + "testBuildResolution", + async (module) => { const { buildType: detectedBuild, buildDetails } = detectBuildType(module); - - // Detect module format (CJS vs ESM) const detectedFormat = detectModuleFormat(); - const errors = validateBuildResolution( - detectedBuild, - detectedFormat, - expectedBuild, - expectedFormat, - buildDetails, - ); - - if (errors.length > 0) { - return { - status: "fail" as const, - name: testName, - error: { message: errors.join(" ") }, - }; + if (detectedBuild === "unknown") { + throw new Error( + `Build type is unknown - configureBrowser() or configureNode() was not called. ${buildDetails || ""}`, + ); } - // Build success message - const message = buildSuccessMessage( - detectedBuild, - detectedFormat, - expectedBuild, - expectedFormat, - ); + const parts: string[] = [`Detected ${detectedBuild} build`]; - return { - status: "pass" as const, - name: testName, - message, - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - }; - } -} + if (detectedFormat !== "unknown") { + parts.push(`${detectedFormat} format`); + } + + return parts.join(", "); + }, +); function detectBuildType(module: BraintrustModule): { buildType: "browser" | "node" | "unknown"; @@ -751,6 +455,7 @@ function detectBuildType(module: BraintrustModule): { }; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const testing = module._exportsForTestingOnly as any; const iso = testing.isomorph; @@ -779,12 +484,8 @@ function detectBuildType(module: BraintrustModule): { }; } -/** - * Detect module format (CJS vs ESM) by resolving the actual file path - */ function detectModuleFormat(): "cjs" | "esm" | "unknown" { const packageSpec = "braintrust"; - // Try ESM resolution first try { if ( typeof import.meta !== "undefined" && @@ -801,145 +502,27 @@ function detectModuleFormat(): "cjs" | "esm" | "unknown" { if (resolvedPath.endsWith(".mjs")) { return "esm"; } - // If resolved but not .mjs, check if it's .js (CJS) if (resolvedPath.endsWith(".js") && !resolvedPath.endsWith(".mjs")) { return "cjs"; } } } catch { - // import.meta.resolve might not be available or might throw - // Continue to try CJS resolution + // import.meta.resolve might not be available } - // Try CJS resolution try { if (typeof require !== "undefined" && require.resolve) { const resolved = require.resolve(packageSpec); - // CJS files end with .js (not .mjs) if (resolved.endsWith(".js") && !resolved.endsWith(".mjs")) { return "cjs"; } - // If resolved to .mjs, it's ESM if (resolved.endsWith(".mjs")) { return "esm"; } } } catch { - // require.resolve might not be available or might throw + // require.resolve might not be available } return "unknown"; } - -/** - * Validate detected build type and format against expectations - */ -function validateBuildResolution( - detectedBuild: "browser" | "node" | "unknown", - detectedFormat: "cjs" | "esm" | "unknown", - expectedBuild?: "browser" | "node", - expectedFormat?: "cjs" | "esm", - buildDetails?: string, -): string[] { - const errors: string[] = []; - - // Always error if build type is unknown (not configured) - if (detectedBuild === "unknown") { - errors.push( - `Build type is unknown - configureBrowser() or configureNode() was not called. ${buildDetails || ""}`, - ); - return errors; - } - - // Validate build type matches expectation - if (expectedBuild && detectedBuild !== expectedBuild) { - errors.push( - `Expected ${expectedBuild} build but detected ${detectedBuild} build. ${buildDetails || ""}`, - ); - } - - // Validate module format matches expectation - if ( - expectedFormat && - detectedFormat !== expectedFormat && - detectedFormat !== "unknown" - ) { - errors.push( - `Expected ${expectedFormat} format but detected ${detectedFormat} format.`, - ); - } - - return errors; -} - -/** - * Build success message for test result - */ -function buildSuccessMessage( - detectedBuild: "browser" | "node" | "unknown", - detectedFormat: "cjs" | "esm" | "unknown", - expectedBuild?: "browser" | "node", - expectedFormat?: "cjs" | "esm", -): string { - const parts: string[] = []; - - if (detectedBuild !== "unknown") { - const buildMsg = `Detected ${detectedBuild} build`; - const expectedMsg = expectedBuild ? ` (expected ${expectedBuild})` : ""; - parts.push(`${buildMsg}${expectedMsg}`); - } - - if (detectedFormat !== "unknown") { - const formatMsg = `${detectedFormat} format`; - const expectedMsg = expectedFormat ? ` (expected ${expectedFormat})` : ""; - parts.push(`${formatMsg}${expectedMsg}`); - } - - return parts.join(", ") || "Build resolution check passed"; -} - -/** - * Run all import verification tests - * - * This forces bundlers to process the full Braintrust export graph, - * preventing tree-shaking false positives. - * - * Note: Only tests runtime value exports (functions, classes, objects). - * TypeScript type-only exports are not tested as they don't exist at runtime. - * - * @param module - The Braintrust module to test - * @param options - Optional test configuration - */ -export async function runImportVerificationTests( - module: BraintrustModule, - options: { - expectedBuild: "browser" | "node"; - expectedFormat: "cjs" | "esm"; - }, -): Promise { - const results: TestResult[] = []; - - // All runtime value exports must exist in all builds - results.push(await testCoreLoggingExports(module)); - results.push(await testDatasetExports(module)); - results.push(await testPromptExports(module)); - results.push(await testTracingExports(module)); - results.push(await testClientWrapperExports(module)); - results.push(await testUtilityExports(module)); - results.push(await testFunctionExports(module)); - results.push(await testFramework2Exports(module)); - results.push(await testIDGeneratorExports(module)); - results.push(await testTestingExports(module)); - results.push(await testStateManagementExports(module)); - results.push(await testExperimentExports(module)); - results.push(await testEvalExports(module)); - results.push( - await testBuildResolution( - module, - options.expectedBuild, - options.expectedFormat, - ), - ); - - return results; -} diff --git a/js/smoke/shared/src/suites/prompt-templating.ts b/js/smoke/shared/src/suites/prompt-templating.ts index 4dc43b9bd..dcbcc4380 100644 --- a/js/smoke/shared/src/suites/prompt-templating.ts +++ b/js/smoke/shared/src/suites/prompt-templating.ts @@ -3,38 +3,14 @@ * Tests Mustache and Nunjucks template rendering in Prompt class */ -import type { TestResult } from "../helpers/types"; import { assertEqual } from "../helpers/assertions"; +import { register } from "../helpers/register"; -/** - * Interface for accessing Prompt class from braintrust module - * Uses a flexible type to accommodate the actual Prompt class structure - * which has generics and complex return types - */ -export interface PromptModule { - Prompt: { - new ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - metadata: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - defaults: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - noTrace: boolean, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ): any; - }; -} - -/** - * Test Mustache template rendering - */ -export async function testMustacheTemplate( - module: PromptModule, -): Promise { - const testName = "testMustacheTemplate"; - - try { - const { Prompt } = module; +export const testMustacheTemplate = register( + "testMustacheTemplate", + async (module) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const Prompt = module.Prompt as any; const mustachePrompt = new Prompt( { @@ -70,152 +46,53 @@ export async function testMustacheTemplate( "Mustache template should render simple variable", ); - return { - status: "pass" as const, - name: testName, - message: "Mustache template test passed", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, - }, - message: `Test failed: ${error instanceof Error ? error.message : String(error)}`, - }; - } -} - -/** - * Test Nunjucks template rendering - */ -export async function testNunjucksTemplate( - module: PromptModule, -): Promise { - const testName = "testNunjucksTemplate"; + return "Mustache template test passed"; + }, +); - try { - const { Prompt } = module; +export const testNunjucksTemplate = register( + "testNunjucksTemplate", + async (module) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const Prompt = module.Prompt as any; - let nunjucksPrompt; - try { - nunjucksPrompt = new Prompt( - { - name: "nunjucks-test", - slug: "nunjucks-test", - prompt_data: { - prompt: { - type: "chat", - messages: [ - { - role: "user", - content: - "Items: {% for item in items %}{{ item.name }}{% if not loop.last %}, {% endif %}{% endfor %}", - }, - ], - }, - options: { - model: "gpt-4", - }, + const nunjucksPrompt = new Prompt( + { + name: "nunjucks-test", + slug: "nunjucks-test", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: + "Items: {% for item in items %}{{ item.name }}{% if not loop.last %}, {% endif %}{% endfor %}", + }, + ], + }, + options: { + model: "gpt-4", }, }, - {}, - false, - ); - } catch (constructorError) { - return { - status: "fail" as const, - name: testName, - error: { - message: - constructorError instanceof Error - ? constructorError.message - : String(constructorError), - stack: - constructorError instanceof Error - ? constructorError.stack - : undefined, - }, - message: `Failed to create Prompt: ${constructorError instanceof Error ? constructorError.message : String(constructorError)}`, - }; - } - - let nunjucksResult; - try { - nunjucksResult = nunjucksPrompt.build( - { - items: [{ name: "apple" }, { name: "banana" }, { name: "cherry" }], - }, - { templateFormat: "nunjucks" }, - ); - } catch (buildError) { - return { - status: "fail" as const, - name: testName, - error: { - message: - buildError instanceof Error - ? buildError.message - : String(buildError), - stack: buildError instanceof Error ? buildError.stack : undefined, - }, - message: `Failed to build prompt: ${buildError instanceof Error ? buildError.message : String(buildError)}`, - }; - } - - try { - const expected = "Items: apple, banana, cherry"; - const actual = nunjucksResult.messages[0]?.content; - assertEqual( - actual, - expected, - `Nunjucks template should render loop correctly`, - ); - } catch (assertError) { - return { - status: "fail" as const, - name: testName, - error: { - message: - assertError instanceof Error - ? assertError.message - : String(assertError), - stack: assertError instanceof Error ? assertError.stack : undefined, - }, - message: `Assertion failed: ${assertError instanceof Error ? assertError.message : String(assertError)}`, - }; - } - - return { - status: "pass" as const, - name: testName, - message: "Nunjucks template test passed", - }; - } catch (error) { - return { - status: "fail" as const, - name: testName, - error: { - message: error instanceof Error ? error.message : String(error), - stack: error instanceof Error ? error.stack : undefined, }, - message: `Test failed: ${error instanceof Error ? error.message : String(error)}`, - }; - } -} + {}, + false, + ); -/** - * Run all prompt templating tests - */ -export async function runPromptTemplatingTests( - module: PromptModule, -): Promise { - const results: TestResult[] = []; + const nunjucksResult = nunjucksPrompt.build( + { + items: [{ name: "apple" }, { name: "banana" }, { name: "cherry" }], + }, + { templateFormat: "nunjucks" }, + ); - results.push(await testMustacheTemplate(module)); - results.push(await testNunjucksTemplate(module)); + assertEqual( + nunjucksResult.messages[0]?.content, + "Items: apple, banana, cherry", + "Nunjucks template should render loop correctly", + ); - return results; -} + return "Nunjucks template test passed"; + }, +); diff --git a/js/smoke/tests/otel-v1/tsconfig.json b/js/smoke/tests/otel-v1/tsconfig.json deleted file mode 100644 index dc1fa471a..000000000 --- a/js/smoke/tests/otel-v1/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "Node", - "strict": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "isolatedModules": true, - "types": ["node"] - }, - "include": ["otel_example.ts"], - "exclude": ["node_modules"] -} diff --git a/js/smoke/tests/span/tsconfig.json b/js/smoke/tests/span/tsconfig.json deleted file mode 100644 index 4bdb1a460..000000000 --- a/js/smoke/tests/span/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "Node", - "strict": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "isolatedModules": true, - "types": ["node"] - }, - "include": ["simple_span_example.ts", "span_test_helper.ts"], - "exclude": ["node_modules"] -} From e722771f865f79de6775470f110b517cbc98a9a3 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Thu, 29 Jan 2026 14:49:36 -0800 Subject: [PATCH 41/57] Remove advanced templating option (#1277) Nunjucks templating is known to not work in cloudflare environments due to a restriction on eval() capability. In order to isolate the templating dependency and provide a new cloudflare package, this change will remove nunjucks as a templating option from the base sdk. Users who would like to use the advanced templating will need to install a separate @braintrust/template-nunjucks package that will register the templating option for use as a plugin. Adds an integration test with the main braintrust build that runs the two packages together and updates a few of our other integration tests to run the full test suite. --------- Co-authored-by: Alex Z Co-authored-by: Alex Z Co-authored-by: Ankur Goyal --- .github/workflows/js.yaml | 52 +- .../templates-nunjucks-build-test.yaml | 46 ++ Makefile | 3 +- integrations/browser-js/README.md | 75 ++ integrations/browser-js/package.json | 58 ++ integrations/browser-js/src/browser-config.ts | 48 ++ integrations/browser-js/src/index.ts | 5 + integrations/browser-js/tsconfig.json | 15 + integrations/browser-js/tsup.config.ts | 14 + integrations/browser-js/turbo.json | 10 + integrations/browser-js/vitest.config.ts | 7 + integrations/langchain-js/vitest.config.ts | 1 + integrations/openai-agents-js/src/index.ts | 3 +- .../src/openai-agents-integration.test.ts | 43 +- .../openai-agents-js/vitest.config.ts | 1 + integrations/otel-js/otel-v1/vitest.config.ts | 3 + integrations/otel-js/otel-v2/vitest.config.ts | 3 + .../smoke/scenarios/otel-v1/.gitignore | 0 .../otel-js}/smoke/scenarios/otel-v1/Makefile | 10 +- .../smoke/scenarios/otel-v1/README.md | 0 .../smoke/scenarios/otel-v1/mise.toml | 0 .../smoke/scenarios/otel-v1/package.json | 4 +- .../scenarios/otel-v1/src/test-helpers.ts | 0 .../scenarios/otel-v1/tests/basic.test.ts | 2 +- .../scenarios/otel-v1/tests/filtering.test.ts | 2 +- .../otel-v1/tests/shared-suite.test.ts | 14 +- .../smoke/scenarios/otel-v1/tsconfig.json | 0 integrations/otel-js/vitest.config.ts | 6 +- integrations/templates-nunjucks/package.json | 42 + .../smoke/scenarios/deno-node/Makefile | 37 + .../smoke/scenarios/deno-node/deno.json | 16 + .../smoke/scenarios/deno-node/mise.toml | 3 + .../deno-node/tests/shared-suite.test.ts | 27 + .../smoke/scenarios/jest/Makefile | 48 ++ .../smoke/scenarios/jest/package.json | 16 + .../scenarios/jest/tests/jest-basic.test.js | 26 + .../smoke/scenarios/nextjs/.gitignore | 6 + .../smoke/scenarios/nextjs/Makefile | 56 ++ .../smoke/scenarios/nextjs/next-env.d.ts | 6 + .../smoke/scenarios/nextjs/next.config.mjs | 4 + .../smoke/scenarios/nextjs/package.json | 17 + .../scenarios/nextjs/playwright.config.mts | 26 + .../nextjs/src/app/api/test/route.ts | 128 +++ .../smoke/scenarios/nextjs/src/app/layout.tsx | 11 + .../smoke/scenarios/nextjs/src/app/page.tsx | 3 + .../scenarios/nextjs/tests/nextjs.test.ts | 14 + .../smoke/scenarios/nextjs/tsconfig.json | 35 + .../smoke/scenarios/node-esm/Makefile | 55 ++ .../smoke/scenarios/node-esm/package.json | 14 + .../scenarios/node-esm/tests/basic.test.ts | 28 + .../templates-nunjucks/src/index.test.ts | 728 ++++++++++++++++++ integrations/templates-nunjucks/src/index.ts | 142 ++++ integrations/templates-nunjucks/tsconfig.json | 13 + .../templates-nunjucks/tsup.config.ts | 10 + .../templates-nunjucks/vitest.config.ts | 7 + integrations/temporal-js/vitest.config.ts | 4 +- integrations/vercel-ai-sdk/vitest.config.ts | 7 + js/Makefile | 17 +- js/README.md | 19 + js/deno.json | 6 + js/package.json | 12 +- js/smoke/Makefile | 144 ++-- js/smoke/README.md | 81 +- .../scenarios/browser-main-package/.gitignore | 5 + .../scenarios/browser-main-package/Makefile | 14 + .../scenarios/browser-main-package/README.md | 64 ++ .../browser-main-package/esbuild.config.mjs | 18 + .../scenarios/browser-main-package/mise.toml | 2 + .../browser-main-package/package.json | 18 + .../pages/browser-message-test.html | 17 + .../browser-main-package/playwright.config.ts | 26 + .../src/browser-message-test.ts | 58 ++ .../tests/browser-message.test.ts | 88 +++ .../browser-main-package/tsconfig.json | 16 + .../src/worker-node-esm.ts | 5 +- .../package.json | 1 + .../src/worker.ts | 7 +- .../package.json | 1 + .../src/worker.ts | 7 +- .../package.json | 1 + .../src/worker.ts | 7 +- .../package.json | 1 + .../src/worker.ts | 7 +- .../src/worker.ts | 5 +- .../src/worker.ts | 8 +- js/smoke/scenarios/deno-browser/Makefile | 3 +- js/smoke/scenarios/deno-browser/deno.json | 2 +- .../deno-browser/tests/shared-suite.test.ts | 6 +- js/smoke/scenarios/deno-node/Makefile | 3 +- .../deno-node/tests/shared-suite.test.ts | 8 +- js/smoke/scenarios/jest-node/Makefile | 3 +- .../jest-node/tests/shared-suite.test.js | 9 +- .../nextjs-instrumentation/package.json | 1 + .../src/app/api/smoke-test/edge/route.ts | 7 +- .../src/app/api/smoke-test/node/route.ts | 8 +- .../scenarios/playwright-browser/package.json | 1 + .../playwright-browser/src/browser-tests.ts | 7 +- .../playwright-browser/tests/browser.test.ts | 10 +- js/smoke/shared/package-lock.json | 3 + js/smoke/shared/src/helpers/register.ts | 6 +- js/src/browser-config.ts | 30 +- js/src/browser.ts | 13 +- js/src/exports.ts | 16 +- js/src/framework.test.ts | 7 +- js/src/isomorph.ts | 12 - js/src/logger.test.ts | 32 +- js/src/logger.ts | 30 +- js/src/node.ts | 11 - js/src/prompt.test.ts | 17 +- js/src/template/nunjucks-env.ts | 48 -- js/src/template/nunjucks-render.test.ts | 215 ------ js/src/template/nunjucks-utils.ts | 6 - js/src/template/nunjucks.ts | 3 - js/src/template/registry.ts | 161 ++++ js/src/template/renderer.ts | 31 +- js/tsup.config.ts | 29 +- pnpm-lock.yaml | 131 +++- 117 files changed, 2948 insertions(+), 530 deletions(-) create mode 100644 .github/workflows/templates-nunjucks-build-test.yaml create mode 100644 integrations/browser-js/README.md create mode 100644 integrations/browser-js/package.json create mode 100644 integrations/browser-js/src/browser-config.ts create mode 100644 integrations/browser-js/src/index.ts create mode 100644 integrations/browser-js/tsconfig.json create mode 100644 integrations/browser-js/tsup.config.ts create mode 100644 integrations/browser-js/turbo.json create mode 100644 integrations/browser-js/vitest.config.ts rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/.gitignore (100%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/Makefile (78%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/README.md (100%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/mise.toml (100%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/package.json (73%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/src/test-helpers.ts (100%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/tests/basic.test.ts (97%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/tests/filtering.test.ts (98%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/tests/shared-suite.test.ts (80%) rename {js => integrations/otel-js}/smoke/scenarios/otel-v1/tsconfig.json (100%) create mode 100644 integrations/templates-nunjucks/package.json create mode 100644 integrations/templates-nunjucks/smoke/scenarios/deno-node/Makefile create mode 100644 integrations/templates-nunjucks/smoke/scenarios/deno-node/deno.json create mode 100644 integrations/templates-nunjucks/smoke/scenarios/deno-node/mise.toml create mode 100644 integrations/templates-nunjucks/smoke/scenarios/deno-node/tests/shared-suite.test.ts create mode 100644 integrations/templates-nunjucks/smoke/scenarios/jest/Makefile create mode 100644 integrations/templates-nunjucks/smoke/scenarios/jest/package.json create mode 100644 integrations/templates-nunjucks/smoke/scenarios/jest/tests/jest-basic.test.js create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/.gitignore create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/Makefile create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/next-env.d.ts create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/next.config.mjs create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/package.json create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/playwright.config.mts create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/api/test/route.ts create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/layout.tsx create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/page.tsx create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/tests/nextjs.test.ts create mode 100644 integrations/templates-nunjucks/smoke/scenarios/nextjs/tsconfig.json create mode 100644 integrations/templates-nunjucks/smoke/scenarios/node-esm/Makefile create mode 100644 integrations/templates-nunjucks/smoke/scenarios/node-esm/package.json create mode 100644 integrations/templates-nunjucks/smoke/scenarios/node-esm/tests/basic.test.ts create mode 100644 integrations/templates-nunjucks/src/index.test.ts create mode 100644 integrations/templates-nunjucks/src/index.ts create mode 100644 integrations/templates-nunjucks/tsconfig.json create mode 100644 integrations/templates-nunjucks/tsup.config.ts create mode 100644 integrations/templates-nunjucks/vitest.config.ts create mode 100644 js/deno.json create mode 100644 js/smoke/scenarios/browser-main-package/.gitignore create mode 100644 js/smoke/scenarios/browser-main-package/Makefile create mode 100644 js/smoke/scenarios/browser-main-package/README.md create mode 100644 js/smoke/scenarios/browser-main-package/esbuild.config.mjs create mode 100644 js/smoke/scenarios/browser-main-package/mise.toml create mode 100644 js/smoke/scenarios/browser-main-package/package.json create mode 100644 js/smoke/scenarios/browser-main-package/pages/browser-message-test.html create mode 100644 js/smoke/scenarios/browser-main-package/playwright.config.ts create mode 100644 js/smoke/scenarios/browser-main-package/src/browser-message-test.ts create mode 100644 js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts create mode 100644 js/smoke/scenarios/browser-main-package/tsconfig.json delete mode 100644 js/src/template/nunjucks-env.ts delete mode 100644 js/src/template/nunjucks-render.test.ts delete mode 100644 js/src/template/nunjucks-utils.ts delete mode 100644 js/src/template/nunjucks.ts create mode 100644 js/src/template/registry.ts diff --git a/.github/workflows/js.yaml b/.github/workflows/js.yaml index ba40b3cad..81aa19881 100644 --- a/.github/workflows/js.yaml +++ b/.github/workflows/js.yaml @@ -57,6 +57,14 @@ jobs: PACKED_TARBALL=$(npm pack --pack-destination artifacts) echo "packed_tarball=$PACKED_TARBALL" >> "$GITHUB_OUTPUT" + - name: Pack @braintrust/browser + id: prepare_browser_artifact + working-directory: integrations/browser-js + shell: bash + run: | + PACKED_BROWSER_TARBALL=$(npm pack --pack-destination ../../js/artifacts) + echo "packed_browser_tarball=$PACKED_BROWSER_TARBALL" >> "$GITHUB_OUTPUT" + - name: Build and pack @braintrust/otel id: prepare_otel_artifact shell: bash @@ -89,11 +97,22 @@ jobs: PACKED_OTEL_TARBALL=$(npm pack --pack-destination ../../js/artifacts) echo "packed_otel_tarball=$PACKED_OTEL_TARBALL" >> "$GITHUB_OUTPUT" + - name: Build and pack @braintrust/templates-nunjucks + id: prepare_templates_nunjucks_artifact + shell: bash + run: | + cd integrations/templates-nunjucks + pnpm run build + PACKED_NUNJUCKS_TARBALL=$(npm pack --pack-destination ../../js/artifacts) + echo "packed_nunjucks_tarball=$PACKED_NUNJUCKS_TARBALL" >> "$GITHUB_OUTPUT" + - name: List artifacts before upload shell: bash run: | echo "Braintrust tarball: ${{ steps.prepare_artifact.outputs.packed_tarball }}" + echo "Browser tarball: ${{ steps.prepare_browser_artifact.outputs.packed_browser_tarball }}" echo "Otel tarball: ${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}" + echo "Templates-nunjucks tarball: ${{ steps.prepare_templates_nunjucks_artifact.outputs.packed_nunjucks_tarball }}" ls -la js/artifacts/ - name: Upload build artifacts @@ -102,7 +121,9 @@ jobs: name: ${{ steps.artifact.outputs.name }}-${{ matrix.node-version }}-dist path: | js/artifacts/${{ steps.prepare_artifact.outputs.packed_tarball }} + js/artifacts/${{ steps.prepare_browser_artifact.outputs.packed_browser_tarball }} js/artifacts/${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }} + js/artifacts/${{ steps.prepare_templates_nunjucks_artifact.outputs.packed_nunjucks_tarball }} retention-days: 1 api-compatibility: @@ -210,8 +231,15 @@ jobs: working-directory: js/smoke shell: bash run: | - # Use the same auto-discovery logic as the Makefile - SCENARIOS=$(command find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | sort | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "Discovering local and integration scenarios..." + SCRIPTDIR="../../integrations" + # Local scenarios (under js/smoke/scenarios): emit their directory names + LOCAL=$(find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | tr '\n' ' ') + # Integration scenarios: emit as integration/name + INTEGRATIONS=$(find "$SCRIPTDIR" -type f -path '*/smoke/scenarios/*/Makefile' 2>/dev/null | sed "s|^$SCRIPTDIR/||" | sed 's|/Makefile$||' | sed 's|/smoke/scenarios/|/|' | tr '\n' ' ') + ALL="${LOCAL} ${INTEGRATIONS}" + # Convert space-separated list to JSON array + SCENARIOS=$(printf "%s\n" $ALL | jq -R -s -c 'split("\n") | map(select(length>0))') echo "scenarios=$SCENARIOS" >> "$GITHUB_OUTPUT" echo "Discovered scenarios: $SCENARIOS" @@ -255,6 +283,15 @@ jobs: fi done + # Copy browser tarball to well-known path + for f in braintrust-browser-[0-9]*.tgz; do + if [ -f "$f" ]; then + cp "$f" braintrust-browser-latest.tgz + echo "Copied $f to braintrust-browser-latest.tgz" + break + fi + done + # Copy otel tarball to well-known path for f in braintrust-otel-[0-9]*.tgz; do if [ -f "$f" ]; then @@ -264,6 +301,15 @@ jobs: fi done + # Copy templates-nunjucks-js tarball to well-known path + for f in braintrust-templates-nunjucks-js-[0-9]*.tgz; do + if [ -f "$f" ]; then + cp "$f" braintrust-templates-nunjucks-js-latest.tgz + echo "Copied $f to braintrust-templates-nunjucks-js-latest.tgz" + break + fi + done + - name: Build shared test package (once for all scenarios) working-directory: js/smoke/shared shell: bash @@ -278,7 +324,9 @@ jobs: BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }} CI: true BRAINTRUST_TAR: ../artifacts/braintrust-latest.tgz + BRAINTRUST_BROWSER_TAR: ../artifacts/braintrust-browser-latest.tgz BRAINTRUST_OTEL_TAR: ../artifacts/braintrust-otel-latest.tgz + BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR: ../artifacts/braintrust-templates-nunjucks-js-latest.tgz SMOKE_V2_SHARED_DIST: shared/dist run: | make test ${{ matrix.scenario }} diff --git a/.github/workflows/templates-nunjucks-build-test.yaml b/.github/workflows/templates-nunjucks-build-test.yaml new file mode 100644 index 000000000..ea48d56b3 --- /dev/null +++ b/.github/workflows/templates-nunjucks-build-test.yaml @@ -0,0 +1,46 @@ +name: templates-nunjucks-js + +on: + pull_request: + paths: + - "integrations/templates-nunjucks/**" + - "js/**" + - ".github/workflows/templates-nunjucks-build-test.yaml" + push: + branches: [main] + paths: + - "integrations/templates-nunjucks/**" + - "js/**" + +jobs: + build-and-test: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node-version: [20, 22] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - uses: pnpm/action-setup@v4 + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build braintrust + working-directory: js + run: pnpm run build + + - name: Build @braintrust/templates-nunjucks-js + working-directory: integrations/templates-nunjucks + run: pnpm run build + + - name: Run @braintrust/templates-nunjucks-js tests + working-directory: integrations/templates-nunjucks + run: pnpm run test diff --git a/Makefile b/Makefile index 71a4182f6..162b8871e 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,8 @@ js-build: pnpm run build js-test: js-build - pnpm run test + # Run tests only for the JS workspace packages and exclude integration scenario tests + pnpm --filter ./js... run test cd js && make test js-docs: js-build diff --git a/integrations/browser-js/README.md b/integrations/browser-js/README.md new file mode 100644 index 000000000..929c68553 --- /dev/null +++ b/integrations/browser-js/README.md @@ -0,0 +1,75 @@ +# Braintrust Browser SDK + +Official browser-only SDK for [Braintrust](https://braintrust.dev). + +This is an integration package that provides browser-optimized builds of the Braintrust SDK with AsyncLocalStorage polyfill support for standard browsers. + +## Installation + +```bash +npm install @braintrust/browser braintrust +# or +pnpm add @braintrust/browser braintrust +# or +yarn add @braintrust/browser braintrust +``` + +Note: `braintrust` is a peer dependency and must be installed alongside `@braintrust/browser`. + +## Usage + +```typescript +import * as braintrust from "@braintrust/browser"; + +const experiment = await braintrust.init("BrowserExperiment", { + apiKey: "YOUR_API_KEY", +}); + +// Use tracing in browser +const result = await braintrust.traced( + async () => { + // Your code here + return "result"; + }, + { name: "myOperation" }, +); +``` + +## Differences from Main Package + +This package: + +- **Includes** `als-browser` polyfill for AsyncLocalStorage (bundled) +- **Requires** `braintrust` as a peer dependency + +## When to Use + +Use `@braintrust/browser` when: + +- Building browser-only applications +- Need AsyncLocalStorage support in standard browsers + +Use `braintrust` directly when: + +- Building Node.js applications +- Using in Next.js or other full-stack frameworks (with proper module resolution) +- Need CLI tools or filesystem access + +## Features + +All browser-compatible features from the main SDK: + +- Logging and tracing +- Experiments and datasets +- Prompt management +- AI provider wrappers (OpenAI, Anthropic, Google) +- Evaluation framework +- OpenTelemetry integration + +## Documentation + +For full documentation, visit [https://www.braintrust.dev/docs](https://www.braintrust.dev/docs) + +## License + +Apache-2.0 diff --git a/integrations/browser-js/package.json b/integrations/browser-js/package.json new file mode 100644 index 000000000..aa4485367 --- /dev/null +++ b/integrations/browser-js/package.json @@ -0,0 +1,58 @@ +{ + "name": "@braintrust/browser", + "version": "0.0.2", + "description": "Braintrust SDK for browser environments with AsyncLocalStorage polyfill", + "type": "module", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + } + }, + "files": [ + "dist", + "README.md" + ], + "scripts": { + "build": "tsup", + "watch": "tsup --watch", + "clean": "rm -rf dist", + "test": "vitest run" + }, + "dependencies": { + "als-browser": "^1.0.1" + }, + "devDependencies": { + "@types/node": "^20.10.5", + "braintrust": "workspace:*", + "tsup": "^8.3.5", + "typescript": "^5.3.3", + "vitest": "^2.1.9" + }, + "peerDependencies": { + "braintrust": ">=3.0.0", + "zod": "^3.25.34 || ^4.0" + }, + "peerDependenciesMeta": { + "braintrust": { + "optional": false + }, + "zod": { + "optional": false + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/braintrustdata/braintrust-sdk.git", + "directory": "sdk/integrations/browser-js" + }, + "homepage": "https://www.braintrust.dev/docs", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + } +} diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts new file mode 100644 index 000000000..139cc3d90 --- /dev/null +++ b/integrations/browser-js/src/browser-config.ts @@ -0,0 +1,48 @@ +import { _internalIso as iso, _internalSetInitialState } from "braintrust"; +import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; + +let browserConfigured = false; + +export function configureBrowser() { + if (browserConfigured) { + return; + } + + // Set build type indicator + iso.buildType = "browser"; + + iso.newAsyncLocalStorage = () => new BrowserAsyncLocalStorage(); + + iso.getEnv = (name: string) => { + if (typeof process === "undefined" || typeof process.env === "undefined") { + return undefined; + } + return process.env[name]; + }; + + // noop implementations for git config + iso.getRepoInfo = async () => ({ + commit: null, + branch: null, + tag: null, + dirty: false, + }); + iso.getCallerLocation = () => undefined; + + // Implement browser-compatible hash function using a simple hash algorithm + iso.hash = (data: string): string => { + // Simple hash function for browser compatibility + let hash = 0; + for (let i = 0; i < data.length; i++) { + const char = data.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash = hash & hash; // Convert to 32bit integer + } + // Convert to hex string + const hashHex = (hash >>> 0).toString(16).padStart(8, "0"); + return hashHex.repeat(8).substring(0, 64); // Make it look like a SHA-256 hash length + }; + + _internalSetInitialState(); + browserConfigured = true; +} diff --git a/integrations/browser-js/src/index.ts b/integrations/browser-js/src/index.ts new file mode 100644 index 000000000..70b350745 --- /dev/null +++ b/integrations/browser-js/src/index.ts @@ -0,0 +1,5 @@ +import { configureBrowser } from "./browser-config"; + +configureBrowser(); + +export * from "braintrust"; diff --git a/integrations/browser-js/tsconfig.json b/integrations/browser-js/tsconfig.json new file mode 100644 index 000000000..94649b1d8 --- /dev/null +++ b/integrations/browser-js/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "declaration": true, + "lib": ["es2022", "dom"], + "module": "esnext", + "target": "es2022", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/integrations/browser-js/tsup.config.ts b/integrations/browser-js/tsup.config.ts new file mode 100644 index 000000000..b532d4d5c --- /dev/null +++ b/integrations/browser-js/tsup.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["esm"], + dts: true, + sourcemap: true, + clean: true, + external: ["braintrust", "zod"], + target: "es2022", + platform: "browser", + outDir: "./dist", + treeshake: true, +}); diff --git a/integrations/browser-js/turbo.json b/integrations/browser-js/turbo.json new file mode 100644 index 000000000..6b90853c5 --- /dev/null +++ b/integrations/browser-js/turbo.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "tasks": { + "build": { + "dependsOn": ["braintrust#build"], + "outputs": ["dist/**"] + } + } +} diff --git a/integrations/browser-js/vitest.config.ts b/integrations/browser-js/vitest.config.ts new file mode 100644 index 000000000..73a26a648 --- /dev/null +++ b/integrations/browser-js/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, +}); diff --git a/integrations/langchain-js/vitest.config.ts b/integrations/langchain-js/vitest.config.ts index 197422ec0..d16bcb8cc 100644 --- a/integrations/langchain-js/vitest.config.ts +++ b/integrations/langchain-js/vitest.config.ts @@ -3,5 +3,6 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { setupFiles: ["./src/test/setup.ts"], + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], }, }); diff --git a/integrations/openai-agents-js/src/index.ts b/integrations/openai-agents-js/src/index.ts index 95a18edd5..4a6a565d3 100644 --- a/integrations/openai-agents-js/src/index.ts +++ b/integrations/openai-agents-js/src/index.ts @@ -382,7 +382,8 @@ export class OpenAIAgentsTraceProcessor { if (!data.metrics.completion_tokens && usage.completionTokens) data.metrics.completion_tokens = usage.completionTokens; if (usage.input_tokens_details?.cached_tokens != null) - data.metrics.prompt_cached_tokens = usage.input_tokens_details.cached_tokens; + data.metrics.prompt_cached_tokens = + usage.input_tokens_details.cached_tokens; } return data; diff --git a/integrations/openai-agents-js/src/openai-agents-integration.test.ts b/integrations/openai-agents-js/src/openai-agents-integration.test.ts index 618da167b..75c954942 100644 --- a/integrations/openai-agents-js/src/openai-agents-integration.test.ts +++ b/integrations/openai-agents-js/src/openai-agents-integration.test.ts @@ -908,7 +908,7 @@ describe( output_tokens: 50, total_tokens: 150, input_tokens_details: { - cached_tokens: 80, // check for this later + cached_tokens: 80, // check for this later }, }, }, @@ -934,9 +934,17 @@ describe( const metrics = (responseSpanLog as any).metrics; assert.ok(metrics, "Response span should have metrics"); assert.equal(metrics.prompt_tokens, 100, "Should have prompt_tokens"); - assert.equal(metrics.completion_tokens, 50, "Should have completion_tokens"); + assert.equal( + metrics.completion_tokens, + 50, + "Should have completion_tokens", + ); assert.equal(metrics.tokens, 150, "Should have total tokens"); - assert.equal(metrics.prompt_cached_tokens, 80, "Should extract cached_tokens to prompt_cached_tokens"); + assert.equal( + metrics.prompt_cached_tokens, + 80, + "Should extract cached_tokens to prompt_cached_tokens", + ); }); test("Response span handles zero cached tokens correctly", async () => { @@ -965,7 +973,7 @@ describe( input_tokens: 100, output_tokens: 50, input_tokens_details: { - cached_tokens: 0, // Zero is a valid value + cached_tokens: 0, // Zero is a valid value }, }, }, @@ -977,7 +985,9 @@ describe( await processor.onSpanEnd(responseSpan); const spans = await backgroundLogger.drain(); - const responseSpanLog = spans.find((s: any) => s.span_attributes?.type === "llm"); + const responseSpanLog = spans.find( + (s: any) => s.span_attributes?.type === "llm", + ); const metrics = (responseSpanLog as any).metrics; // Zero should be logged, not skipped @@ -1024,11 +1034,16 @@ describe( await processor.onSpanEnd(responseSpan); const spans = await backgroundLogger.drain(); - const responseSpanLog = spans.find((s: any) => s.span_attributes?.type === "llm"); + const responseSpanLog = spans.find( + (s: any) => s.span_attributes?.type === "llm", + ); const metrics = (responseSpanLog as any).metrics; // Should not have prompt_cached_tokens if not present in usage - assert.isUndefined(metrics.prompt_cached_tokens, "Should not add prompt_cached_tokens if not in usage"); + assert.isUndefined( + metrics.prompt_cached_tokens, + "Should not add prompt_cached_tokens if not in usage", + ); }); test("Generation span extracts cached tokens from usage", async () => { @@ -1060,7 +1075,7 @@ describe( output_tokens: 75, total_tokens: 275, input_tokens_details: { - cached_tokens: 150, // Test Generation span extraction + cached_tokens: 150, // Test Generation span extraction }, }, }, @@ -1080,8 +1095,16 @@ describe( const metrics = (generationSpanLog as any).metrics; assert.ok(metrics, "Generation span should have metrics"); assert.equal(metrics.prompt_tokens, 200, "Should have prompt_tokens"); - assert.equal(metrics.completion_tokens, 75, "Should have completion_tokens"); - assert.equal(metrics.prompt_cached_tokens, 150, "Should extract cached_tokens from Generation span"); + assert.equal( + metrics.completion_tokens, + 75, + "Should have completion_tokens", + ); + assert.equal( + metrics.prompt_cached_tokens, + 150, + "Should extract cached_tokens from Generation span", + ); }); }, ); diff --git a/integrations/openai-agents-js/vitest.config.ts b/integrations/openai-agents-js/vitest.config.ts index be2185492..8e30c5974 100644 --- a/integrations/openai-agents-js/vitest.config.ts +++ b/integrations/openai-agents-js/vitest.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], // Add any specific test configuration if needed }, }); diff --git a/integrations/otel-js/otel-v1/vitest.config.ts b/integrations/otel-js/otel-v1/vitest.config.ts index 8c8114c32..fd400cc49 100644 --- a/integrations/otel-js/otel-v1/vitest.config.ts +++ b/integrations/otel-js/otel-v1/vitest.config.ts @@ -17,4 +17,7 @@ export default defineConfig({ alias: createOtelAliases(cwd), } : {}, + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, }); diff --git a/integrations/otel-js/otel-v2/vitest.config.ts b/integrations/otel-js/otel-v2/vitest.config.ts index 8c8114c32..fd400cc49 100644 --- a/integrations/otel-js/otel-v2/vitest.config.ts +++ b/integrations/otel-js/otel-v2/vitest.config.ts @@ -17,4 +17,7 @@ export default defineConfig({ alias: createOtelAliases(cwd), } : {}, + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, }); diff --git a/js/smoke/scenarios/otel-v1/.gitignore b/integrations/otel-js/smoke/scenarios/otel-v1/.gitignore similarity index 100% rename from js/smoke/scenarios/otel-v1/.gitignore rename to integrations/otel-js/smoke/scenarios/otel-v1/.gitignore diff --git a/js/smoke/scenarios/otel-v1/Makefile b/integrations/otel-js/smoke/scenarios/otel-v1/Makefile similarity index 78% rename from js/smoke/scenarios/otel-v1/Makefile rename to integrations/otel-js/smoke/scenarios/otel-v1/Makefile index 0b72d0207..83e3338f5 100644 --- a/js/smoke/scenarios/otel-v1/Makefile +++ b/integrations/otel-js/smoke/scenarios/otel-v1/Makefile @@ -13,7 +13,7 @@ setup: echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ else \ echo "==> Building SDK"; \ - cd ../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ + cd ../../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p artifacts && pnpm pack --pack-destination artifacts; \ \ for f in artifacts/braintrust-*.tgz; do \ if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ @@ -27,7 +27,7 @@ setup: @# Build shared package (if not running from parent) @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ echo "==> Building shared package"; \ - cd ../../shared && npm ci && npm run build; \ + cd ../../../shared && npm ci && npm run build; \ fi @# Check if BRAINTRUST_OTEL_TAR is set (from parent or CI), otherwise build @@ -35,11 +35,11 @@ setup: echo "==> Using BRAINTRUST_OTEL_TAR: $(BRAINTRUST_OTEL_TAR)"; \ else \ echo "==> Building @braintrust/otel package"; \ - cd ../../../../integrations/otel-js && pnpm exec turbo build --filter=@braintrust/otel && pnpm pack --pack-destination ../../js/artifacts; \ + cd ../../../../../integrations/otel-js && pnpm exec turbo build --filter=@braintrust/otel && pnpm pack --pack-destination ../../js/artifacts; \ \ - for f in ../../js/artifacts/braintrust-otel-*.tgz; do \ + for f in ../../../js/artifacts/braintrust-otel-*.tgz; do \ if [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ - cp "$$f" ../../js/artifacts/braintrust-otel-latest.tgz; \ + cp "$$f" ../../../js/artifacts/braintrust-otel-latest.tgz; \ break; \ fi; \ done; \ diff --git a/js/smoke/scenarios/otel-v1/README.md b/integrations/otel-js/smoke/scenarios/otel-v1/README.md similarity index 100% rename from js/smoke/scenarios/otel-v1/README.md rename to integrations/otel-js/smoke/scenarios/otel-v1/README.md diff --git a/js/smoke/scenarios/otel-v1/mise.toml b/integrations/otel-js/smoke/scenarios/otel-v1/mise.toml similarity index 100% rename from js/smoke/scenarios/otel-v1/mise.toml rename to integrations/otel-js/smoke/scenarios/otel-v1/mise.toml diff --git a/js/smoke/scenarios/otel-v1/package.json b/integrations/otel-js/smoke/scenarios/otel-v1/package.json similarity index 73% rename from js/smoke/scenarios/otel-v1/package.json rename to integrations/otel-js/smoke/scenarios/otel-v1/package.json index 335a0b33b..50b0a8700 100644 --- a/js/smoke/scenarios/otel-v1/package.json +++ b/integrations/otel-js/smoke/scenarios/otel-v1/package.json @@ -3,8 +3,8 @@ "private": true, "type": "module", "dependencies": { - "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz", + "braintrust": "file:../../../../../js/artifacts/braintrust-latest.tgz", + "@braintrust/otel": "file:../../../../../js/artifacts/braintrust-otel-latest.tgz", "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.9.0", "@opentelemetry/exporter-trace-otlp-http": "^0.53.0", diff --git a/js/smoke/scenarios/otel-v1/src/test-helpers.ts b/integrations/otel-js/smoke/scenarios/otel-v1/src/test-helpers.ts similarity index 100% rename from js/smoke/scenarios/otel-v1/src/test-helpers.ts rename to integrations/otel-js/smoke/scenarios/otel-v1/src/test-helpers.ts diff --git a/js/smoke/scenarios/otel-v1/tests/basic.test.ts b/integrations/otel-js/smoke/scenarios/otel-v1/tests/basic.test.ts similarity index 97% rename from js/smoke/scenarios/otel-v1/tests/basic.test.ts rename to integrations/otel-js/smoke/scenarios/otel-v1/tests/basic.test.ts index 2031df34d..8ae35e369 100644 --- a/js/smoke/scenarios/otel-v1/tests/basic.test.ts +++ b/integrations/otel-js/smoke/scenarios/otel-v1/tests/basic.test.ts @@ -8,7 +8,7 @@ import { displayTestResults, hasFailures, type TestResult, -} from "../../../shared/dist/index.mjs"; +} from "../../../../../../js/smoke/shared/dist/index.mjs"; async function main() { const results: TestResult[] = []; diff --git a/js/smoke/scenarios/otel-v1/tests/filtering.test.ts b/integrations/otel-js/smoke/scenarios/otel-v1/tests/filtering.test.ts similarity index 98% rename from js/smoke/scenarios/otel-v1/tests/filtering.test.ts rename to integrations/otel-js/smoke/scenarios/otel-v1/tests/filtering.test.ts index 3fdfab0a4..0a7cf10a9 100644 --- a/js/smoke/scenarios/otel-v1/tests/filtering.test.ts +++ b/integrations/otel-js/smoke/scenarios/otel-v1/tests/filtering.test.ts @@ -8,7 +8,7 @@ import { displayTestResults, hasFailures, type TestResult, -} from "../../../shared/dist/index.mjs"; +} from "../../../../../../js/smoke/shared/dist/index.mjs"; type OtelPayload = { resourceSpans?: Array<{ diff --git a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts b/integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts similarity index 80% rename from js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts rename to integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts index 5559e89ac..83fba976f 100644 --- a/js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts +++ b/integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts @@ -4,6 +4,7 @@ import { runTests, + expectFailure, testBasicSpanLogging, testMultipleSpans, testDirectLogging, @@ -25,7 +26,10 @@ import { testTestingExports, testStateManagementExports, testBuildResolution, -} from "../../../shared/dist/index.js"; + testMustacheTemplate, + testNunjucksTemplate, + testEvalSmoke, +} from "../../../../../../js/smoke/shared/dist/index.js"; async function runSharedTestSuites() { const braintrust = await import("braintrust"); @@ -55,6 +59,14 @@ async function runSharedTestSuites() { testAsyncLocalStorageTraced, testNestedTraced, testCurrentSpan, + testEvalSmoke, + testMustacheTemplate, + expectFailure( + testNunjucksTemplate, + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", + ), ], }); diff --git a/js/smoke/scenarios/otel-v1/tsconfig.json b/integrations/otel-js/smoke/scenarios/otel-v1/tsconfig.json similarity index 100% rename from js/smoke/scenarios/otel-v1/tsconfig.json rename to integrations/otel-js/smoke/scenarios/otel-v1/tsconfig.json diff --git a/integrations/otel-js/vitest.config.ts b/integrations/otel-js/vitest.config.ts index 8fb6f2dcf..73a26a648 100644 --- a/integrations/otel-js/vitest.config.ts +++ b/integrations/otel-js/vitest.config.ts @@ -1,3 +1,7 @@ import { defineConfig } from "vitest/config"; -export default defineConfig({}); +export default defineConfig({ + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, +}); diff --git a/integrations/templates-nunjucks/package.json b/integrations/templates-nunjucks/package.json new file mode 100644 index 000000000..71c0a490b --- /dev/null +++ b/integrations/templates-nunjucks/package.json @@ -0,0 +1,42 @@ +{ + "name": "@braintrust/templates-nunjucks-js", + "version": "0.0.1", + "description": "Nunjucks templating support for the Braintrust JS SDK", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "module": "./dist/index.mjs", + "require": "./dist/index.js" + } + }, + "files": [ + "dist/**/*" + ], + "scripts": { + "build": "tsup", + "watch": "tsup --watch", + "clean": "rm -r dist/*", + "test": "vitest run --exclude 'smoke/scenarios/**'" + }, + "author": "Braintrust Data Inc.", + "license": "Apache-2.0", + "dependencies": { + "nunjucks": "^3.2.4" + }, + "peerDependencies": { + "braintrust": ">=3.0.0" + }, + "devDependencies": { + "@types/nunjucks": "^3.2.6", + "@types/node": "^20.10.5", + "braintrust": "workspace:*", + "tsup": "^8.5.1", + "typescript": "5.5.4", + "vitest": "^2.1.9" + } +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/deno-node/Makefile b/integrations/templates-nunjucks/smoke/scenarios/deno-node/Makefile new file mode 100644 index 000000000..92a53564b --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/deno-node/Makefile @@ -0,0 +1,37 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up templates-nunjucks deno scenario" + mise install + + @# Build or extract braintrust SDK (workspace link will use dist/) + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Extracting SDK tarball for workspace link"; \ + TARBALL_PATH="$$(cd ../../../../../js/smoke && pwd)/$(BRAINTRUST_TAR)"; \ + echo "==> Resolved tarball path: $$TARBALL_PATH"; \ + cd ../../../../../js && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ + else \ + echo "==> Building SDK"; \ + cd ../../../../../js && pnpm build; \ + fi + + @# Build or extract @braintrust/templates-nunjucks-js (workspace link will use dist/) + @if [ -n "$(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)" ]; then \ + echo "==> Extracting templates-nunjucks tarball for workspace link"; \ + TARBALL_PATH="$$(cd ../../../../../js/smoke && pwd)/$(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)"; \ + echo "==> Resolved tarball path: $$TARBALL_PATH"; \ + cd ../../.. && tar -xzf "$$TARBALL_PATH" --strip-components=1 package/dist; \ + else \ + echo "==> Building @braintrust/templates-nunjucks-js package"; \ + cd ../../../../.. && pnpm install && pnpm --filter=@braintrust/templates-nunjucks-js build; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../../../../js/smoke/shared && npm install && npm run build; \ + fi + +test: setup + @echo "==> Running deno tests" + mise exec -- deno test --no-check --sloppy-imports --allow-all tests/*.test.ts diff --git a/integrations/templates-nunjucks/smoke/scenarios/deno-node/deno.json b/integrations/templates-nunjucks/smoke/scenarios/deno-node/deno.json new file mode 100644 index 000000000..deba541b0 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/deno-node/deno.json @@ -0,0 +1,16 @@ +{ + "imports": { + "@std/assert": "jsr:@std/assert@^1.0.14", + "@braintrust/smoke-test-shared": "jsr:@braintrust/smoke-test-shared", + "@braintrust/templates-nunjucks-js": "npm:@braintrust/templates-nunjucks-js", + "braintrust": "npm:braintrust", + "zod": "npm:zod@^4.2.1", + "zod/": "npm:/zod@^4.2.1/" + }, + "nodeModulesDir": "auto", + "links": [ + "../../../../../js", + "../../../", + "../../../../../js/smoke/shared" + ] +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/deno-node/mise.toml b/integrations/templates-nunjucks/smoke/scenarios/deno-node/mise.toml new file mode 100644 index 000000000..dd563ce6f --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/deno-node/mise.toml @@ -0,0 +1,3 @@ +[tools] +deno = "latest" +pnpm = "10.26.2" diff --git a/integrations/templates-nunjucks/smoke/scenarios/deno-node/tests/shared-suite.test.ts b/integrations/templates-nunjucks/smoke/scenarios/deno-node/tests/shared-suite.test.ts new file mode 100644 index 000000000..5800d3e6b --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/deno-node/tests/shared-suite.test.ts @@ -0,0 +1,27 @@ +// @ts-nocheck +/** + * Templates-Nunjucks Deno smoke test - testing template rendering only + */ + +import { assertEquals } from "@std/assert"; +import { + runTests, + testMustacheTemplate, + testNunjucksTemplate, +} from "@braintrust/smoke-test-shared"; +import * as braintrust from "braintrust"; +import { nunjucksPlugin } from "@braintrust/templates-nunjucks-js"; + +Deno.test("Run template tests with Nunjucks", async () => { + // Register nunjucks plugin before running tests + braintrust.registerTemplatePlugin(nunjucksPlugin); + + const { failed } = await runTests({ + name: "templates-nunjucks-deno", + braintrust, + tests: [testMustacheTemplate, testNunjucksTemplate], + skipCoverage: true, + }); + + assertEquals(failed.length, 0, "All template tests should pass"); +}); diff --git a/integrations/templates-nunjucks/smoke/scenarios/jest/Makefile b/integrations/templates-nunjucks/smoke/scenarios/jest/Makefile new file mode 100644 index 000000000..29291218a --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/jest/Makefile @@ -0,0 +1,48 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up templates-nunjucks jest scenario" + mise install + + @# Build SDK and shared package if not provided + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p js/artifacts && pnpm --filter=braintrust pack --pack-destination js/artifacts; \ + for f in js/artifacts/braintrust-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-templates-nunjucks-js-latest.tgz" ]; then \ + cp "$$f" js/artifacts/braintrust-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../../../../js/smoke/shared && npm install && npm run build; \ + fi + + @# Build @braintrust/templates-nunjucks-js package + @if [ -n "$(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR: $(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)"; \ + else \ + echo "==> Building @braintrust/templates-nunjucks-js package"; \ + cd ../../../../.. && pnpm exec turbo build --filter=@braintrust/templates-nunjucks-js && cd integrations/templates-nunjucks && pnpm pack --pack-destination ../js/artifacts; \ + for f in ../../js/artifacts/braintrust-templates-nunjucks-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-templates-nunjucks-js-latest.tgz" ]; then \ + cp "$$f" ../../js/artifacts/braintrust-templates-nunjucks-js-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + npm install --no-package-lock + +test: setup + @echo "==> Running jest tests" + @# Run only tests under the local tests/ directory to avoid workspace-wide discovery + npx jest --passWithNoTests --roots ./tests diff --git a/integrations/templates-nunjucks/smoke/scenarios/jest/package.json b/integrations/templates-nunjucks/smoke/scenarios/jest/package.json new file mode 100644 index 000000000..703b21d4d --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/jest/package.json @@ -0,0 +1,16 @@ +{ + "name": "smoke-templates-nunjucks-jest", + "private": true, + "type": "commonjs", + "dependencies": { + "braintrust": "file:../../../../../js/artifacts/braintrust-latest.tgz", + "@braintrust/templates-nunjucks-js": "file:../../../../../js/artifacts/braintrust-templates-nunjucks-js-latest.tgz" + }, + "devDependencies": { + "@types/jest": "^29.5.0", + "@types/node": "^20.10.5", + "jest": "^29.7.0", + "ts-jest": "^29.1.0", + "typescript": "^5.4.4" + } +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/jest/tests/jest-basic.test.js b/integrations/templates-nunjucks/smoke/scenarios/jest/tests/jest-basic.test.js new file mode 100644 index 000000000..98aa16d55 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/jest/tests/jest-basic.test.js @@ -0,0 +1,26 @@ +const { + runTests, + testMustacheTemplate, + testNunjucksTemplate, +} = require("../../../../../../js/smoke/shared/dist/index.js"); +const braintrust = require("braintrust"); +const { nunjucksPlugin } = require("@braintrust/templates-nunjucks-js"); + +test("Templates-Nunjucks basic behavior", async () => { + // Register nunjucks plugin before running tests + braintrust.registerTemplatePlugin(nunjucksPlugin); + + const { failed } = await runTests({ + name: "templates-nunjucks-jest", + braintrust, + tests: [testMustacheTemplate, testNunjucksTemplate], + skipCoverage: true, + }); + + if (failed.length > 0) { + const msg = failed + .map((f) => `${f.name}: ${f.error ?? "failed"}`) + .join("\n"); + throw new Error(`Found failures:\n${msg}`); + } +}); diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/.gitignore b/integrations/templates-nunjucks/smoke/scenarios/nextjs/.gitignore new file mode 100644 index 000000000..a3f58edb0 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +.next/ +test-results/ +*.log +.env.local +package-lock.json diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/Makefile b/integrations/templates-nunjucks/smoke/scenarios/nextjs/Makefile new file mode 100644 index 000000000..3191aeadf --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/Makefile @@ -0,0 +1,56 @@ +.PHONY: setup test + +setup: + @echo "==> Setting up templates-nunjucks nextjs scenario" + mise install + + @# Build SDK and shared package if not provided + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p js/artifacts && pnpm --filter=braintrust pack --pack-destination js/artifacts; \ + for f in js/artifacts/braintrust-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-templates-nunjucks-js-latest.tgz" ]; then \ + cp "$$f" js/artifacts/braintrust-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../../../../js/smoke/shared && npm install && npm run build; \ + fi + + @# Build @braintrust/templates-nunjucks-js package + @if [ -n "$(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR: $(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)"; \ + else \ + echo "==> Building @braintrust/templates-nunjucks-js package"; \ + cd ../../../../.. && \ + pnpm exec turbo build --filter=@braintrust/templates-nunjucks-js && \ + cd integrations/templates-nunjucks && \ + pnpm pack --pack-destination ../../js/artifacts && \ + cd ../../js/artifacts && \ + for f in braintrust-templates-nunjucks-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-templates-nunjucks-js-latest.tgz" ]; then \ + cp "$$f" braintrust-templates-nunjucks-js-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @echo "==> Cleaning and reinstalling node_modules to pick up new tarballs" + rm -rf node_modules package-lock.json .next + npm install --no-package-lock + +test: setup + @echo "==> Running Next.js integration test" + @echo "==> Building Next.js app" + npx next build + @echo "==> Starting Next.js dev server and running Playwright tests" + npx playwright test diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/next-env.d.ts b/integrations/templates-nunjucks/smoke/scenarios/nextjs/next-env.d.ts new file mode 100644 index 000000000..830fb594c --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/next.config.mjs b/integrations/templates-nunjucks/smoke/scenarios/nextjs/next.config.mjs new file mode 100644 index 000000000..4678774e6 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/package.json b/integrations/templates-nunjucks/smoke/scenarios/nextjs/package.json new file mode 100644 index 000000000..22c862740 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/package.json @@ -0,0 +1,17 @@ +{ + "name": "smoke-templates-nunjucks-nextjs", + "private": true, + "dependencies": { + "braintrust": "file:../../../../../js/artifacts/braintrust-latest.tgz", + "@braintrust/templates-nunjucks-js": "file:../../../../../js/artifacts/braintrust-templates-nunjucks-js-latest.tgz", + "next": "^15.1.4", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@playwright/test": "^1.49.1", + "@types/node": "^20.11.5", + "@types/react": "^18.2.48", + "typescript": "^5.3.3" + } +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/playwright.config.mts b/integrations/templates-nunjucks/smoke/scenarios/nextjs/playwright.config.mts new file mode 100644 index 000000000..ec75bdd0d --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/playwright.config.mts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from "@playwright/test"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +export default defineConfig({ + testDir: "./tests", + timeout: 30000, + webServer: { + command: "npx next dev --port 3456", + port: 3456, + cwd: __dirname, + timeout: 120000, + reuseExistingServer: !process.env.CI, + }, + use: { + baseURL: "http://localhost:3456", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], +}); diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/api/test/route.ts b/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/api/test/route.ts new file mode 100644 index 000000000..27827c73a --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/api/test/route.ts @@ -0,0 +1,128 @@ +import { NextResponse } from "next/server"; +import { registerTemplatePlugin, Prompt } from "braintrust"; +import { nunjucksPlugin } from "@braintrust/templates-nunjucks-js"; + +export const runtime = "nodejs"; + +export async function GET() { + console.log("API route called - starting dynamic imports"); + try { + registerTemplatePlugin(nunjucksPlugin); + + const results = []; + + // Test 1: Basic nunjucks template rendering + const prompt = new Prompt( + { + id: "test-prompt-1", + _xact_id: "test-xact", + project_id: "test-project", + name: "nunjucks-nextjs-test", + slug: "nunjucks-nextjs-test", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: + "Items: {% for item in items %}{{ item.name }}{% if not loop.last %}, {% endif %}{% endfor %}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { items: [{ name: "apple" }, { name: "banana" }, { name: "cherry" }] }, + { templateFormat: "nunjucks" }, + ); + if (result.messages[0]?.content === "Items: apple, banana, cherry") { + results.push({ + status: "pass", + name: "Nunjucks template loop rendering", + }); + } else { + results.push({ + status: "fail", + name: "Nunjucks template loop rendering", + error: { + message: `Expected "Items: apple, banana, cherry", got "${result.messages[0]?.content}"`, + }, + }); + } + + // Test 2: Conditional rendering + const conditionalPrompt = new Prompt( + { + id: "test-prompt-2", + _xact_id: "test-xact", + project_id: "test-project", + name: "nunjucks-conditional-test", + slug: "nunjucks-conditional-test", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: + "{% if showGreeting %}Hello, {{ name }}!{% else %}Goodbye!{% endif %}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const conditionalResult = conditionalPrompt.build( + { showGreeting: true, name: "World" }, + { templateFormat: "nunjucks" }, + ); + + if (conditionalResult.messages[0]?.content === "Hello, World!") { + results.push({ + status: "pass", + name: "Nunjucks conditional rendering", + }); + } else { + results.push({ + status: "fail", + name: "Nunjucks conditional rendering", + error: { + message: `Expected "Hello, World!", got "${conditionalResult.messages[0]?.content}"`, + }, + }); + } + + const failures = results.filter((r) => r.status === "fail"); + + return NextResponse.json( + { + success: failures.length === 0, + message: + failures.length > 0 + ? `${failures.length} test(s) failed` + : "All tests passed", + content: result.messages[0]?.content, + totalTests: results.length, + passedTests: results.filter((r) => r.status === "pass").length, + failedTests: failures.length, + results, + }, + { status: failures.length === 0 ? 200 : 500 }, + ); + } catch (error) { + return NextResponse.json( + { success: false, error: String(error) }, + { status: 500 }, + ); + } +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/layout.tsx b/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/layout.tsx new file mode 100644 index 000000000..225b6038d --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/page.tsx b/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/page.tsx new file mode 100644 index 000000000..cfaa25088 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/src/app/page.tsx @@ -0,0 +1,3 @@ +export default function Home() { + return
Templates-Nunjucks Next.js Test
; +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/tests/nextjs.test.ts b/integrations/templates-nunjucks/smoke/scenarios/nextjs/tests/nextjs.test.ts new file mode 100644 index 000000000..e08fe5ee0 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/tests/nextjs.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from "@playwright/test"; + +test("Nunjucks template rendering in Next.js API route", async ({ + request, +}) => { + const response = await request.get("/api/test"); + + const text = await response.text(); + const data = JSON.parse(text); + + expect(response.ok()).toBeTruthy(); + expect(data.success).toBe(true); + expect(data.content).toBe("Items: apple, banana, cherry"); +}); diff --git a/integrations/templates-nunjucks/smoke/scenarios/nextjs/tsconfig.json b/integrations/templates-nunjucks/smoke/scenarios/nextjs/tsconfig.json new file mode 100644 index 000000000..f619795e7 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/nextjs/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "noEmit": true, + "incremental": true, + "module": "esnext", + "esModuleInterop": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "plugins": [ + { + "name": "next" + } + ] + }, + "include": [ + "next-env.d.ts", + ".next/types/**/*.ts", + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/node-esm/Makefile b/integrations/templates-nunjucks/smoke/scenarios/node-esm/Makefile new file mode 100644 index 000000000..4c705d23d --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/node-esm/Makefile @@ -0,0 +1,55 @@ +.PHONY: setup test + +# ============================================================================ +# Setup +# ============================================================================ + +setup: + @echo "==> Setting up templates-nunjucks scenario" + mise install + + @# Check if BRAINTRUST_TAR is set (from parent or CI), otherwise build + @if [ -n "$(BRAINTRUST_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TAR: $(BRAINTRUST_TAR)"; \ + else \ + echo "==> Building SDK"; \ + cd ../../../../.. && pnpm exec turbo build --filter=braintrust && mkdir -p js/artifacts && pnpm --filter=braintrust pack --pack-destination js/artifacts; \ + for f in js/artifacts/braintrust-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ] && \ + [ "$$(basename $$f)" != "braintrust-templates-nunjucks-latest.tgz" ]; then \ + cp "$$f" js/artifacts/braintrust-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + @# Build shared package (if not running from parent) + @if [ -z "$(SMOKE_V2_SHARED_DIST)" ]; then \ + echo "==> Building shared package"; \ + cd ../../../../../js/smoke/shared && npm install && npm run build; \ + fi + + @# Build @braintrust/templates-nunjucks-js package into js/artifacts + @if [ -n "$(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)" ]; then \ + echo "==> Using BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR: $(BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR)"; \ + else \ + echo "==> Building @braintrust/templates-nunjucks-js package"; \ + cd ../../../../.. && pnpm exec turbo build --filter=@braintrust/templates-nunjucks-js && cd integrations/templates-nunjucks && pnpm pack --pack-destination ../js/artifacts; \ + for f in ../../js/artifacts/braintrust-templates-nunjucks-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-templates-nunjucks-js-latest.tgz" ]; then \ + cp "$$f" ../../js/artifacts/braintrust-templates-nunjucks-js-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + + npm install --no-package-lock + +# ============================================================================ +# Test +# ============================================================================ + +test: setup + @echo "==> Running templates-nunjucks tests" + npx tsx tests/basic.test.ts diff --git a/integrations/templates-nunjucks/smoke/scenarios/node-esm/package.json b/integrations/templates-nunjucks/smoke/scenarios/node-esm/package.json new file mode 100644 index 000000000..942dfbbf5 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/node-esm/package.json @@ -0,0 +1,14 @@ +{ + "name": "smoke-templates-nunjucks-integration", + "private": true, + "type": "module", + "dependencies": { + "braintrust": "file:../../../../../js/artifacts/braintrust-latest.tgz", + "@braintrust/templates-nunjucks-js": "file:../../../../../js/artifacts/braintrust-templates-nunjucks-js-latest.tgz" + }, + "devDependencies": { + "@types/node": "^20.10.5", + "tsx": "^4.19.2", + "typescript": "^5.4.4" + } +} diff --git a/integrations/templates-nunjucks/smoke/scenarios/node-esm/tests/basic.test.ts b/integrations/templates-nunjucks/smoke/scenarios/node-esm/tests/basic.test.ts new file mode 100644 index 000000000..0e53dce22 --- /dev/null +++ b/integrations/templates-nunjucks/smoke/scenarios/node-esm/tests/basic.test.ts @@ -0,0 +1,28 @@ +import { + runTests, + testMustacheTemplate, + testNunjucksTemplate, +} from "../../../../../../js/smoke/shared/dist/index.mjs"; +import * as braintrust from "braintrust"; +import { nunjucksPlugin } from "@braintrust/templates-nunjucks-js"; + +async function main() { + // Register nunjucks plugin before running tests + braintrust.registerTemplatePlugin(nunjucksPlugin); + + const { failed } = await runTests({ + name: "templates-nunjucks-basic-render", + braintrust, + tests: [testMustacheTemplate, testNunjucksTemplate], + skipCoverage: true, + }); + + if (failed.length > 0) { + process.exit(1); + } +} + +main().catch((err) => { + console.error("Fatal error:", err); + process.exit(1); +}); diff --git a/integrations/templates-nunjucks/src/index.test.ts b/integrations/templates-nunjucks/src/index.test.ts new file mode 100644 index 000000000..60bee39c1 --- /dev/null +++ b/integrations/templates-nunjucks/src/index.test.ts @@ -0,0 +1,728 @@ +import { describe, test, expect, beforeAll } from "vitest"; +import { registerTemplatePlugin, Prompt } from "braintrust"; +import { nunjucksPlugin } from "./index"; + +// Register and activate the plugin for all tests +beforeAll(() => { + // registerTemplatePlugin will auto-activate using the plugin's + // `defaultOptions` when available. + registerTemplatePlugin(nunjucksPlugin); +}); + +describe("nunjucks rendering via Prompt", () => { + test("renders variable and control structures", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: + "Hello {{ name | upper }} {% if age > 18 %}Adult{% else %}Minor{% endif %}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { name: "alice", age: 30 }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("Hello ALICE Adult"); + }); + + test("loops render", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: `{% for item in items %}{{ item }},{% endfor %}`, + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { items: ["a", "b"] }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("a,b,"); + }); + + test("strict mode throws for missing top-level variable", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "Hello {{ name }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build({ user: "x" }, { templateFormat: "nunjucks", strict: true }), + ).toThrow(); + }); + + test("strict mode passes for defined variable and filters", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "Hello {{ name | upper }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build( + { name: "alice" }, + { templateFormat: "nunjucks", strict: true }, + ), + ).not.toThrow(); + }); + + test("strict mode: for over undefined is empty (does not throw)", () => { + const prompt1 = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: `{% for item in items %}{{ item }}{% endfor %}`, + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt1.build( + { items: [1, 2, 3] }, + { templateFormat: "nunjucks", strict: true }, + ), + ).not.toThrow(); + + expect(() => + prompt1.build({}, { templateFormat: "nunjucks", strict: true }), + ).not.toThrow(); + }); + + test("strict mode: nested path with numeric index using brackets", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: `{{ user.addresses[2].city }}`, + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const ok = { user: { addresses: [{}, {}, { city: "SF" }] } }; + expect(() => + prompt.build(ok, { templateFormat: "nunjucks", strict: true }), + ).not.toThrow(); + + const bad = { user: {} }; + expect(() => + prompt.build(bad, { templateFormat: "nunjucks", strict: true }), + ).toThrow(); + }); + + test("renders nested object properties", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ user.profile.name }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { user: { profile: { name: "Alice" } } }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("Alice"); + }); + + test("renders multiple variables with context", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: + "{{ firstName }} {{ lastName }} is {{ age }} years old", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { firstName: "Bob", lastName: "Smith", age: 25 }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("Bob Smith is 25 years old"); + }); + + test("renders with string concatenation", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ greeting ~ ' ' ~ name }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { greeting: "Hello", name: "World" }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("Hello World"); + }); + + test("renders numeric operations", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "Total: {{ price * quantity }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { price: 10, quantity: 3 }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("Total: 30"); + }); + + test("renders with filters and context", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ message | upper | trim }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { message: " hello world " }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("HELLO WORLD"); + }); + + test("renders array elements with index", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "First: {{ items[0] }}, Last: {{ items[2] }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { items: ["apple", "banana", "cherry"] }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("First: apple, Last: cherry"); + }); + + test("renders nested arrays and objects", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ users[0].name }} from {{ users[0].city }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { + users: [ + { name: "John", city: "NYC" }, + { name: "Jane", city: "LA" }, + ], + }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("John from NYC"); + }); + + test("renders with default filter", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ name | default('Guest') }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result1 = prompt.build( + { name: "Alice" }, + { templateFormat: "nunjucks" }, + ); + expect(result1.messages[0]?.content).toBe("Alice"); + + const result2 = prompt.build({}, { templateFormat: "nunjucks" }); + expect(result2.messages[0]?.content).toBe("Guest"); + }); + + test("renders ternary expressions", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ user.name if user else 'Anonymous' }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result1 = prompt.build( + { user: { name: "Alice" } }, + { templateFormat: "nunjucks" }, + ); + expect(result1.messages[0]?.content).toBe("Alice"); + + const result2 = prompt.build({}, { templateFormat: "nunjucks" }); + expect(result2.messages[0]?.content).toBe("Anonymous"); + }); + + test("renders with multiple filters chained", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ text | lower | trim }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { text: " HELLO WORLD " }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("hello world"); + }); + + test("renders complex nested context", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: + "{{ order.customer.name }} ordered {{ order.items[0].name }} for ${{ order.total }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { + order: { + customer: { name: "Alice" }, + items: [{ name: "Widget", price: 10 }], + total: 10, + }, + }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("Alice ordered Widget for $10"); + }); + + test("renders with length filter on arrays", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "You have {{ items | length }} items", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { items: ["a", "b", "c", "d"] }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("You have 4 items"); + }); + + test("renders with join filter", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ tags | join(', ') }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + const result = prompt.build( + { tags: ["red", "green", "blue"] }, + { templateFormat: "nunjucks" }, + ); + expect(result.messages[0]?.content).toBe("red, green, blue"); + }); +}); + +describe("nunjucks linting", () => { + test("lint throws for missing variable", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "Hello {{ user.name }}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build({}, { templateFormat: "nunjucks", strict: true }), + ).toThrow(); + }); + + test("lint passes for valid template with loops", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: `{% for item in items %}{{ item }}{% endfor %}`, + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build({}, { templateFormat: "nunjucks", strict: true }), + ).not.toThrow(); + }); + + test("lint passes for valid template with conditionals", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: `{% if user %}{{ user.name }}{% endif %}`, + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build({}, { templateFormat: "nunjucks", strict: true }), + ).not.toThrow(); + }); + + test("lint throws for invalid template syntax", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{{ unclosed", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build({}, { templateFormat: "nunjucks", strict: true }), + ).toThrow(); + }); + + test("lint throws for mismatched tags", () => { + const prompt = new Prompt( + { + name: "test-prompt", + slug: "test-prompt", + prompt_data: { + prompt: { + type: "chat", + messages: [ + { + role: "user", + content: "{% if x %}{% endfor %}", + }, + ], + }, + options: { model: "gpt-4" }, + }, + }, + {}, + false, + ); + + expect(() => + prompt.build({}, { templateFormat: "nunjucks", strict: true }), + ).toThrow(); + }); +}); diff --git a/integrations/templates-nunjucks/src/index.ts b/integrations/templates-nunjucks/src/index.ts new file mode 100644 index 000000000..e88e1cb1e --- /dev/null +++ b/integrations/templates-nunjucks/src/index.ts @@ -0,0 +1,142 @@ +import * as nunjucks from "nunjucks"; + +import type { TemplateRendererPlugin } from "braintrust"; + +/** + * Configuration options for the Nunjucks template renderer. + * + * @example + * ```typescript + * import { registerTemplatePlugin } from "braintrust"; + * import { nunjucksPlugin, type NunjucksOptions } from "@braintrust/templates-nunjucks-js"; + * + * // Configure options before registering + * nunjucksPlugin.defaultOptions = { + * autoescape: true, + * throwOnUndefined: false + * } as NunjucksOptions; + * + * registerTemplatePlugin(nunjucksPlugin); + * ``` + */ +export interface NunjucksOptions { + /** + * Controls whether HTML escaping is enabled for template variables. + * + * When `true` (default), variables are automatically HTML-escaped to prevent XSS attacks. + * When `false`, variables are rendered as-is without escaping. + * + * @default true + * @example + * ```typescript + * // With autoescape enabled (default) + * nunjucksPlugin.defaultOptions = { autoescape: true }; + * // Template: "{{ html }}" + * // Variables: { html: "
Test
" } + * // Output: "<div>Test</div>" + * + * // With autoescape disabled + * nunjucksPlugin.defaultOptions = { autoescape: false }; + * // Output: "
Test
" + * ``` + */ + autoescape?: boolean; + + /** + * Controls whether undefined variables throw errors. + * + * When `true`, accessing undefined variables throws an error, making it easier to catch typos. + * When `false` (default), undefined variables render as empty strings. + * + * Note: When using `prompt.build()` with `strict: true`, this is always enabled for linting. + * + * @default false + * @example + * ```typescript + * // Lenient mode (default) - typos render as empty + * nunjucksPlugin.defaultOptions = { throwOnUndefined: false }; + * // Template: "Hello {{ userName }}" + * // Variables: { userName: "Alice" } + * // Output: "Hello Alice" + * + * // Strict mode - typos throw errors + * nunjucksPlugin.defaultOptions = { throwOnUndefined: true }; + * // Output: Error: Variable 'userName' is undefined + * ``` + */ + throwOnUndefined?: boolean; +} + +/** + * Nunjucks template renderer plugin for Braintrust. + * + * Provides support for Nunjucks/Jinja2-style templating in Braintrust prompts, + * including loops, conditionals, filters, and more. + * + * @example + * ```typescript + * import { registerTemplatePlugin, Prompt } from "braintrust"; + * import { nunjucksPlugin } from "@braintrust/templates-nunjucks-js"; + * + * // Register the plugin + * registerTemplatePlugin(nunjucksPlugin); + * + * // Use in prompts + * const prompt = new Prompt({ + * name: "example", + * slug: "example", + * prompt_data: { + * prompt: { + * type: "chat", + * messages: [{ + * role: "user", + * content: "{% for item in items %}{{ item }}{% if not loop.last %}, {% endif %}{% endfor %}" + * }] + * }, + * options: { model: "gpt-4" } + * } + * }, {}, false); + * + * const result = prompt.build( + * { items: ["apple", "banana", "cherry"] }, + * { templateFormat: "nunjucks" } + * ); + * // Output: "apple, banana, cherry" + * ``` + */ +export const nunjucksPlugin: TemplateRendererPlugin = { + name: "nunjucks", + defaultOptions: { + autoescape: true, + throwOnUndefined: false, + } as NunjucksOptions, + createRenderer() { + const opts = (this.defaultOptions ?? {}) as NunjucksOptions; + const autoescape = opts.autoescape ?? true; + const throwOnUndefined = opts.throwOnUndefined ?? false; + + const env = new nunjucks.Environment(null, { + autoescape, + throwOnUndefined, + }); + + const strictEnv = new nunjucks.Environment(null, { + autoescape: true, + throwOnUndefined: true, + }); + + return { + render( + template: string, + variables: Record, + _escape: (v: unknown) => string, + strict: boolean, + ) { + return (strict ? strictEnv : env).renderString(template, variables); + }, + lint(template: string, variables: Record) { + strictEnv.renderString(template, variables); + }, + }; + }, +}; diff --git a/integrations/templates-nunjucks/tsconfig.json b/integrations/templates-nunjucks/tsconfig.json new file mode 100644 index 000000000..47119abe2 --- /dev/null +++ b/integrations/templates-nunjucks/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "declaration": true, + "lib": ["es2022"], + "module": "esnext", + "target": "es2022", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/integrations/templates-nunjucks/tsup.config.ts b/integrations/templates-nunjucks/tsup.config.ts new file mode 100644 index 000000000..41099bc7a --- /dev/null +++ b/integrations/templates-nunjucks/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["cjs", "esm"], + outDir: "dist", + dts: true, + splitting: true, + clean: true, +}); diff --git a/integrations/templates-nunjucks/vitest.config.ts b/integrations/templates-nunjucks/vitest.config.ts new file mode 100644 index 000000000..73a26a648 --- /dev/null +++ b/integrations/templates-nunjucks/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, +}); diff --git a/integrations/temporal-js/vitest.config.ts b/integrations/temporal-js/vitest.config.ts index 77a73cf2e..73a26a648 100644 --- a/integrations/temporal-js/vitest.config.ts +++ b/integrations/temporal-js/vitest.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ - test: {}, + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, }); diff --git a/integrations/vercel-ai-sdk/vitest.config.ts b/integrations/vercel-ai-sdk/vitest.config.ts index e69de29bb..73a26a648 100644 --- a/integrations/vercel-ai-sdk/vitest.config.ts +++ b/integrations/vercel-ai-sdk/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["tests/**/*.test.ts", "src/**/*.test.ts"], + }, +}); diff --git a/js/Makefile b/js/Makefile index 125beef2b..42ee5a23e 100644 --- a/js/Makefile +++ b/js/Makefile @@ -163,23 +163,10 @@ clean: SMOKE_DIR := smoke -# Run smoke tests (always prepares - relies on turbo/tsup caching for build efficiency) +# Run smoke tests - delegates to smoke/Makefile which handles auto-discovery and tarball creation # Usage: make test-smoke [TEST_NAME...] test-smoke: - @TESTS="$(filter-out test-smoke,$(MAKECMDGOALS))"; \ - SMOKE_ABS="$$(pwd)/$(SMOKE_DIR)"; \ - cd $(SMOKE_DIR) && ./prepare-tests.sh $$TESTS; \ - EXIT_CODE=0; \ - cd $$SMOKE_ABS && ./run-tests.sh $$TESTS || EXIT_CODE=$$?; \ - echo ""; \ - echo "Restoring package files..."; \ - cd $$SMOKE_ABS && \ - for dir in tests/*/; do \ - if [ -f "$$dir/package.json" ] && grep -q '"restore"' "$$dir/package.json" 2>/dev/null; then \ - (cd "$$dir" && npm run restore >/dev/null 2>&1 && echo " ✓ Restored $$(basename $$dir)") || true; \ - fi; \ - done; \ - exit $$EXIT_CODE + @cd $(SMOKE_DIR) && $(MAKE) test $(filter-out test-smoke,$(MAKECMDGOALS)) # Allow passing test names as make targets (they become no-ops) cloudflare-worker deno nextjs-instrumentation otel-v1 span span-jest: diff --git a/js/README.md b/js/README.md index 1b09f9b4b..e09fc1f9e 100644 --- a/js/README.md +++ b/js/README.md @@ -42,3 +42,22 @@ async function main() { main().catch(console.error); ``` + +### Browser Support + +**For browser-only applications, use the dedicated browser package:** + +```bash +npm install @braintrust/browser +``` + +The `@braintrust/browser` package is optimized for browser environments and includes the `als-browser` polyfill for AsyncLocalStorage support. It's a standalone package with no peer dependencies. + +**When to use each package:** + +- **`braintrust`** (this package) - For Node.js applications, full-stack frameworks (Next.js, etc.), and edge runtimes with native AsyncLocalStorage (Cloudflare Workers, Vercel Edge) +- **`@braintrust/browser`** - For browser-only applications that need AsyncLocalStorage support in standard browsers + +See the [@braintrust/browser README](../integrations/browser-js/README.md) for more details. + +**Breaking change in v3.0.0:** The `braintrust/browser` subpath export has been deprecated. Browser users should migrate to the `@braintrust/browser` package. diff --git a/js/deno.json b/js/deno.json new file mode 100644 index 000000000..353175f94 --- /dev/null +++ b/js/deno.json @@ -0,0 +1,6 @@ +{ + "name": "braintrust", + "exports": { + ".": "./dist/index.mjs" + } +} diff --git a/js/package.json b/js/package.json index b211d7cfb..b9d5c9f9a 100644 --- a/js/package.json +++ b/js/package.json @@ -1,7 +1,7 @@ { "name": "braintrust", - "version": "2.1.0", - "description": "SDK for integrating Braintrust", + "version": "3.0.0", + "description": "SDK for integrating Braintrust.", "repository": { "type": "git", "url": "git+https://github.com/braintrustdata/braintrust-sdk.git", @@ -33,12 +33,12 @@ "browser": "./dist/browser.mjs", "import": "./dist/index.mjs", "require": "./dist/index.js", - "default": "./dist/browser.mjs" + "default": "./dist/index.mjs" }, "./browser": { "import": "./dist/browser.mjs", - "module": "./dist/browser.mjs", - "require": "./dist/browser.js" + "require": "./dist/browser.js", + "default": "./dist/browser.mjs" }, "./node": { "types": "./dist/index.d.ts", @@ -132,7 +132,6 @@ "dependencies": { "@ai-sdk/provider": "^1.1.3", "@next/env": "^14.2.3", - "@types/nunjucks": "^3.2.6", "@vercel/functions": "^1.0.2", "argparse": "^2.0.1", "boxen": "^8.0.1", @@ -148,7 +147,6 @@ "http-errors": "^2.0.0", "minimatch": "^9.0.3", "mustache": "^4.2.0", - "nunjucks": "^3.2.4", "pluralize": "^8.0.0", "simple-git": "^3.21.0", "source-map": "^0.7.4", diff --git a/js/smoke/Makefile b/js/smoke/Makefile index effaa15e5..bcd11e472 100644 --- a/js/smoke/Makefile +++ b/js/smoke/Makefile @@ -1,36 +1,52 @@ -# Auto-discover scenarios (any folder in scenarios/ with a Makefile) -SCENARIOS := $(shell find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | sort) +## Discover integration scenarios under ../../integrations +SCRIPTDIR := ../../integrations +LOCAL_MAKEFILES := $(shell find scenarios -type f -path 'scenarios/*/Makefile' -not -path '*/node_modules/*' 2>/dev/null) +INTEGRATION_MAKEFILES := $(shell find $(SCRIPTDIR) -type f -path '*/smoke/scenarios/*/Makefile' -not -path '*/node_modules/*' 2>/dev/null) +SCENARIO_MAKEFILES := $(LOCAL_MAKEFILES) $(INTEGRATION_MAKEFILES) +LOCAL_SCENARIOS := $(patsubst scenarios/%/Makefile,%,$(LOCAL_MAKEFILES)) +INTEGRATION_SCENARIOS := $(shell echo "$(INTEGRATION_MAKEFILES)" | tr ' ' '\n' | sed 's|$(SCRIPTDIR)/||' | sed 's|/smoke/scenarios/|/|' | sed 's|/Makefile$$||' | tr '\n' ' ') +SCENARIOS := $(LOCAL_SCENARIOS) $(INTEGRATION_SCENARIOS) -.PHONY: help setup test list clean +.PHONY: help setup test list clean discover -# ============================================================================= -# Help -# ============================================================================= +# Declare all scenarios as phony targets with empty recipes +# This prevents "No rule to make target" errors when running: make test scenario-name +.PHONY: $(LOCAL_SCENARIOS) $(INTEGRATION_SCENARIOS) +$(LOCAL_SCENARIOS) $(INTEGRATION_SCENARIOS): + @: # Empty recipe - actual test logic is in the test target + +## ============================================================================ +## Help +## ============================================================================ help: @echo "Smoke Test Infrastructure" @echo "" @echo "Available targets:" - @echo " make test - Run all scenarios (builds SDK once if needed)" - @echo " make test - Run specific scenario (e.g., make test otel-v1)" - @echo " make setup - Ensure SDK artifacts + shared package are ready" - @echo " make clean - Remove all build artifacts (force rebuild)" - @echo " make list - List discovered scenarios" + @echo " make test - Run all discovered integration scenarios" + @echo " make test - Run specific scenario (e.g., make test templates-nunjucks/basic-render)" + @echo " make setup - Ensure SDK artifacts + shared package are ready" + @echo " make clean - Remove all build artifacts (force rebuild)" + @echo " make list - List discovered scenarios" @echo "" @echo "Environment variables:" @echo " BRAINTRUST_TAR - Path to braintrust tarball (auto-set by parent when running locally)" + @echo " BRAINTRUST_BROWSER_TAR - Path to browser tarball (auto-set by parent when running locally)" @echo " BRAINTRUST_OTEL_TAR - Path to otel tarball (auto-set by parent when running locally)" @echo " SMOKE_V2_SHARED_DIST - Path to shared package dist (auto-set by parent when running locally)" @echo "" - @echo "Running individual scenarios:" - @echo " cd scenarios/otel-v1 && make test - Runs standalone, builds if needed" - @echo "" - @echo "Discovered scenarios:" - @for scenario in $(SCENARIOS); do echo " - $$scenario"; done + @echo "Discovered local scenarios:"; \ + for s in $(LOCAL_SCENARIOS); do \ + if [ -n "$$s" ]; then echo " - $$s"; fi; \ + done; \ + echo "Discovered integration scenarios:"; \ + for s in $(INTEGRATION_SCENARIOS); do \ + if [ -n "$$s" ]; then echo " - $$s"; fi; \ + done -# ============================================================================= -# Setup - Build SDK + shared package -# ============================================================================= +## ============================================================================ +## Setup - Build SDK + shared package +## ============================================================================ setup: @echo "==> Setting up smoke" @@ -42,16 +58,28 @@ setup: else \ echo "==> Building SDK and creating tarball"; \ cd ../../.. && pnpm exec turbo build --filter=braintrust && pnpm --filter=braintrust pack --pack-destination sdk/js/artifacts; \ - \ for f in sdk/js/artifacts/braintrust-*.tgz; do \ - if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && \ - [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ]; then \ + if [ "$$(basename $$f)" != "braintrust-latest.tgz" ] && [ "$$(basename $$f)" != "braintrust-otel-latest.tgz" ] && [ "$$(basename $$f)" != "braintrust-browser-latest.tgz" ]; then \ cp "$$f" sdk/js/artifacts/braintrust-latest.tgz; \ break; \ fi; \ done; \ fi + @# Build browser package and create tarball if not provided + @if [ -n "$(BRAINTRUST_BROWSER_TAR)" ] && [ -f "$(BRAINTRUST_BROWSER_TAR)" ]; then \ + echo "==> Using provided BRAINTRUST_BROWSER_TAR: $(BRAINTRUST_BROWSER_TAR)"; \ + else \ + echo "==> Building browser package and creating tarball"; \ + cd ../../.. && pnpm exec turbo build --filter=@braintrust/browser && pnpm --filter=@braintrust/browser pack --pack-destination sdk/js/artifacts; \ + for f in sdk/js/artifacts/braintrust-browser-*.tgz; do \ + if [ "$$(basename $$f)" != "braintrust-browser-latest.tgz" ]; then \ + cp "$$f" sdk/js/artifacts/braintrust-browser-latest.tgz; \ + break; \ + fi; \ + done; \ + fi + @# Build shared package if not provided @if [ -n "$(SMOKE_V2_SHARED_DIST)" ] && [ -d "$(SMOKE_V2_SHARED_DIST)" ]; then \ echo "==> Using provided SMOKE_V2_SHARED_DIST: $(SMOKE_V2_SHARED_DIST)"; \ @@ -64,52 +92,72 @@ setup: fi; \ fi -# ============================================================================= -# Clean - Remove all build artifacts -# ============================================================================= +## ============================================================================ +## Clean - Remove all build artifacts +## ============================================================================ clean: @echo "==> Cleaning smoke artifacts" rm -rf ../artifacts/*.tgz rm -rf shared/dist shared/node_modules -# ============================================================================= -# Test - Run scenarios -# ============================================================================= +## ============================================================================ +## Test - Run scenarios +## ============================================================================ + +# Support positional scenario argument: make test integration/name + test: - @REQUESTED="$(filter-out test,$(MAKECMDGOALS))"; \ - \ + @# Collect requested scenario names (strip any trailing /Makefile if provided by user) + @REQUESTED_RAW="$(filter-out test,$(MAKECMDGOALS))"; \ + REQUESTED="$$(echo $$REQUESTED_RAW | tr ' ' '\n' | sed 's|/Makefile$$||' | tr '\n' ' ' | xargs)"; \ if [ -z "$$REQUESTED" ]; then \ SCENARIOS_TO_RUN="$(SCENARIOS)"; \ - echo "==> Running all scenarios"; \ + echo "==> Running all discovered scenarios"; \ else \ SCENARIOS_TO_RUN=""; \ for scenario in $$REQUESTED; do \ - if [ ! -d "scenarios/$$scenario" ]; then \ - echo "Error: Scenario '$$scenario' not found"; \ + if echo "$$scenario" | grep -q '/'; then \ + integration=$$(echo $$scenario | cut -d/ -f1); \ + name=$$(echo $$scenario | cut -d/ -f2-); \ + dir="$(SCRIPTDIR)/$$integration/smoke/scenarios/$$name"; \ + else \ + dir="scenarios/$$scenario"; \ + fi; \ + if [ ! -d "$$dir" ]; then \ + echo "Error: Scenario '$$scenario' not found at $$dir"; \ echo "Available scenarios:"; \ - for s in $(SCENARIOS); do echo " - $$s"; done; \ + for s in $(LOCAL_SCENARIOS) $(INTEGRATION_SCENARIOS); do \ + echo " - $$s"; \ + done; \ exit 1; \ fi; \ - SCENARIOS_TO_RUN="$$SCENARIOS_TO_RUN $$scenario"; \ + SCENARIOS_TO_RUN="$$SCENARIOS_TO_RUN $$dir"; \ done; \ - echo "==> Running scenarios:$$SCENARIOS_TO_RUN"; \ + echo "==> Running scenarios: $$REQUESTED"; \ fi; \ \ $(MAKE) setup; \ \ : $${BRAINTRUST_TAR:=../artifacts/braintrust-latest.tgz}; \ + : $${BRAINTRUST_BROWSER_TAR:=../artifacts/braintrust-browser-latest.tgz}; \ : $${BRAINTRUST_OTEL_TAR:=../artifacts/braintrust-otel-latest.tgz}; \ : $${SMOKE_V2_SHARED_DIST:=shared/dist}; \ - export BRAINTRUST_TAR BRAINTRUST_OTEL_TAR SMOKE_V2_SHARED_DIST; \ + export BRAINTRUST_TAR BRAINTRUST_BROWSER_TAR BRAINTRUST_OTEL_TAR SMOKE_V2_SHARED_DIST; \ \ FAILED_SCENARIOS=""; \ for scenario in $$SCENARIOS_TO_RUN; do \ echo ""; \ echo "=== Testing $$scenario ==="; \ - if ! $(MAKE) -C scenarios/$$scenario test; then \ - FAILED_SCENARIOS="$$FAILED_SCENARIOS $$scenario"; \ + if [ -f "$$scenario/Makefile" ]; then \ + if ! $(MAKE) -C $$scenario test; then \ + FAILED_SCENARIOS="$$FAILED_SCENARIOS $$(echo $$scenario | sed 's|$(SCRIPTDIR)/||' | sed 's|/scenarios/|/|')"; \ + fi; \ + elif [ -f "$$scenario/test.js" ]; then \ + ( cd $$scenario && node test.js ) || FAILED_SCENARIOS="$$FAILED_SCENARIOS $$(echo $$scenario | sed 's|$(SCRIPTDIR)/||' | sed 's|/scenarios/|/|')"; \ + else \ + FAILED_SCENARIOS="$$FAILED_SCENARIOS $$(echo $$scenario | sed 's|$(SCRIPTDIR)/||' | sed 's|/scenarios/|/|')"; \ fi; \ done; \ \ @@ -121,17 +169,11 @@ test: echo "✓ All requested scenarios passed"; \ fi -# ============================================================================= -# List - Show discovered scenarios -# ============================================================================= +## ============================================================================ +## List - Show discovered scenarios +## ============================================================================ list: - @echo "Discovered scenarios:" - @for scenario in $(SCENARIOS); do echo " - $$scenario"; done - -# ============================================================================= -# Make scenario names valid targets (no-ops to support "make test otel-v1") -# ============================================================================= - -$(SCENARIOS): - @: + @echo "Discovered scenarios:"; \ + for s in $(SCENARIOS); do echo " - $$s"; done + @echo '' diff --git a/js/smoke/README.md b/js/smoke/README.md index f0b52cec5..89b725452 100644 --- a/js/smoke/README.md +++ b/js/smoke/README.md @@ -5,9 +5,18 @@ Smoke test infrastructure verifying SDK installation across different runtimes a ## Quick Reference ```bash -make test # Run all scenarios (doesn't exit early on failures) -make test otel-v1 # Run specific scenario -make list # List available scenarios +# From sdk/js/: +make test-smoke # Run all scenarios + +# From sdk/js/smoke/: +make test # Run all scenarios (local + integration) +make test deno-node # Run specific local scenario +make test templates-nunjucks/jest # Run integration scenario +make list # List all discovered scenarios + +# From a specific scenario: +cd scenarios/deno-node +make test # Auto-creates tarball if needed ``` ## Output Standardization (REQUIRED) @@ -182,6 +191,72 @@ test: setup This ensures all tests run and display their results, but the suite still fails if any test failed. +## Environment Variables & Tarball Creation + +### Automatic Tarball Creation + +Scenarios automatically create tarballs if they're not provided via environment variables. This happens during the `setup` target: + +1. **Check for existing tarball**: If `BRAINTRUST_TAR` env var is set and points to a valid file, use it +2. **Build from source**: Otherwise, build SDK and create tarball: + + ```bash + cd ../../.. && pnpm exec turbo build --filter=braintrust && \ + mkdir-p artifacts && pnpm pack --pack-destination artifacts + ``` + +3. **Rename to well-known path**: Copy to `braintrust-latest.tgz` for consistent references + +### Environment Variables + +- **`BRAINTRUST_TAR`**: Path to braintrust tarball (auto-created if not set) + + - Example: `../artifacts/braintrust-latest.tgz` + +- **`BRAINTRUST_OTEL_TAR`**: Path to @braintrust/otel tarball (auto-created for scenarios that need it) + + - Example: `../artifacts/braintrust-otel-latest.tgz` + +- **`BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR`**: Path to @braintrust/templates-nunjucks-js tarball + + - Example: `../artifacts/braintrust-templates-nunjucks-js-latest.tgz` + +- **`SMOKE_V2_SHARED_DIST`**: Path to shared test utilities (auto-built if not set) + - Example: `shared/dist` + +### Local vs CI Execution + +**Locally:** + +- Tarballs auto-created on first run +- Cached for subsequent runs (fast) +- Run from any level: `sdk/js/`, `sdk/js/smoke/`, or scenario directory + +**In CI** (`.github/workflows/js.yaml`): + +1. **Build job**: Creates all tarballs (braintrust, otel, templates-nunjucks), uploads as artifacts +2. **Smoke-discover job**: Auto-discovers all scenarios (local + integration) +3. **Smoke-test job**: Downloads tarballs, runs all scenarios in parallel with `fail-fast: false` + +## Integration Scenarios + +Integration scenarios test SDK integrations and are located under `../../integrations/*/scenarios/`: + +### Templates-Nunjucks + +- **templates-nunjucks/basic-render**: Basic Nunjucks template rendering +- **templates-nunjucks/deno**: Deno runtime with Nunjucks +- **templates-nunjucks/jest**: Jest test runner with Nunjucks +- **templates-nunjucks/nextjs**: Next.js integration with Nunjucks + +### OpenTelemetry (OTel) + +- **otel-js/otel-v1**: OpenTelemetry smoke test scenario (using shared test suite) + +Note: The `otel-js/otel-v1` and `otel-js/otel-v2` directories at the root of `integrations/otel-js/` are integration test environments (not smoke tests) and use a different test runner (vitest). + +All integration scenarios are automatically discovered and run alongside local scenarios. + ## Design Principles ### Well-Known Tarball Paths diff --git a/js/smoke/scenarios/browser-main-package/.gitignore b/js/smoke/scenarios/browser-main-package/.gitignore new file mode 100644 index 000000000..2bbe28c25 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +package-lock.json +test-results/ +playwright-report/ diff --git a/js/smoke/scenarios/browser-main-package/Makefile b/js/smoke/scenarios/browser-main-package/Makefile new file mode 100644 index 000000000..704f7aa07 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/Makefile @@ -0,0 +1,14 @@ +.PHONY: install build test clean + +install: + npm install + npx playwright install --with-deps chromium + +build: install + node esbuild.config.mjs + +test: build + npx playwright test + +clean: + rm -rf node_modules dist package-lock.json diff --git a/js/smoke/scenarios/browser-main-package/README.md b/js/smoke/scenarios/browser-main-package/README.md new file mode 100644 index 000000000..581f3fbe7 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/README.md @@ -0,0 +1,64 @@ +# Browser Main Package Smoke Test + +This smoke test verifies that the informational message appears when using the browser build from the main `braintrust` package. + +## What This Tests + +When a user imports from the main `braintrust` package in a browser environment: + +```typescript +import * as braintrust from "braintrust"; +``` + +The bundler (via the `"browser"` field in package.json) will resolve to the browser build (`dist/browser.mjs`), which should: + +1. Show an informational console message suggesting `@braintrust/browser` for optimal use +2. Provide working browser-safe implementations +3. Not include Node.js modules + +## Test Structure + +- **src/browser-message-test.ts** - Browser test script that imports from main package +- **pages/browser-message-test.html** - HTML page to run the test +- **tests/browser-message.test.ts** - Playwright test that verifies the message + +## Running the Test + +```bash +make test +``` + +Or step by step: + +```bash +# Install dependencies +make install + +# Build the test bundle +make build + +# Run Playwright tests +npx playwright test +``` + +## What Gets Verified + +✓ Import from main package works in browser +✓ Basic functions are available (init, newId, traceable) +✓ Informational message appears in console +✓ Message mentions "@braintrust/browser" package +✓ No Node.js module errors + +## Expected Console Output + +When the test runs, you should see: + +``` +Braintrust SDK Browser Build +You are using a browser-compatible build from the main package. +For optimal browser support consider: + npm install @braintrust/browser + import * as braintrust from "@braintrust/browser" +``` + +This message guides users toward the optimized `@braintrust/browser` package while ensuring the main package works correctly in browsers. diff --git a/js/smoke/scenarios/browser-main-package/esbuild.config.mjs b/js/smoke/scenarios/browser-main-package/esbuild.config.mjs new file mode 100644 index 000000000..681330c31 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/esbuild.config.mjs @@ -0,0 +1,18 @@ +import esbuild from "esbuild"; +import { rmSync } from "node:fs"; + +rmSync("dist", { recursive: true, force: true }); + +await esbuild.build({ + entryPoints: ["src/browser-message-test.ts"], + bundle: true, + format: "esm", + outdir: "dist", + platform: "browser", + target: "es2022", + sourcemap: true, + mainFields: ["browser", "module", "main"], + external: [], +}); + +console.log("Build complete!"); diff --git a/js/smoke/scenarios/browser-main-package/mise.toml b/js/smoke/scenarios/browser-main-package/mise.toml new file mode 100644 index 000000000..6a0493c69 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/mise.toml @@ -0,0 +1,2 @@ +[tools] +node = "22" diff --git a/js/smoke/scenarios/browser-main-package/package.json b/js/smoke/scenarios/browser-main-package/package.json new file mode 100644 index 000000000..bd3bc537a --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/package.json @@ -0,0 +1,18 @@ +{ + "name": "smoke-browser-main-package", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Smoke test for main package browser build with informational message", + "dependencies": { + "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "zod": "^4.3.5" + }, + "devDependencies": { + "@playwright/test": "^1.51.1", + "@types/node": "^20.10.5", + "esbuild": "^0.27.2", + "http-server": "^14.1.1", + "typescript": "^5.4.4" + } +} diff --git a/js/smoke/scenarios/browser-main-package/pages/browser-message-test.html b/js/smoke/scenarios/browser-main-package/pages/browser-message-test.html new file mode 100644 index 000000000..3f23e1f2e --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/pages/browser-message-test.html @@ -0,0 +1,17 @@ + + + + + + Braintrust Main Package Browser Build Test + + +

Braintrust Main Package Browser Build Test

+

+ This test verifies the informational message appears when using the + browser build from the main package. +

+
+ + + diff --git a/js/smoke/scenarios/browser-main-package/playwright.config.ts b/js/smoke/scenarios/browser-main-package/playwright.config.ts new file mode 100644 index 000000000..3cce5c28d --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/playwright.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from "@playwright/test"; + +export default defineConfig({ + testDir: "./tests", + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: 1, + reporter: "list", + use: { + baseURL: "http://localhost:8765", + trace: "on-first-retry", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], + webServer: { + command: "npx http-server -p 8765", + port: 8765, + reuseExistingServer: !process.env.CI, + timeout: 10000, + }, +}); diff --git a/js/smoke/scenarios/browser-main-package/src/browser-message-test.ts b/js/smoke/scenarios/browser-main-package/src/browser-message-test.ts new file mode 100644 index 000000000..dd728e468 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/src/browser-message-test.ts @@ -0,0 +1,58 @@ +declare global { + interface Window { + __btBrowserMessageTest?: { + completed: boolean; + consoleMessages: string[]; + importSuccessful: boolean; + hasInit: boolean; + hasNewId: boolean; + hasTraceable: boolean; + }; + } +} + +// Capture console.info messages BEFORE importing braintrust +const capturedMessages: string[] = []; +const originalConsoleInfo = console.info; +console.info = (...args: any[]) => { + const message = args.join(" "); + capturedMessages.push(message); + originalConsoleInfo.apply(console, args); +}; + +// Import from main package browser export AFTER setting up console capture +// This must be done dynamically to ensure console.info is overridden first +const braintrust = await import("braintrust/browser"); + +// Test that imports work +const importSuccessful = true; +const hasInit = typeof braintrust.init === "function"; +const hasNewId = typeof braintrust.newId === "function"; +const hasTraceable = typeof braintrust.traceable === "function"; + +// Store results +window.__btBrowserMessageTest = { + completed: true, + consoleMessages: capturedMessages, + importSuccessful, + hasInit, + hasNewId, + hasTraceable, +}; + +// Display results +const output = document.getElementById("output"); +if (output) { + output.innerHTML = ` +

Test Results

+
    +
  • Import successful: ${importSuccessful ? "✓" : "✗"}
  • +
  • Has init function: ${hasInit ? "✓" : "✗"}
  • +
  • Has newId function: ${hasNewId ? "✓" : "✗"}
  • +
  • Has traceable function: ${hasTraceable ? "✓" : "✗"}
  • +
  • Console messages captured: ${capturedMessages.length}
  • +
+

Console Messages:

+
${capturedMessages.join("\n")}
+ `; +} diff --git a/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts b/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts new file mode 100644 index 000000000..d815136e3 --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts @@ -0,0 +1,88 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Braintrust Main Package Browser Build", () => { + test("should display informational message when using browser build", async ({ + page, + baseURL, + }) => { + const consoleMessages: string[] = []; + + // Capture console.info messages + page.on("console", (msg) => { + if (msg.type() === "info") { + consoleMessages.push(msg.text()); + } else if (msg.type() === "error") { + console.error(`[Browser Console Error] ${msg.text()}`); + } + }); + + page.on("pageerror", (error) => { + console.error("[Browser Page Error]", error.message); + }); + + // Load the test page + const response = await page.goto( + `${baseURL}/pages/browser-message-test.html`, + { + waitUntil: "domcontentloaded", + timeout: 10000, + }, + ); + + if (!response || !response.ok()) { + throw new Error(`Failed to load page: ${response?.status()}`); + } + + // Wait for test to complete + await page.waitForFunction( + () => { + return (window as any).__btBrowserMessageTest?.completed === true; + }, + { timeout: 10000 }, + ); + + // Get test results + const testResults = await page.evaluate( + () => (window as any).__btBrowserMessageTest, + ); + + // Log results for debugging + console.log("Test Results:", testResults); + console.log("Captured Console Messages:", consoleMessages); + + // Assertions + expect(testResults).toBeTruthy(); + expect(testResults.completed).toBe(true); + expect(testResults.importSuccessful).toBe(true); + expect(testResults.hasInit).toBe(true); + expect(testResults.hasNewId).toBe(true); + expect(testResults.hasTraceable).toBe(true); + + // Expected message from browser-config.ts + const expectedMessage = + "This entrypoint is no longer supported.\n\n" + + "You should be using entrypoints:\n\n" + + "- `/workerd` (cloudflare envs)\n" + + "- `/edge-light` (next-js or other edge envs)\n\n" + + "If you'd like to use braintrust in the browser use the dedicated package: @braintrust/browser\n"; + + // Verify the full informational message appears in console + const hasInformationalMessage = consoleMessages.some( + (msg) => msg === expectedMessage, + ); + + expect(hasInformationalMessage).toBe(true); + + // Also verify from captured messages in the page + const hasCapturedMessage = testResults.consoleMessages.some( + (msg: string) => msg === expectedMessage, + ); + + expect(hasCapturedMessage).toBe(true); + + console.log("✓ Complete informational message verified"); + console.log( + "✓ Main package browser build working correctly with full message", + ); + }); +}); diff --git a/js/smoke/scenarios/browser-main-package/tsconfig.json b/js/smoke/scenarios/browser-main-package/tsconfig.json new file mode 100644 index 000000000..d1677290d --- /dev/null +++ b/js/smoke/scenarios/browser-main-package/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022", "DOM"], + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*", "tests/**/*"] +} diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts index 90f59075c..bfe08e49b 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts @@ -78,8 +78,9 @@ app.get("/api/test", async (c) => { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Disallowed in this environment"), - "Cloudflare Workers blocks dynamic code generation (eval/Function)", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json index 272211cad..8b0168d16 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json @@ -4,6 +4,7 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "hono": "^4.11.1", "react": "^19.2.1", "react-dom": "^19.2.1", diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts index 29fbbbd41..887aa1d0d 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts @@ -28,7 +28,7 @@ import { testEvalSmoke, } from "../../../shared"; -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; const app = new Hono<{ Bindings: Env }>(); @@ -73,8 +73,9 @@ app.get("/api/test", async (c) => { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Nunjucks templating is not supported"), - "Nunjucks not supported in browser build", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json index c0edc8625..9a8899a7a 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json @@ -4,6 +4,7 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "hono": "^4.11.1", "zod": "^3.25.76" }, diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts index c440196ba..33b9cfe33 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts @@ -28,7 +28,7 @@ import { testEvalSmoke, } from "../../../shared"; -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; const app = new Hono<{ Bindings: Env }>(); @@ -73,8 +73,9 @@ app.get("/api/test", async (c) => { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Nunjucks templating is not supported"), - "Nunjucks not supported in browser build", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json b/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json index c39db0404..65ba9854f 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json @@ -4,6 +4,7 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "zod": "^3.25.76" }, "devDependencies": { diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts index a80533a28..28d7d810a 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; import { runTests, expectFailure, @@ -64,8 +64,9 @@ export default { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("String template rendering. Disallowed"), - "Nunjucks evals not supported", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json index 5e8ae393f..438b44a00 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json @@ -4,6 +4,7 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "zod": "^3.25.76" }, "devDependencies": { diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts index 56e8c1cc1..328496ebb 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; import { runTests, expectFailure, @@ -64,8 +64,9 @@ export default { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Nunjucks templating is not supported"), - "Nunjucks not supported in browser build", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts index 17c8e186e..6fd2f7f01 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts @@ -64,8 +64,9 @@ export default { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Disallowed in this environment"), - "Cloudflare Workers blocks dynamic code generation (eval/Function)", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts index 8090a2fce..86a08c0cf 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts @@ -1,6 +1,7 @@ import * as braintrust from "braintrust/node"; import { runTests, + expectFailure, testBasicSpanLogging, testMultipleSpans, testDirectLogging, @@ -61,7 +62,12 @@ export default { testCurrentSpan, testEvalSmoke, testMustacheTemplate, - testNunjucksTemplate, + expectFailure( + testNunjucksTemplate, + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", + ), ], }); diff --git a/js/smoke/scenarios/deno-browser/Makefile b/js/smoke/scenarios/deno-browser/Makefile index 09ad4910d..8c95c70db 100644 --- a/js/smoke/scenarios/deno-browser/Makefile +++ b/js/smoke/scenarios/deno-browser/Makefile @@ -15,4 +15,5 @@ setup: fi; \ test: setup - deno test --sloppy-imports --allow-all tests/*.test.ts + @# Run only tests under the local tests/ directory + mise exec -- deno test --sloppy-imports --allow-all tests/*.test.ts diff --git a/js/smoke/scenarios/deno-browser/deno.json b/js/smoke/scenarios/deno-browser/deno.json index ab612b4d0..db0573ac5 100644 --- a/js/smoke/scenarios/deno-browser/deno.json +++ b/js/smoke/scenarios/deno-browser/deno.json @@ -2,7 +2,7 @@ "imports": { "@std/assert": "jsr:@std/assert@^1.0.14", "@braintrust/smoke-test-shared": "jsr:@braintrust/smoke-test-shared", - "braintrust": "npm:braintrust/browser" + "@braintrust/browser": "npm:@braintrust/browser@^0.0.2-rc.0" }, "nodeModulesDir": "auto", "links": [ diff --git a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts index 2c37b4f98..eb3dd0884 100644 --- a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts @@ -32,7 +32,7 @@ import { testNunjucksTemplate, testEvalSmoke, } from "@braintrust/smoke-test-shared"; -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; Deno.test("Run shared test suites (browser build)", async () => { const { failed } = await runTests({ @@ -65,8 +65,8 @@ Deno.test("Run shared test suites (browser build)", async () => { expectFailure( testNunjucksTemplate, (e: { message: string }) => - e.message.includes("Nunjucks templating is not supported"), - "Nunjucks not supported in browser build", + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/deno-node/Makefile b/js/smoke/scenarios/deno-node/Makefile index 3a7c730a7..05babbc0f 100644 --- a/js/smoke/scenarios/deno-node/Makefile +++ b/js/smoke/scenarios/deno-node/Makefile @@ -15,4 +15,5 @@ setup: fi; \ test: setup - deno test --sloppy-imports --allow-all tests/*.test.ts + @# Run only tests under the local tests/ directory + mise exec -- deno test --sloppy-imports --allow-all tests/*.test.ts diff --git a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts index 543312576..3286585cb 100644 --- a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts @@ -6,6 +6,7 @@ import { assertEquals } from "@std/assert"; import { runTests, + expectFailure, testBasicSpanLogging, testMultipleSpans, testDirectLogging, @@ -61,7 +62,12 @@ Deno.test("Run shared test suites", async () => { testCurrentSpan, testEvalSmoke, testMustacheTemplate, - testNunjucksTemplate, + expectFailure( + testNunjucksTemplate, + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", + ), ], }); diff --git a/js/smoke/scenarios/jest-node/Makefile b/js/smoke/scenarios/jest-node/Makefile index 22f859f8c..ccdff2cf0 100644 --- a/js/smoke/scenarios/jest-node/Makefile +++ b/js/smoke/scenarios/jest-node/Makefile @@ -36,4 +36,5 @@ setup: test: setup @echo "==> Running jest-node tests" - npx jest + @# Run only tests under the local tests/ directory to avoid workspace-wide discovery + npx jest --passWithNoTests --roots ./tests diff --git a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js index 33c2d24a4..13aeffdf4 100644 --- a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js +++ b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js @@ -1,5 +1,6 @@ const { runTests, + expectFailure, testBasicSpanLogging, testMultipleSpans, testDirectLogging, @@ -23,6 +24,7 @@ const { testBuildResolution, testMustacheTemplate, testNunjucksTemplate, + testEvalSmoke, } = require("../../../shared/dist/index.js"); const braintrust = require("braintrust"); @@ -53,8 +55,13 @@ test("shared test suites pass in Jest", async () => { testAsyncLocalStorageTraced, testNestedTraced, testCurrentSpan, + testEvalSmoke, testMustacheTemplate, - testNunjucksTemplate, + expectFailure( + testNunjucksTemplate, + (e) => e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", + ), ], }); diff --git a/js/smoke/scenarios/nextjs-instrumentation/package.json b/js/smoke/scenarios/nextjs-instrumentation/package.json index e8faeef10..19528dbd4 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/package.json +++ b/js/smoke/scenarios/nextjs-instrumentation/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz", "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.200.0", diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts index c0bf8769c..79beb7dff 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts @@ -32,7 +32,7 @@ import { testEvalSmoke, } from "../../../../../../../shared"; -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; export const runtime = "edge"; @@ -68,8 +68,9 @@ export async function GET() { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Nunjucks templating is not supported"), - "Nunjucks not supported in Edge Runtime", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts index 1730617da..7c86e8440 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts @@ -5,6 +5,7 @@ import { NextResponse } from "next/server"; import { runTests, + expectFailure, testBasicSpanLogging, testMultipleSpans, testDirectLogging, @@ -65,7 +66,12 @@ export async function GET() { testCurrentSpan, testEvalSmoke, testMustacheTemplate, - testNunjucksTemplate, + expectFailure( + testNunjucksTemplate, + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", + ), ], }); diff --git a/js/smoke/scenarios/playwright-browser/package.json b/js/smoke/scenarios/playwright-browser/package.json index 49818a121..e703f5b2d 100644 --- a/js/smoke/scenarios/playwright-browser/package.json +++ b/js/smoke/scenarios/playwright-browser/package.json @@ -6,6 +6,7 @@ "description": "Playwright browser smoke test for Braintrust SDK", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", + "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "zod": "^4.3.5" }, "devDependencies": { diff --git a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts index e56a78d0a..f28a9ada7 100644 --- a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts +++ b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust"; +import * as braintrust from "@braintrust/browser"; import { runTests, expectFailure, @@ -84,8 +84,9 @@ async function runAllTestSuites() { testMustacheTemplate, expectFailure( testNunjucksTemplate, - (e) => e.message.includes("Nunjucks templating is not supported"), - "Nunjucks not supported in browser build", + (e: { message: string }) => + e.message.includes("requires @braintrust/template-nunjucks"), + "Nunjucks requires separate package", ), ], }); diff --git a/js/smoke/scenarios/playwright-browser/tests/browser.test.ts b/js/smoke/scenarios/playwright-browser/tests/browser.test.ts index fec302726..42dd1a9c5 100644 --- a/js/smoke/scenarios/playwright-browser/tests/browser.test.ts +++ b/js/smoke/scenarios/playwright-browser/tests/browser.test.ts @@ -110,11 +110,19 @@ test.describe("Braintrust SDK Browser Tests", () => { name: `All tests (${smoke.sections.tests.passed} passed)`, }); } else { + // Extract individual test failures for better error reporting + const failureDetails = smoke.sections.tests.failures + .map( + (f) => + ` • ${f.testName}: ${f.error}${f.message ? ` (${f.message})` : ""}`, + ) + .join("\n"); + results.push({ status: "fail", name: "All tests", error: { - message: `Completed: ${smoke.sections.tests.completed}, Passed: ${smoke.sections.tests.passed}, Failed: ${smoke.sections.tests.failed}`, + message: `Completed: ${smoke.sections.tests.completed}, Passed: ${smoke.sections.tests.passed}, Failed: ${smoke.sections.tests.failed}\n\nFailed tests:\n${failureDetails}`, }, }); } diff --git a/js/smoke/shared/package-lock.json b/js/smoke/shared/package-lock.json index f67d631b2..32ad0c26b 100644 --- a/js/smoke/shared/package-lock.json +++ b/js/smoke/shared/package-lock.json @@ -933,6 +933,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -1125,6 +1126,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -1419,6 +1421,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/js/smoke/shared/src/helpers/register.ts b/js/smoke/shared/src/helpers/register.ts index 663481b5e..9b45d0126 100644 --- a/js/smoke/shared/src/helpers/register.ts +++ b/js/smoke/shared/src/helpers/register.ts @@ -120,6 +120,7 @@ export interface RunTestsOptions { name: string; braintrust: BraintrustModule; tests: TestFn[]; + skipCoverage?: boolean; } export interface TestRunResults { @@ -142,6 +143,7 @@ export async function runTests({ name, braintrust, tests, + skipCoverage = false, }: RunTestsOptions): Promise { const results: TestResult[] = []; @@ -149,7 +151,9 @@ export async function runTests({ results.push(await test(braintrust)); } - results.push(validateCoverage(results)); + if (!skipCoverage) { + results.push(validateCoverage(results)); + } displayTestResults({ scenarioName: name, results }); diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts index 2607a4ec1..718ec83cb 100644 --- a/js/src/browser-config.ts +++ b/js/src/browser-config.ts @@ -1,3 +1,6 @@ +// Browser-safe isomorph that noops Node.js features +// This file is only used for the /browser, /edge-light, /workerd exports + import iso from "./isomorph"; import { _internalSetInitialState } from "./logger"; @@ -10,13 +13,30 @@ declare global { } // End copied code +let messageShown = false; let browserConfigured = false; -export function configureBrowser() { + +/** + * Configure the isomorph for browser environments. + */ +export function configureBrowser(): void { if (browserConfigured) { return; } - // Set build type indicator + // Show informational message once + if (!messageShown && typeof console !== "undefined") { + console.info( + "This entrypoint is no longer supported.\n\n" + + "You should be using entrypoints:\n\n" + + "- `/workerd` (cloudflare envs)\n" + + "- `/edge-light` (next-js or other edge envs)\n\n" + + "If you'd like to use braintrust in the browser use the dedicated package: @braintrust/browser\n", + ); + messageShown = true; + } + + // Configure browser-safe implementations iso.buildType = "browser"; try { @@ -34,12 +54,6 @@ export function configureBrowser() { return process.env[name]; }; - iso.renderNunjucksString = () => { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); - }; - // Implement browser-compatible hash function using a simple hash algorithm iso.hash = (data: string): string => { // Simple hash function for browser compatibility diff --git a/js/src/browser.ts b/js/src/browser.ts index 706b2bb4b..9f4f756d1 100644 --- a/js/src/browser.ts +++ b/js/src/browser.ts @@ -1,7 +1,16 @@ +/** + * Browser-compatible build of the Braintrust SDK. + * + * This build uses a noop isomorph that provides browser-safe implementations + * for Node.js-specific features. + * + * For optimal browser support with AsyncLocalStorage polyfill, consider: + * npm install @braintrust/browser + * import * as braintrust from '@braintrust/browser'; + */ + import { configureBrowser } from "./browser-config"; configureBrowser(); -// eslint-disable-next-line no-restricted-syntax -- already enforced in exports export * from "./exports"; -export * as default from "./exports"; diff --git a/js/src/exports.ts b/js/src/exports.ts index fee5d4b43..420e1bd03 100644 --- a/js/src/exports.ts +++ b/js/src/exports.ts @@ -103,12 +103,26 @@ export { registerOtelFlush, } from "./logger"; +// Internal isomorph layer for platform-specific implementations +import _internalIso from "./isomorph"; +export { _internalIso }; + export { isTemplateFormat, parseTemplateFormat, renderTemplateContent, } from "./template/renderer"; -export type { TemplateFormat } from "./template/renderer"; +export type { TemplateFormat } from "./template/registry"; + +export type { + TemplateRenderer, + TemplateRendererPlugin, +} from "./template/registry"; +export { + registerTemplatePlugin, + getTemplateRenderer, + templateRegistry, +} from "./template/registry"; export type { InvokeFunctionArgs, InvokeReturn } from "./functions/invoke"; export { initFunction, invoke } from "./functions/invoke"; diff --git a/js/src/framework.test.ts b/js/src/framework.test.ts index 62129fe17..0b3c7f7d8 100644 --- a/js/src/framework.test.ts +++ b/js/src/framework.test.ts @@ -1075,9 +1075,10 @@ describe("framework2 metadata support", () => { // Check that template_format is stored at the top level of prompt data expect(prompt.templateFormat).toBe("nunjucks"); - // Verify it renders correctly - const result = prompt.build({ name: "World" }); - expect(result.messages[0].content).toBe("Hello World"); + // Verify it requires the addon to render + expect(() => prompt.build({ name: "World" })).toThrow( + "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'.", + ); }); }); }); diff --git a/js/src/isomorph.ts b/js/src/isomorph.ts index 690fdcb38..eef739889 100644 --- a/js/src/isomorph.ts +++ b/js/src/isomorph.ts @@ -75,13 +75,6 @@ export interface Common { // zlib (promisified and type-erased). gunzip?: (data: any) => Promise; gzip?: (data: any) => Promise; - - // Nunjucks template rendering (lints if strict is true) - renderNunjucksString: ( - template: string, - variables: Record, - options?: { strict?: boolean }, - ) => string; } const iso: Common = { @@ -92,11 +85,6 @@ const iso: Common = { getCallerLocation: () => undefined, newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(), processOn: (_0, _1) => {}, - renderNunjucksString: () => { - throw new Error( - "Nunjucks templating is not supported in this build. Use templateFormat: 'mustache' (or omit templateFormat).", - ); - }, basename: (filepath: string) => filepath.split(/[\\/]/).pop() || filepath, writeln: (text: string) => console.log(text), }; diff --git a/js/src/logger.test.ts b/js/src/logger.test.ts index 7123985ed..a9ad24bce 100644 --- a/js/src/logger.test.ts +++ b/js/src/logger.test.ts @@ -209,30 +209,16 @@ describe("prompt.build structured output templating", () => { false, ); - const result = prompt.build( - { - user: { name: "ada" }, - }, - { templateFormat: "nunjucks" }, - ); - - expect(result).toMatchObject({ - response_format: { - type: "json_schema", - json_schema: { - name: "schema", - schema: { - type: "object", - properties: { - greeting: { - type: "string", - description: "Hello ADA", - }, - }, - }, + expect(() => + prompt.build( + { + user: { name: "ada" }, }, - }, - }); + { templateFormat: "nunjucks" }, + ), + ).toThrow( + "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'.", + ); }); test("prompt.build with structured output templating", () => { diff --git a/js/src/logger.ts b/js/src/logger.ts index 9d1838dde..b1beb1548 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -75,8 +75,8 @@ import Mustache from "mustache"; import { parseTemplateFormat, renderTemplateContent, - type TemplateFormat, } from "./template/renderer"; +import type { TemplateFormat } from "./template/registry"; import { z, ZodError } from "zod/v3"; import { @@ -6497,25 +6497,15 @@ function renderTemplatedObject( options: { strict?: boolean; templateFormat: TemplateFormat }, ): unknown { if (typeof obj === "string") { - const strict = !!options.strict; - if (options.templateFormat === "nunjucks") { - return iso.renderNunjucksString(obj, args, { strict }); - } - if (options.templateFormat === "mustache") { - if (strict) { - lintMustacheTemplate(obj, args); - } - return Mustache.render(obj, args, undefined, { - escape: (value) => { - if (typeof value === "string") { - return value; - } else { - return JSON.stringify(value); - } - }, - }); - } - return obj; + return renderTemplateContent( + obj, + args, + (value) => (typeof value === "string" ? value : JSON.stringify(value)), + { + strict: options.strict, + templateFormat: options.templateFormat, + }, + ); } else if (isArray(obj)) { return obj.map((item) => renderTemplatedObject(item, args, options)); } else if (isObject(obj)) { diff --git a/js/src/node.ts b/js/src/node.ts index df453a3a8..2351c6ca4 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -9,8 +9,6 @@ import iso from "./isomorph"; import { getRepoInfo, getPastNAncestors } from "./gitutil"; import { getCallerLocation } from "./stackutil"; import { _internalSetInitialState } from "./logger"; -import { renderNunjucksString as nunjucksRender } from "./template/nunjucks-env"; -import { lintTemplate as nunjucksLint } from "./template/nunjucks-utils"; import { promisify } from "node:util"; import * as zlib from "node:zlib"; @@ -26,15 +24,6 @@ export function configureNode() { iso.processOn = (event: string, handler: (code: unknown) => void) => { process.on(event, handler); }; - iso.renderNunjucksString = (template, variables, options = {}) => { - const strict = options.strict ?? false; - - if (strict) { - nunjucksLint(template, variables); - } - - return nunjucksRender(template, variables, { strict }); - }; iso.basename = path.basename; iso.writeln = (text: string) => process.stdout.write(text + "\n"); iso.pathJoin = path.join; diff --git a/js/src/prompt.test.ts b/js/src/prompt.test.ts index c822a39d7..849158cc2 100644 --- a/js/src/prompt.test.ts +++ b/js/src/prompt.test.ts @@ -168,8 +168,9 @@ describe("prompt template_format", () => { true, ); - const result = prompt.build({ name: "World" }); - expect(result.messages[0].content).toBe("Hello World"); + expect(() => prompt.build({ name: "World" })).toThrow( + "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'.", + ); }); test("defaults to mustache when no templateFormat specified", () => { @@ -258,8 +259,11 @@ describe("prompt template_format", () => { true, ); - const result = prompt.build({ text: "Hello" }, { flavor: "completion" }); - expect(result.prompt).toBe("Complete this: Hello"); + expect(() => + prompt.build({ text: "Hello" }, { flavor: "completion" }), + ).toThrow( + "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'.", + ); }); }); @@ -298,10 +302,9 @@ describe("prompt template_format (unconfigured/browser-like)", () => { ); expect(() => prompt.build({ name: "World" })).toThrowError( - /Nunjucks templating is not supported in this build/, + /Nunjucks templating requires @braintrust\/template-nunjucks/, ); }); - test("throws unsupported error after configureBrowser()", async () => { vi.resetModules(); const { configureBrowser } = await import("./browser-config"); @@ -339,7 +342,7 @@ describe("prompt template_format (unconfigured/browser-like)", () => { ); expect(() => prompt.build({ name: "World" })).toThrowError( - /Nunjucks templating is not supported in this build/, + /Nunjucks templating requires @braintrust\/template-nunjucks/, ); }); }); diff --git a/js/src/template/nunjucks-env.ts b/js/src/template/nunjucks-env.ts deleted file mode 100644 index 16232f72b..000000000 --- a/js/src/template/nunjucks-env.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { nunjucks } from "./nunjucks"; -import type { Environment as NunjucksEnvironment } from "nunjucks"; -import { SyncLazyValue } from "../util"; - -const createNunjucksEnv = (throwOnUndefined: boolean): NunjucksEnvironment => { - return new nunjucks.Environment(null, { - autoescape: true, - throwOnUndefined, - }); -}; - -const nunjucksEnv = new SyncLazyValue(() => - createNunjucksEnv(false), -); - -const nunjucksStrictEnv = new SyncLazyValue(() => - createNunjucksEnv(true), -); - -export function getNunjucksEnv(options?: { - strict?: boolean; -}): NunjucksEnvironment { - const strict = options?.strict ?? false; - return strict ? nunjucksStrictEnv.get() : nunjucksEnv.get(); -} - -export function renderNunjucksString( - template: string, - variables: Record, - options?: { strict?: boolean }, -): string { - const strict = options?.strict ?? false; - try { - return getNunjucksEnv({ strict }).renderString(template, variables); - } catch (error) { - if ( - error instanceof Error && - error.message.includes( - "Code generation from strings disallowed for this context", - ) - ) { - throw new Error( - `String template rendering. Disallowed in this environment for security reasons. Try a different template renderer. Original error: ${error.message}`, - ); - } - throw error; - } -} diff --git a/js/src/template/nunjucks-render.test.ts b/js/src/template/nunjucks-render.test.ts deleted file mode 100644 index e6dd85ae1..000000000 --- a/js/src/template/nunjucks-render.test.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { describe, test, expect } from "vitest"; -import { lintTemplate } from "./nunjucks-utils"; -import { getNunjucksEnv } from "./nunjucks-env"; - -function getEnv() { - return getNunjucksEnv({ strict: false }); -} - -function getStrictEnv() { - return getNunjucksEnv({ strict: true }); -} - -describe("nunjucks rendering", () => { - test("renders variable and control structures", () => { - const env = getEnv(); - const out = env.renderString( - "Hello {{ name | upper }} {% if age > 18 %}Adult{% else %}Minor{% endif %}", - { name: "alice", age: 30 }, - ); - expect(out).toBe("Hello ALICE Adult"); - }); - - test("loops render", () => { - const env = getEnv(); - const out = env.renderString( - `{% for item in items %}{{ item }},{% endfor %}`, - { items: ["a", "b"] }, - ); - expect(out).toBe("a,b,"); - }); - - test("strict mode throws for missing top-level variable", () => { - const env = getStrictEnv(); - const tpl = "Hello {{ name }}"; - expect(() => env.renderString(tpl, { user: "x" })).toThrow(); - }); - - test("strict mode passes for defined variable and filters", () => { - const env = getStrictEnv(); - const tpl = "Hello {{ name | upper }}"; - expect(() => env.renderString(tpl, { name: "alice" })).not.toThrow(); - }); - - test("strict mode: for over undefined is empty (does not throw)", () => { - const env = getStrictEnv(); - const tpl = `{% for item in items %}{{ item }}{% endfor %}`; - expect(() => env.renderString(tpl, { items: [1, 2, 3] })).not.toThrow(); - expect(() => env.renderString(tpl, {})).not.toThrow(); - }); - - test("strict mode: nested path with numeric index using brackets", () => { - const env = getStrictEnv(); - const tpl = `{{ user.addresses[2].city }}`; - const ok = { user: { addresses: [{}, {}, { city: "SF" }] } }; - expect(() => env.renderString(tpl, ok)).not.toThrow(); - const bad = { user: {} }; - expect(() => env.renderString(tpl, bad)).toThrow(); - }); - - test("renders nested object properties", () => { - const env = getEnv(); - const out = env.renderString("{{ user.profile.name }}", { - user: { profile: { name: "Alice" } }, - }); - expect(out).toBe("Alice"); - }); - - test("renders multiple variables with context", () => { - const env = getEnv(); - const out = env.renderString( - "{{ firstName }} {{ lastName }} is {{ age }} years old", - { firstName: "Bob", lastName: "Smith", age: 25 }, - ); - expect(out).toBe("Bob Smith is 25 years old"); - }); - - test("renders with string concatenation", () => { - const env = getEnv(); - const out = env.renderString("{{ greeting ~ ' ' ~ name }}", { - greeting: "Hello", - name: "World", - }); - expect(out).toBe("Hello World"); - }); - - test("renders numeric operations", () => { - const env = getEnv(); - const out = env.renderString("Total: {{ price * quantity }}", { - price: 10, - quantity: 3, - }); - expect(out).toBe("Total: 30"); - }); - - test("renders with filters and context", () => { - const env = getEnv(); - const out = env.renderString("{{ message | upper | trim }}", { - message: " hello world ", - }); - expect(out).toBe("HELLO WORLD"); - }); - - test("renders array elements with index", () => { - const env = getEnv(); - const out = env.renderString( - "First: {{ items[0] }}, Last: {{ items[2] }}", - { - items: ["apple", "banana", "cherry"], - }, - ); - expect(out).toBe("First: apple, Last: cherry"); - }); - - test("renders nested arrays and objects", () => { - const env = getEnv(); - const out = env.renderString( - "{{ users[0].name }} from {{ users[0].city }}", - { - users: [ - { name: "John", city: "NYC" }, - { name: "Jane", city: "LA" }, - ], - }, - ); - expect(out).toBe("John from NYC"); - }); - - test("renders with default filter", () => { - const env = getEnv(); - const out1 = env.renderString("{{ name | default('Guest') }}", { - name: "Alice", - }); - expect(out1).toBe("Alice"); - const out2 = env.renderString("{{ name | default('Guest') }}", {}); - expect(out2).toBe("Guest"); - }); - - test("renders ternary expressions", () => { - const env = getEnv(); - const out1 = env.renderString("{{ user.name if user else 'Anonymous' }}", { - user: { name: "Alice" }, - }); - expect(out1).toBe("Alice"); - const out2 = env.renderString( - "{{ user.name if user else 'Anonymous' }}", - {}, - ); - expect(out2).toBe("Anonymous"); - }); - - test("renders with multiple filters chained", () => { - const env = getEnv(); - const out = env.renderString("{{ text | lower | trim }}", { - text: " HELLO WORLD ", - }); - expect(out).toBe("hello world"); - }); - - test("renders complex nested context", () => { - const env = getEnv(); - const out = env.renderString( - "{{ order.customer.name }} ordered {{ order.items[0].name }} for ${{ order.total }}", - { - order: { - customer: { name: "Alice" }, - items: [{ name: "Widget", price: 10 }], - total: 10, - }, - }, - ); - expect(out).toBe("Alice ordered Widget for $10"); - }); - - test("renders with length filter on arrays", () => { - const env = getEnv(); - const out = env.renderString("You have {{ items | length }} items", { - items: ["a", "b", "c", "d"], - }); - expect(out).toBe("You have 4 items"); - }); - - test("renders with join filter", () => { - const env = getEnv(); - const out = env.renderString("{{ tags | join(', ') }}", { - tags: ["red", "green", "blue"], - }); - expect(out).toBe("red, green, blue"); - }); -}); - -describe("nunjucks lintTemplate", () => { - test("passes for valid template syntax", () => { - expect(() => lintTemplate("Hello {{ user.name }}", {})).toThrow(); - }); - - test("passes for valid template with loops", () => { - expect(() => - lintTemplate(`{% for item in items %}{{ item }}{% endfor %}`, {}), - ).not.toThrow(); - }); - - test("passes for valid template with conditionals", () => { - expect(() => - lintTemplate(`{% if user %}{{ user.name }}{% endif %}`, {}), - ).not.toThrow(); - }); - - test("throws for invalid template syntax", () => { - expect(() => lintTemplate("{{ unclosed", {})).toThrow(); - }); - - test("throws for mismatched tags", () => { - expect(() => lintTemplate("{% if x %}{% endfor %}", {})).toThrow(); - }); -}); diff --git a/js/src/template/nunjucks-utils.ts b/js/src/template/nunjucks-utils.ts deleted file mode 100644 index 7afd682cd..000000000 --- a/js/src/template/nunjucks-utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getNunjucksEnv } from "./nunjucks-env"; - -export function lintTemplate(template: string, context: any): void { - const env = getNunjucksEnv({ strict: true }); - env.renderString(template, context); -} diff --git a/js/src/template/nunjucks.ts b/js/src/template/nunjucks.ts deleted file mode 100644 index a7a60ffa0..000000000 --- a/js/src/template/nunjucks.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as nunjucksNodeModule from "nunjucks"; - -export const nunjucks = nunjucksNodeModule; diff --git a/js/src/template/registry.ts b/js/src/template/registry.ts new file mode 100644 index 000000000..a71817c7e --- /dev/null +++ b/js/src/template/registry.ts @@ -0,0 +1,161 @@ +import Mustache from "mustache"; + +import { lintTemplate as lintMustacheTemplate } from "./mustache-utils"; + +export type TemplateFormat = "mustache" | "nunjucks" | "none"; + +export interface TemplateRenderer { + render: ( + template: string, + variables: Record, + escape: (v: unknown) => string, + strict: boolean, + ) => string; + lint?: (template: string, variables: Record) => void; +} + +/** + * A template renderer plugin that can be registered with Braintrust. + * + * Plugins provide support for different template engines (e.g., Nunjucks). + * They use a factory pattern where the plugin is registered once, then activated with specific + * configuration options when needed. + * + * @example + * ```typescript + * import type { TemplateRendererPlugin } from "braintrust"; + * + * export const myPlugin: TemplateRendererPlugin = { + * name: "my-template-engine", + * version: "1.0.0", + * defaultOptions: { strict: false }, + * createRenderer(options?: unknown) { + * const opts = options ?? this.defaultOptions; + * return { + * render(template, variables, escape, strict) { + * // Your rendering logic here + * } + * }; + * } + * }; + * ``` + */ +export interface TemplateRendererPlugin { + /** + * Unique identifier for this plugin. + * Must match the format string used in `templateFormat` option. + */ + name: string; + + /** + * Factory function that creates a renderer instance. + * + * @param options - If not provided, `defaultOptions` is used. + * @returns A configured TemplateRenderer instance + */ + createRenderer: () => TemplateRenderer; + + /** + * Default configuration options for this plugin. + */ + defaultOptions?: unknown; +} + +class TemplatePluginRegistry { + private plugins = new Map< + string, + { plugin: TemplateRendererPlugin; renderer?: TemplateRenderer } + >(); + + register(plugin: TemplateRendererPlugin): void { + if (this.plugins.has(plugin.name)) { + console.warn( + `Template plugin '${plugin.name}' already registered, overwriting`, + ); + } + + const entry = { + plugin, + renderer: + plugin.defaultOptions !== undefined + ? plugin.createRenderer() + : undefined, + }; + + this.plugins.set(plugin.name, entry); + } + + getAvailable(): string[] { + return Array.from(this.plugins.keys()); + } + + get(name: string): TemplateRenderer | undefined { + return this.plugins.get(name)?.renderer; + } + + isRegistered(name: string): boolean { + return this.plugins.has(name); + } +} + +export const templateRegistry = new TemplatePluginRegistry(); + +/** + * Register a template plugin and optionally activate it + * + * If `options` is provided it will be used to create the active renderer. + * If `options` is omitted but the plugin defines `defaultOptions`, the + * registry will activate the renderer using those defaults. + */ +export const registerTemplatePlugin = + templateRegistry.register.bind(templateRegistry); + +/** + * Gets an active template renderer by name. + * + * Returns `undefined` if the renderer is not active. + * + * @param name - Name of the renderer to retrieve + * @returns The active renderer, or undefined if not activated + * + * @example + * ```typescript + * import { getTemplateRenderer } from "braintrust"; + * + * const renderer = getTemplateRenderer("nunjucks"); + * if (renderer) { + * const output = renderer.render(template, variables, escape, strict); + * } + * ``` + */ +export const getTemplateRenderer = templateRegistry.get.bind(templateRegistry); + +// Built-in mustache plugin +const jsonEscape = (v: unknown) => + typeof v === "string" ? v : JSON.stringify(v); + +const mustachePlugin: TemplateRendererPlugin = { + name: "mustache", + defaultOptions: { strict: true, escape: jsonEscape }, + createRenderer() { + const opts = (this.defaultOptions ?? {}) as any; + const escapeFn: (v: unknown) => string = opts?.escape ?? jsonEscape; + const strictDefault: boolean = + typeof opts?.strict === "boolean" ? opts.strict : true; + + return { + render(template, variables, escape, strict) { + const esc = escape ?? escapeFn; + const strictMode = typeof strict === "boolean" ? strict : strictDefault; + if (strictMode) lintMustacheTemplate(template, variables); + return Mustache.render(template, variables, undefined, { escape: esc }); + }, + lint(template, variables) { + lintMustacheTemplate(template, variables); + }, + }; + }, +}; + +// Auto-register built-in mustache plugin. +registerTemplatePlugin(mustachePlugin); diff --git a/js/src/template/renderer.ts b/js/src/template/renderer.ts index 2d002cde7..4fc34203c 100644 --- a/js/src/template/renderer.ts +++ b/js/src/template/renderer.ts @@ -1,8 +1,6 @@ -import Mustache from "mustache"; -import { lintTemplate as lintMustacheTemplate } from "./mustache-utils"; -import iso from "../isomorph"; +import { getTemplateRenderer, type TemplateFormat } from "./registry"; -export type TemplateFormat = "mustache" | "nunjucks" | "none"; +export type { TemplateFormat } from "./registry"; export function isTemplateFormat(v: unknown): v is TemplateFormat { return v === "mustache" || v === "nunjucks" || v === "none"; @@ -23,15 +21,22 @@ export function renderTemplateContent( ): string { const strict = !!options.strict; const templateFormat = parseTemplateFormat(options.templateFormat); - if (templateFormat === "nunjucks") { - return iso.renderNunjucksString(template, variables, { strict }); - } else if (templateFormat === "mustache") { - if (strict) { - lintMustacheTemplate(template, variables); + if (templateFormat === "none") { + return template; + } + + const renderer = getTemplateRenderer(templateFormat); + if (!renderer) { + if (templateFormat === "nunjucks") { + throw new Error( + "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'.", + ); } - return Mustache.render(template, variables, undefined, { - escape, - }); + throw new Error(`No template renderer registered for ${templateFormat}`); + } + + if (strict && renderer.lint) { + renderer.lint(template, variables); } - return template; + return renderer.render(template, variables, escape, strict); } diff --git a/js/tsup.config.ts b/js/tsup.config.ts index f5100c6cb..875d4ec22 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -18,21 +18,6 @@ export default defineConfig([ splitting: true, clean: true, }, - { - entry: ["src/browser.ts"], - format: ["cjs", "esm"], - outDir: "dist", - removeNodeProtocol: false, - external: ["zod"], - dts: { - // Split DTS generation to reduce memory usage - compilerOptions: { - skipLibCheck: true, - }, - }, - splitting: true, - clean: false, - }, { entry: { cli: "src/cli/index.ts" }, format: ["cjs"], @@ -73,4 +58,18 @@ export default defineConfig([ splitting: true, clean: true, }, + // Browser/edge exports - single build used by browser, edge-light, and workerd + { + entry: { + browser: "src/browser.ts", + }, + format: ["cjs", "esm"], + outDir: "dist", + external: ["zod"], + removeNodeProtocol: false, + platform: "browser", + splitting: false, + dts: true, + clean: false, + }, ]); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3d52aaae..37220265d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,31 @@ importers: specifier: ^2.5.6 version: 2.5.6 + integrations/browser-js: + dependencies: + als-browser: + specifier: ^1.0.1 + version: 1.0.1 + zod: + specifier: ^3.25.34 || ^4.0 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^20.10.5 + version: 20.19.16 + braintrust: + specifier: workspace:* + version: link:../../js + tsup: + specifier: ^8.3.5 + version: 8.5.1(@swc/core@1.15.8)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.5.4)(yaml@2.8.2) + typescript: + specifier: ^5.3.3 + version: 5.5.4 + vitest: + specifier: ^2.1.9 + version: 2.1.9(@types/node@20.19.16)(msw@2.6.6(@types/node@20.19.16)(typescript@5.5.4))(terser@5.44.1) + integrations/langchain-js: devDependencies: '@langchain/anthropic': @@ -118,6 +143,31 @@ importers: specifier: 5.5.4 version: 5.5.4 + integrations/templates-nunjucks: + dependencies: + nunjucks: + specifier: ^3.2.4 + version: 3.2.4 + devDependencies: + '@types/node': + specifier: ^20.10.5 + version: 20.19.16 + '@types/nunjucks': + specifier: ^3.2.6 + version: 3.2.6 + braintrust: + specifier: workspace:* + version: link:../../js + tsup: + specifier: ^8.5.1 + version: 8.5.1(@swc/core@1.15.8)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.5.4)(yaml@2.8.2) + typescript: + specifier: 5.5.4 + version: 5.5.4 + vitest: + specifier: ^2.1.9 + version: 2.1.9(@types/node@20.19.16)(msw@2.6.6(@types/node@20.19.16)(typescript@5.5.4))(terser@5.44.1) + integrations/temporal-js: devDependencies: '@temporalio/activity': @@ -196,9 +246,6 @@ importers: '@next/env': specifier: ^14.2.3 version: 14.2.3 - '@types/nunjucks': - specifier: ^3.2.6 - version: 3.2.6 '@vercel/functions': specifier: ^1.0.2 version: 1.0.2 @@ -244,9 +291,6 @@ importers: mustache: specifier: ^4.2.0 version: 4.2.0 - nunjucks: - specifier: ^3.2.4 - version: 3.2.4 pluralize: specifier: ^8.0.0 version: 8.0.0 @@ -2649,6 +2693,9 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + als-browser@1.0.1: + resolution: {integrity: sha512-DjavKf6zf4DFPdEmgsEM474MBjFcZG/1amv2/+WHGf61kVQWqf7XEn4jvpjFS4ssQbh/pkmYThaPfQK1ERC+3g==} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -8275,6 +8322,15 @@ snapshots: msw: 2.6.6(@types/node@20.19.16)(typescript@5.4.4) vite: 5.4.14(@types/node@20.19.16)(terser@5.44.1) + '@vitest/mocker@2.1.9(msw@2.6.6(@types/node@20.19.16)(typescript@5.5.4))(vite@5.4.14(@types/node@20.19.16)(terser@5.44.1))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.19 + optionalDependencies: + msw: 2.6.6(@types/node@20.19.16)(typescript@5.5.4) + vite: 5.4.14(@types/node@20.19.16)(terser@5.44.1) + '@vitest/mocker@2.1.9(msw@2.6.6(@types/node@20.19.9)(typescript@5.4.4))(vite@5.4.14(@types/node@20.19.9)(terser@5.44.1))': dependencies: '@vitest/spy': 2.1.9 @@ -8555,6 +8611,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + als-browser@1.0.1: {} + ansi-align@3.0.1: dependencies: string-width: 4.2.3 @@ -10831,6 +10889,32 @@ snapshots: - '@types/node' optional: true + msw@2.6.6(@types/node@20.19.16)(typescript@5.5.4): + dependencies: + '@bundled-es-modules/cookie': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 5.0.2(@types/node@20.19.16) + '@mswjs/interceptors': 0.37.3 + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.5 + chalk: 4.1.2 + graphql: 16.9.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + strict-event-emitter: 0.5.1 + type-fest: 4.30.0 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - '@types/node' + optional: true + msw@2.6.6(@types/node@20.19.9)(typescript@5.4.4): dependencies: '@bundled-es-modules/cookie': 2.0.1 @@ -12468,6 +12552,41 @@ snapshots: - supports-color - terser + vitest@2.1.9(@types/node@20.19.16)(msw@2.6.6(@types/node@20.19.16)(typescript@5.5.4))(terser@5.44.1): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(msw@2.6.6(@types/node@20.19.16)(typescript@5.5.4))(vite@5.4.14(@types/node@20.19.16)(terser@5.44.1)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.2.0 + debug: 4.4.3 + expect-type: 1.2.0 + magic-string: 0.30.19 + pathe: 1.1.2 + std-env: 3.8.1 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 1.2.0 + vite: 5.4.14(@types/node@20.19.16)(terser@5.44.1) + vite-node: 2.1.9(@types/node@20.19.16)(terser@5.44.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.19.16 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vitest@2.1.9(@types/node@20.19.9)(msw@2.6.6(@types/node@20.19.9)(typescript@5.4.4))(terser@5.44.1): dependencies: '@vitest/expect': 2.1.9 From 3ffe46afb8eb06e31782e1f4fa10042be76de629 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Mon, 9 Feb 2026 13:24:10 -0800 Subject: [PATCH 42/57] modify dependency --- integrations/browser-js/package.json | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/integrations/browser-js/package.json b/integrations/browser-js/package.json index aa4485367..891beb833 100644 --- a/integrations/browser-js/package.json +++ b/integrations/browser-js/package.json @@ -23,7 +23,8 @@ "test": "vitest run" }, "dependencies": { - "als-browser": "^1.0.1" + "als-browser": "^1.0.1", + "braintrust": ">=3.0.0" }, "devDependencies": { "@types/node": "^20.10.5", @@ -33,13 +34,9 @@ "vitest": "^2.1.9" }, "peerDependencies": { - "braintrust": ">=3.0.0", "zod": "^3.25.34 || ^4.0" }, "peerDependenciesMeta": { - "braintrust": { - "optional": false - }, "zod": { "optional": false } From 715f2a58da7548d41c086f4cd37c73fdf283523a Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Mon, 9 Feb 2026 13:25:36 -0800 Subject: [PATCH 43/57] make dependency reliant on 3.0.0 version --- integrations/browser-js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/browser-js/package.json b/integrations/browser-js/package.json index 891beb833..68a639b69 100644 --- a/integrations/browser-js/package.json +++ b/integrations/browser-js/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "als-browser": "^1.0.1", - "braintrust": ">=3.0.0" + "braintrust": ">=3.0.0-rc.29" }, "devDependencies": { "@types/node": "^20.10.5", From 4f5eb822c2d92c6f6d47873880c5c5c02194a3a7 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Mon, 9 Feb 2026 13:31:27 -0800 Subject: [PATCH 44/57] update lockfile --- pnpm-lock.yaml | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 671af5ccf..2d6746472 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: als-browser: specifier: ^1.0.1 version: 1.0.1 + braintrust: + specifier: '>=3.0.0-rc.29' + version: 3.0.0-rc.29(zod@3.25.76) zod: specifier: ^3.25.34 || ^4.0 version: 3.25.76 @@ -27,9 +30,6 @@ importers: '@types/node': specifier: ^20.10.5 version: 20.19.16 - braintrust: - specifier: workspace:* - version: link:../../js tsup: specifier: ^8.3.5 version: 8.5.1(@swc/core@1.15.8)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.5.4)(yaml@2.8.2) @@ -2862,6 +2862,12 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + braintrust@3.0.0-rc.29: + resolution: {integrity: sha512-MTY0hCsBlRZcpYUf+WYeQOFcKK6Wto9P71q5UktAhIna+Gr6ZDPfp7jKIl6Mv9O8cD+PKBYBvL7pPwNTIfLkeA==} + hasBin: true + peerDependencies: + zod: ^3.25.34 || ^4.0 + browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -8894,6 +8900,35 @@ snapshots: dependencies: fill-range: 7.1.1 + braintrust@3.0.0-rc.29(zod@3.25.76): + dependencies: + '@ai-sdk/provider': 1.1.3 + '@next/env': 14.2.3 + '@vercel/functions': 1.0.2 + argparse: 2.0.1 + boxen: 8.0.1 + chalk: 4.1.2 + cli-progress: 3.12.0 + cli-table3: 0.6.5 + cors: 2.8.5 + dotenv: 16.4.5 + esbuild: 0.27.0 + eventsource-parser: 1.1.2 + express: 4.21.2 + graceful-fs: 4.2.11 + http-errors: 2.0.0 + minimatch: 9.0.5 + mustache: 4.2.0 + pluralize: 8.0.0 + simple-git: 3.21.0 + source-map: 0.7.6 + termi-link: 1.1.0 + uuid: 9.0.1 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - supports-color + browserslist@4.28.1: dependencies: baseline-browser-mapping: 2.9.14 From 490fe4dfd1fa76d065d92244a5d226b36d230b01 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Mon, 9 Feb 2026 14:56:21 -0800 Subject: [PATCH 45/57] ensure only one copy of browser configuration is enabled --- integrations/browser-js/src/browser-config.ts | 9 +++++---- integrations/browser-js/src/global.d.ts | 11 +++++++++++ integrations/browser-js/src/symbols.ts | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 integrations/browser-js/src/global.d.ts create mode 100644 integrations/browser-js/src/symbols.ts diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts index 139cc3d90..cb084ea78 100644 --- a/integrations/browser-js/src/browser-config.ts +++ b/integrations/browser-js/src/browser-config.ts @@ -1,10 +1,10 @@ import { _internalIso as iso, _internalSetInitialState } from "braintrust"; import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; - -let browserConfigured = false; +import { BROWSER_CONFIGURED_KEY } from "./symbols"; export function configureBrowser() { - if (browserConfigured) { + // @ts-expect-error - TS limitation with symbol indexing across modules + if (globalThis[BROWSER_CONFIGURED_KEY]) { return; } @@ -44,5 +44,6 @@ export function configureBrowser() { }; _internalSetInitialState(); - browserConfigured = true; + // @ts-expect-error - TS limitation with symbol indexing across modules + globalThis[BROWSER_CONFIGURED_KEY] = true; } diff --git a/integrations/browser-js/src/global.d.ts b/integrations/browser-js/src/global.d.ts new file mode 100644 index 000000000..964bef554 --- /dev/null +++ b/integrations/browser-js/src/global.d.ts @@ -0,0 +1,11 @@ +import { BROWSER_CONFIGURED_KEY } from "./symbols"; + +export {}; + +type BaseGlobalThis = typeof globalThis; + +declare global { + var globalThis: BaseGlobalThis & { + [BROWSER_CONFIGURED_KEY]?: boolean; + }; +} diff --git a/integrations/browser-js/src/symbols.ts b/integrations/browser-js/src/symbols.ts new file mode 100644 index 000000000..7581c8daf --- /dev/null +++ b/integrations/browser-js/src/symbols.ts @@ -0,0 +1 @@ +export const BROWSER_CONFIGURED_KEY = Symbol.for("braintrust-browser"); From 72d42616385bf6690f1b8cf71add84e4ccd3bda6 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Mon, 9 Feb 2026 15:30:47 -0800 Subject: [PATCH 46/57] change to casting as --- integrations/browser-js/src/browser-config.ts | 6 ++---- integrations/browser-js/src/global.d.ts | 11 ----------- 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 integrations/browser-js/src/global.d.ts diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts index cb084ea78..0f7a47f77 100644 --- a/integrations/browser-js/src/browser-config.ts +++ b/integrations/browser-js/src/browser-config.ts @@ -3,8 +3,7 @@ import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; import { BROWSER_CONFIGURED_KEY } from "./symbols"; export function configureBrowser() { - // @ts-expect-error - TS limitation with symbol indexing across modules - if (globalThis[BROWSER_CONFIGURED_KEY]) { + if ((globalThis as any)[BROWSER_CONFIGURED_KEY]) { return; } @@ -44,6 +43,5 @@ export function configureBrowser() { }; _internalSetInitialState(); - // @ts-expect-error - TS limitation with symbol indexing across modules - globalThis[BROWSER_CONFIGURED_KEY] = true; + (globalThis as any)[BROWSER_CONFIGURED_KEY] = true; } diff --git a/integrations/browser-js/src/global.d.ts b/integrations/browser-js/src/global.d.ts deleted file mode 100644 index 964bef554..000000000 --- a/integrations/browser-js/src/global.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BROWSER_CONFIGURED_KEY } from "./symbols"; - -export {}; - -type BaseGlobalThis = typeof globalThis; - -declare global { - var globalThis: BaseGlobalThis & { - [BROWSER_CONFIGURED_KEY]?: boolean; - }; -} From 347b5d62b41333a5cc9502a501a7484e80968483 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Wed, 11 Feb 2026 10:25:02 -0800 Subject: [PATCH 47/57] add symbols to main braintrust package for configuring node and setting up logger --- js/src/cli/functions/load-module.ts | 4 +++- js/src/logger.ts | 7 ++++++- js/src/node.ts | 6 ++++++ js/src/symbols.ts | 2 ++ 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 js/src/symbols.ts diff --git a/js/src/cli/functions/load-module.ts b/js/src/cli/functions/load-module.ts index 3b84f5e65..e3b2f98b2 100644 --- a/js/src/cli/functions/load-module.ts +++ b/js/src/cli/functions/load-module.ts @@ -2,6 +2,7 @@ import nodeModulesPaths from "../jest/nodeModulesPaths"; import path, { dirname } from "path"; import { _internalGetGlobalState } from "../../logger"; import { EvaluatorFile } from "../../framework"; +import { BRAINTRUST_STATE_KEY } from "../../symbols"; function evalWithModuleContext(inFile: string, evalFn: () => T): T { const modulePaths = [...module.paths]; @@ -29,7 +30,8 @@ export function loadModule({ reporters: {}, }; globalThis._lazy_load = true; - globalThis.__inherited_braintrust_state = _internalGetGlobalState(); + const state = _internalGetGlobalState(); + (globalThis as any)[BRAINTRUST_STATE_KEY] = state; const __filename = inFile; const __dirname = dirname(__filename); new Function("require", "module", "__filename", "__dirname", moduleText)( diff --git a/js/src/logger.ts b/js/src/logger.ts index 0245f5069..3b7e9c5fb 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -3,6 +3,7 @@ import { v4 as uuidv4 } from "uuid"; import { Queue, DEFAULT_QUEUE_SIZE } from "./queue"; +import { BRAINTRUST_STATE_KEY } from "./symbols"; import { IDGenerator, getIdGenerator } from "./id-gen"; import { _urljoin, @@ -542,6 +543,9 @@ export const NOOP_SPAN_PERMALINK = "https://braintrust.dev/noop-span"; // mechanism to propagate the initial state from some toplevel creator. declare global { var __inherited_braintrust_state: BraintrustState; + interface Global { + [key: symbol]: any; + } } const loginSchema = z.strictObject({ @@ -968,6 +972,7 @@ export function _internalSetInitialState() { return; } _globalState = + (globalThis as any)[BRAINTRUST_STATE_KEY] || globalThis.__inherited_braintrust_state || new BraintrustState({ /*empty login options*/ @@ -4395,7 +4400,7 @@ export async function login( } await _globalState.login(options); - globalThis.__inherited_braintrust_state = _globalState; + (globalThis as any)[BRAINTRUST_STATE_KEY] = _globalState; return _globalState; } diff --git a/js/src/node.ts b/js/src/node.ts index 2351c6ca4..ab84b6f6d 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -11,8 +11,13 @@ import { getCallerLocation } from "./stackutil"; import { _internalSetInitialState } from "./logger"; import { promisify } from "node:util"; import * as zlib from "node:zlib"; +import { NODE_CONFIGURED_KEY } from "./symbols"; export function configureNode() { + if ((globalThis as any)[NODE_CONFIGURED_KEY]) { + return; + } + // Set build type indicator iso.buildType = "node"; @@ -49,4 +54,5 @@ export function configureNode() { iso.hash = (data) => crypto.createHash("sha256").update(data).digest("hex"); _internalSetInitialState(); + (globalThis as any)[NODE_CONFIGURED_KEY] = true; } diff --git a/js/src/symbols.ts b/js/src/symbols.ts new file mode 100644 index 000000000..c96afe20b --- /dev/null +++ b/js/src/symbols.ts @@ -0,0 +1,2 @@ +export const BRAINTRUST_STATE_KEY = Symbol.for("braintrust-state"); +export const NODE_CONFIGURED_KEY = Symbol.for("braintrust-node"); From 3c523bdb3265496aef61f83f7934b837b6661f6b Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Wed, 11 Feb 2026 10:51:09 -0800 Subject: [PATCH 48/57] fix --- js/src/logger.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/logger.ts b/js/src/logger.ts index 3b7e9c5fb..981d1d474 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -4372,7 +4372,7 @@ export async function login( ): Promise { const { forceLogin = false } = options || {}; - if (_globalState.loggedIn && !forceLogin) { + if (_globalState && _globalState.loggedIn && !forceLogin) { // We have already logged in. If any provided login inputs disagree with our // existing settings, raise an Exception warning the user to try again with // `forceLogin: true`. @@ -4399,6 +4399,10 @@ export async function login( return _globalState; } + if (!_globalState) { + _internalSetInitialState(); + } + await _globalState.login(options); (globalThis as any)[BRAINTRUST_STATE_KEY] = _globalState; return _globalState; From 9b887f9937cea05c34666cec14dc7c0e93fb238f Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Wed, 11 Feb 2026 13:21:47 -0800 Subject: [PATCH 49/57] some weird state management --- integrations/browser-js/src/browser-config.ts | 6 ------ integrations/browser-js/src/symbols.ts | 1 - js/src/node.ts | 6 ------ js/src/symbols.ts | 1 - 4 files changed, 14 deletions(-) delete mode 100644 integrations/browser-js/src/symbols.ts diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts index 0f7a47f77..3ff67987e 100644 --- a/integrations/browser-js/src/browser-config.ts +++ b/integrations/browser-js/src/browser-config.ts @@ -1,12 +1,7 @@ import { _internalIso as iso, _internalSetInitialState } from "braintrust"; import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; -import { BROWSER_CONFIGURED_KEY } from "./symbols"; export function configureBrowser() { - if ((globalThis as any)[BROWSER_CONFIGURED_KEY]) { - return; - } - // Set build type indicator iso.buildType = "browser"; @@ -43,5 +38,4 @@ export function configureBrowser() { }; _internalSetInitialState(); - (globalThis as any)[BROWSER_CONFIGURED_KEY] = true; } diff --git a/integrations/browser-js/src/symbols.ts b/integrations/browser-js/src/symbols.ts deleted file mode 100644 index 7581c8daf..000000000 --- a/integrations/browser-js/src/symbols.ts +++ /dev/null @@ -1 +0,0 @@ -export const BROWSER_CONFIGURED_KEY = Symbol.for("braintrust-browser"); diff --git a/js/src/node.ts b/js/src/node.ts index ab84b6f6d..2351c6ca4 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -11,13 +11,8 @@ import { getCallerLocation } from "./stackutil"; import { _internalSetInitialState } from "./logger"; import { promisify } from "node:util"; import * as zlib from "node:zlib"; -import { NODE_CONFIGURED_KEY } from "./symbols"; export function configureNode() { - if ((globalThis as any)[NODE_CONFIGURED_KEY]) { - return; - } - // Set build type indicator iso.buildType = "node"; @@ -54,5 +49,4 @@ export function configureNode() { iso.hash = (data) => crypto.createHash("sha256").update(data).digest("hex"); _internalSetInitialState(); - (globalThis as any)[NODE_CONFIGURED_KEY] = true; } diff --git a/js/src/symbols.ts b/js/src/symbols.ts index c96afe20b..8ae48e8d5 100644 --- a/js/src/symbols.ts +++ b/js/src/symbols.ts @@ -1,2 +1 @@ export const BRAINTRUST_STATE_KEY = Symbol.for("braintrust-state"); -export const NODE_CONFIGURED_KEY = Symbol.for("braintrust-node"); From 44426cb0e0fdb16fde51daf8038264841ddd8edd Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 13 Feb 2026 13:51:04 -0800 Subject: [PATCH 50/57] fix an issue with global state --- integrations/browser-js/README.md | 2 +- integrations/browser-js/src/browser-config.ts | 7 ++- js/src/browser-config.ts | 3 +- js/src/browser.ts | 1 + js/src/cli/functions/load-module.ts | 4 +- js/src/logger.ts | 63 ++++++++++--------- js/src/node.ts | 7 +++ js/src/symbol-name.ts | 2 + js/src/symbols.ts | 4 +- js/src/template/plugins/mustache.ts | 29 +++++++++ js/src/template/registry.ts | 32 +--------- js/src/util.ts | 2 + 12 files changed, 88 insertions(+), 68 deletions(-) create mode 100644 js/src/symbol-name.ts create mode 100644 js/src/template/plugins/mustache.ts diff --git a/integrations/browser-js/README.md b/integrations/browser-js/README.md index 929c68553..ac826905c 100644 --- a/integrations/browser-js/README.md +++ b/integrations/browser-js/README.md @@ -40,7 +40,7 @@ const result = await braintrust.traced( This package: - **Includes** `als-browser` polyfill for AsyncLocalStorage (bundled) -- **Requires** `braintrust` as a peer dependency +- **Requires** `braintrust` ## When to Use diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts index 3ff67987e..a625c6ce3 100644 --- a/integrations/browser-js/src/browser-config.ts +++ b/integrations/browser-js/src/browser-config.ts @@ -1,4 +1,9 @@ -import { _internalIso as iso, _internalSetInitialState } from "braintrust"; +import { + _internalIso as iso, + _internalSetInitialState, + BraintrustState, +} from "braintrust"; +import { BRAINTRUST_STATE_SYMBOL_NAME } from "braintrust/symbol-name"; import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; export function configureBrowser() { diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts index 718ec83cb..bd1fcb5d1 100644 --- a/js/src/browser-config.ts +++ b/js/src/browser-config.ts @@ -2,7 +2,8 @@ // This file is only used for the /browser, /edge-light, /workerd exports import iso from "./isomorph"; -import { _internalSetInitialState } from "./logger"; +import { _internalSetInitialState, BraintrustState } from "./logger"; +import { BRAINTRUST_STATE_SYMBOL_NAME } from "./symbol-name"; // This is copied from next.js. It seems they define AsyncLocalStorage in the edge // environment, even though it's not defined in the browser. diff --git a/js/src/browser.ts b/js/src/browser.ts index 9f4f756d1..bb53bcda2 100644 --- a/js/src/browser.ts +++ b/js/src/browser.ts @@ -14,3 +14,4 @@ import { configureBrowser } from "./browser-config"; configureBrowser(); export * from "./exports"; +export * as default from "./exports"; diff --git a/js/src/cli/functions/load-module.ts b/js/src/cli/functions/load-module.ts index e3b2f98b2..c60235c8b 100644 --- a/js/src/cli/functions/load-module.ts +++ b/js/src/cli/functions/load-module.ts @@ -1,8 +1,8 @@ import nodeModulesPaths from "../jest/nodeModulesPaths"; import path, { dirname } from "path"; import { _internalGetGlobalState } from "../../logger"; +import { BRAINTRUST_STATE_SYMBOL_NAME } from "../../symbol-name"; import { EvaluatorFile } from "../../framework"; -import { BRAINTRUST_STATE_KEY } from "../../symbols"; function evalWithModuleContext(inFile: string, evalFn: () => T): T { const modulePaths = [...module.paths]; @@ -31,7 +31,7 @@ export function loadModule({ }; globalThis._lazy_load = true; const state = _internalGetGlobalState(); - (globalThis as any)[BRAINTRUST_STATE_KEY] = state; + (globalThis as any)[Symbol.for(BRAINTRUST_STATE_SYMBOL_NAME)] = state; const __filename = inFile; const __dirname = dirname(__filename); new Function("require", "module", "__filename", "__dirname", moduleText)( diff --git a/js/src/logger.ts b/js/src/logger.ts index 981d1d474..d6aa507be 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -3,7 +3,6 @@ import { v4 as uuidv4 } from "uuid"; import { Queue, DEFAULT_QUEUE_SIZE } from "./queue"; -import { BRAINTRUST_STATE_KEY } from "./symbols"; import { IDGenerator, getIdGenerator } from "./id-gen"; import { _urljoin, @@ -39,7 +38,8 @@ import { VALID_SOURCES, isArray, isObject, -} from "../util/index"; +} from "./util"; +import { BRAINTRUST_STATE_SYMBOL_NAME } from "./symbol-name"; import { type AnyModelParamsType as AnyModelParam, AttachmentReference as attachmentReferenceSchema, @@ -96,7 +96,6 @@ const parametersRowSchema = z.object({ type ParametersRow = z.infer; import { waitUntil } from "@vercel/functions"; -import Mustache from "mustache"; import { parseTemplateFormat, renderTemplateContent, @@ -539,10 +538,8 @@ export const NOOP_SPAN = new NoopSpan(); export const NOOP_SPAN_PERMALINK = "https://braintrust.dev/noop-span"; // In certain situations (e.g. the cli), we want separately-compiled modules to -// use the same state as the toplevel module. This global variable serves as a -// mechanism to propagate the initial state from some toplevel creator. +// use the same state as the toplevel module. Use a symbol on `globalThis. declare global { - var __inherited_braintrust_state: BraintrustState; interface Global { [key: symbol]: any; } @@ -960,23 +957,26 @@ function initTestExperiment( } /** - * This function should be invoked exactly once after configuring the `iso` - * object based on the platform. See js/src/node.ts for an example. + * Initialize the global Braintrust state lazily, it only creates the BraintrustState instance on the first invocation. + * + * The state is stored in a global symbol to ensure cross-bundle compatibility. + * + * This is invoked by platform-specific initialization functions (configureNode/configureBrowser) + * * @internal */ export function _internalSetInitialState() { if (_globalState) { - console.warn( - "global state already set, should only call _internalSetInitialState once", - ); return; } - _globalState = - (globalThis as any)[BRAINTRUST_STATE_KEY] || - globalThis.__inherited_braintrust_state || - new BraintrustState({ - /*empty login options*/ - }); + const sym = Symbol.for(BRAINTRUST_STATE_SYMBOL_NAME); + let existing = (globalThis as any)[sym]; + if (!existing) { + const state = new BraintrustState({}); + (globalThis as any)[sym] = state; + existing = state; + } + _globalState = existing; } /** * @internal @@ -4353,7 +4353,7 @@ export type FullLoginOptions = LoginOptions & { export function setMaskingFunction( maskingFunction: ((value: unknown) => unknown) | null, ): void { - _globalState.setMaskingFunction(maskingFunction); + _internalGetGlobalState().setMaskingFunction(maskingFunction); } /** @@ -4372,7 +4372,8 @@ export async function login( ): Promise { const { forceLogin = false } = options || {}; - if (_globalState && _globalState.loggedIn && !forceLogin) { + const state = _internalGetGlobalState(); + if (state.loggedIn && !forceLogin) { // We have already logged in. If any provided login inputs disagree with our // existing settings, raise an Exception warning the user to try again with // `forceLogin: true`. @@ -4387,25 +4388,24 @@ export async function login( ); } } - checkUpdatedParam("appUrl", options.appUrl, _globalState.appUrl); + checkUpdatedParam("appUrl", options.appUrl, state.appUrl); checkUpdatedParam( "apiKey", options.apiKey ? HTTPConnection.sanitize_token(options.apiKey) : undefined, - _globalState.loginToken, + state.loginToken, ); - checkUpdatedParam("orgName", options.orgName, _globalState.orgName); - return _globalState; + checkUpdatedParam("orgName", options.orgName, state.orgName); + return state; } - if (!_globalState) { + if (!state) { _internalSetInitialState(); } - await _globalState.login(options); - (globalThis as any)[BRAINTRUST_STATE_KEY] = _globalState; - return _globalState; + await state.login(options); + return state; } export async function loginToState(options: LoginOptions = {}) { @@ -4968,7 +4968,7 @@ export async function flush(options?: OptionalStateArg): Promise { * @param fetch The fetch implementation to use. */ export function setFetch(fetch: typeof globalThis.fetch): void { - _globalState.setFetch(fetch); + _internalGetGlobalState().setFetch(fetch); } function startSpanAndIsLogger( @@ -7636,9 +7636,10 @@ async function simulateLoginForTests() { // This is a helper function to simulate a logout for testing. function simulateLogoutForTests() { - _globalState.resetLoginInfo(); - _globalState.appUrl = "https://www.braintrust.dev"; - return _globalState; + const state = _internalGetGlobalState(); + state.resetLoginInfo(); + state.appUrl = "https://www.braintrust.dev"; + return state; } /** diff --git a/js/src/node.ts b/js/src/node.ts index 2351c6ca4..a88033c9e 100644 --- a/js/src/node.ts +++ b/js/src/node.ts @@ -12,7 +12,13 @@ import { _internalSetInitialState } from "./logger"; import { promisify } from "node:util"; import * as zlib from "node:zlib"; +let nodeConfigured = false; + export function configureNode() { + if (nodeConfigured) { + return; + } + // Set build type indicator iso.buildType = "node"; @@ -49,4 +55,5 @@ export function configureNode() { iso.hash = (data) => crypto.createHash("sha256").update(data).digest("hex"); _internalSetInitialState(); + nodeConfigured = true; } diff --git a/js/src/symbol-name.ts b/js/src/symbol-name.ts new file mode 100644 index 000000000..2613f6927 --- /dev/null +++ b/js/src/symbol-name.ts @@ -0,0 +1,2 @@ +// Central name for the shared global symbol used to store Braintrust state. +export const BRAINTRUST_STATE_SYMBOL_NAME = "braintrust-state"; diff --git a/js/src/symbols.ts b/js/src/symbols.ts index 8ae48e8d5..8789d1fe8 100644 --- a/js/src/symbols.ts +++ b/js/src/symbols.ts @@ -1 +1,3 @@ -export const BRAINTRUST_STATE_KEY = Symbol.for("braintrust-state"); +import { BRAINTRUST_STATE_SYMBOL_NAME } from "./symbol-name"; + +export const BRAINTRUST_STATE_KEY = Symbol.for(BRAINTRUST_STATE_SYMBOL_NAME); diff --git a/js/src/template/plugins/mustache.ts b/js/src/template/plugins/mustache.ts new file mode 100644 index 000000000..7c50826b8 --- /dev/null +++ b/js/src/template/plugins/mustache.ts @@ -0,0 +1,29 @@ +import Mustache from "mustache"; +import type { TemplateRendererPlugin } from "../registry"; +import { lintTemplate as lintMustacheTemplate } from "../mustache-utils"; + +const jsonEscape = (v: unknown) => + typeof v === "string" ? v : JSON.stringify(v); + +export const mustachePlugin: TemplateRendererPlugin = { + name: "mustache", + defaultOptions: { strict: true, escape: jsonEscape }, + createRenderer() { + const opts = (this.defaultOptions ?? {}) as any; + const escapeFn: (v: unknown) => string = opts?.escape ?? jsonEscape; + const strictDefault: boolean = + typeof opts?.strict === "boolean" ? opts.strict : true; + + return { + render(template, variables, escape, strict) { + const esc = escape ?? escapeFn; + const strictMode = typeof strict === "boolean" ? strict : strictDefault; + if (strictMode) lintMustacheTemplate(template, variables); + return Mustache.render(template, variables, undefined, { escape: esc }); + }, + lint(template, variables) { + lintMustacheTemplate(template, variables); + }, + }; + }, +}; diff --git a/js/src/template/registry.ts b/js/src/template/registry.ts index a71817c7e..a0686eb10 100644 --- a/js/src/template/registry.ts +++ b/js/src/template/registry.ts @@ -1,6 +1,4 @@ -import Mustache from "mustache"; - -import { lintTemplate as lintMustacheTemplate } from "./mustache-utils"; +import { mustachePlugin } from "./plugins/mustache"; export type TemplateFormat = "mustache" | "nunjucks" | "none"; @@ -130,32 +128,4 @@ export const registerTemplatePlugin = */ export const getTemplateRenderer = templateRegistry.get.bind(templateRegistry); -// Built-in mustache plugin -const jsonEscape = (v: unknown) => - typeof v === "string" ? v : JSON.stringify(v); - -const mustachePlugin: TemplateRendererPlugin = { - name: "mustache", - defaultOptions: { strict: true, escape: jsonEscape }, - createRenderer() { - const opts = (this.defaultOptions ?? {}) as any; - const escapeFn: (v: unknown) => string = opts?.escape ?? jsonEscape; - const strictDefault: boolean = - typeof opts?.strict === "boolean" ? opts.strict : true; - - return { - render(template, variables, escape, strict) { - const esc = escape ?? escapeFn; - const strictMode = typeof strict === "boolean" ? strict : strictDefault; - if (strictMode) lintMustacheTemplate(template, variables); - return Mustache.render(template, variables, undefined, { escape: esc }); - }, - lint(template, variables) { - lintMustacheTemplate(template, variables); - }, - }; - }, -}; - -// Auto-register built-in mustache plugin. registerTemplatePlugin(mustachePlugin); diff --git a/js/src/util.ts b/js/src/util.ts index 3875b3629..7f2f351a0 100644 --- a/js/src/util.ts +++ b/js/src/util.ts @@ -1,3 +1,5 @@ +export * from "../util"; + export const GLOBAL_PROJECT = "Global"; // Given a function to execute, a catch handler, and a finally handler, runs the function and From 71d5ef56ebbc01143d1a76d6a450608122d817a6 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Fri, 13 Feb 2026 14:21:59 -0800 Subject: [PATCH 51/57] remove unused import --- integrations/browser-js/src/browser-config.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts index a625c6ce3..3ff67987e 100644 --- a/integrations/browser-js/src/browser-config.ts +++ b/integrations/browser-js/src/browser-config.ts @@ -1,9 +1,4 @@ -import { - _internalIso as iso, - _internalSetInitialState, - BraintrustState, -} from "braintrust"; -import { BRAINTRUST_STATE_SYMBOL_NAME } from "braintrust/symbol-name"; +import { _internalIso as iso, _internalSetInitialState } from "braintrust"; import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; export function configureBrowser() { From aff32446f060f9f08e5f58f7235a4e1852c4967a Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Mon, 16 Feb 2026 14:29:04 -0800 Subject: [PATCH 52/57] update readme and exports --- integrations/browser-js/README.md | 2 ++ js/package.json | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/integrations/browser-js/README.md b/integrations/browser-js/README.md index ac826905c..95b7e53e8 100644 --- a/integrations/browser-js/README.md +++ b/integrations/browser-js/README.md @@ -4,6 +4,8 @@ Official browser-only SDK for [Braintrust](https://braintrust.dev). This is an integration package that provides browser-optimized builds of the Braintrust SDK with AsyncLocalStorage polyfill support for standard browsers. +Note: This package supports limited functionality in the browser; however, using it in a browser environment currently results in CORS errors. + ## Installation ```bash diff --git a/js/package.json b/js/package.json index faae590a6..d51a3cd62 100644 --- a/js/package.json +++ b/js/package.json @@ -35,6 +35,16 @@ "require": "./dist/index.js", "default": "./dist/index.mjs" }, + "./workerd": { + "import": "./dist/browser.mjs", + "require": "./dist/browser.js", + "default": "./dist/browser.mjs" + }, + "./edge-light": { + "import": "./dist/browser.mjs", + "require": "./dist/browser.js", + "default": "./dist/browser.mjs" + }, "./browser": { "import": "./dist/browser.mjs", "require": "./dist/browser.js", From 0ca79c536e8e5ca802a7526f815046c3b2d4813b Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 17 Feb 2026 13:53:52 -0800 Subject: [PATCH 53/57] replace and don't re-use the string variable --- js/src/browser-config.ts | 3 +-- js/src/cli/functions/load-module.ts | 3 +-- js/src/logger.ts | 3 +-- js/src/symbol-name.ts | 2 -- js/src/symbols.ts | 4 +--- 5 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 js/src/symbol-name.ts diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts index bd1fcb5d1..718ec83cb 100644 --- a/js/src/browser-config.ts +++ b/js/src/browser-config.ts @@ -2,8 +2,7 @@ // This file is only used for the /browser, /edge-light, /workerd exports import iso from "./isomorph"; -import { _internalSetInitialState, BraintrustState } from "./logger"; -import { BRAINTRUST_STATE_SYMBOL_NAME } from "./symbol-name"; +import { _internalSetInitialState } from "./logger"; // This is copied from next.js. It seems they define AsyncLocalStorage in the edge // environment, even though it's not defined in the browser. diff --git a/js/src/cli/functions/load-module.ts b/js/src/cli/functions/load-module.ts index c60235c8b..8551da92c 100644 --- a/js/src/cli/functions/load-module.ts +++ b/js/src/cli/functions/load-module.ts @@ -1,7 +1,6 @@ import nodeModulesPaths from "../jest/nodeModulesPaths"; import path, { dirname } from "path"; import { _internalGetGlobalState } from "../../logger"; -import { BRAINTRUST_STATE_SYMBOL_NAME } from "../../symbol-name"; import { EvaluatorFile } from "../../framework"; function evalWithModuleContext(inFile: string, evalFn: () => T): T { @@ -31,7 +30,7 @@ export function loadModule({ }; globalThis._lazy_load = true; const state = _internalGetGlobalState(); - (globalThis as any)[Symbol.for(BRAINTRUST_STATE_SYMBOL_NAME)] = state; + (globalThis as any)[Symbol.for("braintrust-state")] = state; const __filename = inFile; const __dirname = dirname(__filename); new Function("require", "module", "__filename", "__dirname", moduleText)( diff --git a/js/src/logger.ts b/js/src/logger.ts index 4fe2e8f98..47dd304f1 100644 --- a/js/src/logger.ts +++ b/js/src/logger.ts @@ -39,7 +39,6 @@ import { isArray, isObject, } from "./util"; -import { BRAINTRUST_STATE_SYMBOL_NAME } from "./symbol-name"; import { type AnyModelParamsType as AnyModelParam, AttachmentReference as attachmentReferenceSchema, @@ -969,7 +968,7 @@ export function _internalSetInitialState() { if (_globalState) { return; } - const sym = Symbol.for(BRAINTRUST_STATE_SYMBOL_NAME); + const sym = Symbol.for("braintrust-state"); let existing = (globalThis as any)[sym]; if (!existing) { const state = new BraintrustState({}); diff --git a/js/src/symbol-name.ts b/js/src/symbol-name.ts deleted file mode 100644 index 2613f6927..000000000 --- a/js/src/symbol-name.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Central name for the shared global symbol used to store Braintrust state. -export const BRAINTRUST_STATE_SYMBOL_NAME = "braintrust-state"; diff --git a/js/src/symbols.ts b/js/src/symbols.ts index 8789d1fe8..8ae48e8d5 100644 --- a/js/src/symbols.ts +++ b/js/src/symbols.ts @@ -1,3 +1 @@ -import { BRAINTRUST_STATE_SYMBOL_NAME } from "./symbol-name"; - -export const BRAINTRUST_STATE_KEY = Symbol.for(BRAINTRUST_STATE_SYMBOL_NAME); +export const BRAINTRUST_STATE_KEY = Symbol.for("braintrust-state"); From 73c28c3106484c4db4329f0873451b59e3ad0698 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 17 Feb 2026 15:43:11 -0800 Subject: [PATCH 54/57] remove the symbol file --- js/src/symbols.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 js/src/symbols.ts diff --git a/js/src/symbols.ts b/js/src/symbols.ts deleted file mode 100644 index 8ae48e8d5..000000000 --- a/js/src/symbols.ts +++ /dev/null @@ -1 +0,0 @@ -export const BRAINTRUST_STATE_KEY = Symbol.for("braintrust-state"); From cec096008648fad89cb46c4b3d8fd85aaad8aa80 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 17 Feb 2026 15:50:52 -0800 Subject: [PATCH 55/57] update readme with email --- integrations/browser-js/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/browser-js/README.md b/integrations/browser-js/README.md index 95b7e53e8..10f09ceaa 100644 --- a/integrations/browser-js/README.md +++ b/integrations/browser-js/README.md @@ -4,7 +4,7 @@ Official browser-only SDK for [Braintrust](https://braintrust.dev). This is an integration package that provides browser-optimized builds of the Braintrust SDK with AsyncLocalStorage polyfill support for standard browsers. -Note: This package supports limited functionality in the browser; however, using it in a browser environment currently results in CORS errors. +Note: This package supports limited functionality in the browser. We're aware of a CORS issue that users may run into if they use this outside of the braintrust.dev domain. If you'd like to use this package in your own domain, please provide us feedback [support@braintrust.dev](mailto:support@braintrust.dev) ## Installation From 429595ee84fcbb7a3ea8fe8f411ff005b10d09c9 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 17 Feb 2026 18:30:07 -0800 Subject: [PATCH 56/57] Small pending improvements to bt 3.x (#1383) --- integrations/browser-js/package.json | 2 +- integrations/browser-js/src/browser-config.ts | 2 +- js/dev/index.ts | 2 +- js/examples/ai-sdk/stopWhen.ts | 2 +- js/package.json | 18 ++--- .../tests/browser-message.test.ts | 27 ------- .../shared/src/suites/import-verification.ts | 1 + js/src/browser-config.ts | 73 ------------------- js/src/browser/config.ts | 51 +++++++++++++ js/src/{browser.ts => browser/index.ts} | 6 +- js/src/cli/index.ts | 2 +- js/src/edge-light/config.ts | 50 +++++++++++++ js/src/edge-light/index.ts | 13 ++++ js/src/framework.test.ts | 2 +- js/src/functions/invoke.test.ts | 2 +- js/src/isomorph.ts | 8 +- js/src/logger-misc.test.ts | 2 +- js/src/logger.test.ts | 2 +- js/src/masking.test.ts | 2 +- js/src/{node.ts => node/config.ts} | 11 ++- js/src/{ => node}/index.ts | 7 +- js/src/parameters.test.ts | 2 +- js/src/prompt-cache/disk-cache.test.ts | 2 +- js/src/prompt-cache/prompt-cache.test.ts | 2 +- js/src/prompt.test.ts | 4 +- js/src/span-cache.test.ts | 2 +- js/src/trace.test.ts | 2 +- js/src/workerd/config.ts | 50 +++++++++++++ js/src/workerd/index.ts | 13 ++++ js/src/wrappers/ai-sdk/ai-sdk.test.ts | 2 +- js/src/wrappers/anthropic.test.ts | 2 +- .../claude-agent-sdk/claude-agent-sdk.test.ts | 2 +- js/src/wrappers/google-genai.test.ts | 2 +- js/src/wrappers/oai.test.ts | 2 +- .../api-compatibility.test.ts | 6 +- js/tsup.config.ts | 11 +-- 36 files changed, 237 insertions(+), 152 deletions(-) delete mode 100644 js/src/browser-config.ts create mode 100644 js/src/browser/config.ts rename js/src/{browser.ts => browser/index.ts} (75%) create mode 100644 js/src/edge-light/config.ts create mode 100644 js/src/edge-light/index.ts rename js/src/{node.ts => node/config.ts} (87%) rename js/src/{ => node}/index.ts (88%) create mode 100644 js/src/workerd/config.ts create mode 100644 js/src/workerd/index.ts diff --git a/integrations/browser-js/package.json b/integrations/browser-js/package.json index 68a639b69..233900945 100644 --- a/integrations/browser-js/package.json +++ b/integrations/browser-js/package.json @@ -1,6 +1,6 @@ { "name": "@braintrust/browser", - "version": "0.0.2", + "version": "0.0.2-rc.4", "description": "Braintrust SDK for browser environments with AsyncLocalStorage polyfill", "type": "module", "module": "./dist/index.js", diff --git a/integrations/browser-js/src/browser-config.ts b/integrations/browser-js/src/browser-config.ts index 3ff67987e..ace837d42 100644 --- a/integrations/browser-js/src/browser-config.ts +++ b/integrations/browser-js/src/browser-config.ts @@ -3,7 +3,7 @@ import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; export function configureBrowser() { // Set build type indicator - iso.buildType = "browser"; + iso.buildType = "browser-js"; iso.newAsyncLocalStorage = () => new BrowserAsyncLocalStorage(); diff --git a/js/dev/index.ts b/js/dev/index.ts index da73e2a93..7ac9af952 100644 --- a/js/dev/index.ts +++ b/js/dev/index.ts @@ -1,4 +1,4 @@ -import { configureNode } from "../src/node"; +import { configureNode } from "../src/node/config"; configureNode(); diff --git a/js/examples/ai-sdk/stopWhen.ts b/js/examples/ai-sdk/stopWhen.ts index 28eea52fc..3ac971f10 100644 --- a/js/examples/ai-sdk/stopWhen.ts +++ b/js/examples/ai-sdk/stopWhen.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import * as ai from "ai"; import { wrapAISDK } from "ai-sdk"; import { initLogger } from "../../../logger"; -import { configureNode } from "../../../node"; +import { configureNode } from "../../../node/config"; import { openai } from "@ai-sdk/openai"; configureNode(); diff --git a/js/package.json b/js/package.json index d51a3cd62..6d40c5be6 100644 --- a/js/package.json +++ b/js/package.json @@ -24,8 +24,8 @@ "./package.json": "./package.json", ".": { "types": "./dist/index.d.ts", - "edge-light": "./dist/browser.mjs", - "workerd": "./dist/browser.mjs", + "edge-light": "./dist/edge-light.mjs", + "workerd": "./dist/workerd.mjs", "node": { "import": "./dist/index.mjs", "require": "./dist/index.js" @@ -36,14 +36,14 @@ "default": "./dist/index.mjs" }, "./workerd": { - "import": "./dist/browser.mjs", - "require": "./dist/browser.js", - "default": "./dist/browser.mjs" + "import": "./dist/workerd.mjs", + "require": "./dist/workerd.js", + "default": "./dist/workerd.mjs" }, "./edge-light": { - "import": "./dist/browser.mjs", - "require": "./dist/browser.js", - "default": "./dist/browser.mjs" + "import": "./dist/edge-light.mjs", + "require": "./dist/edge-light.js", + "default": "./dist/edge-light.mjs" }, "./browser": { "import": "./dist/browser.mjs", @@ -78,7 +78,7 @@ "build": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" tsup", "watch": "tsup --watch", "clean": "rm -r dist/* && rm -r dev/dist/*", - "docs": "npx typedoc --options typedoc.json src/index.ts", + "docs": "npx typedoc --options typedoc.json src/node/index.ts", "test": "vitest run --exclude \"src/wrappers/**/*.test.ts\" --exclude \"src/otel/**/*.test.ts\" --exclude \"smoke/**/*.test.ts\" --exclude \"src/zod/**/*.test.ts\" --exclude \"tests/api-compatibility/**\"", "test:api-compat": "vitest run tests/api-compatibility/api-compatibility.test.ts", "test:anthropic": "vitest run src/wrappers/anthropic.test.ts", diff --git a/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts b/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts index d815136e3..8c5d9fb7e 100644 --- a/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts +++ b/js/smoke/scenarios/browser-main-package/tests/browser-message.test.ts @@ -57,32 +57,5 @@ test.describe("Braintrust Main Package Browser Build", () => { expect(testResults.hasInit).toBe(true); expect(testResults.hasNewId).toBe(true); expect(testResults.hasTraceable).toBe(true); - - // Expected message from browser-config.ts - const expectedMessage = - "This entrypoint is no longer supported.\n\n" + - "You should be using entrypoints:\n\n" + - "- `/workerd` (cloudflare envs)\n" + - "- `/edge-light` (next-js or other edge envs)\n\n" + - "If you'd like to use braintrust in the browser use the dedicated package: @braintrust/browser\n"; - - // Verify the full informational message appears in console - const hasInformationalMessage = consoleMessages.some( - (msg) => msg === expectedMessage, - ); - - expect(hasInformationalMessage).toBe(true); - - // Also verify from captured messages in the page - const hasCapturedMessage = testResults.consoleMessages.some( - (msg: string) => msg === expectedMessage, - ); - - expect(hasCapturedMessage).toBe(true); - - console.log("✓ Complete informational message verified"); - console.log( - "✓ Main package browser build working correctly with full message", - ); }); }); diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index e276c5aaa..4a023bca5 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -469,6 +469,7 @@ function detectBuildType(module: BraintrustModule): { const buildType = iso.buildType; if ( buildType === "browser" || + buildType === "browser-js" || buildType === "node" || buildType === "unknown" ) { diff --git a/js/src/browser-config.ts b/js/src/browser-config.ts deleted file mode 100644 index 718ec83cb..000000000 --- a/js/src/browser-config.ts +++ /dev/null @@ -1,73 +0,0 @@ -// Browser-safe isomorph that noops Node.js features -// This file is only used for the /browser, /edge-light, /workerd exports - -import iso from "./isomorph"; -import { _internalSetInitialState } from "./logger"; - -// This is copied from next.js. It seems they define AsyncLocalStorage in the edge -// environment, even though it's not defined in the browser. -import type { AsyncLocalStorage as NodeAsyncLocalStorage } from "async_hooks"; - -declare global { - var AsyncLocalStorage: typeof NodeAsyncLocalStorage; -} -// End copied code - -let messageShown = false; -let browserConfigured = false; - -/** - * Configure the isomorph for browser environments. - */ -export function configureBrowser(): void { - if (browserConfigured) { - return; - } - - // Show informational message once - if (!messageShown && typeof console !== "undefined") { - console.info( - "This entrypoint is no longer supported.\n\n" + - "You should be using entrypoints:\n\n" + - "- `/workerd` (cloudflare envs)\n" + - "- `/edge-light` (next-js or other edge envs)\n\n" + - "If you'd like to use braintrust in the browser use the dedicated package: @braintrust/browser\n", - ); - messageShown = true; - } - - // Configure browser-safe implementations - iso.buildType = "browser"; - - try { - if (typeof AsyncLocalStorage !== "undefined") { - iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); - } - } catch { - // Ignore - } - - iso.getEnv = (name: string) => { - if (typeof process === "undefined" || typeof process.env === "undefined") { - return undefined; - } - return process.env[name]; - }; - - // Implement browser-compatible hash function using a simple hash algorithm - iso.hash = (data: string): string => { - // Simple hash function for browser compatibility - let hash = 0; - for (let i = 0; i < data.length; i++) { - const char = data.charCodeAt(i); - hash = (hash << 5) - hash + char; - hash = hash & hash; // Convert to 32bit integer - } - // Convert to hex string - const hashHex = (hash >>> 0).toString(16).padStart(8, "0"); - return hashHex.repeat(8).substring(0, 64); // Make it look like a SHA-256 hash length - }; - - _internalSetInitialState(); - browserConfigured = true; -} diff --git a/js/src/browser/config.ts b/js/src/browser/config.ts new file mode 100644 index 000000000..8dd2bf5db --- /dev/null +++ b/js/src/browser/config.ts @@ -0,0 +1,51 @@ +import iso from "../isomorph"; +import { _internalSetInitialState } from "../logger"; + +import type { AsyncLocalStorage as NodeAsyncLocalStorage } from "async_hooks"; + +declare global { + var AsyncLocalStorage: typeof NodeAsyncLocalStorage; + var __BRAINTRUST_BROWSER_PKG__: boolean | undefined; +} + +let browserConfigured = false; + +/** + * Configure the isomorph for browser environments. + */ +export function configureBrowser(): void { + if (browserConfigured) { + return; + } + + iso.buildType = "browser"; + + try { + if (typeof AsyncLocalStorage !== "undefined") { + iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); + } + } catch { + // Ignore + } + + iso.getEnv = (name: string) => { + if (typeof process === "undefined" || typeof process.env === "undefined") { + return undefined; + } + return process.env[name]; + }; + + iso.hash = (data: string): string => { + let hash = 0; + for (let i = 0; i < data.length; i++) { + const char = data.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash = hash & hash; + } + const hashHex = (hash >>> 0).toString(16).padStart(8, "0"); + return hashHex.repeat(8).substring(0, 64); + }; + + _internalSetInitialState(); + browserConfigured = true; +} diff --git a/js/src/browser.ts b/js/src/browser/index.ts similarity index 75% rename from js/src/browser.ts rename to js/src/browser/index.ts index bb53bcda2..f478444b7 100644 --- a/js/src/browser.ts +++ b/js/src/browser/index.ts @@ -9,9 +9,9 @@ * import * as braintrust from '@braintrust/browser'; */ -import { configureBrowser } from "./browser-config"; +import { configureBrowser } from "./config"; configureBrowser(); -export * from "./exports"; -export * as default from "./exports"; +export * from "../exports"; +export * as default from "../exports"; diff --git a/js/src/cli/index.ts b/js/src/cli/index.ts index b0ed5fbaa..b29c78152 100755 --- a/js/src/cli/index.ts +++ b/js/src/cli/index.ts @@ -40,7 +40,7 @@ import { runEvaluator, } from "../framework"; import { fancyReporter, warning } from "./reporters/eval"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; import { isEmpty } from "../util"; import { loadEnvConfig } from "@next/env"; import type { diff --git a/js/src/edge-light/config.ts b/js/src/edge-light/config.ts new file mode 100644 index 000000000..a437f1b9c --- /dev/null +++ b/js/src/edge-light/config.ts @@ -0,0 +1,50 @@ +import iso from "../isomorph"; +import { _internalSetInitialState } from "../logger"; + +import type { AsyncLocalStorage as NodeAsyncLocalStorage } from "async_hooks"; + +declare global { + var AsyncLocalStorage: typeof NodeAsyncLocalStorage; +} + +let edgeLightConfigured = false; + +/** + * Configure the isomorph for edge-light runtime environments (Vercel Edge, Next.js Edge, etc.). + */ +export function configureEdgeLight(): void { + if (edgeLightConfigured) { + return; + } + + iso.buildType = "browser"; + + try { + if (typeof AsyncLocalStorage !== "undefined") { + iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); + } + } catch { + // Ignore + } + + iso.getEnv = (name: string) => { + if (typeof process === "undefined" || typeof process.env === "undefined") { + return undefined; + } + return process.env[name]; + }; + + iso.hash = (data: string): string => { + let hash = 0; + for (let i = 0; i < data.length; i++) { + const char = data.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash = hash & hash; + } + const hashHex = (hash >>> 0).toString(16).padStart(8, "0"); + return hashHex.repeat(8).substring(0, 64); + }; + + _internalSetInitialState(); + edgeLightConfigured = true; +} diff --git a/js/src/edge-light/index.ts b/js/src/edge-light/index.ts new file mode 100644 index 000000000..4c6ef7bbf --- /dev/null +++ b/js/src/edge-light/index.ts @@ -0,0 +1,13 @@ +/** + * Edge Light runtime build of the Braintrust SDK. + * + * This build is optimized for edge runtime environments like Vercel Edge Runtime, + * Next.js Edge Runtime, and other edge platforms that support AsyncLocalStorage. + */ + +import { configureEdgeLight } from "./config"; + +configureEdgeLight(); + +export * from "../exports"; +export * as default from "../exports"; diff --git a/js/src/framework.test.ts b/js/src/framework.test.ts index 9a4172430..0ffff004b 100644 --- a/js/src/framework.test.ts +++ b/js/src/framework.test.ts @@ -14,7 +14,7 @@ import { runEvaluator, } from "./framework"; import { _exportsForTestingOnly, BraintrustState } from "./logger"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; import type { ProgressReporter } from "./reporters/types"; import { InternalAbortError } from "./util"; diff --git a/js/src/functions/invoke.test.ts b/js/src/functions/invoke.test.ts index f887512ca..653d48ddb 100644 --- a/js/src/functions/invoke.test.ts +++ b/js/src/functions/invoke.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, beforeEach, afterEach, vi } from "vitest"; import { initFunction } from "./invoke"; import { _internalGetGlobalState, _exportsForTestingOnly } from "../logger"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; describe("initFunction", () => { beforeEach(() => { diff --git a/js/src/isomorph.ts b/js/src/isomorph.ts index eef739889..9b479eb52 100644 --- a/js/src/isomorph.ts +++ b/js/src/isomorph.ts @@ -30,7 +30,13 @@ class DefaultAsyncLocalStorage implements IsoAsyncLocalStorage { } export interface Common { - buildType: "browser" | "node" | "unknown"; + buildType: + | "browser" // deprecated, use /workerd or /edge-light entrypoints for edge environments + | "browser-js" // @braintrust/browser package + | "node" + | "edge-light" + | "workerd" + | "unknown"; getRepoInfo: ( settings?: GitMetadataSettings, diff --git a/js/src/logger-misc.test.ts b/js/src/logger-misc.test.ts index 381557fcb..d40ab7edd 100644 --- a/js/src/logger-misc.test.ts +++ b/js/src/logger-misc.test.ts @@ -20,7 +20,7 @@ import { import { SpanObjectTypeV3 } from "../util/index"; import { LazyValue } from "./util"; import { BackgroundLogEvent, IS_MERGE_FIELD } from "../util/index"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; configureNode(); diff --git a/js/src/logger.test.ts b/js/src/logger.test.ts index 577055c0d..ca9b22ed5 100644 --- a/js/src/logger.test.ts +++ b/js/src/logger.test.ts @@ -24,7 +24,7 @@ import { isTemplateFormat, renderTemplateContent, } from "./template/renderer"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; import { writeFile, unlink } from "node:fs/promises"; import { join } from "node:path"; import { tmpdir } from "node:os"; diff --git a/js/src/masking.test.ts b/js/src/masking.test.ts index 7b74c5af9..cb4c977f8 100644 --- a/js/src/masking.test.ts +++ b/js/src/masking.test.ts @@ -9,7 +9,7 @@ import { currentSpan, setMaskingFunction, } from "./logger"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; configureNode(); diff --git a/js/src/node.ts b/js/src/node/config.ts similarity index 87% rename from js/src/node.ts rename to js/src/node/config.ts index 2351c6ca4..f6ca7eee2 100644 --- a/js/src/node.ts +++ b/js/src/node/config.ts @@ -4,16 +4,15 @@ import * as fs from "node:fs/promises"; import * as os from "node:os"; import * as fsSync from "node:fs"; import * as crypto from "node:crypto"; - -import iso from "./isomorph"; -import { getRepoInfo, getPastNAncestors } from "./gitutil"; -import { getCallerLocation } from "./stackutil"; -import { _internalSetInitialState } from "./logger"; import { promisify } from "node:util"; import * as zlib from "node:zlib"; +import iso from "../isomorph"; +import { getRepoInfo, getPastNAncestors } from "../gitutil"; +import { getCallerLocation } from "../stackutil"; +import { _internalSetInitialState } from "../logger"; + export function configureNode() { - // Set build type indicator iso.buildType = "node"; iso.getRepoInfo = getRepoInfo; diff --git a/js/src/index.ts b/js/src/node/index.ts similarity index 88% rename from js/src/index.ts rename to js/src/node/index.ts index ebea4d0fb..821cbcaaa 100644 --- a/js/src/index.ts +++ b/js/src/node/index.ts @@ -51,10 +51,9 @@ * @module braintrust */ -import { configureNode } from "./node"; +import { configureNode } from "./config"; configureNode(); -// eslint-disable-next-line no-restricted-syntax -- already enforced in exports -export * from "./exports"; -export * as default from "./exports"; +export * from "../exports"; +export * as default from "../exports"; diff --git a/js/src/parameters.test.ts b/js/src/parameters.test.ts index 3bcfb9323..cce63d7bd 100644 --- a/js/src/parameters.test.ts +++ b/js/src/parameters.test.ts @@ -2,7 +2,7 @@ import { expect, test, beforeAll } from "vitest"; import { runEvaluator } from "./framework"; import { z } from "zod/v3"; import { type ProgressReporter } from "./reporters/types"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; beforeAll(() => { configureNode(); diff --git a/js/src/prompt-cache/disk-cache.test.ts b/js/src/prompt-cache/disk-cache.test.ts index 0767c8c92..ed0664346 100644 --- a/js/src/prompt-cache/disk-cache.test.ts +++ b/js/src/prompt-cache/disk-cache.test.ts @@ -3,7 +3,7 @@ import * as path from "path"; import { DiskCache } from "./disk-cache"; import { tmpdir } from "os"; import { beforeEach, describe, it, afterEach, expect } from "vitest"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; describe("DiskCache", () => { configureNode(); diff --git a/js/src/prompt-cache/prompt-cache.test.ts b/js/src/prompt-cache/prompt-cache.test.ts index 284b521fb..e8716f268 100644 --- a/js/src/prompt-cache/prompt-cache.test.ts +++ b/js/src/prompt-cache/prompt-cache.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "os"; import { beforeEach, describe, it, afterEach, expect } from "vitest"; import type { PromptKey } from "./prompt-cache"; import { DiskCache } from "./disk-cache"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; import { LRUCache } from "./lru-cache"; describe("PromptCache", () => { diff --git a/js/src/prompt.test.ts b/js/src/prompt.test.ts index 849158cc2..3e18470ff 100644 --- a/js/src/prompt.test.ts +++ b/js/src/prompt.test.ts @@ -1,5 +1,5 @@ import { beforeAll, describe, test, expect, vi } from "vitest"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; import { Prompt } from "./logger"; import { type PromptDataType as PromptData } from "./generated_types"; @@ -307,7 +307,7 @@ describe("prompt template_format (unconfigured/browser-like)", () => { }); test("throws unsupported error after configureBrowser()", async () => { vi.resetModules(); - const { configureBrowser } = await import("./browser-config"); + const { configureBrowser } = await import("./browser/config"); const { Prompt: BrowserConfiguredPrompt } = await import("./logger"); configureBrowser(); diff --git a/js/src/span-cache.test.ts b/js/src/span-cache.test.ts index e3e010cfa..8479da30f 100644 --- a/js/src/span-cache.test.ts +++ b/js/src/span-cache.test.ts @@ -7,7 +7,7 @@ import { beforeAll, } from "vitest"; import { SpanCache } from "./span-cache"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; describe("SpanCache (disk-based)", () => { let cache: SpanCache; diff --git a/js/src/trace.test.ts b/js/src/trace.test.ts index 6ea4a4188..a050e2028 100644 --- a/js/src/trace.test.ts +++ b/js/src/trace.test.ts @@ -9,7 +9,7 @@ import { } from "vitest"; import { CachedSpanFetcher, LocalTrace, SpanData, SpanFetchFn } from "./trace"; import { _exportsForTestingOnly, _internalGetGlobalState } from "./logger"; -import { configureNode } from "./node"; +import { configureNode } from "./node/config"; // Mock the invoke function vi.mock("./functions/invoke", () => ({ diff --git a/js/src/workerd/config.ts b/js/src/workerd/config.ts new file mode 100644 index 000000000..181e86b46 --- /dev/null +++ b/js/src/workerd/config.ts @@ -0,0 +1,50 @@ +import iso from "../isomorph"; +import { _internalSetInitialState } from "../logger"; + +import type { AsyncLocalStorage as NodeAsyncLocalStorage } from "async_hooks"; + +declare global { + var AsyncLocalStorage: typeof NodeAsyncLocalStorage; +} + +let workerdConfigured = false; + +/** + * Configure the isomorph for Cloudflare Workers (workerd) runtime. + */ +export function configureWorkerd(): void { + if (workerdConfigured) { + return; + } + + iso.buildType = "browser"; + + try { + if (typeof AsyncLocalStorage !== "undefined") { + iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); + } + } catch { + // Ignore + } + + iso.getEnv = (name: string) => { + if (typeof process === "undefined" || typeof process.env === "undefined") { + return undefined; + } + return process.env[name]; + }; + + iso.hash = (data: string): string => { + let hash = 0; + for (let i = 0; i < data.length; i++) { + const char = data.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash = hash & hash; + } + const hashHex = (hash >>> 0).toString(16).padStart(8, "0"); + return hashHex.repeat(8).substring(0, 64); + }; + + _internalSetInitialState(); + workerdConfigured = true; +} diff --git a/js/src/workerd/index.ts b/js/src/workerd/index.ts new file mode 100644 index 000000000..7f1f92300 --- /dev/null +++ b/js/src/workerd/index.ts @@ -0,0 +1,13 @@ +/** + * Cloudflare Workers (workerd) build of the Braintrust SDK. + * + * This build is optimized for Cloudflare Workers and other workerd-based + * runtime environments. + */ + +import { configureWorkerd } from "./config"; + +configureWorkerd(); + +export * from "../exports"; +export * as default from "../exports"; diff --git a/js/src/wrappers/ai-sdk/ai-sdk.test.ts b/js/src/wrappers/ai-sdk/ai-sdk.test.ts index 0617edddf..4b86abdaa 100644 --- a/js/src/wrappers/ai-sdk/ai-sdk.test.ts +++ b/js/src/wrappers/ai-sdk/ai-sdk.test.ts @@ -10,7 +10,7 @@ import { expectTypeOf, expect, } from "vitest"; -import { configureNode } from "../../node"; +import { configureNode } from "../../node/config"; import * as ai from "ai"; import { openai } from "@ai-sdk/openai"; import { diff --git a/js/src/wrappers/anthropic.test.ts b/js/src/wrappers/anthropic.test.ts index ee6d1757e..bfa80422f 100644 --- a/js/src/wrappers/anthropic.test.ts +++ b/js/src/wrappers/anthropic.test.ts @@ -11,7 +11,7 @@ import { import Anthropic from "@anthropic-ai/sdk"; import { wrapAnthropic } from "./anthropic"; import { _exportsForTestingOnly, Attachment, initLogger } from "../logger"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; import { getCurrentUnixTimestamp } from "../util"; // use the cheapest model for tests diff --git a/js/src/wrappers/claude-agent-sdk/claude-agent-sdk.test.ts b/js/src/wrappers/claude-agent-sdk/claude-agent-sdk.test.ts index fcc4a3a62..9ddeb7036 100644 --- a/js/src/wrappers/claude-agent-sdk/claude-agent-sdk.test.ts +++ b/js/src/wrappers/claude-agent-sdk/claude-agent-sdk.test.ts @@ -9,7 +9,7 @@ import { } from "vitest"; import { wrapClaudeAgentSDK } from "./claude-agent-sdk"; import { initLogger, _exportsForTestingOnly } from "../../logger"; -import { configureNode } from "../../node"; +import { configureNode } from "../../node/config"; import { z } from "zod/v3"; debugger; diff --git a/js/src/wrappers/google-genai.test.ts b/js/src/wrappers/google-genai.test.ts index c37e9e33c..45586f810 100644 --- a/js/src/wrappers/google-genai.test.ts +++ b/js/src/wrappers/google-genai.test.ts @@ -7,7 +7,7 @@ import { describe, expect, } from "vitest"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; import * as googleGenAI from "@google/genai"; import { _exportsForTestingOnly, diff --git a/js/src/wrappers/oai.test.ts b/js/src/wrappers/oai.test.ts index 80c6bda65..5553e63ee 100644 --- a/js/src/wrappers/oai.test.ts +++ b/js/src/wrappers/oai.test.ts @@ -8,7 +8,7 @@ import { expect, vi, } from "vitest"; -import { configureNode } from "../node"; +import { configureNode } from "../node/config"; import OpenAI from "openai"; import { _exportsForTestingOnly, diff --git a/js/tests/api-compatibility/api-compatibility.test.ts b/js/tests/api-compatibility/api-compatibility.test.ts index 5315182a9..056656092 100644 --- a/js/tests/api-compatibility/api-compatibility.test.ts +++ b/js/tests/api-compatibility/api-compatibility.test.ts @@ -96,8 +96,10 @@ function getEntrypointName(entryFile: string, outDir: string): string { const basename = path.basename(entryFile, path.extname(entryFile)); // Map common patterns to friendly names - if (entryFile.includes("src/index.ts")) return "main"; - if (entryFile.includes("src/browser.ts")) return "browser"; + if (entryFile.includes("src/node/index.ts")) return "main"; + if (entryFile.includes("src/browser/index.ts")) return "browser"; + if (entryFile.includes("src/edge-light/index.ts")) return "edge-light"; + if (entryFile.includes("src/workerd/index.ts")) return "workerd"; if (entryFile.includes("dev/index.ts")) return "dev"; if (entryFile.includes("util/index.ts")) return "util"; diff --git a/js/tsup.config.ts b/js/tsup.config.ts index 875d4ec22..98072f5c1 100644 --- a/js/tsup.config.ts +++ b/js/tsup.config.ts @@ -1,10 +1,9 @@ import { defineConfig } from "tsup"; -import fs from "node:fs"; -import { builtinModules } from "node:module"; export default defineConfig([ + // Node.js entrypoint { - entry: ["src/index.ts"], + entry: ["src/node/index.ts"], format: ["cjs", "esm"], outDir: "dist", external: ["zod"], @@ -58,10 +57,12 @@ export default defineConfig([ splitting: true, clean: true, }, - // Browser/edge exports - single build used by browser, edge-light, and workerd + // Browser/edge entrypoints { entry: { - browser: "src/browser.ts", + browser: "src/browser/index.ts", + "edge-light": "src/edge-light/index.ts", + workerd: "src/workerd/index.ts", }, format: ["cjs", "esm"], outDir: "dist", From c16291cfc507debcdaeb925d2f5b3669ff6717e8 Mon Sep 17 00:00:00 2001 From: Caitlin Pinn Date: Tue, 17 Feb 2026 21:42:05 -0800 Subject: [PATCH 57/57] Remove braintrust browser from some wrangler tests (#1386) Add als-browser to the main package for cloudflare workerd Test for specific build configuration from the braintrust package. --- .../otel-v1/tests/shared-suite.test.ts | 2 +- js/package.json | 1 + .../src/worker-node-esm.ts | 6 +-- .../package.json | 1 - .../src/worker.ts | 4 +- .../package.json | 1 - .../src/worker.ts | 4 +- .../package.json | 1 - .../src/worker.ts | 4 +- .../package.json | 1 - .../src/worker.ts | 4 +- .../src/worker.ts | 4 +- .../src/worker.ts | 2 +- .../deno-browser/tests/shared-suite.test.ts | 2 +- .../deno-node/tests/shared-suite.test.ts | 2 +- .../jest-node/tests/shared-suite.test.js | 2 +- .../nextjs-instrumentation/package.json | 1 - .../src/app/api/smoke-test/edge/route.ts | 4 +- .../src/app/api/smoke-test/node/route.ts | 2 +- .../scenarios/playwright-browser/package.json | 1 - .../playwright-browser/src/browser-tests.ts | 4 +- .../shared/src/suites/import-verification.ts | 38 +++++++++++++++---- js/src/browser/config.ts | 4 +- js/src/edge-light/config.ts | 2 +- js/src/workerd/config.ts | 17 ++------- pnpm-lock.yaml | 3 ++ 26 files changed, 65 insertions(+), 52 deletions(-) diff --git a/integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts b/integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts index 83fba976f..7d59e9df9 100644 --- a/integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts +++ b/integrations/otel-js/smoke/scenarios/otel-v1/tests/shared-suite.test.ts @@ -51,7 +51,7 @@ async function runSharedTestSuites() { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("node"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/package.json b/js/package.json index 6d40c5be6..67538c869 100644 --- a/js/package.json +++ b/js/package.json @@ -144,6 +144,7 @@ "@next/env": "^14.2.3", "@vercel/functions": "^1.0.2", "ajv": "^8.17.1", + "als-browser": "^1.0.0", "argparse": "^2.0.1", "boxen": "^8.0.1", "chalk": "^4.1.2", diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts index bfe08e49b..06ce5ca3f 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev-node-esm/src/worker-node-esm.ts @@ -28,7 +28,7 @@ import { testEvalSmoke, } from "../../../shared"; -import * as braintrust from "braintrust/node"; +import * as braintrust from "braintrust"; const app = new Hono<{ Bindings: Env }>(); @@ -41,7 +41,7 @@ GET /api/ - Basic API endpoint GET /api/test - Run shared test suites This worker tests the Braintrust SDK (Node.js ESM build) in a Vite + Hono + Cloudflare Workers environment. -Explicitly imports "braintrust/node" to test Node.js ESM build resolution.`), +`), ); app.get("/api/", (c) => @@ -66,7 +66,7 @@ app.get("/api/test", async (c) => { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json index 8b0168d16..272211cad 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/package.json @@ -4,7 +4,6 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "hono": "^4.11.1", "react": "^19.2.1", "react-dom": "^19.2.1", diff --git a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts index 887aa1d0d..8c8f8940e 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-vite-dev/src/worker.ts @@ -28,7 +28,7 @@ import { testEvalSmoke, } from "../../../shared"; -import * as braintrust from "@braintrust/browser"; +import * as braintrust from "braintrust"; const app = new Hono<{ Bindings: Env }>(); @@ -61,7 +61,7 @@ app.get("/api/test", async (c) => { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json index 9a8899a7a..c0edc8625 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/package.json @@ -4,7 +4,6 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "hono": "^4.11.1", "zod": "^3.25.76" }, diff --git a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts index 33b9cfe33..792d64d33 100644 --- a/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-vite-hono-wrangler-dev/src/worker.ts @@ -28,7 +28,7 @@ import { testEvalSmoke, } from "../../../shared"; -import * as braintrust from "@braintrust/browser"; +import * as braintrust from "braintrust"; const app = new Hono<{ Bindings: Env }>(); @@ -61,7 +61,7 @@ app.get("/api/test", async (c) => { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json b/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json index 65ba9854f..c39db0404 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/package.json @@ -4,7 +4,6 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "zod": "^3.25.76" }, "devDependencies": { diff --git a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts index 28d7d810a..94ea7de95 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "@braintrust/browser"; +import * as braintrust from "braintrust"; import { runTests, expectFailure, @@ -52,7 +52,7 @@ export default { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json index 438b44a00..5e8ae393f 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/package.json @@ -4,7 +4,6 @@ "type": "module", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "zod": "^3.25.76" }, "devDependencies": { diff --git a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts index 328496ebb..81ec98406 100644 --- a/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-browser-no-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "@braintrust/browser"; +import * as braintrust from "braintrust"; import { runTests, expectFailure, @@ -52,7 +52,7 @@ export default { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts index 6fd2f7f01..6d9d08a62 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-compat/src/worker.ts @@ -1,4 +1,4 @@ -import * as braintrust from "braintrust/node"; +import * as braintrust from "braintrust"; import { runTests, expectFailure, @@ -52,7 +52,7 @@ export default { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts index 86a08c0cf..8d2100519 100644 --- a/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts +++ b/js/smoke/scenarios/cloudflare-worker-node-no-compat/src/worker.ts @@ -52,7 +52,7 @@ export default { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("workerd"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts index eb3dd0884..b1c902672 100644 --- a/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-browser/tests/shared-suite.test.ts @@ -52,7 +52,7 @@ Deno.test("Run shared test suites (browser build)", async () => { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("browser"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts index 3286585cb..cd70263a0 100644 --- a/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts +++ b/js/smoke/scenarios/deno-node/tests/shared-suite.test.ts @@ -52,7 +52,7 @@ Deno.test("Run shared test suites", async () => { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("node"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js index 13aeffdf4..fef664bd7 100644 --- a/js/smoke/scenarios/jest-node/tests/shared-suite.test.js +++ b/js/smoke/scenarios/jest-node/tests/shared-suite.test.js @@ -47,7 +47,7 @@ test("shared test suites pass in Jest", async () => { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("node"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/nextjs-instrumentation/package.json b/js/smoke/scenarios/nextjs-instrumentation/package.json index 19528dbd4..e8faeef10 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/package.json +++ b/js/smoke/scenarios/nextjs-instrumentation/package.json @@ -8,7 +8,6 @@ }, "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "@braintrust/otel": "file:../../../artifacts/braintrust-otel-latest.tgz", "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.200.0", diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts index 79beb7dff..36adffd31 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/edge/route.ts @@ -32,7 +32,7 @@ import { testEvalSmoke, } from "../../../../../../../shared"; -import * as braintrust from "@braintrust/browser"; +import * as braintrust from "braintrust"; export const runtime = "edge"; @@ -56,7 +56,7 @@ export async function GET() { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("edge-light"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts index 7c86e8440..e4a52ebf7 100644 --- a/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts +++ b/js/smoke/scenarios/nextjs-instrumentation/src/app/api/smoke-test/node/route.ts @@ -56,7 +56,7 @@ export async function GET() { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("node"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/scenarios/playwright-browser/package.json b/js/smoke/scenarios/playwright-browser/package.json index e703f5b2d..49818a121 100644 --- a/js/smoke/scenarios/playwright-browser/package.json +++ b/js/smoke/scenarios/playwright-browser/package.json @@ -6,7 +6,6 @@ "description": "Playwright browser smoke test for Braintrust SDK", "dependencies": { "braintrust": "file:../../../artifacts/braintrust-latest.tgz", - "@braintrust/browser": "file:../../../artifacts/braintrust-browser-latest.tgz", "zod": "^4.3.5" }, "devDependencies": { diff --git a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts index f28a9ada7..8a1a0d65d 100644 --- a/js/smoke/scenarios/playwright-browser/src/browser-tests.ts +++ b/js/smoke/scenarios/playwright-browser/src/browser-tests.ts @@ -1,4 +1,4 @@ -import * as braintrust from "@braintrust/browser"; +import * as braintrust from "braintrust"; import { runTests, expectFailure, @@ -72,7 +72,7 @@ async function runAllTestSuites() { testIDGeneratorExports, testTestingExports, testStateManagementExports, - testBuildResolution, + testBuildResolution("browser"), testBasicSpanLogging, testMultipleSpans, testDirectLogging, diff --git a/js/smoke/shared/src/suites/import-verification.ts b/js/smoke/shared/src/suites/import-verification.ts index 4a023bca5..39515d3dc 100644 --- a/js/smoke/shared/src/suites/import-verification.ts +++ b/js/smoke/shared/src/suites/import-verification.ts @@ -18,7 +18,7 @@ */ import { assertType, assertDefined } from "../helpers/assertions"; -import { register } from "../helpers/register"; +import { register, type TestFn } from "../helpers/register"; /** * Interface for the Braintrust module based on exports.ts @@ -422,9 +422,15 @@ export const testStateManagementExports = register( }, ); -export const testBuildResolution = register( - "testBuildResolution", - async (module) => { +export function testBuildResolution( + expectedBuildType?: + | "browser" + | "browser-js" + | "edge-light" + | "workerd" + | "node", +): TestFn { + return register("testBuildResolution", async (module) => { const { buildType: detectedBuild, buildDetails } = detectBuildType(module); const detectedFormat = detectModuleFormat(); @@ -434,18 +440,34 @@ export const testBuildResolution = register( ); } + if (expectedBuildType && detectedBuild !== expectedBuildType) { + throw new Error( + `Expected build type "${expectedBuildType}" but detected "${detectedBuild}"`, + ); + } + const parts: string[] = [`Detected ${detectedBuild} build`]; + if (expectedBuildType) { + parts.push(`(expected: ${expectedBuildType})`); + } + if (detectedFormat !== "unknown") { parts.push(`${detectedFormat} format`); } return parts.join(", "); - }, -); + }); +} function detectBuildType(module: BraintrustModule): { - buildType: "browser" | "node" | "unknown"; + buildType: + | "browser" + | "browser-js" + | "edge-light" + | "workerd" + | "node" + | "unknown"; buildDetails: string; } { if (!module._exportsForTestingOnly) { @@ -470,6 +492,8 @@ function detectBuildType(module: BraintrustModule): { if ( buildType === "browser" || buildType === "browser-js" || + buildType === "edge-light" || + buildType === "workerd" || buildType === "node" || buildType === "unknown" ) { diff --git a/js/src/browser/config.ts b/js/src/browser/config.ts index 8dd2bf5db..74946c877 100644 --- a/js/src/browser/config.ts +++ b/js/src/browser/config.ts @@ -1,6 +1,6 @@ import iso from "../isomorph"; import { _internalSetInitialState } from "../logger"; - +import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; import type { AsyncLocalStorage as NodeAsyncLocalStorage } from "async_hooks"; declare global { @@ -23,6 +23,8 @@ export function configureBrowser(): void { try { if (typeof AsyncLocalStorage !== "undefined") { iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); + } else { + iso.newAsyncLocalStorage = () => new BrowserAsyncLocalStorage(); } } catch { // Ignore diff --git a/js/src/edge-light/config.ts b/js/src/edge-light/config.ts index a437f1b9c..d4583f794 100644 --- a/js/src/edge-light/config.ts +++ b/js/src/edge-light/config.ts @@ -17,7 +17,7 @@ export function configureEdgeLight(): void { return; } - iso.buildType = "browser"; + iso.buildType = "edge-light"; try { if (typeof AsyncLocalStorage !== "undefined") { diff --git a/js/src/workerd/config.ts b/js/src/workerd/config.ts index 181e86b46..048a723c4 100644 --- a/js/src/workerd/config.ts +++ b/js/src/workerd/config.ts @@ -1,11 +1,6 @@ import iso from "../isomorph"; import { _internalSetInitialState } from "../logger"; - -import type { AsyncLocalStorage as NodeAsyncLocalStorage } from "async_hooks"; - -declare global { - var AsyncLocalStorage: typeof NodeAsyncLocalStorage; -} +import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser"; let workerdConfigured = false; @@ -17,15 +12,9 @@ export function configureWorkerd(): void { return; } - iso.buildType = "browser"; + iso.buildType = "workerd"; - try { - if (typeof AsyncLocalStorage !== "undefined") { - iso.newAsyncLocalStorage = () => new AsyncLocalStorage(); - } - } catch { - // Ignore - } + iso.newAsyncLocalStorage = () => new BrowserAsyncLocalStorage(); iso.getEnv = (name: string) => { if (typeof process === "undefined" || typeof process.env === "undefined") { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d6746472..d8e1f83b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -252,6 +252,9 @@ importers: ajv: specifier: ^8.17.1 version: 8.17.1 + als-browser: + specifier: ^1.0.0 + version: 1.0.1 argparse: specifier: ^2.0.1 version: 2.0.1