diff --git a/CHANGELOG.md b/CHANGELOG.md index e443e39..e8505b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added +- Consume translations from the central `@escalated-dev/locale` npm package. The package is loaded as the base layer, this package's `resources/lang/{locale}/messages.json` files are deep-merged on top as overrides, and host apps can drop further overrides into `resources/lang/overrides/{locale}/messages.json`. See `resources/lang/overrides/README.md` for the layering rules and a sample `config/i18n.ts` chain for `@adonisjs/i18n` v3+. + ### Changed - **BREAKING**: Upgraded to AdonisJS v7. Host applications must be on AdonisJS Core ^7.0, Lucid ^22.0, Auth ^10.0, Inertia ^4.0, Drive ^4.0, Mail ^10.0, and Node.js 24+. Bundles Dependabot updates #58 (auth 10.1), #59 (drive 4.0), #60 (lucid 22.4), #62 (session 8.1). - Internal: replaced `response.redirect().toRoute(name)` with a small `redirectToRoute` helper to bypass v7's strict, host-augmented `RoutesList` types in plugin code (runtime semantics unchanged). diff --git a/README.md b/README.md index 8c94873..efeee47 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ authorization: { - **SSO:** SAML and JWT-based single sign-on - **RBAC:** Role-based access control with granular permissions - **Automation:** Configurable automation rules with conditions and actions -- **i18n:** Multi-language support (EN, ES, FR, DE) +- **i18n:** Multi-language support sourced from the central `@escalated-dev/locale` npm package, with optional per-host overrides under `resources/lang/overrides/` - **Plugin System:** Extensible via TypeScript SDK plugins - **REST API:** Token-authenticated API with rate limiting - **Import Framework:** Bulk data import support @@ -443,6 +443,26 @@ const assignmentService = await app.container.make('escalated.assignmentService' await assignmentService.autoAssign(ticket) ``` +## Translations (i18n) + +Translations are sourced from the central [`@escalated-dev/locale`](https://github.com/escalated-dev/escalated-locale) +npm package and shared with every Escalated host plugin (Laravel, Rails, +Django, Spring, etc.). Three layers are merged at runtime, with later +layers winning on key conflict: + +1. **Central package** — `@escalated-dev/locale/locales/{locale}/` +2. **Bundled local** — `resources/lang/{locale}/messages.json` (this package) +3. **Host overrides** — `resources/lang/overrides/{locale}/messages.json` + +To override a single string in your host app, create a file under +`resources/lang/overrides/{locale}/messages.json` containing only the keys +you want to change — everything else falls through to the central package. + +If your host app uses `@adonisjs/i18n` v3+ directly (in addition to the +plugin's own `t()` helper), see `resources/lang/overrides/README.md` for a +sample `config/i18n.ts` that chains `loaders.fs()` against the central +package and your host's `app.languageFilesPath()`. + ## Frontend Package This package serves only the backend API via Inertia.js. The shared Vue 3 frontend components are provided by the `@escalated-dev/escalated` package, which is framework-agnostic and works with all Escalated backends (AdonisJS, Laravel, Rails, Django). diff --git a/package-lock.json b/package-lock.json index 51bb302..7ec1f53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.5.0", "license": "MIT", "dependencies": { + "@escalated-dev/locale": "github:escalated-dev/escalated-locale#v0.1.2", "@escalated-dev/plugin-sdk": "https://codeload.github.com/escalated-dev/escalated-plugin-sdk/tar.gz/refs/tags/v0.1.2", "@xmldom/xmldom": "^0.9.10", "luxon": "^3.7.2" @@ -87,20 +88,6 @@ "youch": "^4.1.0-beta.11 || ^4.1.0" } }, - "node_modules/@adonisjs/ace/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/application": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@adonisjs/application/-/application-9.0.0.tgz", @@ -128,20 +115,6 @@ } } }, - "node_modules/@adonisjs/application/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/assembler": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/@adonisjs/assembler/-/assembler-8.4.0.tgz", @@ -179,21 +152,6 @@ "typescript": "^5.0.0 || ^6.0.0" } }, - "node_modules/@adonisjs/assembler/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/auth": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/@adonisjs/auth/-/auth-10.1.0.tgz", @@ -265,20 +223,6 @@ "@adonisjs/http-server": "^8.0.0-next.17 || ^8.0.0" } }, - "node_modules/@adonisjs/bodyparser/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@adonisjs/cache/-/cache-2.1.0.tgz", @@ -319,20 +263,6 @@ "node": ">=24.0.0" } }, - "node_modules/@adonisjs/config/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/core": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/@adonisjs/core/-/core-7.3.2.tgz", @@ -404,33 +334,6 @@ } } }, - "node_modules/@adonisjs/core/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, - "node_modules/@adonisjs/core/node_modules/@sindresorhus/is": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-8.0.0.tgz", - "integrity": "sha512-YvOsokBE5NsyHuXMnwEVB7lgFk6lX8F4OXCruYVgFII0hUHof0RGUvhMoabVt9hRqbg+qVzayzEG24RCcxcYeA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=22" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, "node_modules/@adonisjs/drive": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@adonisjs/drive/-/drive-4.0.0.tgz", @@ -484,20 +387,6 @@ "node": ">=24.0.0" } }, - "node_modules/@adonisjs/env/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/eslint-config": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@adonisjs/eslint-config/-/eslint-config-3.0.0.tgz", @@ -554,18 +443,17 @@ "@adonisjs/fold": "^11.0.0-next.4 || ^11.0.0" } }, - "node_modules/@adonisjs/events/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", + "node_modules/@adonisjs/events/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", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@adonisjs/fold": { @@ -582,20 +470,6 @@ "node": ">=24.0.0" } }, - "node_modules/@adonisjs/fold/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/hash": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/@adonisjs/hash/-/hash-10.1.0.tgz", @@ -622,20 +496,6 @@ } } }, - "node_modules/@adonisjs/hash/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/health": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@adonisjs/health/-/health-3.1.0.tgz", @@ -650,20 +510,6 @@ "node": ">=24.0.0" } }, - "node_modules/@adonisjs/health/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/http-server": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/@adonisjs/http-server/-/http-server-8.2.0.tgz", @@ -707,18 +553,17 @@ } } }, - "node_modules/@adonisjs/http-server/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", + "node_modules/@adonisjs/http-server/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", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@adonisjs/http-transformers": { @@ -793,20 +638,6 @@ } } }, - "node_modules/@adonisjs/inertia/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/logger": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@adonisjs/logger/-/logger-7.1.1.tgz", @@ -830,20 +661,6 @@ } } }, - "node_modules/@adonisjs/logger/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/lucid": { "version": "22.4.2", "resolved": "https://registry.npmjs.org/@adonisjs/lucid/-/lucid-22.4.2.tgz", @@ -888,20 +705,6 @@ } } }, - "node_modules/@adonisjs/lucid/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/mail": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/@adonisjs/mail/-/mail-10.2.0.tgz", @@ -1040,20 +843,6 @@ } } }, - "node_modules/@adonisjs/session/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@adonisjs/transmit": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@adonisjs/transmit/-/transmit-3.0.1.tgz", @@ -1104,21 +893,6 @@ } } }, - "node_modules/@adonisjs/vite/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@antfu/install-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", @@ -1210,6 +984,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1228,6 +1005,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1246,6 +1026,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1264,6 +1047,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1387,32 +1173,22 @@ } } }, - "node_modules/@boringnode/bus/node_modules/@noble/hashes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", - "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@boringnode/bus/node_modules/@paralleldrive/cuid2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-3.3.0.tgz", - "integrity": "sha512-OqiFvSOF0dBSesELYY2CAMa4YINvlLpvKOz/rv6NeZEqiyttlHgv98Juwv4Ch+GrEV7IZ8jfI2VcEoYUjXXCjw==", + "node_modules/@boringnode/bus/node_modules/@poppinss/utils": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-6.10.1.tgz", + "integrity": "sha512-da+MMyeXhBaKtxQiWPfy7+056wk3lVIhioJnXHXkJ2/OHDaZfFcyKHNl1R06sdYO8lIRXcXdoZ6LO2ARmkAREA==", "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "^2.0.1", - "bignumber.js": "^9.3.1", - "error-causes": "^3.0.2" + "@poppinss/exception": "^1.2.1", + "@poppinss/object-builder": "^1.1.0", + "@poppinss/string": "^1.3.0", + "flattie": "^1.1.1", + "safe-stable-stringify": "^2.5.0", + "secure-json-parse": "^4.0.0" }, - "bin": { - "cuid2": "bin/cuid2.js" + "engines": { + "node": ">=18.16.0" } }, "node_modules/@boringnode/encryption": { @@ -1428,20 +1204,6 @@ "node": ">=20.6" } }, - "node_modules/@boringnode/encryption/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/@boringnode/transmit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@boringnode/transmit/-/transmit-0.4.0.tgz", @@ -1458,6 +1220,24 @@ "node": ">=20.6" } }, + "node_modules/@boringnode/transmit/node_modules/@poppinss/utils": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-6.10.1.tgz", + "integrity": "sha512-da+MMyeXhBaKtxQiWPfy7+056wk3lVIhioJnXHXkJ2/OHDaZfFcyKHNl1R06sdYO8lIRXcXdoZ6LO2ARmkAREA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.1", + "@poppinss/object-builder": "^1.1.0", + "@poppinss/string": "^1.3.0", + "flattie": "^1.1.1", + "safe-stable-stringify": "^2.5.0", + "secure-json-parse": "^4.0.0" + }, + "engines": { + "node": ">=18.16.0" + } + }, "node_modules/@chevrotain/cst-dts-gen": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.2.0.tgz", @@ -1981,6 +1761,11 @@ "node": ">=18" } }, + "node_modules/@escalated-dev/locale": { + "version": "0.1.2", + "resolved": "git+ssh://git@github.com/escalated-dev/escalated-locale.git#db1afd52b378529eeb9ede81862d85192f580a5c", + "license": "MIT" + }, "node_modules/@escalated-dev/plugin-sdk": { "version": "0.1.0", "resolved": "https://codeload.github.com/escalated-dev/escalated-plugin-sdk/tar.gz/refs/tags/v0.1.2", @@ -2112,29 +1897,43 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.1", + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2216,22 +2015,8 @@ "supports-color": "^10.2.2", "timekeeper": "^2.3.1" }, - "engines": { - "node": ">=18.16.0" - } - }, - "node_modules/@japa/runner/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" + "engines": { + "node": ">=18.16.0" } }, "node_modules/@jest/diff-sequences": { @@ -2291,6 +2076,19 @@ "node": ">=8" } }, + "node_modules/@noble/hashes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", + "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2332,6 +2130,21 @@ "node": ">= 8" } }, + "node_modules/@paralleldrive/cuid2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-3.3.0.tgz", + "integrity": "sha512-OqiFvSOF0dBSesELYY2CAMa4YINvlLpvKOz/rv6NeZEqiyttlHgv98Juwv4Ch+GrEV7IZ8jfI2VcEoYUjXXCjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^2.0.1", + "bignumber.js": "^9.3.1", + "error-causes": "^3.0.2" + }, + "bin": { + "cuid2": "bin/cuid2.js" + } + }, "node_modules/@phc/format": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", @@ -2402,6 +2215,19 @@ "supports-color": "^10.0.0" } }, + "node_modules/@poppinss/dumper/node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@poppinss/exception": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", @@ -2498,16 +2324,16 @@ } }, "node_modules/@poppinss/string": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@poppinss/string/-/string-1.7.1.tgz", - "integrity": "sha512-OrLzv/nGDU6l6dLXIQHe8nbNSWWfuSbpB/TW5nRpZFf49CLuQlIHlSPN9IdSUv2vG+59yGM6LoibsaHn8B8mDw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@poppinss/string/-/string-1.7.2.tgz", + "integrity": "sha512-A182GLDfi36iDCbhDrHB0xzrPM1fO3GHnhCDIdadf8C6eycgct4m7zusbLwEh6GPaj2Pz5BVos7XK16w7tZ7wQ==", "dev": true, "license": "MIT", "dependencies": { "@types/pluralize": "^0.0.33", "case-anything": "^3.1.2", "pluralize": "^8.0.0", - "slugify": "^1.6.6" + "slugify": "^1.6.9" } }, "node_modules/@poppinss/types": { @@ -2518,21 +2344,17 @@ "license": "MIT" }, "node_modules/@poppinss/utils": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-6.10.1.tgz", - "integrity": "sha512-da+MMyeXhBaKtxQiWPfy7+056wk3lVIhioJnXHXkJ2/OHDaZfFcyKHNl1R06sdYO8lIRXcXdoZ6LO2ARmkAREA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/exception": "^1.2.1", + "@poppinss/exception": "^1.2.3", "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.3.0", - "flattie": "^1.1.1", - "safe-stable-stringify": "^2.5.0", - "secure-json-parse": "^4.0.0" - }, - "engines": { - "node": ">=18.16.0" + "@poppinss/string": "^1.7.1", + "@poppinss/types": "^1.2.1", + "flattie": "^1.1.1" } }, "node_modules/@poppinss/validator-lite": { @@ -2640,6 +2462,9 @@ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2655,6 +2480,9 @@ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2670,6 +2498,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2685,6 +2516,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2700,6 +2534,9 @@ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2715,6 +2552,9 @@ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2730,6 +2570,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2745,6 +2588,9 @@ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2760,6 +2606,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2775,6 +2624,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2790,6 +2642,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2805,6 +2660,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2820,6 +2678,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2933,13 +2794,13 @@ "license": "MIT" }, "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==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-8.0.0.tgz", + "integrity": "sha512-YvOsokBE5NsyHuXMnwEVB7lgFk6lX8F4OXCruYVgFII0hUHof0RGUvhMoabVt9hRqbg+qVzayzEG24RCcxcYeA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=22" }, "funding": { "url": "https://github.com/sindresorhus/is?sponsor=1" @@ -3071,13 +2932,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.2.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", - "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.16.0" + "undici-types": "~7.19.0" } }, "node_modules/@types/nodemailer": { @@ -3105,17 +2966,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz", - "integrity": "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.1.tgz", + "integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.58.0", - "@typescript-eslint/type-utils": "8.58.0", - "@typescript-eslint/utils": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/type-utils": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -3128,22 +2989,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.58.0", + "@typescript-eslint/parser": "^8.59.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.0.tgz", - "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", + "integrity": "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.58.0", - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3" }, "engines": { @@ -3159,14 +3030,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.0.tgz", - "integrity": "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", + "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.58.0", - "@typescript-eslint/types": "^8.58.0", + "@typescript-eslint/tsconfig-utils": "^8.59.1", + "@typescript-eslint/types": "^8.59.1", "debug": "^4.4.3" }, "engines": { @@ -3181,14 +3052,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.0.tgz", - "integrity": "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", + "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0" + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3199,9 +3070,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.0.tgz", - "integrity": "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", + "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", "dev": true, "license": "MIT", "engines": { @@ -3216,15 +3087,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.0.tgz", - "integrity": "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.1.tgz", + "integrity": "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0", - "@typescript-eslint/utils": "8.58.0", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -3241,9 +3112,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz", - "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", + "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", "dev": true, "license": "MIT", "engines": { @@ -3255,16 +3126,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.0.tgz", - "integrity": "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", + "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.58.0", - "@typescript-eslint/tsconfig-utils": "8.58.0", - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/visitor-keys": "8.58.0", + "@typescript-eslint/project-service": "8.59.1", + "@typescript-eslint/tsconfig-utils": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3283,16 +3154,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz", - "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", + "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.58.0", - "@typescript-eslint/types": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0" + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3307,13 +3178,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.0.tgz", - "integrity": "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", + "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/types": "8.59.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3496,10 +3367,20 @@ "node": ">=8.0.0" } }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/baseline-browser-mapping": { - "version": "2.10.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.16.tgz", - "integrity": "sha512-Lyf3aK28zpsD1yQMiiHD4RvVb6UdMoo8xzG2XzFIfR9luPzOpcBlAsT/qfB1XWS1bxWT+UtE4WmQgsp297FYOA==", + "version": "2.10.25", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.25.tgz", + "integrity": "sha512-QO/VHsXCQdnzADMfmkeOPvHdIAkoB7i0/rGjINPJEetLx75hNttVWGQ/jycHUDP9zZ9rupbm60WRxcwViB0MiA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3522,13 +3403,6 @@ "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/bentocache": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/bentocache/-/bentocache-1.6.1.tgz", @@ -3591,16 +3465,6 @@ "node": "18 || 20 || >=22" } }, - "node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -3649,9 +3513,9 @@ } }, "node_modules/builtin-modules": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", - "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.1.0.tgz", + "integrity": "sha512-c5JxaDrzwRjq3WyJkI1AGR5xy6Gr6udlt7sQPbl09+3ckB+Zo2qqQ2KhCTBr7Q8dHB43bENGYEk4xddrFH/b7A==", "dev": true, "license": "MIT", "engines": { @@ -3689,9 +3553,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001786", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001786.tgz", - "integrity": "sha512-4oxTZEvqmLLrERwxO76yfKM7acZo310U+v4kqexI2TL1DkkUEMT8UijrxxcnVdxR3qkVf5awGRX+4Z6aPHVKrA==", + "version": "1.0.30001791", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz", + "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==", "dev": true, "funding": [ { @@ -3885,13 +3749,6 @@ "@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==", - "dev": true, - "license": "MIT" - }, "node_modules/cli-table3/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", @@ -4228,21 +4085,6 @@ "node": ">=18.16.0" } }, - "node_modules/edge.js/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/edgejs-parser": { "version": "0.2.19", "resolved": "https://registry.npmjs.org/edgejs-parser/-/edgejs-parser-0.2.19.tgz", @@ -4261,16 +4103,16 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.332", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.332.tgz", - "integrity": "sha512-7OOtytmh/rINMLwaFTbcMVvYXO3AUm029X0LcyfYk0B557RlPkdpTpnH9+htMlfu5dKwOmT0+Zs2Aw+lnn6TeQ==", + "version": "1.5.349", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.349.tgz", + "integrity": "sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==", "dev": true, "license": "ISC" }, "node_modules/emittery": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.2.0.tgz", - "integrity": "sha512-KxdRyyFcS85pH3dnU8Y5yFUm2YJdaHwcBZWrfG8o89ZY9a13/f9itbN+YG3ELbBo9Pg5zvIozstmuV8bX13q6g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.2.1.tgz", + "integrity": "sha512-sFz64DCRjirhwHLxofFqxYQm6DCp6o0Ix7jwKQvuCHPn4GMRZNuBZyLPu9Ccmk/QSCAMZt6FOUqA8JZCQvA9fw==", "dev": true, "license": "MIT", "engines": { @@ -4280,6 +4122,13 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -4564,182 +4413,71 @@ "funding": { "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" }, - "peerDependencies": { - "eslint": ">=9.38.0" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", - "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.16.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^5.0.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": ">=9.38.0" } }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "yocto-queue": "^0.1.0" + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/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==", + "node_modules/eslint/node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, "engines": { - "node": ">=10" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/esm": { @@ -5031,6 +4769,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-up-simple": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", @@ -5058,16 +4813,6 @@ "node": ">=16" } }, - "node_modules/flat-cache/node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, "node_modules/flatted": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", @@ -5117,20 +4862,6 @@ } } }, - "node_modules/flydrive/node_modules/@poppinss/utils": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", - "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.3", - "@poppinss/object-builder": "^1.1.0", - "@poppinss/string": "^1.7.1", - "@poppinss/types": "^1.2.1", - "flattie": "^1.1.1" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -5266,6 +4997,19 @@ "node": ">=10.13.0" } }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5300,9 +5044,9 @@ } }, "node_modules/hosted-git-info": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz", - "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", "dev": true, "license": "ISC", "dependencies": { @@ -5459,9 +5203,9 @@ } }, "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -5840,6 +5584,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -5851,9 +5605,9 @@ } }, "node_modules/knex": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/knex/-/knex-3.2.9.tgz", - "integrity": "sha512-dtAILTjBMaG8YloP5oBxohDIKyIsdQ/TkcVvSjhsksvsjeH63Y0PADyuMDfNZKbVT3Rlx3vEYVBlecbPT/KerA==", + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.2.10.tgz", + "integrity": "sha512-oypTHfrc9i72iyxaUQBKHOxhcr0xM65MPf6FpN02nimsftXwzXprIkLjfXdubvhbu4PMWLp023q8o8CYvHSuZw==", "dev": true, "license": "MIT", "dependencies": { @@ -5865,7 +5619,7 @@ "get-package-type": "^0.1.0", "getopts": "2.3.0", "interpret": "^2.2.0", - "lodash": "^4.17.21", + "lodash": "^4.18.1", "pg-connection-string": "2.6.2", "rechoir": "^0.8.0", "resolve-from": "^5.0.0", @@ -6057,6 +5811,22 @@ "node": ">= 0.8.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", @@ -6121,9 +5891,9 @@ } }, "node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -6188,9 +5958,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -6291,9 +6061,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.37", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", - "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", "dev": true, "license": "MIT" }, @@ -6443,6 +6213,38 @@ "node": ">= 0.8.0" } }, + "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": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-timeout": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", @@ -6499,6 +6301,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-json/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-ms": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", @@ -6521,6 +6336,16 @@ "license": "MIT", "peer": true }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6905,22 +6730,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-package-up/node_modules/type-fest": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", - "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "dependencies": { - "tagged-tag": "^1.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/read-pkg": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-10.1.0.tgz", @@ -6941,22 +6750,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", - "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "dependencies": { - "tagged-tag": "^1.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/read-pkg/node_modules/unicorn-magic": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", @@ -7197,6 +6990,13 @@ "queue-microtask": "^1.2.2" } }, + "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/safe-stable-stringify": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", @@ -7338,9 +7138,9 @@ } }, "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==", + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", "dev": true, "license": "MIT", "engines": { @@ -7687,14 +7487,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -7801,13 +7601,16 @@ } }, "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.6.0.tgz", + "integrity": "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==", "dev": true, "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, "engines": { - "node": ">=16" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7843,16 +7646,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.58.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.0.tgz", - "integrity": "sha512-e2TQzKfaI85fO+F3QywtX+tCTsu/D3WW5LVU6nz8hTFKFZ8yBJ6mSYRpXqdR3mFjPWmO0eWsTa5f+UpAOe/FMA==", + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.1.tgz", + "integrity": "sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.58.0", - "@typescript-eslint/parser": "8.58.0", - "@typescript-eslint/typescript-estree": "8.58.0", - "@typescript-eslint/utils": "8.58.0" + "@typescript-eslint/eslint-plugin": "8.59.1", + "@typescript-eslint/parser": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7893,9 +7696,9 @@ } }, "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==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "dev": true, "license": "MIT" }, @@ -8192,6 +7995,19 @@ "node": "^20.19.0 || ^22.12.0 || >=23" } }, + "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/yoctocolors": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", diff --git a/package.json b/package.json index 6a82143..7bd41c7 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "prepublishOnly": "npm run build" }, "dependencies": { + "@escalated-dev/locale": "github:escalated-dev/escalated-locale#v0.1.2", "@escalated-dev/plugin-sdk": "https://codeload.github.com/escalated-dev/escalated-plugin-sdk/tar.gz/refs/tags/v0.1.2", "@xmldom/xmldom": "^0.9.10", "luxon": "^3.7.2" diff --git a/resources/lang/overrides/.gitkeep b/resources/lang/overrides/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resources/lang/overrides/README.md b/resources/lang/overrides/README.md new file mode 100644 index 0000000..14759e6 --- /dev/null +++ b/resources/lang/overrides/README.md @@ -0,0 +1,70 @@ +# Translation Overrides + +Translations in escalated-adonis are loaded from three layers, in order: + +1. **Central package** — `@escalated-dev/locale` (canonical strings shared + across every Escalated host plugin). +2. **Bundled local** — `resources/lang/{locale}/messages.json` shipped with + this package (this directory's siblings). +3. **Host overrides** — `resources/lang/overrides/{locale}/messages.json` + (this directory). + +Later layers win on key conflict via deep-merge — only the keys you specify +get overridden; the rest fall through to the central package. + +## When to add an override here + +- A string in the central package reads correctly but you want different + wording for this AdonisJS-specific surface. +- You ship a stub/page that introduces a new key and the central package has + not yet been updated to include it. +- You need a temporary fix while a translation PR lands upstream in + `@escalated-dev/escalated-locale`. + +## When NOT to add an override here + +- The string is wrong for everyone — open a PR against + [`escalated-dev/escalated-locale`](https://github.com/escalated-dev/escalated-locale) + instead so every host plugin benefits. + +## Format + +Identical to the bundled local files — one `messages.json` per locale: + +``` +resources/lang/overrides/en/messages.json +resources/lang/overrides/de/messages.json +resources/lang/overrides/fr/messages.json +``` + +Only include the keys you actually want to override; everything else +falls through. + +## Host applications + +If your AdonisJS app uses `@adonisjs/i18n` v3+ directly, you can chain its +`fs` loaders the same way in `config/i18n.ts`: + +```ts +import { defineConfig, formatters, loaders } from '@adonisjs/i18n' +import app from '@adonisjs/core/services/app' +import { createRequire } from 'node:module' + +const require = createRequire(import.meta.url) +const centralLocale = require.resolve('@escalated-dev/locale/package.json') +const centralDir = new URL('./locales', `file://${centralLocale}`).pathname + +export default defineConfig({ + formatter: formatters.icu(), + defaultLocale: 'en', + loaders: [ + // Base layer: central package translations. + loaders.fs({ location: centralDir }), + // Override layer: host app's own resources/lang/. + loaders.fs({ location: app.languageFilesPath() }), + ], +}) +``` + +The last loader in the array wins on key conflict, matching the override +semantics of this package's internal loader. diff --git a/src/support/i18n.ts b/src/support/i18n.ts index 55dc80b..d64bb60 100644 --- a/src/support/i18n.ts +++ b/src/support/i18n.ts @@ -1,25 +1,142 @@ -import { readFileSync, existsSync } from 'node:fs' -import { join } from 'node:path' +import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs' +import { createRequire } from 'node:module' +import { join, dirname } from 'node:path' import { fileURLToPath } from 'node:url' -import { dirname } from 'node:path' -let translations: Record = {} +/** + * Translation loader for escalated-adonis. + * + * Translations are merged from two sources, with later sources overriding + * earlier ones on key conflict: + * + * 1. **Central package** (`@escalated-dev/locale`) — canonical translations + * shared across every Escalated host plugin. Resolved from + * `node_modules` at runtime. + * 2. **Local overrides** (`resources/lang/{locale}/messages.json`) — keys + * shipped with this package that should win over the central source. + * Customers can also drop their own files under `resources/lang/overrides/` + * to layer host-app-specific overrides. + * + * Host apps using `@adonisjs/i18n` v3+ should configure two `fs` loaders in + * `config/i18n.ts` — see the README for the canonical chain. + */ + +const translations: Record> = {} let currentLocale = 'en' const currentFilePath = fileURLToPath(import.meta.url) const currentDirPath = dirname(currentFilePath) -const langDir = join(currentDirPath, '../../resources/lang') +const localLangDir = join(currentDirPath, '../../resources/lang') + +/** + * Resolve the central `@escalated-dev/locale` package's lang directory. + * + * Returns `null` if the package is not installed (e.g. during early bootstrap + * before `npm install` has run, or in a stripped-down test fixture). + */ +function resolveCentralLangDir(): string | null { + try { + const require = createRequire(import.meta.url) + const pkgJsonPath = require.resolve('@escalated-dev/locale/package.json') + return join(dirname(pkgJsonPath), 'locales') + } catch { + return null + } +} + +/** + * Recursively collect every JSON file under `dir` and merge its contents into + * `target` keyed by relative path. Sub-directories yield nested keys so a file + * `dir/foo/bar.json` becomes `target.foo.bar`. + */ +function loadJsonTree(dir: string): Record { + if (!existsSync(dir)) return {} + const out: Record = {} + + for (const entry of readdirSync(dir)) { + const full = join(dir, entry) + const stat = statSync(full) + if (stat.isDirectory()) { + out[entry] = loadJsonTree(full) + } else if (entry.endsWith('.json')) { + const key = entry.replace(/\.json$/, '') + try { + const parsed = JSON.parse(readFileSync(full, 'utf-8')) + // For the canonical `messages.json` file, hoist its keys to the top + // level so existing call sites (`t('tickets.created')`) keep working. + if (key === 'messages' && parsed && typeof parsed === 'object') { + Object.assign(out, parsed) + } else { + out[key] = parsed + } + } catch { + // Ignore unparseable JSON; treat as missing. + } + } + } + + return out +} + +/** + * Deep-merge `source` into `target`. `source` wins on conflict at any depth. + * Pure values (strings, numbers, arrays) replace; only plain objects merge. + */ +function deepMerge(target: Record, source: Record): Record { + for (const [key, value] of Object.entries(source)) { + if ( + value && + typeof value === 'object' && + !Array.isArray(value) && + target[key] && + typeof target[key] === 'object' && + !Array.isArray(target[key]) + ) { + target[key] = deepMerge({ ...target[key] }, value) + } else { + target[key] = value + } + } + return target +} function loadLocale(locale: string): Record { - const filePath = join(langDir, locale, 'messages.json') - if (existsSync(filePath)) { - return JSON.parse(readFileSync(filePath, 'utf-8')) + const merged: Record = {} + + // 1. Base: central package translations + const centralDir = resolveCentralLangDir() + if (centralDir) { + deepMerge(merged, loadJsonTree(join(centralDir, locale))) } - return {} + + // 2. Override: this package's bundled local translations + deepMerge(merged, loadJsonTree(join(localLangDir, locale))) + + // 3. Override: host-app `resources/lang/overrides/{locale}/` if present + // (only meaningful when the package is invoked from a host app's + // runtime cwd; harmless otherwise). + deepMerge(merged, loadJsonTree(join(localLangDir, 'overrides', locale))) + + return merged } -// Load all locales at startup -for (const locale of ['en', 'es', 'fr', 'de']) { +// Eagerly load all known locales at module-init time. +for (const locale of [ + 'ar', + 'de', + 'en', + 'es', + 'fr', + 'it', + 'ja', + 'ko', + 'nl', + 'pl', + 'pt-BR', + 'ru', + 'tr', + 'zh-CN', +]) { translations[locale] = loadLocale(locale) } diff --git a/stubs/config/i18n.stub b/stubs/config/i18n.stub new file mode 100644 index 0000000..18a5aea --- /dev/null +++ b/stubs/config/i18n.stub @@ -0,0 +1,56 @@ +{{{ + exports({ + to: app.configPath('i18n.ts') + }) +}}} +/* +|-------------------------------------------------------------------------- +| @adonisjs/i18n configuration with central Escalated translations +|-------------------------------------------------------------------------- +| +| Chains two filesystem loaders so translations from the central +| `@escalated-dev/locale` package are used as the canonical base, and your +| host app's `resources/lang/` directory layers on top as overrides. +| +| `@adonisjs/i18n` v3+ merges loaders in array order — the LAST loader +| wins on key conflict. Keep `app.languageFilesPath()` last so your local +| translations override the central package. +| +*/ + +import { defineConfig, formatters, loaders } from '@adonisjs/i18n' +import app from '@adonisjs/core/services/app' +import { createRequire } from 'node:module' +import { dirname, join } from 'node:path' + +const require = createRequire(import.meta.url) +const centralPkgJson = require.resolve('@escalated-dev/locale/package.json') +const centralLocalesDir = join(dirname(centralPkgJson), 'locales') + +const i18nConfig = defineConfig({ + formatter: formatters.icu(), + defaultLocale: 'en', + fallback: { /* perLocaleFallbacks */ }, + + loaders: [ + /** + * Base layer: canonical Escalated translations shared across every + * host framework plugin. Provided by the `@escalated-dev/locale` + * npm package. + */ + loaders.fs({ + location: centralLocalesDir, + }), + + /** + * Override layer: this app's own `resources/lang/{locale}/` directory. + * Last loader wins, so any keys you add here will replace the + * matching keys from the central package on a per-key basis. + */ + loaders.fs({ + location: app.languageFilesPath(), + }), + ], +}) + +export default i18nConfig