diff --git a/.vscode/launch.json b/.vscode/launch.json index 39394521da5..fa0fa7453fc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -16,9 +16,8 @@ "name": "Debug Server", "runtimeExecutable": "node", "runtimeArgs": [ - "--loader", - "ts-node/esm", - "--experimental-specifier-resolution=node", + "--import", + "tsx", "${workspaceFolder}/src/server/Server.ts" ], "env": { diff --git a/CLAUDE.md b/CLAUDE.md index ac330e5cb79..6851fe56abd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -102,7 +102,7 @@ Only `tests/client/**` runs under jsdom; everything else runs in the `node` envi ## Tech Stack -- **Bundler:** Vite + TypeScript 6 +- **Bundler:** Vite + TypeScript 7 - **Rendering:** Custom WebGL2 renderer (`src/client/render/`) - **UI Components:** Lit (LitElement) + Tailwind CSS 4 - **Audio:** Howler.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52e2e1c6ef3..f91c5f64984 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,6 +56,7 @@ Using AI tools is fine — but you **MUST** understand the code you are submitti - **Node.js**: Version 24.15.0 or newer in the Node 24 release line. - **npm**: Version 12.1.0 or newer in the npm 12 release line. If Node.js bundled an older version, run `npm install --global --ignore-scripts npm@12.1.0` before installing project dependencies. - **Git**: For version control. +- **Editor**: The project type-checks with TypeScript 7, which has no JavaScript API for editor extensions to drive. In VS Code, install the [TypeScript 7 native preview extension](https://marketplace.visualstudio.com/items?itemName=TypeScriptTeam.native-preview) to get language support for the workspace. ### Installation diff --git a/docs/EnginePackageSplit.md b/docs/EnginePackageSplit.md index e32e03fbd53..402c6ddb550 100644 --- a/docs/EnginePackageSplit.md +++ b/docs/EnginePackageSplit.md @@ -1,6 +1,6 @@ # Implementation: single-PR package split for #1701 -Status: implemented (2026-10-05); see [As built](#as-built) for where it differs from the plan. Tracks [#1701](https://github.com/openfrontio/OpenFrontIO/issues/1701). +Status: implemented (2026-10-05); see [As built](#as-built) for where it differs from the plan. Tracks [#1701](https://github.com/openfrontio/OpenFrontIO/issues/1701). The split landed; the codemod it used is [disabled](#the-codemod) until TypeScript 7.1 ships a compiler API again. One PR turns `src/core` into three npm workspace packages, `@openfront/engine-api`, `@openfront/engine` and `@openfront/shared`, with no behaviour change. It's built as ordered commits: the code changes first, each small enough to read, then one generated commit that only moves files. Analysis is against `main` at `89fe8a704`. @@ -115,6 +115,19 @@ Eight commits. Every one compiles, passes `npm test` on its own and leaves the t One script, `scripts/split-packages/run.ts`, built on the `typescript` compiler API (already a dependency) and run with `tsx`. It only rewrites import specifiers and runs `git mv`; it never edits declarations, so its output is easy to trust. It's deleted in a follow-up PR once the split has landed. +> **Tooling status (2026-10-23): disabled.** The codemod and the analysis +> scripts next to it (`scripts/split-packages/`) are built on the `typescript` +> compiler API, which TypeScript 7.0 no longer ships - the package only +> exports a version string. The replacement API (`typescript/sync`, +> `typescript/ast`) arrives with TypeScript 7.1: it is in beta now +> (`npm i -D typescript@7.1.0-beta`) and the final release is expected in +> December 2026. Until then the scripts are kept as they are, but they are not +> type-checked and they refuse to run, so **the next package split has to wait +> for that release**. To re-enable them: install `typescript@7.1.0-beta`, drop +> the `@ts-nocheck` markers and the `assertCompilerApiAvailable()` guards, and +> port the AST calls to the 7.1 API. See +> [#4982](https://github.com/openfrontio/OpenFrontIO/issues/4982). + **Input: `moves.json`, one file per commit that uses it.** ```json diff --git a/package-lock.json b/package-lock.json index 60d1ef4c491..97b6f495f00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,6 @@ "nanoid": "^5.1.16", "node-html-parser": "^7.1.0", "obscenity": "^0.4.6", - "ts-node": "^10.9.2", "tsx": "^4.22.4", "winston": "^3.19.0", "ws": "^8.21.0", @@ -74,12 +73,14 @@ "lit": "^3.3.2", "marked": "^18.0.5", "mrmime": "^2.0.1", + "oxc-parser": "^0.154.0", + "oxc-transform": "^0.154.0", "oxfmt": "^0.73.0", "oxlint": "^1.88.0", "oxlint-plugin-eslint": "^1.88.0", "oxlint-tsgolint": "^7.0.2004", "tailwindcss": "^4.2.4", - "typescript": "^6.0.3", + "typescript": "^7.0.2", "vite": "^8.0.16", "vite-plugin-html": "^3.2.2", "vitest": "^4.1.11", @@ -223,28 +224,6 @@ "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==", - "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==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", @@ -1040,6 +1019,7 @@ "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" @@ -1070,6 +1050,7 @@ "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": { @@ -1455,30 +1436,724 @@ "integrity": "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==", "license": "Apache-2.0", "engines": { - "node": ">=14" + "node": ">=14" + } + }, + "node_modules/@opentelemetry/winston-transport": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.26.0.tgz", + "integrity": "sha512-JHGw8T/u7g/U/LavVL040FLv38bAZZUkwwjckGFDQO3ohqJmcyXRvPqgKuvm/S+GRoEonoSkRrrl62kAPYU76A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.216.0", + "winston-transport": "4.*" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + } + }, + "node_modules/@oxc-parser/binding-android-arm-eabi": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.154.0.tgz", + "integrity": "sha512-sDdEtDl7vKdCvf54j72RJbowE3jCmyRz/+oOB6IAwQxAHZ0eI+Dcj4hvVnm0b9Dy31plUkdmfds9C+/Zt895Tg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.154.0.tgz", + "integrity": "sha512-UHrDPELzvWZoVkIDdSycj4bzcTMCJG3IbN++mSUgVBaUtNtWHjQ98U6Vz5bpF/1Ic3FYJyYhMr74huO5tVvpZw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-arm64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.154.0.tgz", + "integrity": "sha512-mokYzajOSXxtSRDWCdHARGdntrKH+rZZ24Jzo8AtafyNzz0NARmpMm26Tc5B6qiGrr6UliWibHCOif1qRN2vaA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.154.0.tgz", + "integrity": "sha512-WbtUBrclOVItWfLRSvs+Z/WLtXxJ2Ctv50PyuX894HzDN5/e0qzxVpTNPIVMzOerBhgKtFsSMcfxlYIAbvdVgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.154.0.tgz", + "integrity": "sha512-YooHZSLawOe2fqm+lDdG8oAaQh2NYV/RMYTYzWRLy72stm2BgE9O/8Al6kFENjkmzyyBccDLLBirGxVtpzQfrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.154.0.tgz", + "integrity": "sha512-hKOwhZbrXdTwc4bGVfbLCXl9f2swl6zWdISocLQSNX9MgPmwHE3qGzOUkCrkuGpwdCVHPnkfOwsqTuYsrP5uNg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.154.0.tgz", + "integrity": "sha512-tnjiooXEU013349O/yxKbF5Cusp1CfHWQ8kYR8tGeRzR/P4sOpQGQo21fsS71M0fMD6ESLq+lbvXFWi43PuKeQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.154.0.tgz", + "integrity": "sha512-Cao2kj+8d7BT6XJU1gV9eVQjV+Cr+e8vQm3tddDRZiM2hHrMDxwy3j6t+ofaSl0idyuPPCZ4AlpmQoj8yOT1QA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.154.0.tgz", + "integrity": "sha512-uiwA0V3q8llWA7/8r+a9BBjk4j5YMDmi6wfOsyQfGOJMQSLHEiZ3HI8ulea766ykUa9wJFWk9XWEl4uJrZLQqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-ppc64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.154.0.tgz", + "integrity": "sha512-LICfN0Xs4Zdko+bJy6eOAEQojDuIR26suF2JtOsMaXjgbCrpRSH7/NCvJhY13YvYBx12V6hnwrL8n0lk0rbNJQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.154.0.tgz", + "integrity": "sha512-gbbSYxLF8ssRbQ2qQPy+2EhGNwNH1bAoRdkk6cnWaKHqmCikpSIPtpXjFbCCtjTi0uojqOM3ghFQwQPbDQsU0Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-musl": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.154.0.tgz", + "integrity": "sha512-nSnRYYDLCcRVjSQzF3g6rKqCNYwo5o+aQgnn8BBXfe+ofCgMGlGqkfRyvXm6ptZvoxNkkWtLlqM8W7Xc3j6ZnQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.154.0.tgz", + "integrity": "sha512-BxBQoJKtzRQgZEKQIt6CDUm8RGKC5T8Qo4576yDa5/xgc10X3fBDItMbRabzLtbUBfTqKLl+8AVr/H6CF7W22g==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.154.0.tgz", + "integrity": "sha512-/whkust2vYy+GjRUVL5cWaJmEu6jkdFfo5mkxgckyeOX61eMwo4iBoiwzeJZeMWAdzb/XOtQyLApHhFht3sOWA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.154.0.tgz", + "integrity": "sha512-EXURTyW9riw4B/kZnnE+58emAtw6+3VEszQfXUZkRqGaKIcmWDYkZtKB+xY/blHvuZ+Qy/fDclc31nmUCgtkSA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-openharmony-arm64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.154.0.tgz", + "integrity": "sha512-ZRFooyH3qsR6vuR4jFGlG3XM36490SvvXtNaUahBK4zHpooMdTHNaOMtGGJI0EW38m5hi4rOco9kw7ZwCIp28w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.154.0.tgz", + "integrity": "sha512-U0Vp+4lvwUa/PnOCJTZOjydj1rX2+VLHz4Y2vSFqlN8/7LTiURgD7z4uQ9yNv9O/NlU3mELBnPDlu7aaSYG1zQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-ia32-msvc": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.154.0.tgz", + "integrity": "sha512-Hc8QgsFY5eUUP25we8TISUruibG2cDt0H4IcPG9RKdabb6odkCzIqjV6Gk9beGWGuOwMVCr81H/Su1q363LCCg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.154.0.tgz", + "integrity": "sha512-hD7judkUMA/hZPoamvKADs6+an1smp8UTK0aMYRijkvi00K/1vl7vEtmyn2JyQ9S+vibtnfcNzxqTLGyJUZCRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@oxc-transform/binding-android-arm-eabi": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-android-arm-eabi/-/binding-android-arm-eabi-0.154.0.tgz", + "integrity": "sha512-Wqd1sJDGwaDPlO2BFdLD7+OMQR4T3Y9PaqS1D+kjjHPEJZ2lotY8cm67d6Otp0IaS7uKGU76S8aa5mHJwTvwXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-android-arm64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-android-arm64/-/binding-android-arm64-0.154.0.tgz", + "integrity": "sha512-X236HnhL/WzibySNF8UA5Mk9sLtx8OWSKOhzpHDfmR0gLNK9Rhnr6bCO35+bdgiUWpBZEdxxe9/a5brRZzuMww==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-darwin-arm64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-arm64/-/binding-darwin-arm64-0.154.0.tgz", + "integrity": "sha512-CRewaU+ThBKqDthUOOrmwEu8XfPsnKRuwiO6a/OXMJbQ7l9/247N1WTxMMWZWBkJObK5pjd/oDAaGxvmJjTcWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-darwin-x64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-x64/-/binding-darwin-x64-0.154.0.tgz", + "integrity": "sha512-dQhIDr8+AtgIimzFX1XNEsnQfFGVH/aBGoR4u5HgCXu1B9ISAgbDr91N72ehN769eNrNnRUP18weNuNVzHL5kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-freebsd-x64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-freebsd-x64/-/binding-freebsd-x64-0.154.0.tgz", + "integrity": "sha512-QWEPzmEPPIzZ/y6k0vsiwcUqCtrOHuRNovmW6VeG4y07fBSfVp35uweGQrxoJL/XebkR19M4sIpnFTwcniV6pA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm-gnueabihf": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.154.0.tgz", + "integrity": "sha512-C+tHdgh6dDMgJMkxYSv+5pC8XtHySJx5G1POi5GmADZITPXhvZT6NDUkzToOs9Ja8BMYgejhOeK6G3++AwoF+A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm-musleabihf": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.154.0.tgz", + "integrity": "sha512-odNOaCqjIJUPM7h3y3+ZgBVZTbPWzFyuMSG2uRRIFB3If5q3d5d7hCK3/CMIeVy7g4JT8IRPoBDttYW/lX6cAg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.154.0.tgz", + "integrity": "sha512-clfcZaasfgkzqkrT2zwMDtLIUDoiu7f3tyoV5QFnlYKFQvJ5zA5tWhjacPZWKnRh7W9UjfILGo4W/Z/4zOXoCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm64-musl": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.154.0.tgz", + "integrity": "sha512-60PLk9egLY1QyZhuC8fEI5yuDSSch9BzQn8B7YYEwRtXtHnvk9U3Rjk7x9TvN+QeDLwPSDQm+nOGyKyuYFusUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-ppc64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.154.0.tgz", + "integrity": "sha512-Tvh6NamG/Qkg1V+X+o9zO38GGnbImAvtLR5eappfdImOh6cHHq9Lp7HLTY3LO9OTaiLEPejFo/hpAPMPxQ3SYw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-riscv64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.154.0.tgz", + "integrity": "sha512-RF0+/kQzlnvN0PPbWP1E2Zn6ayYztkPj97K/N9yLa1t+zWdfppBve8ww0lAszkd60J1akYW4TfUhQJiIYXVWGQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-riscv64-musl": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.154.0.tgz", + "integrity": "sha512-vU0UF00U21tcIINr/3BKSNJCyrUigHjo/8bF5msZnZ3R61Yyh8sTHrunbw6sQIDYZykb9N9tHKlrt35N5iEhRQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-s390x-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.154.0.tgz", + "integrity": "sha512-1e8afsXnXzsgirRRhJx4pV7e2a9xfFMGT9wSNeCEuBCY7pFXE6t81Wp3K6gbIMkrHbdZLPzjvvudvrBcSUpZKA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-x64-gnu": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.154.0.tgz", + "integrity": "sha512-+k8nMWTqEPPwTt3pdNaH1Ek/HY5Cf7idDOUhoLkWErWiUBCGGpYND47xad+mbN1v0j7CaPP2qHWTsRhN8LReKw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-linux-x64-musl": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-musl/-/binding-linux-x64-musl-0.154.0.tgz", + "integrity": "sha512-wSgC5avEHzEzdSNAO4E7Sq3JppVJCLYgSK1IOuS4f6VOU5eui+HtMdQIeRYsKTc+vANG5YaQ+0c0dHuEo4/kZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-openharmony-arm64": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-openharmony-arm64/-/binding-openharmony-arm64-0.154.0.tgz", + "integrity": "sha512-4kyIYf1EUdMa2x1PebyHNQF+BVkSWBd2fniMubBZZsPCUwtKv89wOzIjQ7EJLrvWFYWLIa4KdUNoKbuvunIJLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-transform/binding-win32-arm64-msvc": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.154.0.tgz", + "integrity": "sha512-ftqAPU2DcYT9bonTogmNIOFDoILnCehdL2DFz8OCY9+z0LZaPY1F4v/Es0VE22m8++C/hbuNPVHpTYaUPNMrNw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@opentelemetry/winston-transport": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.26.0.tgz", - "integrity": "sha512-JHGw8T/u7g/U/LavVL040FLv38bAZZUkwwjckGFDQO3ohqJmcyXRvPqgKuvm/S+GRoEonoSkRrrl62kAPYU76A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.216.0", - "winston-transport": "4.*" - }, + "node_modules/@oxc-transform/binding-win32-ia32-msvc": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.154.0.tgz", + "integrity": "sha512-NdX4YzkjY6zkq/61WZYfdTBu5d+LsuQLmJf/P3wNPgTmfHeO9V7K7CHrfBrU7VbwtA26qM28+zr29LXPhEbGEw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^18.19.0 || >=20.6.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxc-project/types": { - "version": "0.133.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", - "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "node_modules/@oxc-transform/binding-win32-x64-msvc": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.154.0.tgz", + "integrity": "sha512-gdkSxCHFdO3w/QPmooRORWAr/HxIwAKSnnN4QLPnf2cR2156Ux5oYLU63u2PnE64402KtX2pBhr+Psgq/peDxg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@oxfmt/binding-android-arm-eabi": { @@ -2842,30 +3517,6 @@ "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "license": "MIT" - }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -3284,96 +3935,436 @@ "resolved": "https://registry.npmjs.org/@types/msgpack5/-/msgpack5-3.4.6.tgz", "integrity": "sha512-0wbcgl7xuiMH02FPWzGYkfB5zkRDLNq58ElkpFB8iikNVJ/kMbFYlcSC4rNYWkLHLAeTCdjUT2yJ24+FzgzwhQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/readable-stream": "*", - "bl": ">=5.1.0" + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/readable-stream": "*", + "bl": ">=5.1.0" + } + }, + "node_modules/@types/node": { + "version": "24.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", + "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/pg": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.20.0.tgz", + "integrity": "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/readable-stream": { + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.21.tgz", + "integrity": "sha512-19eKVv9tugr03IgfXlA9UVUVRbW6IuqRO5B92Dl4a6pT7K8uaGrNS0GkxiZD0BOk6PLuXl5FhWl//eX/pzYdTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/node": { - "version": "24.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", - "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/pg": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.20.0.tgz", - "integrity": "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==", + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", - "license": "MIT" + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "license": "MIT" + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/readable-stream": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.21.tgz", - "integrity": "sha512-19eKVv9tugr03IgfXlA9UVUVRbW6IuqRO5B92Dl4a6pT7K8uaGrNS0GkxiZD0BOk6PLuXl5FhWl//eX/pzYdTQ==", + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*" + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT" + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "devOptional": true, - "license": "MIT" + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" } }, "node_modules/@vitest/coverage-v8": { @@ -3603,6 +4594,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3611,18 +4603,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", @@ -4318,12 +5298,6 @@ "node": ">=6.6.0" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "license": "MIT" - }, "node_modules/cross-env": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", @@ -6591,12 +7565,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "license": "ISC" - }, "node_modules/marked": { "version": "18.0.5", "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.5.tgz", @@ -6932,6 +7900,87 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oxc-parser": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.154.0.tgz", + "integrity": "sha512-Gr/6fkjZwi937c4Tsz8y0iO4U0FLPkZI6JSVucLAIvQyqh379px7RS8ORIc0HOORbFjXZ6zyqWLl53qxhSeofw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "^0.154.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/oxc-project" + }, + "optionalDependencies": { + "@oxc-parser/binding-android-arm-eabi": "0.154.0", + "@oxc-parser/binding-android-arm64": "0.154.0", + "@oxc-parser/binding-darwin-arm64": "0.154.0", + "@oxc-parser/binding-darwin-x64": "0.154.0", + "@oxc-parser/binding-freebsd-x64": "0.154.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.154.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.154.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.154.0", + "@oxc-parser/binding-linux-arm64-musl": "0.154.0", + "@oxc-parser/binding-linux-ppc64-gnu": "0.154.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.154.0", + "@oxc-parser/binding-linux-riscv64-musl": "0.154.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.154.0", + "@oxc-parser/binding-linux-x64-gnu": "0.154.0", + "@oxc-parser/binding-linux-x64-musl": "0.154.0", + "@oxc-parser/binding-openharmony-arm64": "0.154.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.154.0", + "@oxc-parser/binding-win32-ia32-msvc": "0.154.0", + "@oxc-parser/binding-win32-x64-msvc": "0.154.0" + } + }, + "node_modules/oxc-parser/node_modules/@oxc-project/types": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.154.0.tgz", + "integrity": "sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/oxc-transform": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/oxc-transform/-/oxc-transform-0.154.0.tgz", + "integrity": "sha512-f1i5S4wm+a5t6baY5mw/+LFLt95VpOwwcU56TlSGfd23c5DstR2k9RKj0vv16/7/ra+ptU09D83sNOL4fza1NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/oxc-project" + }, + "optionalDependencies": { + "@oxc-transform/binding-android-arm-eabi": "0.154.0", + "@oxc-transform/binding-android-arm64": "0.154.0", + "@oxc-transform/binding-darwin-arm64": "0.154.0", + "@oxc-transform/binding-darwin-x64": "0.154.0", + "@oxc-transform/binding-freebsd-x64": "0.154.0", + "@oxc-transform/binding-linux-arm-gnueabihf": "0.154.0", + "@oxc-transform/binding-linux-arm-musleabihf": "0.154.0", + "@oxc-transform/binding-linux-arm64-gnu": "0.154.0", + "@oxc-transform/binding-linux-arm64-musl": "0.154.0", + "@oxc-transform/binding-linux-ppc64-gnu": "0.154.0", + "@oxc-transform/binding-linux-riscv64-gnu": "0.154.0", + "@oxc-transform/binding-linux-riscv64-musl": "0.154.0", + "@oxc-transform/binding-linux-s390x-gnu": "0.154.0", + "@oxc-transform/binding-linux-x64-gnu": "0.154.0", + "@oxc-transform/binding-linux-x64-musl": "0.154.0", + "@oxc-transform/binding-openharmony-arm64": "0.154.0", + "@oxc-transform/binding-win32-arm64-msvc": "0.154.0", + "@oxc-transform/binding-win32-ia32-msvc": "0.154.0", + "@oxc-transform/binding-win32-x64-msvc": "0.154.0" + } + }, "node_modules/oxfmt": { "version": "0.73.0", "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.73.0.tgz", @@ -8475,64 +9524,6 @@ "node": ">= 14.0.0" } }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "license": "MIT" - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -8603,16 +9594,38 @@ } }, "node_modules/typescript": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", - "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "dev": true, "license": "Apache-2.0", "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "tsc": "bin/tsc" }, "engines": { - "node": ">=14.17" + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" } }, "node_modules/ua-parser-js": { @@ -8682,12 +9695,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "license": "MIT" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -9461,15 +10468,6 @@ "node": ">=8" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/zod": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.2.tgz", diff --git a/package.json b/package.json index 6098a248e70..c5ed3ad2516 100644 --- a/package.json +++ b/package.json @@ -75,12 +75,14 @@ "lit": "^3.3.2", "marked": "^18.0.5", "mrmime": "^2.0.1", + "oxc-parser": "^0.154.0", + "oxc-transform": "^0.154.0", "oxfmt": "^0.73.0", "oxlint": "^1.88.0", - "oxlint-tsgolint": "^7.0.2004", "oxlint-plugin-eslint": "^1.88.0", + "oxlint-tsgolint": "^7.0.2004", "tailwindcss": "^4.2.4", - "typescript": "^6.0.3", + "typescript": "^7.0.2", "vite": "^8.0.16", "vite-plugin-html": "^3.2.2", "vitest": "^4.1.11", @@ -120,7 +122,6 @@ "nanoid": "^5.1.16", "node-html-parser": "^7.1.0", "obscenity": "^0.4.6", - "ts-node": "^10.9.2", "tsx": "^4.22.4", "winston": "^3.19.0", "ws": "^8.21.0", diff --git a/scripts/split-packages/check-move.ts b/scripts/split-packages/check-move.ts index cfbd1ef193f..9d24264fa38 100644 --- a/scripts/split-packages/check-move.ts +++ b/scripts/split-packages/check-move.ts @@ -7,9 +7,20 @@ * Usage: npx tsx scripts/split-packages/check-move.ts [ []] * Defaults: base HEAD~1, head HEAD. Pass --cached as head for the index. */ +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck import { execFileSync } from "child_process"; import ts from "typescript"; -import { moduleRefs, parse, ROOT } from "./lib"; +import { assertCompilerApiAvailable, moduleRefs, parse, ROOT } from "./lib"; + +assertCompilerApiAvailable(); // Config edits the move forces (docs/EnginePackageSplit.md, "Tooling changes // the move forces"), plus the move's own inputs. diff --git a/scripts/split-packages/closure.ts b/scripts/split-packages/closure.ts index 7423c03db22..b3b90f37019 100644 --- a/scripts/split-packages/closure.ts +++ b/scripts/split-packages/closure.ts @@ -7,7 +7,25 @@ * --exclude: core files to treat as engine-only entries (not traversed), * e.g. src/core/worker/Worker.worker.ts */ -import { listSourceFiles, moduleRefs, parse, rel, resolveSpec } from "./lib"; +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck +import { + assertCompilerApiAvailable, + listSourceFiles, + moduleRefs, + parse, + rel, + resolveSpec, +} from "./lib"; + +assertCompilerApiAvailable(); const argv = process.argv.slice(2); const excluded = new Set(); diff --git a/scripts/split-packages/cut.ts b/scripts/split-packages/cut.ts index 60b83e28f0a..382c1ba7335 100644 --- a/scripts/split-packages/cut.ts +++ b/scripts/split-packages/cut.ts @@ -6,8 +6,20 @@ * Usage: npx tsx scripts/split-packages/cut.ts * A re-export is named "export:"; `declare global` is "global". */ +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck import fs from "fs"; import ts from "typescript"; +import { assertCompilerApiAvailable } from "./lib"; + +assertCompilerApiAvailable(); const [from, to, list] = process.argv.slice(2); const names = new Set(list.split(",")); const text = fs.readFileSync(from, "utf8"); diff --git a/scripts/split-packages/decl-closure.ts b/scripts/split-packages/decl-closure.ts index 654f4dbbb4a..1cdfd019567 100644 --- a/scripts/split-packages/decl-closure.ts +++ b/scripts/split-packages/decl-closure.ts @@ -4,8 +4,19 @@ * * Usage: npx tsx scripts/split-packages/decl-closure.ts */ +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck import ts from "typescript"; -import { abs, parse } from "./lib"; +import { abs, assertCompilerApiAvailable, parse } from "./lib"; + +assertCompilerApiAvailable(); const [file, rootList] = process.argv.slice(2); const sf = parse(abs(file)); diff --git a/scripts/split-packages/imported-names.ts b/scripts/split-packages/imported-names.ts index 1c3960ea720..8988a674f69 100644 --- a/scripts/split-packages/imported-names.ts +++ b/scripts/split-packages/imported-names.ts @@ -4,15 +4,27 @@ * * Usage: npx tsx scripts/split-packages/imported-names.ts ... */ +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck import ts from "typescript"; import { abs, + assertCompilerApiAvailable, listSourceFiles, moduleRefs, parse, rel, resolveSpec, } from "./lib"; + +assertCompilerApiAvailable(); const target = abs(process.argv[2]); const prefixes = process.argv.slice(3); const names = new Map>(); diff --git a/scripts/split-packages/lib.ts b/scripts/split-packages/lib.ts index 6bc17b71ae7..a4cdef38e2b 100644 --- a/scripts/split-packages/lib.ts +++ b/scripts/split-packages/lib.ts @@ -2,11 +2,37 @@ * Module-reference scanning and resolution shared by the split-packages * codemod and analysis scripts. Throwaway tooling for #1701. */ +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck import fs from "fs"; import path from "path"; import ts from "typescript"; import { fileURLToPath } from "url"; +/** + * The TypeScript compiler API the codemod is built on. TypeScript 7.0 has + * none, so every script that needs it stops here with an explanation + * instead of failing with "ts.createSourceFile is not a function". + */ +export function assertCompilerApiAvailable(): void { + const api = ts as unknown as { createSourceFile?: unknown }; + if (typeof api.createSourceFile !== "function") { + throw new Error( + "scripts/split-packages is disabled: TypeScript 7.0 ships no compiler " + + "API. Use typescript@7.1.0-beta to run it now; the 7.1 API is " + + "expected to ship in December 2026. See " + + "https://github.com/openfrontio/OpenFrontIO/issues/4982", + ); + } +} + export const ROOT = path.resolve( path.dirname(fileURLToPath(import.meta.url)), "../..", diff --git a/scripts/split-packages/run.ts b/scripts/split-packages/run.ts index 2d1e8c8d62c..1eaa08a27ac 100644 --- a/scripts/split-packages/run.ts +++ b/scripts/split-packages/run.ts @@ -19,12 +19,22 @@ * `export *` of a split file, a package importing the root app) is flagged * and the run exits non-zero. Running it twice is a no-op. */ +// DISABLED: TypeScript 7.0 ships no JavaScript compiler API - the package +// only exports a version string - so this script cannot parse TypeScript any +// more. The replacement API (typescript/sync, typescript/ast) arrives with +// TypeScript 7.1: it is in beta today (`npm i -D typescript@7.1.0-beta`) and +// the final release is expected in December 2026. Until then this script is +// kept as it is, but is not type-checked and refuses to run. The next split +// has to wait for that release. +// See https://github.com/openfrontio/OpenFrontIO/issues/4982 +// @ts-nocheck import { execFileSync } from "child_process"; import fs from "fs"; import path from "path"; import ts from "typescript"; import { abs, + assertCompilerApiAvailable, listSourceFiles, moduleRefs, parse, @@ -34,6 +44,8 @@ import { specifierFor, } from "./lib"; +assertCompilerApiAvailable(); + interface SymbolMove { from: string; to: string; diff --git a/tests/LayerBoundaries.test.ts b/tests/LayerBoundaries.test.ts index 80cd4445dfa..681143f9d57 100644 --- a/tests/LayerBoundaries.test.ts +++ b/tests/LayerBoundaries.test.ts @@ -8,10 +8,12 @@ * so the list only shrinks. */ import fs from "fs"; +import { type Node } from "oxc-parser"; +import { transformSync } from "oxc-transform"; import path from "path"; -import ts from "typescript"; import { fileURLToPath } from "url"; import { describe, expect, test } from "vitest"; +import { forEachChild, isStringLiteral, parseSource } from "./util/sourceAst"; const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); @@ -117,54 +119,54 @@ function walk(dir: string, out: string[] = []): string[] { function specifiers(file: string): string[] { const text = fs.readFileSync(path.join(ROOT, file), "utf8"); - const sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true); + const program = parseSource(file, text); const out: string[] = []; - const visit = (node: ts.Node) => { + const visit = (node: Node) => { if ( - (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && - node.moduleSpecifier && - ts.isStringLiteral(node.moduleSpecifier) + node.type === "ImportDeclaration" || + node.type === "ExportNamedDeclaration" || + node.type === "ExportAllDeclaration" ) { - out.push(node.moduleSpecifier.text); - } else if ( - ts.isImportTypeNode(node) && - ts.isLiteralTypeNode(node.argument) && - ts.isStringLiteral(node.argument.literal) - ) { - out.push(node.argument.literal.text); - } else if ( - ts.isCallExpression(node) && - node.expression.kind === ts.SyntaxKind.ImportKeyword && - node.arguments.length > 0 && - ts.isStringLiteralLike(node.arguments[0]) - ) { - out.push(node.arguments[0].text); + const source = node.source; + if (source !== null && isStringLiteral(source)) { + out.push(source.value); + } + } else if (node.type === "TSImportType") { + if (isStringLiteral(node.source)) { + out.push(node.source.value); + } + } else if (node.type === "ImportExpression") { + if (isStringLiteral(node.source)) { + out.push(node.source.value); + } } - ts.forEachChild(node, visit); + forEachChild(node, visit); }; - visit(sf); + visit(program); return out; } /** - * The imports and re-exports left once TypeScript compiles the source: an - * import used only as a type is erased, so it loads nothing. + * The imports and re-exports left once the types are erased: an import used + * only as a type is erased, so it loads nothing. */ function runtimeSpecifiers(source: string): string[] { - const js = ts.transpileModule(source, { - compilerOptions: { - module: ts.ModuleKind.ESNext, - target: ts.ScriptTarget.ESNext, - }, - }).outputText; - const sf = ts.createSourceFile("out.js", js, ts.ScriptTarget.Latest); - return sf.statements.flatMap((s) => - (ts.isImportDeclaration(s) || ts.isExportDeclaration(s)) && - s.moduleSpecifier && - ts.isStringLiteral(s.moduleSpecifier) - ? [s.moduleSpecifier.text] - : [], - ); + const js = transformSync("input.ts", source, { sourcemap: false }).code; + const program = parseSource("out.js", js); + const out: string[] = []; + for (const statement of program.body) { + if ( + statement.type === "ImportDeclaration" || + statement.type === "ExportNamedDeclaration" || + statement.type === "ExportAllDeclaration" + ) { + const specifier = statement.source; + if (specifier !== null && isStringLiteral(specifier)) { + out.push(specifier.value); + } + } + } + return out; } function probe(base: string): string | null { diff --git a/tests/TranslationSystem.test.ts b/tests/TranslationSystem.test.ts index 425ee8b2352..d0e2217a5df 100644 --- a/tests/TranslationSystem.test.ts +++ b/tests/TranslationSystem.test.ts @@ -1,7 +1,16 @@ import fs from "fs"; import IntlMessageFormat from "intl-messageformat"; +import { + type CallExpression, + type Expression, + type Node, + type ObjectProperty, + type PropertyKey, + type StringLiteral, + type TemplateLiteral, +} from "oxc-parser"; import path from "path"; -import ts from "typescript"; +import { forEachChild, isStringLiteral, parseSource } from "./util/sourceAst"; const PROJECT_ROOT = path.join(__dirname, ".."); const LANGUAGE_DIR = path.join(PROJECT_ROOT, "resources", "lang"); @@ -66,6 +75,9 @@ type ScanResult = { dynamicPrefixes: Set; }; +/** A template literal without substitutions. */ +type PlainTemplateLiteral = TemplateLiteral & { expressions: [] }; + function flattenKeys(obj: Record, prefix = ""): string[] { const keys: string[] = []; for (const [key, value] of Object.entries(obj)) { @@ -193,49 +205,67 @@ function prefixToRegex(prefix: string): RegExp { return new RegExp(`^${escapeRegex(prefix)}.+$`); } -function isTranslateTextCall(node: ts.CallExpression): boolean { - if (ts.isIdentifier(node.expression)) { - return node.expression.text === "translateText"; +function isTranslateTextCall(node: CallExpression): boolean { + const callee = node.callee; + if (callee.type === "Identifier") { + return callee.name === "translateText"; } - if (ts.isPropertyAccessExpression(node.expression)) { - return node.expression.name.text === "translateText"; + // A computed member expression (`obj["translateText"]`) is not a plain + // property access, so it does not count. + if ( + callee.type === "MemberExpression" && + callee.computed === false && + callee.property.type === "Identifier" + ) { + return callee.property.name === "translateText"; } return false; } +function isTemplateLiteral(node: Node): node is PlainTemplateLiteral { + return node.type === "TemplateLiteral" && node.expressions.length === 0; +} + +/** + * A string literal, or a template literal without substitutions: both stand + * in for a translation key. + */ function isStringLiteralLike( - node: ts.Node, -): node is ts.StringLiteral | ts.NoSubstitutionTemplateLiteral { - return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node); + node: Node, +): node is StringLiteral | PlainTemplateLiteral { + return isStringLiteral(node) || isTemplateLiteral(node); } -function getPlusOperands(expr: ts.Expression): ts.Expression[] { - if ( - ts.isBinaryExpression(expr) && - expr.operatorToken.kind === ts.SyntaxKind.PlusToken - ) { +/** The text of a string literal, or of a template literal without substitutions. */ +function stringLiteralText(node: StringLiteral | PlainTemplateLiteral): string { + if (node.type === "Literal") return node.value; + return node.quasis[0].value.cooked ?? node.quasis[0].value.raw; +} + +function getPlusOperands(expr: Expression): Expression[] { + if (expr.type === "BinaryExpression" && expr.operator === "+") { return [...getPlusOperands(expr.left), ...getPlusOperands(expr.right)]; } return [expr]; } -function getStaticStringFromPlus(expr: ts.Expression): string | null { +function getStaticStringFromPlus(expr: Expression): string | null { const parts = getPlusOperands(expr); let value = ""; for (const part of parts) { if (!isStringLiteralLike(part)) return null; - value += part.text; + value += stringLiteralText(part); } return value; } -function getDynamicPrefixFromPlus(expr: ts.Expression): string | null { +function getDynamicPrefixFromPlus(expr: Expression): string | null { const parts = getPlusOperands(expr); if (parts.length === 0) return null; const first = parts[0]; if (!isStringLiteralLike(first)) return null; if (parts.every((part) => isStringLiteralLike(part))) return null; - return first.text || null; + return stringLiteralText(first) || null; } function extractDataI18nKeys(content: string): Set { @@ -273,37 +303,45 @@ function isPotentialTranslationKey( return rootKeys.has(root); } -function isKeyNamedProperty(name: ts.PropertyName): boolean { - if (ts.isIdentifier(name)) return /key$/i.test(name.text); - if (ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name)) { - return /key$/i.test(name.text); +function isKeyNamedProperty(name: PropertyKey): boolean { + if (name.type === "Identifier") return /key$/i.test(name.name); + if (isStringLiteral(name)) return /key$/i.test(name.value); + if (isTemplateLiteral(name)) { + return /key$/i.test(stringLiteralText(name)); } return false; } +/** + * A property assignment (`{ key: value }`) whose name ends in "key". + * Shorthand properties, methods and accessors are separate node kinds and + * do not count, and a computed name (`{ [key]: value }`) is not a name at + * all. + */ +function isKeyNamedPropertyAssignment(node: ObjectProperty): boolean { + if (node.kind !== "init" || node.shorthand || node.method || node.computed) { + return false; + } + return isKeyNamedProperty(node.key); +} + function collectFromExpression( - expression: ts.Expression, + expression: Expression, result: ScanResult, rootKeys: Set, enKeySet: Set, allowBareRoot = false, ): void { if (isStringLiteralLike(expression)) { - if ( - isPotentialTranslationKey( - expression.text, - rootKeys, - enKeySet, - allowBareRoot, - ) - ) { - result.referencedStaticKeys.add(expression.text); + const text = stringLiteralText(expression); + if (isPotentialTranslationKey(text, rootKeys, enKeySet, allowBareRoot)) { + result.referencedStaticKeys.add(text); } return; } - if (ts.isTemplateExpression(expression)) { - const prefix = expression.head.text; + if (expression.type === "TemplateLiteral") { + const prefix = expression.quasis[0].value.cooked ?? ""; if ( prefix.length > 0 && /[._]$/.test(prefix) && @@ -314,10 +352,7 @@ function collectFromExpression( return; } - if ( - ts.isBinaryExpression(expression) && - expression.operatorToken.kind === ts.SyntaxKind.PlusToken - ) { + if (expression.type === "BinaryExpression" && expression.operator === "+") { const staticValue = getStaticStringFromPlus(expression); if (staticValue !== null) { if (isPotentialTranslationKey(staticValue, rootKeys, enKeySet)) { @@ -337,7 +372,7 @@ function collectFromExpression( return; } - if (ts.isParenthesizedExpression(expression)) { + if (expression.type === "ParenthesizedExpression") { collectFromExpression( expression.expression, result, @@ -348,16 +383,16 @@ function collectFromExpression( return; } - if (ts.isConditionalExpression(expression)) { + if (expression.type === "ConditionalExpression") { collectFromExpression( - expression.whenTrue, + expression.consequent, result, rootKeys, enKeySet, allowBareRoot, ); collectFromExpression( - expression.whenFalse, + expression.alternate, result, rootKeys, enKeySet, @@ -373,15 +408,7 @@ function scanTsFile( enKeySet: Set, ): ScanResult { const content = fs.readFileSync(filePath, "utf-8"); - const sourceFile = ts.createSourceFile( - filePath, - content, - ts.ScriptTarget.Latest, - // setParentNodes: nothing in this file reads node.parent, and building the - // parent pointers is about 15% of the parse cost across 566 files. - false, - filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS, - ); + const program = parseSource(filePath, content); const result: ScanResult = { usedKeys: new Set(), @@ -398,45 +425,55 @@ function scanTsFile( result.referencedStaticKeys.add(key); } - const visit = (node: ts.Node) => { + const visit = (node: Node) => { // Broad match: any string literal in any .ts/.tsx file that exactly // matches an en.json key is counted as "used". This is intentionally // permissive to avoid false-positive "unused" reports, but it means a // key appearing in an unrelated context (e.g. a log message or object // key that happens to share the same name) will mask a genuinely // unused translation key. - if (isStringLiteralLike(node) && enKeySet.has(node.text)) { - result.usedKeys.add(node.text); + if (isStringLiteralLike(node)) { + const text = stringLiteralText(node); + if (enKeySet.has(text)) { + result.usedKeys.add(text); + } } - if (ts.isCallExpression(node) && isTranslateTextCall(node)) { + if (node.type === "CallExpression" && isTranslateTextCall(node)) { const firstArg = node.arguments[0]; - if (firstArg !== undefined) { + if (firstArg !== undefined && firstArg.type !== "SpreadElement") { collectFromExpression(firstArg, result, rootKeys, enKeySet, true); } } - if ( - ts.isPropertyAssignment(node) && - isKeyNamedProperty(node.name) && - ts.isExpression(node.initializer) - ) { - collectFromExpression(node.initializer, result, rootKeys, enKeySet); + // Property assignments are read off the object literal they belong to: + // the AST also uses the "Property" type for destructuring targets, which + // are not property assignments. + if (node.type === "ObjectExpression") { + for (const property of node.properties) { + if ( + property.type === "Property" && + isKeyNamedPropertyAssignment(property) + ) { + collectFromExpression(property.value, result, rootKeys, enKeySet); + } + } } if ( - ts.isVariableDeclaration(node) && - ts.isIdentifier(node.name) && - /key$/i.test(node.name.text) && - node.initializer !== undefined + node.type === "VariableDeclarator" && + node.id.type === "Identifier" && + /key$/i.test(node.id.name) && + node.init !== null && + node.init !== undefined ) { - collectFromExpression(node.initializer, result, rootKeys, enKeySet); + collectFromExpression(node.init, result, rootKeys, enKeySet); } - ts.forEachChild(node, visit); + forEachChild(node, visit); }; - visit(sourceFile); + visit(program); for (const key of dataI18nKeys) { if (enKeySet.has(key)) { @@ -642,16 +679,12 @@ describe("Translation System", () => { expect(missingKeys).toEqual([]); expect(unusedKeys).toEqual([]); // 60s, raised from the 30s added in #3861 (May 2026). This is starvation - // headroom, not a budget. Measured over 566 source files (5.0MB): ~1.7s - // locally, split read 0.28s / TS parse 0.68s / AST walk 0.70s, and ~4.0s - // under the v8 coverage CI actually runs (`npm run test:coverage`, - // ci.yml:47) -- down from ~5.0s before the setParentNodes change above. - // That 20% is the whole of what optimisation can buy: parse and walk are - // 82% of the cost and are inherent to reading every source file with the - // TypeScript compiler. What exhausted the old 30s on 1 Sept 2026 was - // >12x starvation from concurrent suites on one machine, which no - // speedup of this size survives. A timeout here reads exactly like the - // i18n regression this test exists to catch, and costs an investigation - // every time, so the margin is deliberately generous. + // headroom, not a budget. Measured over 566 source files (5.0MB): ~1.1s + // locally with oxc-parser, and ~1.3s under the v8 coverage CI actually + // runs (`npm run test:coverage`, ci.yml:47). What exhausted the old 30s + // on 1 Sept 2026 was >12x starvation from concurrent suites on one + // machine, which no speedup of this size survives. A timeout here reads + // exactly like the i18n regression this test exists to catch, and costs + // an investigation every time, so the margin is deliberately generous. }, 60000); }); diff --git a/tests/util/sourceAst.ts b/tests/util/sourceAst.ts new file mode 100644 index 00000000000..ea6aec3e39e --- /dev/null +++ b/tests/util/sourceAst.ts @@ -0,0 +1,63 @@ +/** + * Reading the repository's own source with the oxc parser. + * + * The oxc parser is a standalone TypeScript-aware parser: it needs no + * TypeScript compiler, so the tests that scan the source tree keep working + * with TypeScript 7, which ships no compiler API. + */ +import { + parseSync, + visitorKeys, + type Node, + type Program, + type StringLiteral, +} from "oxc-parser"; + +/** Every literal node shares the type "Literal"; the value tells them apart. */ +type AnyLiteral = Extract; + +/** + * Parses a TypeScript source file. The language follows the file extension. + */ +export function parseSource(fileName: string, text: string): Program { + const { program, errors } = parseSync(fileName, text, { + lang: fileName.endsWith(".tsx") ? "tsx" : "ts", + sourceType: "unambiguous", + }); + if (errors.length > 0) { + throw new Error(`${fileName}: ${errors[0].message}`); + } + return program; +} + +function isNode(value: unknown): value is Node { + return ( + typeof value === "object" && + value !== null && + typeof (value as { type?: unknown }).type === "string" + ); +} + +/** Visits the child nodes of a node, in the order the oxc AST lists them. */ +export function forEachChild(node: Node, visit: (child: Node) => void): void { + const keys = visitorKeys[node.type]; + if (keys === undefined) return; + const record = node as unknown as Record; + for (const key of keys) { + const value = record[key]; + if (Array.isArray(value)) { + for (const item of value) { + if (isNode(item)) visit(item); + } + } else if (isNode(value)) { + visit(value); + } + } +} + +/** Whether a node is a string literal, and not another kind of literal. */ +export function isStringLiteral(node: Node): node is StringLiteral { + return ( + node.type === "Literal" && typeof (node as AnyLiteral).value === "string" + ); +}