@buenojs/bueno 0.8.10 → 0.8.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/index.d.ts +187 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +595 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cli/bin.d.ts +8 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +9 -9
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/add-frontend.d.ts +7 -0
- package/dist/cli/commands/add-frontend.d.ts.map +1 -0
- package/dist/cli/commands/add-frontend.js +376 -0
- package/dist/cli/commands/add-frontend.js.map +1 -0
- package/dist/cli/commands/build.d.ts +7 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +347 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +7 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +205 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +7 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +491 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/help.d.ts +7 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +51 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/index.d.ts +59 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +77 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/migration.d.ts +7 -0
- package/dist/cli/commands/migration.d.ts.map +1 -0
- package/dist/cli/commands/migration.js +295 -0
- package/dist/cli/commands/migration.js.map +1 -0
- package/dist/cli/commands/new.d.ts +7 -0
- package/dist/cli/commands/new.d.ts.map +1 -0
- package/dist/cli/commands/new.js +641 -0
- package/dist/cli/commands/new.js.map +1 -0
- package/dist/cli/commands/start.d.ts +7 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +171 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/core/args.d.ts +61 -0
- package/dist/cli/core/args.d.ts.map +1 -0
- package/dist/cli/core/args.js +224 -0
- package/dist/cli/core/args.js.map +1 -0
- package/dist/cli/core/console.d.ts +135 -0
- package/dist/cli/core/console.d.ts.map +1 -0
- package/dist/cli/core/console.js +268 -0
- package/dist/cli/core/console.js.map +1 -0
- package/dist/cli/core/index.d.ts +10 -0
- package/dist/cli/core/index.d.ts.map +1 -0
- package/dist/cli/core/index.js +10 -0
- package/dist/cli/core/index.js.map +1 -0
- package/dist/cli/core/prompt.d.ts +63 -0
- package/dist/cli/core/prompt.d.ts.map +1 -0
- package/dist/cli/core/prompt.js +338 -0
- package/dist/cli/core/prompt.js.map +1 -0
- package/dist/cli/core/spinner.d.ts +111 -0
- package/dist/cli/core/spinner.d.ts.map +1 -0
- package/dist/cli/core/spinner.js +208 -0
- package/dist/cli/core/spinner.js.map +1 -0
- package/dist/cli/index.d.ts +47 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/templates/database/index.d.ts +24 -0
- package/dist/cli/templates/database/index.d.ts.map +1 -0
- package/dist/cli/templates/database/index.js +49 -0
- package/dist/cli/templates/database/index.js.map +1 -0
- package/dist/cli/templates/database/mysql.d.ts +6 -0
- package/dist/cli/templates/database/mysql.d.ts.map +1 -0
- package/dist/cli/templates/database/mysql.js +12 -0
- package/dist/cli/templates/database/mysql.js.map +1 -0
- package/dist/cli/templates/database/none.d.ts +8 -0
- package/dist/cli/templates/database/none.d.ts.map +1 -0
- package/dist/cli/templates/database/none.js +14 -0
- package/dist/cli/templates/database/none.js.map +1 -0
- package/dist/cli/templates/database/postgresql.d.ts +6 -0
- package/dist/cli/templates/database/postgresql.d.ts.map +1 -0
- package/dist/cli/templates/database/postgresql.js +12 -0
- package/dist/cli/templates/database/postgresql.js.map +1 -0
- package/dist/cli/templates/database/sqlite.d.ts +6 -0
- package/dist/cli/templates/database/sqlite.d.ts.map +1 -0
- package/dist/cli/templates/database/sqlite.js +12 -0
- package/dist/cli/templates/database/sqlite.js.map +1 -0
- package/dist/cli/templates/deploy.d.ts +41 -0
- package/dist/cli/templates/deploy.d.ts.map +1 -0
- package/dist/cli/templates/deploy.js +278 -0
- package/dist/cli/templates/deploy.js.map +1 -0
- package/dist/cli/templates/docker.d.ts +30 -0
- package/dist/cli/templates/docker.d.ts.map +1 -0
- package/dist/cli/templates/docker.js +298 -0
- package/dist/cli/templates/docker.js.map +1 -0
- package/dist/cli/templates/frontend/index.d.ts +25 -0
- package/dist/cli/templates/frontend/index.d.ts.map +1 -0
- package/dist/cli/templates/frontend/index.js +40 -0
- package/dist/cli/templates/frontend/index.js.map +1 -0
- package/dist/cli/templates/frontend/none.d.ts +8 -0
- package/dist/cli/templates/frontend/none.d.ts.map +1 -0
- package/dist/cli/templates/frontend/none.js +15 -0
- package/dist/cli/templates/frontend/none.js.map +1 -0
- package/dist/cli/templates/frontend/react.d.ts +6 -0
- package/dist/cli/templates/frontend/react.d.ts.map +1 -0
- package/dist/cli/templates/frontend/react.js +139 -0
- package/dist/cli/templates/frontend/react.js.map +1 -0
- package/dist/cli/templates/frontend/solid.d.ts +6 -0
- package/dist/cli/templates/frontend/solid.d.ts.map +1 -0
- package/dist/cli/templates/frontend/solid.js +133 -0
- package/dist/cli/templates/frontend/solid.js.map +1 -0
- package/dist/cli/templates/frontend/svelte.d.ts +6 -0
- package/dist/cli/templates/frontend/svelte.d.ts.map +1 -0
- package/dist/cli/templates/frontend/svelte.js +130 -0
- package/dist/cli/templates/frontend/svelte.js.map +1 -0
- package/dist/cli/templates/frontend/vue.d.ts +6 -0
- package/dist/cli/templates/frontend/vue.d.ts.map +1 -0
- package/dist/cli/templates/frontend/vue.js +129 -0
- package/dist/cli/templates/frontend/vue.js.map +1 -0
- package/dist/cli/templates/generators/index.d.ts +29 -0
- package/dist/cli/templates/generators/index.d.ts.map +1 -0
- package/dist/cli/templates/generators/index.js +308 -0
- package/dist/cli/templates/generators/index.js.map +1 -0
- package/dist/cli/templates/generators/types.d.ts +32 -0
- package/dist/cli/templates/generators/types.d.ts.map +1 -0
- package/dist/cli/templates/generators/types.js +21 -0
- package/dist/cli/templates/generators/types.js.map +1 -0
- package/dist/cli/templates/index.d.ts +12 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +18 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/templates/project/api.d.ts +6 -0
- package/dist/cli/templates/project/api.d.ts.map +1 -0
- package/dist/cli/templates/project/api.js +79 -0
- package/dist/cli/templates/project/api.js.map +1 -0
- package/dist/cli/templates/project/default.d.ts +6 -0
- package/dist/cli/templates/project/default.d.ts.map +1 -0
- package/dist/cli/templates/project/default.js +136 -0
- package/dist/cli/templates/project/default.js.map +1 -0
- package/dist/cli/templates/project/fullstack.d.ts +14 -0
- package/dist/cli/templates/project/fullstack.d.ts.map +1 -0
- package/dist/cli/templates/project/fullstack.js +19 -0
- package/dist/cli/templates/project/fullstack.js.map +1 -0
- package/dist/cli/templates/project/index.d.ts +26 -0
- package/dist/cli/templates/project/index.d.ts.map +1 -0
- package/dist/cli/templates/project/index.js +60 -0
- package/dist/cli/templates/project/index.js.map +1 -0
- package/dist/cli/templates/project/minimal.d.ts +6 -0
- package/dist/cli/templates/project/minimal.d.ts.map +1 -0
- package/dist/cli/templates/project/minimal.js +43 -0
- package/dist/cli/templates/project/minimal.js.map +1 -0
- package/dist/cli/templates/project/types.d.ts +80 -0
- package/dist/cli/templates/project/types.d.ts.map +1 -0
- package/dist/cli/templates/project/types.js +7 -0
- package/dist/cli/templates/project/types.js.map +1 -0
- package/dist/cli/templates/project/website.d.ts +8 -0
- package/dist/cli/templates/project/website.d.ts.map +1 -0
- package/dist/cli/templates/project/website.js +312 -0
- package/dist/cli/templates/project/website.js.map +1 -0
- package/dist/cli/utils/fs.d.ts +137 -0
- package/dist/cli/utils/fs.d.ts.map +1 -0
- package/dist/cli/utils/fs.js +350 -0
- package/dist/cli/utils/fs.js.map +1 -0
- package/dist/cli/utils/index.d.ts +9 -0
- package/dist/cli/utils/index.d.ts.map +1 -0
- package/dist/cli/utils/index.js +9 -0
- package/dist/cli/utils/index.js.map +1 -0
- package/dist/cli/utils/strings.d.ts +86 -0
- package/dist/cli/utils/strings.d.ts.map +1 -0
- package/dist/cli/utils/strings.js +190 -0
- package/dist/cli/utils/strings.js.map +1 -0
- package/dist/cli/utils/version.d.ts +15 -0
- package/dist/cli/utils/version.d.ts.map +1 -0
- package/dist/cli/utils/version.js +38 -0
- package/dist/cli/utils/version.js.map +1 -0
- package/dist/config/env-validation.d.ts +49 -0
- package/dist/config/env-validation.d.ts.map +1 -0
- package/dist/config/env-validation.js +77 -0
- package/dist/config/env-validation.js.map +1 -0
- package/dist/config/env.d.ts +167 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +392 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/index.d.ts +168 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +329 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +81 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +242 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merge.d.ts +66 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +226 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/types.d.ts +322 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +443 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validation.d.ts +100 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +548 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/container/forward-ref.d.ts +116 -0
- package/dist/container/forward-ref.d.ts.map +1 -0
- package/dist/container/forward-ref.js +105 -0
- package/dist/container/forward-ref.js.map +1 -0
- package/dist/container/index.d.ts +95 -0
- package/dist/container/index.d.ts.map +1 -0
- package/dist/container/index.js.map +1 -0
- package/dist/context/index.d.ts +143 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js.map +1 -0
- package/dist/database/index.d.ts +219 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/migrations/index.d.ts +151 -0
- package/dist/database/migrations/index.d.ts.map +1 -0
- package/dist/database/migrations/index.js +258 -0
- package/dist/database/migrations/index.js.map +1 -0
- package/dist/database/orm/builder.d.ts +122 -0
- package/dist/database/orm/builder.d.ts.map +1 -0
- package/dist/database/orm/builder.js +355 -0
- package/dist/database/orm/builder.js.map +1 -0
- package/dist/database/orm/casts/index.d.ts +16 -0
- package/dist/database/orm/casts/index.d.ts.map +1 -0
- package/dist/database/orm/casts/index.js +131 -0
- package/dist/database/orm/casts/index.js.map +1 -0
- package/dist/database/orm/casts/types.d.ts +16 -0
- package/dist/database/orm/casts/types.d.ts.map +1 -0
- package/dist/database/orm/casts/types.js +5 -0
- package/dist/database/orm/casts/types.js.map +1 -0
- package/dist/database/orm/compiler.d.ts +90 -0
- package/dist/database/orm/compiler.d.ts.map +1 -0
- package/dist/database/orm/compiler.js +218 -0
- package/dist/database/orm/compiler.js.map +1 -0
- package/dist/database/orm/hooks/index.d.ts +53 -0
- package/dist/database/orm/hooks/index.d.ts.map +1 -0
- package/dist/database/orm/hooks/index.js +81 -0
- package/dist/database/orm/hooks/index.js.map +1 -0
- package/dist/database/orm/index.d.ts +21 -0
- package/dist/database/orm/index.d.ts.map +1 -0
- package/dist/database/orm/index.js +23 -0
- package/dist/database/orm/index.js.map +1 -0
- package/dist/database/orm/model-registry.d.ts +33 -0
- package/dist/database/orm/model-registry.d.ts.map +1 -0
- package/dist/database/orm/model-registry.js +49 -0
- package/dist/database/orm/model-registry.js.map +1 -0
- package/dist/database/orm/model.d.ts +245 -0
- package/dist/database/orm/model.d.ts.map +1 -0
- package/dist/database/orm/model.js +599 -0
- package/dist/database/orm/model.js.map +1 -0
- package/dist/database/orm/relationships/base.d.ts +69 -0
- package/dist/database/orm/relationships/base.d.ts.map +1 -0
- package/dist/database/orm/relationships/base.js +84 -0
- package/dist/database/orm/relationships/base.js.map +1 -0
- package/dist/database/orm/relationships/belongs-to-many.d.ts +47 -0
- package/dist/database/orm/relationships/belongs-to-many.d.ts.map +1 -0
- package/dist/database/orm/relationships/belongs-to-many.js +136 -0
- package/dist/database/orm/relationships/belongs-to-many.js.map +1 -0
- package/dist/database/orm/relationships/belongs-to.d.ts +17 -0
- package/dist/database/orm/relationships/belongs-to.d.ts.map +1 -0
- package/dist/database/orm/relationships/belongs-to.js +38 -0
- package/dist/database/orm/relationships/belongs-to.js.map +1 -0
- package/dist/database/orm/relationships/has-many.d.ts +14 -0
- package/dist/database/orm/relationships/has-many.d.ts.map +1 -0
- package/dist/database/orm/relationships/has-many.js +35 -0
- package/dist/database/orm/relationships/has-many.js.map +1 -0
- package/dist/database/orm/relationships/has-one.d.ts +14 -0
- package/dist/database/orm/relationships/has-one.d.ts.map +1 -0
- package/dist/database/orm/relationships/has-one.js +32 -0
- package/dist/database/orm/relationships/has-one.js.map +1 -0
- package/dist/database/orm/relationships/index.d.ts +10 -0
- package/dist/database/orm/relationships/index.d.ts.map +1 -0
- package/dist/database/orm/relationships/index.js +9 -0
- package/dist/database/orm/relationships/index.js.map +1 -0
- package/dist/database/orm/scopes/index.d.ts +36 -0
- package/dist/database/orm/scopes/index.d.ts.map +1 -0
- package/dist/database/orm/scopes/index.js +47 -0
- package/dist/database/orm/scopes/index.js.map +1 -0
- package/dist/database/schema/index.d.ts +155 -0
- package/dist/database/schema/index.d.ts.map +1 -0
- package/dist/database/schema/index.js +401 -0
- package/dist/database/schema/index.js.map +1 -0
- package/dist/frontend/api-routes.d.ts +189 -0
- package/dist/frontend/api-routes.d.ts.map +1 -0
- package/dist/frontend/api-routes.js +548 -0
- package/dist/frontend/api-routes.js.map +1 -0
- package/dist/frontend/bundler.d.ts +99 -0
- package/dist/frontend/bundler.d.ts.map +1 -0
- package/dist/frontend/bundler.js +555 -0
- package/dist/frontend/bundler.js.map +1 -0
- package/dist/frontend/console-client.d.ts +11 -0
- package/dist/frontend/console-client.d.ts.map +1 -0
- package/dist/frontend/console-client.js +414 -0
- package/dist/frontend/console-client.js.map +1 -0
- package/dist/frontend/console-stream.d.ts +138 -0
- package/dist/frontend/console-stream.d.ts.map +1 -0
- package/dist/frontend/console-stream.js +535 -0
- package/dist/frontend/console-stream.js.map +1 -0
- package/dist/frontend/dev-server.d.ts +174 -0
- package/dist/frontend/dev-server.d.ts.map +1 -0
- package/dist/frontend/dev-server.js +735 -0
- package/dist/frontend/dev-server.js.map +1 -0
- package/dist/frontend/file-router.d.ts +170 -0
- package/dist/frontend/file-router.d.ts.map +1 -0
- package/dist/frontend/file-router.js +531 -0
- package/dist/frontend/file-router.js.map +1 -0
- package/dist/frontend/frameworks/index.d.ts +41 -0
- package/dist/frontend/frameworks/index.d.ts.map +1 -0
- package/dist/frontend/frameworks/index.js +87 -0
- package/dist/frontend/frameworks/index.js.map +1 -0
- package/dist/frontend/frameworks/react.d.ts +32 -0
- package/dist/frontend/frameworks/react.d.ts.map +1 -0
- package/dist/frontend/frameworks/react.js +66 -0
- package/dist/frontend/frameworks/react.js.map +1 -0
- package/dist/frontend/frameworks/solid.d.ts +42 -0
- package/dist/frontend/frameworks/solid.d.ts.map +1 -0
- package/dist/frontend/frameworks/solid.js +84 -0
- package/dist/frontend/frameworks/solid.js.map +1 -0
- package/dist/frontend/frameworks/svelte.d.ts +57 -0
- package/dist/frontend/frameworks/svelte.d.ts.map +1 -0
- package/dist/frontend/frameworks/svelte.js +90 -0
- package/dist/frontend/frameworks/svelte.js.map +1 -0
- package/dist/frontend/frameworks/vue.d.ts +36 -0
- package/dist/frontend/frameworks/vue.d.ts.map +1 -0
- package/dist/frontend/frameworks/vue.js +72 -0
- package/dist/frontend/frameworks/vue.js.map +1 -0
- package/dist/frontend/hmr-client.d.ts +22 -0
- package/dist/frontend/hmr-client.d.ts.map +1 -0
- package/dist/frontend/hmr-client.js +654 -0
- package/dist/frontend/hmr-client.js.map +1 -0
- package/dist/frontend/hmr.d.ts +185 -0
- package/dist/frontend/hmr.d.ts.map +1 -0
- package/dist/frontend/hmr.js +619 -0
- package/dist/frontend/hmr.js.map +1 -0
- package/dist/frontend/index.d.ts +34 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/islands.d.ts +135 -0
- package/dist/frontend/islands.d.ts.map +1 -0
- package/dist/frontend/islands.js +455 -0
- package/dist/frontend/islands.js.map +1 -0
- package/dist/frontend/isr.d.ts +143 -0
- package/dist/frontend/isr.d.ts.map +1 -0
- package/dist/frontend/isr.js +440 -0
- package/dist/frontend/isr.js.map +1 -0
- package/dist/frontend/layout.d.ts +140 -0
- package/dist/frontend/layout.d.ts.map +1 -0
- package/dist/frontend/layout.js +392 -0
- package/dist/frontend/layout.js.map +1 -0
- package/dist/frontend/ssr/react.d.ts +118 -0
- package/dist/frontend/ssr/react.d.ts.map +1 -0
- package/dist/frontend/ssr/react.js +373 -0
- package/dist/frontend/ssr/react.js.map +1 -0
- package/dist/frontend/ssr/solid.d.ts +141 -0
- package/dist/frontend/ssr/solid.d.ts.map +1 -0
- package/dist/frontend/ssr/solid.js +440 -0
- package/dist/frontend/ssr/solid.js.map +1 -0
- package/dist/frontend/ssr/svelte.d.ts +158 -0
- package/dist/frontend/ssr/svelte.d.ts.map +1 -0
- package/dist/frontend/ssr/svelte.js +439 -0
- package/dist/frontend/ssr/svelte.js.map +1 -0
- package/dist/frontend/ssr/vue.d.ts +161 -0
- package/dist/frontend/ssr/vue.d.ts.map +1 -0
- package/dist/frontend/ssr/vue.js +385 -0
- package/dist/frontend/ssr/vue.js.map +1 -0
- package/dist/frontend/ssr.d.ts +147 -0
- package/dist/frontend/ssr.d.ts.map +1 -0
- package/dist/frontend/ssr.js +609 -0
- package/dist/frontend/ssr.js.map +1 -0
- package/dist/frontend/types.d.ts +1902 -0
- package/dist/frontend/types.d.ts.map +1 -0
- package/dist/frontend/types.js +8 -0
- package/dist/frontend/types.js.map +1 -0
- package/dist/graphql/built-in-engine.d.ts +36 -0
- package/dist/graphql/built-in-engine.d.ts.map +1 -0
- package/dist/graphql/built-in-engine.js +443 -0
- package/dist/graphql/built-in-engine.js.map +1 -0
- package/dist/graphql/context-builder.d.ts +44 -0
- package/dist/graphql/context-builder.d.ts.map +1 -0
- package/dist/graphql/context-builder.js +91 -0
- package/dist/graphql/context-builder.js.map +1 -0
- package/dist/graphql/decorators.d.ts +162 -0
- package/dist/graphql/decorators.d.ts.map +1 -0
- package/dist/graphql/decorators.js +291 -0
- package/dist/graphql/decorators.js.map +1 -0
- package/dist/graphql/execution-pipeline.d.ts +67 -0
- package/dist/graphql/execution-pipeline.d.ts.map +1 -0
- package/dist/graphql/execution-pipeline.js +127 -0
- package/dist/graphql/execution-pipeline.js.map +1 -0
- package/dist/graphql/graphql-module.d.ts +70 -0
- package/dist/graphql/graphql-module.d.ts.map +1 -0
- package/dist/graphql/graphql-module.js +442 -0
- package/dist/graphql/graphql-module.js.map +1 -0
- package/dist/graphql/index.d.ts +48 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/metadata.d.ts +37 -0
- package/dist/graphql/metadata.d.ts.map +1 -0
- package/dist/graphql/metadata.js +130 -0
- package/dist/graphql/metadata.js.map +1 -0
- package/dist/graphql/schema-builder.d.ts +34 -0
- package/dist/graphql/schema-builder.d.ts.map +1 -0
- package/dist/graphql/schema-builder.js +251 -0
- package/dist/graphql/schema-builder.js.map +1 -0
- package/dist/graphql/subscription-handler.d.ts +47 -0
- package/dist/graphql/subscription-handler.d.ts.map +1 -0
- package/dist/graphql/subscription-handler.js +201 -0
- package/dist/graphql/subscription-handler.js.map +1 -0
- package/dist/graphql/types.d.ts +252 -0
- package/dist/graphql/types.d.ts.map +1 -0
- package/dist/graphql/types.js +28 -0
- package/dist/graphql/types.js.map +1 -0
- package/dist/health/index.d.ts +176 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/index.js.map +1 -0
- package/dist/i18n/engine.d.ts +105 -0
- package/dist/i18n/engine.d.ts.map +1 -0
- package/dist/i18n/engine.js +248 -0
- package/dist/i18n/engine.js.map +1 -0
- package/dist/i18n/index.d.ts +13 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/loader.d.ts +79 -0
- package/dist/i18n/loader.d.ts.map +1 -0
- package/dist/i18n/loader.js +192 -0
- package/dist/i18n/loader.js.map +1 -0
- package/dist/i18n/middleware.d.ts +96 -0
- package/dist/i18n/middleware.d.ts.map +1 -0
- package/dist/i18n/middleware.js +126 -0
- package/dist/i18n/middleware.js.map +1 -0
- package/dist/i18n/negotiator.d.ts +84 -0
- package/dist/i18n/negotiator.d.ts.map +1 -0
- package/dist/i18n/negotiator.js +139 -0
- package/dist/i18n/negotiator.js.map +1 -0
- package/dist/i18n/types.d.ts +129 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +8 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/drivers/memory.d.ts +38 -0
- package/dist/jobs/drivers/memory.d.ts.map +1 -0
- package/dist/jobs/drivers/memory.js +246 -0
- package/dist/jobs/drivers/memory.js.map +1 -0
- package/dist/jobs/drivers/redis.d.ts +34 -0
- package/dist/jobs/drivers/redis.d.ts.map +1 -0
- package/dist/jobs/drivers/redis.js +355 -0
- package/dist/jobs/drivers/redis.js.map +1 -0
- package/dist/jobs/index.d.ts +12 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/queue.d.ts +93 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +233 -0
- package/dist/jobs/queue.js.map +1 -0
- package/dist/jobs/types.d.ts +193 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +8 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/jobs/worker.d.ts +91 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +300 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/lock/index.d.ts +141 -0
- package/dist/lock/index.d.ts.map +1 -0
- package/dist/lock/index.js.map +1 -0
- package/dist/logger/index.d.ts +156 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/transports/index.d.ts +371 -0
- package/dist/logger/transports/index.d.ts.map +1 -0
- package/dist/logger/transports/index.js +740 -0
- package/dist/logger/transports/index.js.map +1 -0
- package/dist/metrics/index.d.ts +163 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/middleware/built-in.d.ts +50 -0
- package/dist/middleware/built-in.d.ts.map +1 -0
- package/dist/middleware/built-in.js +220 -0
- package/dist/middleware/built-in.js.map +1 -0
- package/dist/middleware/index.d.ts +40 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/migrations/index.d.ts +48 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +3 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/modules/filters.d.ts +150 -0
- package/dist/modules/filters.d.ts.map +1 -0
- package/dist/modules/filters.js +338 -0
- package/dist/modules/filters.js.map +1 -0
- package/dist/modules/guards.d.ts +188 -0
- package/dist/modules/guards.d.ts.map +1 -0
- package/dist/modules/guards.js +278 -0
- package/dist/modules/guards.js.map +1 -0
- package/dist/modules/index.d.ts +266 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/interceptors.d.ts +242 -0
- package/dist/modules/interceptors.d.ts.map +1 -0
- package/dist/modules/interceptors.js +407 -0
- package/dist/modules/interceptors.js.map +1 -0
- package/dist/modules/lazy.d.ts +187 -0
- package/dist/modules/lazy.d.ts.map +1 -0
- package/dist/modules/lazy.js +305 -0
- package/dist/modules/lazy.js.map +1 -0
- package/dist/modules/lifecycle.d.ts +221 -0
- package/dist/modules/lifecycle.d.ts.map +1 -0
- package/dist/modules/lifecycle.js +314 -0
- package/dist/modules/lifecycle.js.map +1 -0
- package/dist/modules/metadata.d.ts +32 -0
- package/dist/modules/metadata.d.ts.map +1 -0
- package/dist/modules/metadata.js +59 -0
- package/dist/modules/metadata.js.map +1 -0
- package/dist/modules/pipes.d.ts +287 -0
- package/dist/modules/pipes.d.ts.map +1 -0
- package/dist/modules/pipes.js +443 -0
- package/dist/modules/pipes.js.map +1 -0
- package/dist/notification/channels/base.d.ts +32 -0
- package/dist/notification/channels/base.d.ts.map +1 -0
- package/dist/notification/channels/base.js +37 -0
- package/dist/notification/channels/base.js.map +1 -0
- package/dist/notification/channels/email.d.ts +37 -0
- package/dist/notification/channels/email.d.ts.map +1 -0
- package/dist/notification/channels/email.js +85 -0
- package/dist/notification/channels/email.js.map +1 -0
- package/dist/notification/channels/push.d.ts +37 -0
- package/dist/notification/channels/push.d.ts.map +1 -0
- package/dist/notification/channels/push.js +84 -0
- package/dist/notification/channels/push.js.map +1 -0
- package/dist/notification/channels/sms.d.ts +37 -0
- package/dist/notification/channels/sms.d.ts.map +1 -0
- package/dist/notification/channels/sms.js +83 -0
- package/dist/notification/channels/sms.js.map +1 -0
- package/dist/notification/channels/whatsapp.d.ts +37 -0
- package/dist/notification/channels/whatsapp.d.ts.map +1 -0
- package/dist/notification/channels/whatsapp.js +81 -0
- package/dist/notification/channels/whatsapp.js.map +1 -0
- package/dist/notification/index.d.ts +15 -0
- package/dist/notification/index.d.ts.map +1 -0
- package/dist/notification/index.js.map +1 -0
- package/dist/notification/service.d.ts +100 -0
- package/dist/notification/service.d.ts.map +1 -0
- package/dist/notification/service.js +279 -0
- package/dist/notification/service.js.map +1 -0
- package/dist/notification/types.d.ts +253 -0
- package/dist/notification/types.d.ts.map +1 -0
- package/dist/notification/types.js +14 -0
- package/dist/notification/types.js.map +1 -0
- package/dist/observability/__tests__/observability.test.d.ts +2 -0
- package/dist/observability/__tests__/observability.test.d.ts.map +1 -0
- package/dist/observability/__tests__/observability.test.js +404 -0
- package/dist/observability/__tests__/observability.test.js.map +1 -0
- package/dist/observability/breadcrumbs.d.ts +48 -0
- package/dist/observability/breadcrumbs.d.ts.map +1 -0
- package/dist/observability/breadcrumbs.js +97 -0
- package/dist/observability/breadcrumbs.js.map +1 -0
- package/dist/observability/index.d.ts +95 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/interceptor.d.ts +19 -0
- package/dist/observability/interceptor.d.ts.map +1 -0
- package/dist/observability/interceptor.js +67 -0
- package/dist/observability/interceptor.js.map +1 -0
- package/dist/observability/service.d.ts +101 -0
- package/dist/observability/service.d.ts.map +1 -0
- package/dist/observability/service.js +249 -0
- package/dist/observability/service.js.map +1 -0
- package/dist/observability/trace.d.ts +21 -0
- package/dist/observability/trace.d.ts.map +1 -0
- package/dist/observability/trace.js +35 -0
- package/dist/observability/trace.js.map +1 -0
- package/dist/observability/types.d.ts +172 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +8 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/openapi/decorators.d.ts +173 -0
- package/dist/openapi/decorators.d.ts.map +1 -0
- package/dist/openapi/decorators.js +276 -0
- package/dist/openapi/decorators.js.map +1 -0
- package/dist/openapi/document-builder.d.ts +82 -0
- package/dist/openapi/document-builder.d.ts.map +1 -0
- package/dist/openapi/document-builder.js +228 -0
- package/dist/openapi/document-builder.js.map +1 -0
- package/dist/openapi/index.d.ts +48 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi/metadata.d.ts +36 -0
- package/dist/openapi/metadata.d.ts.map +1 -0
- package/dist/openapi/metadata.js +78 -0
- package/dist/openapi/metadata.js.map +1 -0
- package/dist/openapi/route-scanner.d.ts +34 -0
- package/dist/openapi/route-scanner.d.ts.map +1 -0
- package/dist/openapi/route-scanner.js +174 -0
- package/dist/openapi/route-scanner.js.map +1 -0
- package/dist/openapi/schema-generator.d.ts +53 -0
- package/dist/openapi/schema-generator.d.ts.map +1 -0
- package/dist/openapi/schema-generator.js +236 -0
- package/dist/openapi/schema-generator.js.map +1 -0
- package/dist/openapi/swagger-module.d.ts +57 -0
- package/dist/openapi/swagger-module.d.ts.map +1 -0
- package/dist/openapi/swagger-module.js +143 -0
- package/dist/openapi/swagger-module.js.map +1 -0
- package/dist/openapi/types.d.ts +344 -0
- package/dist/openapi/types.d.ts.map +1 -0
- package/dist/openapi/types.js +7 -0
- package/dist/openapi/types.js.map +1 -0
- package/dist/orm/index.d.ts +10 -0
- package/dist/orm/index.d.ts.map +1 -0
- package/dist/orm/index.js.map +1 -0
- package/dist/router/index.d.ts +73 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/linear.d.ts +54 -0
- package/dist/router/linear.d.ts.map +1 -0
- package/dist/router/linear.js +261 -0
- package/dist/router/linear.js.map +1 -0
- package/dist/router/regex.d.ts +49 -0
- package/dist/router/regex.d.ts.map +1 -0
- package/dist/router/regex.js +201 -0
- package/dist/router/regex.js.map +1 -0
- package/dist/router/tree.d.ts +112 -0
- package/dist/router/tree.d.ts.map +1 -0
- package/dist/router/tree.js +360 -0
- package/dist/router/tree.js.map +1 -0
- package/dist/rpc/index.d.ts +321 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/schema/index.d.ts +10 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/security/index.d.ts +126 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +309 -0
- package/dist/security/index.js.map +1 -0
- package/dist/ssg/index.d.ts +73 -0
- package/dist/ssg/index.d.ts.map +1 -0
- package/dist/ssg/index.js +464 -0
- package/dist/ssg/index.js.map +1 -0
- package/dist/storage/index.d.ts +99 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +338 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/telemetry/index.d.ts +376 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/template/index.d.ts +7 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js.map +1 -0
- package/dist/templates/engine.d.ts +60 -0
- package/dist/templates/engine.d.ts.map +1 -0
- package/dist/templates/engine.js +177 -0
- package/dist/templates/engine.js.map +1 -0
- package/dist/templates/index.d.ts +9 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/loader.d.ts +45 -0
- package/dist/templates/loader.d.ts.map +1 -0
- package/dist/templates/loader.js +274 -0
- package/dist/templates/loader.js.map +1 -0
- package/dist/templates/renderers/markdown.d.ts +46 -0
- package/dist/templates/renderers/markdown.d.ts.map +1 -0
- package/dist/templates/renderers/markdown.js +181 -0
- package/dist/templates/renderers/markdown.js.map +1 -0
- package/dist/templates/renderers/simple.d.ts +35 -0
- package/dist/templates/renderers/simple.d.ts.map +1 -0
- package/dist/templates/renderers/simple.js +245 -0
- package/dist/templates/renderers/simple.js.map +1 -0
- package/dist/templates/types.d.ts +138 -0
- package/dist/templates/types.d.ts.map +1 -0
- package/dist/templates/types.js +8 -0
- package/dist/templates/types.js.map +1 -0
- package/dist/testing/index.d.ts +539 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types/index.d.ts +116 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/validation/index.d.ts +89 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +276 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/schemas.d.ts +283 -0
- package/dist/validation/schemas.d.ts.map +1 -0
- package/dist/validation/schemas.js +407 -0
- package/dist/validation/schemas.js.map +1 -0
- package/dist/websocket/index.d.ts +252 -0
- package/dist/websocket/index.d.ts.map +1 -0
- package/dist/websocket/index.js +749 -0
- package/dist/websocket/index.js.map +1 -0
- package/package.json +3 -3
- package/src/database/migrations/index.ts +8 -0
- package/src/migrations/index.ts +40 -1
- package/src/types/index.ts +1 -1
- package/tsconfig.json +2 -6
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation Loader — JSON File Loading and Caching
|
|
3
|
+
*
|
|
4
|
+
* Loads locale JSON files from disk, flattens nested keys to dot-notation,
|
|
5
|
+
* caches in memory, and supports hot-reload via file watching.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, watch } from "fs";
|
|
8
|
+
import { join, resolve } from "path";
|
|
9
|
+
// ============= Flattening =============
|
|
10
|
+
/**
|
|
11
|
+
* Recursively flatten a nested object into dot-notation keys.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* flattenTranslations({ nav: { home: "Home", about: "About" } })
|
|
15
|
+
* → Map { "nav.home" → "Home", "nav.about" → "About" }
|
|
16
|
+
*
|
|
17
|
+
* Already-flat keys pass through unchanged.
|
|
18
|
+
* Non-string leaf values are converted via String().
|
|
19
|
+
* Arrays are not recursed — they are stringified as-is.
|
|
20
|
+
*
|
|
21
|
+
* @param obj Object to flatten (or nested structure)
|
|
22
|
+
* @param prefix Current dot-notation prefix (used recursively)
|
|
23
|
+
* @param result Accumulator map (used recursively)
|
|
24
|
+
* @returns Flattened Map with all keys in dot-notation form
|
|
25
|
+
*/
|
|
26
|
+
function flattenTranslations(obj, prefix = "", result = new Map()) {
|
|
27
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
28
|
+
const dotKey = prefix ? `${prefix}.${key}` : key;
|
|
29
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
30
|
+
flattenTranslations(value, dotKey, result);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
result.set(dotKey, String(value ?? ""));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
// ============= Loader =============
|
|
39
|
+
/**
|
|
40
|
+
* Loads and caches locale translation bundles from JSON files.
|
|
41
|
+
* Supports file watching for hot-reload in development.
|
|
42
|
+
*/
|
|
43
|
+
export class TranslationLoader {
|
|
44
|
+
cache = new Map();
|
|
45
|
+
watchers = new Map();
|
|
46
|
+
config;
|
|
47
|
+
constructor(config) {
|
|
48
|
+
this.config = config;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Load a locale bundle. Returns from cache if already loaded.
|
|
52
|
+
*
|
|
53
|
+
* For the default locale:
|
|
54
|
+
* - Throws if the file is not found (cannot proceed without defaults)
|
|
55
|
+
*
|
|
56
|
+
* For non-default locales:
|
|
57
|
+
* - Returns an empty bundle if the file is not found
|
|
58
|
+
* - Fallback in the engine will handle the miss
|
|
59
|
+
*
|
|
60
|
+
* @param locale Locale identifier to load
|
|
61
|
+
* @returns LocaleBundle with flattened translations
|
|
62
|
+
* @throws Error if default locale file is not found
|
|
63
|
+
*/
|
|
64
|
+
load(locale) {
|
|
65
|
+
const cached = this.cache.get(locale);
|
|
66
|
+
if (cached)
|
|
67
|
+
return cached;
|
|
68
|
+
return this._loadFromDisk(locale);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Pre-load all supported locales eagerly.
|
|
72
|
+
* Call this once at application startup for best performance.
|
|
73
|
+
*
|
|
74
|
+
* Non-default locales that are missing are silently skipped
|
|
75
|
+
* (returning empty bundles).
|
|
76
|
+
*/
|
|
77
|
+
preload() {
|
|
78
|
+
for (const locale of this.config.supportedLocales) {
|
|
79
|
+
try {
|
|
80
|
+
this._loadFromDisk(locale);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Non-default locales may legitimately have no file yet
|
|
84
|
+
if (locale !== this.config.defaultLocale) {
|
|
85
|
+
this.cache.set(locale, {
|
|
86
|
+
locale,
|
|
87
|
+
translations: new Map(),
|
|
88
|
+
loadedAt: Date.now(),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Invalidate a locale's cache entry.
|
|
96
|
+
* Forces a reload from disk on the next access.
|
|
97
|
+
*
|
|
98
|
+
* @param locale Locale to invalidate
|
|
99
|
+
*/
|
|
100
|
+
invalidate(locale) {
|
|
101
|
+
this.cache.delete(locale);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Return all currently loaded locale names.
|
|
105
|
+
*
|
|
106
|
+
* @returns Array of loaded locale identifiers
|
|
107
|
+
*/
|
|
108
|
+
loadedLocales() {
|
|
109
|
+
return Array.from(this.cache.keys());
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Enable file watching for a locale (hot reload in dev mode).
|
|
113
|
+
* Invalidates cache and reloads on file change.
|
|
114
|
+
*
|
|
115
|
+
* @param locale Locale file to watch
|
|
116
|
+
*/
|
|
117
|
+
watch(locale) {
|
|
118
|
+
const filePath = this._resolvePath(locale);
|
|
119
|
+
if (!existsSync(filePath))
|
|
120
|
+
return;
|
|
121
|
+
if (this.watchers.has(locale))
|
|
122
|
+
return;
|
|
123
|
+
const watcher = watch(filePath, () => {
|
|
124
|
+
this.invalidate(locale);
|
|
125
|
+
try {
|
|
126
|
+
this._loadFromDisk(locale);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Ignore parse errors during hot reload — log in production
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
this.watchers.set(locale, watcher);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Stop all file watchers.
|
|
136
|
+
* Call this when the application shuts down.
|
|
137
|
+
*/
|
|
138
|
+
stopWatching() {
|
|
139
|
+
for (const watcher of this.watchers.values()) {
|
|
140
|
+
watcher.close();
|
|
141
|
+
}
|
|
142
|
+
this.watchers.clear();
|
|
143
|
+
}
|
|
144
|
+
// ============= Private Helpers =============
|
|
145
|
+
/**
|
|
146
|
+
* Resolve the full file path for a locale.
|
|
147
|
+
* @param locale Locale identifier
|
|
148
|
+
* @returns Full file path to the locale JSON file
|
|
149
|
+
*/
|
|
150
|
+
_resolvePath(locale) {
|
|
151
|
+
return resolve(join(this.config.basePath, `${locale}.json`));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Load a locale file from disk and cache it.
|
|
155
|
+
* @param locale Locale to load
|
|
156
|
+
* @returns LocaleBundle with flattened translations
|
|
157
|
+
* @throws Error if default locale file is not found or JSON is invalid
|
|
158
|
+
*/
|
|
159
|
+
_loadFromDisk(locale) {
|
|
160
|
+
const filePath = this._resolvePath(locale);
|
|
161
|
+
if (!existsSync(filePath)) {
|
|
162
|
+
if (locale === this.config.defaultLocale) {
|
|
163
|
+
throw new Error(`[i18n] Default locale file not found: ${filePath}. ` +
|
|
164
|
+
`Create ${locale}.json in ${this.config.basePath}`);
|
|
165
|
+
}
|
|
166
|
+
// For non-default locales, silently return an empty bundle
|
|
167
|
+
const empty = {
|
|
168
|
+
locale,
|
|
169
|
+
translations: new Map(),
|
|
170
|
+
loadedAt: Date.now(),
|
|
171
|
+
};
|
|
172
|
+
this.cache.set(locale, empty);
|
|
173
|
+
return empty;
|
|
174
|
+
}
|
|
175
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
176
|
+
let parsed;
|
|
177
|
+
try {
|
|
178
|
+
parsed = JSON.parse(raw);
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
throw new Error(`[i18n] Failed to parse locale file ${filePath}: ${String(err)}`);
|
|
182
|
+
}
|
|
183
|
+
const bundle = {
|
|
184
|
+
locale,
|
|
185
|
+
translations: flattenTranslations(parsed),
|
|
186
|
+
loadedAt: Date.now(),
|
|
187
|
+
};
|
|
188
|
+
this.cache.set(locale, bundle);
|
|
189
|
+
return bundle;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/i18n/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAOrC,yCAAyC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,SAAS,mBAAmB,CAC3B,GAA4B,EAC5B,MAAM,GAAG,EAAE,EACX,SAA2B,IAAI,GAAG,EAAE;IAEpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QACjD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1E,mBAAmB,CAAC,KAAgC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACvE,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,qCAAqC;AAErC;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACrB,KAAK,GAA8B,IAAI,GAAG,EAAE,CAAC;IAC7C,QAAQ,GAA0C,IAAI,GAAG,EAAE,CAAC;IAC5D,MAAM,CAAqB;IAEnC,YAAY,MAA0B;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,MAAc;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;OAMG;IACH,OAAO;QACN,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACnD,IAAI,CAAC;gBACJ,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACR,wDAAwD;gBACxD,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;oBAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE;wBACtB,MAAM;wBACN,YAAY,EAAE,IAAI,GAAG,EAAE;wBACvB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;qBACpB,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,MAAc;QACxB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,aAAa;QACZ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAc;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO;QAClC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO;QAEtC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE;YACpC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACxB,IAAI,CAAC;gBACJ,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACR,4DAA4D;YAC7D,CAAC;QACF,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,YAAY;QACX,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,OAAO,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,8CAA8C;IAE9C;;;;OAIG;IACK,YAAY,CAAC,MAAc;QAClC,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;OAKG;IACK,aAAa,CAAC,MAAc;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAE3C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CACd,yCAAyC,QAAQ,IAAI;oBACpD,UAAU,MAAM,YAAY,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CACnD,CAAC;YACH,CAAC;YACD,2DAA2D;YAC3D,MAAM,KAAK,GAAiB;gBAC3B,MAAM;gBACN,YAAY,EAAE,IAAI,GAAG,EAAE;gBACvB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;aACpB,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9B,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,MAA+B,CAAC;QACpC,IAAI,CAAC;YACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACd,sCAAsC,QAAQ,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CAChE,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAiB;YAC5B,MAAM;YACN,YAAY,EAAE,mBAAmB,CAAC,MAAM,CAAC;YACzC,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;SACpB,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,MAAM,CAAC;IACf,CAAC;CACD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* i18n Middleware — Locale Detection and Translation Binding
|
|
3
|
+
*
|
|
4
|
+
* Detects locale from cookie (priority 1) then Accept-Language header (priority 2),
|
|
5
|
+
* binds t() and locale to context, persists locale choice in a cookie.
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from "../context";
|
|
8
|
+
import type { Middleware } from "../middleware";
|
|
9
|
+
import { type I18n } from "./engine";
|
|
10
|
+
import type { I18nConfig, TranslationFunction } from "./types";
|
|
11
|
+
/**
|
|
12
|
+
* Get the current locale from context.
|
|
13
|
+
* Typed helper for accessing the locale set by i18nMiddleware.
|
|
14
|
+
*
|
|
15
|
+
* Returns the default locale ("en") if middleware has not run.
|
|
16
|
+
* Useful in route handlers:
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* router.get('/locale', (ctx) => {
|
|
20
|
+
* const locale = getLocale(ctx); // 'fr', 'en', etc.
|
|
21
|
+
* return ctx.json({ locale });
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* @param ctx Bueno Context instance
|
|
25
|
+
* @returns Current locale, or "en" if middleware hasn't run
|
|
26
|
+
*/
|
|
27
|
+
export declare function getLocale(ctx: Context): string;
|
|
28
|
+
/**
|
|
29
|
+
* Get the bound translation function from context.
|
|
30
|
+
* Typed helper for accessing the t() set by i18nMiddleware.
|
|
31
|
+
*
|
|
32
|
+
* Returns an identity function (returns key as-is) if middleware has not run.
|
|
33
|
+
* Useful in route handlers:
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* router.get('/greeting', (ctx) => {
|
|
37
|
+
* const t = getT(ctx);
|
|
38
|
+
* const message = t('greeting', { name: 'Alice' });
|
|
39
|
+
* return ctx.text(message);
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* @param ctx Bueno Context instance
|
|
43
|
+
* @returns Translation function, or identity function if middleware hasn't run
|
|
44
|
+
*/
|
|
45
|
+
export declare function getT(ctx: Context): TranslationFunction;
|
|
46
|
+
/**
|
|
47
|
+
* Options for i18nMiddleware.
|
|
48
|
+
* Extends I18nConfig and adds an optional pre-constructed I18n instance.
|
|
49
|
+
*/
|
|
50
|
+
export interface I18nMiddlewareOptions extends I18nConfig {
|
|
51
|
+
/**
|
|
52
|
+
* Pre-constructed I18n instance.
|
|
53
|
+
* If not provided, one is created from the other options.
|
|
54
|
+
*
|
|
55
|
+
* Pass this when you want a single shared instance across multiple
|
|
56
|
+
* middleware chains or route groups (prevents double-loading locale files).
|
|
57
|
+
*/
|
|
58
|
+
i18n?: I18n;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create i18n middleware.
|
|
62
|
+
*
|
|
63
|
+
* Locale detection priority:
|
|
64
|
+
* 1. Cookie (bueno_locale or custom cookieName)
|
|
65
|
+
* 2. Accept-Language header
|
|
66
|
+
* 3. Default locale (config.defaultLocale)
|
|
67
|
+
*
|
|
68
|
+
* Sets on context (available via getLocale/getT):
|
|
69
|
+
* - ctx.set('locale', detectedLocale)
|
|
70
|
+
* - ctx.set('t', translationFunction)
|
|
71
|
+
*
|
|
72
|
+
* Sets on response:
|
|
73
|
+
* - Set-Cookie header to persist locale choice
|
|
74
|
+
* - Vary: Accept-Language header (for correct CDN caching)
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const router = new Router();
|
|
79
|
+
* router.use(i18nMiddleware({
|
|
80
|
+
* defaultLocale: 'en',
|
|
81
|
+
* supportedLocales: ['en', 'fr', 'de'],
|
|
82
|
+
* basePath: 'resources/i18n'
|
|
83
|
+
* }));
|
|
84
|
+
*
|
|
85
|
+
* router.get('/hello', (ctx) => {
|
|
86
|
+
* const locale = getLocale(ctx);
|
|
87
|
+
* const t = getT(ctx);
|
|
88
|
+
* return ctx.json({ message: t('greeting') });
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @param options Configuration options
|
|
93
|
+
* @returns Koa-style middleware function
|
|
94
|
+
*/
|
|
95
|
+
export declare function i18nMiddleware(options?: I18nMiddlewareOptions): Middleware;
|
|
96
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/i18n/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,KAAK,IAAI,EAAc,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAI/D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE9C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,mBAAmB,CAEtD;AAID;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,UAAU;IACxD;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;CACZ;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,cAAc,CAC7B,OAAO,GAAE,qBAA0B,GACjC,UAAU,CAoDZ"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* i18n Middleware — Locale Detection and Translation Binding
|
|
3
|
+
*
|
|
4
|
+
* Detects locale from cookie (priority 1) then Accept-Language header (priority 2),
|
|
5
|
+
* binds t() and locale to context, persists locale choice in a cookie.
|
|
6
|
+
*/
|
|
7
|
+
import { createI18n } from "./engine";
|
|
8
|
+
// ============= Typed Context Helpers =============
|
|
9
|
+
/**
|
|
10
|
+
* Get the current locale from context.
|
|
11
|
+
* Typed helper for accessing the locale set by i18nMiddleware.
|
|
12
|
+
*
|
|
13
|
+
* Returns the default locale ("en") if middleware has not run.
|
|
14
|
+
* Useful in route handlers:
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* router.get('/locale', (ctx) => {
|
|
18
|
+
* const locale = getLocale(ctx); // 'fr', 'en', etc.
|
|
19
|
+
* return ctx.json({ locale });
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* @param ctx Bueno Context instance
|
|
23
|
+
* @returns Current locale, or "en" if middleware hasn't run
|
|
24
|
+
*/
|
|
25
|
+
export function getLocale(ctx) {
|
|
26
|
+
return ctx.get("locale") ?? "en";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the bound translation function from context.
|
|
30
|
+
* Typed helper for accessing the t() set by i18nMiddleware.
|
|
31
|
+
*
|
|
32
|
+
* Returns an identity function (returns key as-is) if middleware has not run.
|
|
33
|
+
* Useful in route handlers:
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* router.get('/greeting', (ctx) => {
|
|
37
|
+
* const t = getT(ctx);
|
|
38
|
+
* const message = t('greeting', { name: 'Alice' });
|
|
39
|
+
* return ctx.text(message);
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* @param ctx Bueno Context instance
|
|
43
|
+
* @returns Translation function, or identity function if middleware hasn't run
|
|
44
|
+
*/
|
|
45
|
+
export function getT(ctx) {
|
|
46
|
+
return ctx.get("t") ?? ((key) => key);
|
|
47
|
+
}
|
|
48
|
+
// ============= Middleware Factory =============
|
|
49
|
+
/**
|
|
50
|
+
* Create i18n middleware.
|
|
51
|
+
*
|
|
52
|
+
* Locale detection priority:
|
|
53
|
+
* 1. Cookie (bueno_locale or custom cookieName)
|
|
54
|
+
* 2. Accept-Language header
|
|
55
|
+
* 3. Default locale (config.defaultLocale)
|
|
56
|
+
*
|
|
57
|
+
* Sets on context (available via getLocale/getT):
|
|
58
|
+
* - ctx.set('locale', detectedLocale)
|
|
59
|
+
* - ctx.set('t', translationFunction)
|
|
60
|
+
*
|
|
61
|
+
* Sets on response:
|
|
62
|
+
* - Set-Cookie header to persist locale choice
|
|
63
|
+
* - Vary: Accept-Language header (for correct CDN caching)
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const router = new Router();
|
|
68
|
+
* router.use(i18nMiddleware({
|
|
69
|
+
* defaultLocale: 'en',
|
|
70
|
+
* supportedLocales: ['en', 'fr', 'de'],
|
|
71
|
+
* basePath: 'resources/i18n'
|
|
72
|
+
* }));
|
|
73
|
+
*
|
|
74
|
+
* router.get('/hello', (ctx) => {
|
|
75
|
+
* const locale = getLocale(ctx);
|
|
76
|
+
* const t = getT(ctx);
|
|
77
|
+
* return ctx.json({ message: t('greeting') });
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @param options Configuration options
|
|
82
|
+
* @returns Koa-style middleware function
|
|
83
|
+
*/
|
|
84
|
+
export function i18nMiddleware(options = {}) {
|
|
85
|
+
const engine = options.i18n ?? createI18n(options);
|
|
86
|
+
const negotiator = engine.getNegotiator();
|
|
87
|
+
const cookieName = engine.config.cookieName;
|
|
88
|
+
const cookieMaxAge = engine.config.cookieMaxAge;
|
|
89
|
+
return async (ctx, next) => {
|
|
90
|
+
// --- Step 1: Detect locale ---
|
|
91
|
+
let locale;
|
|
92
|
+
// Priority 1: Cookie
|
|
93
|
+
const cookieLocale = ctx.getCookie(cookieName);
|
|
94
|
+
if (cookieLocale && negotiator.isSupported(cookieLocale)) {
|
|
95
|
+
locale = cookieLocale;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// Priority 2: Accept-Language header
|
|
99
|
+
const acceptLanguage = ctx.getHeader("accept-language") ?? "";
|
|
100
|
+
if (acceptLanguage) {
|
|
101
|
+
const match = negotiator.negotiate(acceptLanguage);
|
|
102
|
+
locale = match.locale;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
locale = engine.config.defaultLocale;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// --- Step 2: Store on context ---
|
|
109
|
+
// Use 'as never' cast for now (same pattern as requestId middleware)
|
|
110
|
+
// Typed access via getLocale(ctx) and getT(ctx) helpers
|
|
111
|
+
ctx.set("locale", locale);
|
|
112
|
+
ctx.set("t", engine.createTranslator(locale));
|
|
113
|
+
// --- Step 3: Call next ---
|
|
114
|
+
const response = await next();
|
|
115
|
+
// --- Step 4: Set cookie on response ---
|
|
116
|
+
// Always refresh the cookie so it stays alive during user session
|
|
117
|
+
const cookieValue = `${cookieName}=${locale}; Max-Age=${cookieMaxAge}; Path=/; SameSite=Lax`;
|
|
118
|
+
response.headers.append("Set-Cookie", cookieValue);
|
|
119
|
+
// --- Step 5: Set Vary header ---
|
|
120
|
+
// Instruct caches to vary on Accept-Language so different locales are cached separately
|
|
121
|
+
const existing = response.headers.get("Vary");
|
|
122
|
+
response.headers.set("Vary", existing ? `${existing}, Accept-Language` : "Accept-Language");
|
|
123
|
+
return response;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/i18n/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAa,UAAU,EAAE,MAAM,UAAU,CAAC;AAGjD,oDAAoD;AAEpD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IACrC,OAAQ,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAwB,IAAI,IAAI,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,IAAI,CAAC,GAAY;IAChC,OAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAqC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAC5E,CAAC;AAmBD,iDAAiD;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,cAAc,CAC7B,UAAiC,EAAE;IAEnC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAEhD,OAAO,KAAK,EACX,GAAY,EACZ,IAA6B,EACT,EAAE;QACtB,gCAAgC;QAChC,IAAI,MAAc,CAAC;QAEnB,qBAAqB;QACrB,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC/C,IAAI,YAAY,IAAI,UAAU,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1D,MAAM,GAAG,YAAY,CAAC;QACvB,CAAC;aAAM,CAAC;YACP,qCAAqC;YACrC,MAAM,cAAc,GAAG,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;YAC9D,IAAI,cAAc,EAAE,CAAC;gBACpB,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;gBACnD,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACP,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;YACtC,CAAC;QACF,CAAC;QAED,mCAAmC;QACnC,qEAAqE;QACrE,wDAAwD;QACxD,GAAG,CAAC,GAAG,CAAC,QAAiB,EAAE,MAAM,CAAC,CAAC;QACnC,GAAG,CAAC,GAAG,CAAC,GAAY,EAAE,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAEvD,4BAA4B;QAC5B,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC;QAE9B,yCAAyC;QACzC,kEAAkE;QAClE,MAAM,WAAW,GAAG,GAAG,UAAU,IAAI,MAAM,aAAa,YAAY,wBAAwB,CAAC;QAC7F,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QAEnD,kCAAkC;QAClC,wFAAwF;QACxF,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9C,QAAQ,CAAC,OAAO,CAAC,GAAG,CACnB,MAAM,EACN,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,mBAAmB,CAAC,CAAC,CAAC,iBAAiB,CAC7D,CAAC;QAEF,OAAO,QAAQ,CAAC;IACjB,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale Negotiation — Accept-Language Header Parsing
|
|
3
|
+
*
|
|
4
|
+
* Parses RFC 7231 Accept-Language headers and matches them against
|
|
5
|
+
* supported locales using exact and language-prefix matching.
|
|
6
|
+
*
|
|
7
|
+
* @see https://tools.ietf.org/html/rfc7231#section-5.3.5
|
|
8
|
+
*/
|
|
9
|
+
import type { LocaleMatch } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* Parsed entry from an Accept-Language header.
|
|
12
|
+
*/
|
|
13
|
+
interface AcceptEntry {
|
|
14
|
+
locale: string;
|
|
15
|
+
quality: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse RFC 7231 Accept-Language header value into quality-sorted entries.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* Input: "en-US,en;q=0.9,fr;q=0.8"
|
|
22
|
+
* Output: [
|
|
23
|
+
* { locale: "en-US", quality: 1.0 },
|
|
24
|
+
* { locale: "en", quality: 0.9 },
|
|
25
|
+
* { locale: "fr", quality: 0.8 }
|
|
26
|
+
* ]
|
|
27
|
+
*
|
|
28
|
+
* @param header Raw Accept-Language header value
|
|
29
|
+
* @returns Array of entries sorted by quality (highest first)
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseAcceptLanguage(header: string): AcceptEntry[];
|
|
32
|
+
/**
|
|
33
|
+
* Normalise a locale tag:
|
|
34
|
+
* - Converts underscore to hyphen ("en_US" → "en-US")
|
|
35
|
+
* - Lowercases language subtag ("EN" → "en")
|
|
36
|
+
* - Uppercases region subtag ("us" → "US")
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* normaliseLocale("en_US") → "en-US"
|
|
40
|
+
* normaliseLocale("EN-us") → "en-US"
|
|
41
|
+
* normaliseLocale("fr") → "fr"
|
|
42
|
+
*
|
|
43
|
+
* @param locale Raw locale string
|
|
44
|
+
* @returns Normalised locale string
|
|
45
|
+
*/
|
|
46
|
+
export declare function normaliseLocale(locale: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Negotiates the best locale match given an Accept-Language header
|
|
49
|
+
* and a list of supported locales.
|
|
50
|
+
*
|
|
51
|
+
* Matching strategy (two-pass):
|
|
52
|
+
* 1. Exact match: find a supported locale that exactly matches (case-normalised) any entry
|
|
53
|
+
* 2. Language prefix match: find a supported locale whose language subtag matches any entry
|
|
54
|
+
* 3. Default: return the configured default locale
|
|
55
|
+
*
|
|
56
|
+
* This two-pass approach ensures correct behavior even when entries
|
|
57
|
+
* are out of quality order, e.g. "fr-CA,de;q=0.9" against ["de","fr"]
|
|
58
|
+
* should return "fr" (via prefix match), not "de".
|
|
59
|
+
*/
|
|
60
|
+
export declare class LocaleNegotiator {
|
|
61
|
+
private supported;
|
|
62
|
+
private defaultLocale;
|
|
63
|
+
constructor(supportedLocales: string[], defaultLocale: string);
|
|
64
|
+
/**
|
|
65
|
+
* Find the best matching locale given a raw Accept-Language header string.
|
|
66
|
+
*
|
|
67
|
+
* @param acceptLanguageHeader Raw Accept-Language header value
|
|
68
|
+
* @returns LocaleMatch with matched locale and strategy used
|
|
69
|
+
*/
|
|
70
|
+
negotiate(acceptLanguageHeader: string): LocaleMatch;
|
|
71
|
+
/**
|
|
72
|
+
* Validate whether a given locale string is in the supported list.
|
|
73
|
+
* Used to validate cookie values before trusting them.
|
|
74
|
+
*
|
|
75
|
+
* Performs strict membership check — does not normalise or approximate.
|
|
76
|
+
* If a cookie contains "fr-CA" but only "fr" is supported, this returns false.
|
|
77
|
+
*
|
|
78
|
+
* @param locale Locale to validate
|
|
79
|
+
* @returns true if locale is in supportedLocales
|
|
80
|
+
*/
|
|
81
|
+
isSupported(locale: string): boolean;
|
|
82
|
+
}
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=negotiator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"negotiator.d.ts","sourceRoot":"","sources":["../../src/i18n/negotiator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C;;GAEG;AACH,UAAU,WAAW;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CAejE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOtD;AAcD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,aAAa,CAAS;gBAElB,gBAAgB,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM;IAK7D;;;;;OAKG;IACH,SAAS,CAAC,oBAAoB,EAAE,MAAM,GAAG,WAAW;IA+BpD;;;;;;;;;OASG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAGpC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale Negotiation — Accept-Language Header Parsing
|
|
3
|
+
*
|
|
4
|
+
* Parses RFC 7231 Accept-Language headers and matches them against
|
|
5
|
+
* supported locales using exact and language-prefix matching.
|
|
6
|
+
*
|
|
7
|
+
* @see https://tools.ietf.org/html/rfc7231#section-5.3.5
|
|
8
|
+
*/
|
|
9
|
+
// ============= Parsing =============
|
|
10
|
+
/**
|
|
11
|
+
* Parse RFC 7231 Accept-Language header value into quality-sorted entries.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* Input: "en-US,en;q=0.9,fr;q=0.8"
|
|
15
|
+
* Output: [
|
|
16
|
+
* { locale: "en-US", quality: 1.0 },
|
|
17
|
+
* { locale: "en", quality: 0.9 },
|
|
18
|
+
* { locale: "fr", quality: 0.8 }
|
|
19
|
+
* ]
|
|
20
|
+
*
|
|
21
|
+
* @param header Raw Accept-Language header value
|
|
22
|
+
* @returns Array of entries sorted by quality (highest first)
|
|
23
|
+
*/
|
|
24
|
+
export function parseAcceptLanguage(header) {
|
|
25
|
+
if (!header.trim())
|
|
26
|
+
return [];
|
|
27
|
+
return header
|
|
28
|
+
.split(",")
|
|
29
|
+
.map((part) => {
|
|
30
|
+
const [localeRaw, qRaw] = part.trim().split(";");
|
|
31
|
+
const locale = localeRaw?.trim() ?? "";
|
|
32
|
+
const quality = qRaw
|
|
33
|
+
? Number.parseFloat(qRaw.trim().replace("q=", ""))
|
|
34
|
+
: 1.0;
|
|
35
|
+
return { locale, quality: isNaN(quality) ? 1.0 : quality };
|
|
36
|
+
})
|
|
37
|
+
.filter((e) => e.locale.length > 0)
|
|
38
|
+
.sort((a, b) => b.quality - a.quality);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Normalise a locale tag:
|
|
42
|
+
* - Converts underscore to hyphen ("en_US" → "en-US")
|
|
43
|
+
* - Lowercases language subtag ("EN" → "en")
|
|
44
|
+
* - Uppercases region subtag ("us" → "US")
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* normaliseLocale("en_US") → "en-US"
|
|
48
|
+
* normaliseLocale("EN-us") → "en-US"
|
|
49
|
+
* normaliseLocale("fr") → "fr"
|
|
50
|
+
*
|
|
51
|
+
* @param locale Raw locale string
|
|
52
|
+
* @returns Normalised locale string
|
|
53
|
+
*/
|
|
54
|
+
export function normaliseLocale(locale) {
|
|
55
|
+
const parts = locale.replace("_", "-").split("-");
|
|
56
|
+
if (parts.length === 0)
|
|
57
|
+
return locale;
|
|
58
|
+
const lang = parts[0].toLowerCase();
|
|
59
|
+
if (parts.length === 1)
|
|
60
|
+
return lang;
|
|
61
|
+
const region = parts[1].toUpperCase();
|
|
62
|
+
return `${lang}-${region}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Extract the language subtag from a locale.
|
|
66
|
+
* @example languageSubtag("en-US") → "en"
|
|
67
|
+
* @param locale Locale identifier
|
|
68
|
+
* @returns Language subtag (first part before hyphen)
|
|
69
|
+
*/
|
|
70
|
+
function languageSubtag(locale) {
|
|
71
|
+
return locale.split("-")[0].toLowerCase();
|
|
72
|
+
}
|
|
73
|
+
// ============= Negotiator =============
|
|
74
|
+
/**
|
|
75
|
+
* Negotiates the best locale match given an Accept-Language header
|
|
76
|
+
* and a list of supported locales.
|
|
77
|
+
*
|
|
78
|
+
* Matching strategy (two-pass):
|
|
79
|
+
* 1. Exact match: find a supported locale that exactly matches (case-normalised) any entry
|
|
80
|
+
* 2. Language prefix match: find a supported locale whose language subtag matches any entry
|
|
81
|
+
* 3. Default: return the configured default locale
|
|
82
|
+
*
|
|
83
|
+
* This two-pass approach ensures correct behavior even when entries
|
|
84
|
+
* are out of quality order, e.g. "fr-CA,de;q=0.9" against ["de","fr"]
|
|
85
|
+
* should return "fr" (via prefix match), not "de".
|
|
86
|
+
*/
|
|
87
|
+
export class LocaleNegotiator {
|
|
88
|
+
supported;
|
|
89
|
+
defaultLocale;
|
|
90
|
+
constructor(supportedLocales, defaultLocale) {
|
|
91
|
+
this.supported = supportedLocales;
|
|
92
|
+
this.defaultLocale = defaultLocale;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Find the best matching locale given a raw Accept-Language header string.
|
|
96
|
+
*
|
|
97
|
+
* @param acceptLanguageHeader Raw Accept-Language header value
|
|
98
|
+
* @returns LocaleMatch with matched locale and strategy used
|
|
99
|
+
*/
|
|
100
|
+
negotiate(acceptLanguageHeader) {
|
|
101
|
+
const entries = parseAcceptLanguage(acceptLanguageHeader);
|
|
102
|
+
// Pass 1: exact match (case-normalised)
|
|
103
|
+
for (const entry of entries) {
|
|
104
|
+
const norm = normaliseLocale(entry.locale);
|
|
105
|
+
const exact = this.supported.find((s) => normaliseLocale(s) === norm);
|
|
106
|
+
if (exact) {
|
|
107
|
+
return { locale: exact, strategy: "exact", source: entry.locale };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Pass 2: language prefix match ("en-US" matches supported "en")
|
|
111
|
+
for (const entry of entries) {
|
|
112
|
+
const lang = languageSubtag(entry.locale);
|
|
113
|
+
const prefix = this.supported.find((s) => languageSubtag(s) === lang);
|
|
114
|
+
if (prefix) {
|
|
115
|
+
return { locale: prefix, strategy: "prefix", source: entry.locale };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Default fallback
|
|
119
|
+
return {
|
|
120
|
+
locale: this.defaultLocale,
|
|
121
|
+
strategy: "default",
|
|
122
|
+
source: "",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Validate whether a given locale string is in the supported list.
|
|
127
|
+
* Used to validate cookie values before trusting them.
|
|
128
|
+
*
|
|
129
|
+
* Performs strict membership check — does not normalise or approximate.
|
|
130
|
+
* If a cookie contains "fr-CA" but only "fr" is supported, this returns false.
|
|
131
|
+
*
|
|
132
|
+
* @param locale Locale to validate
|
|
133
|
+
* @returns true if locale is in supportedLocales
|
|
134
|
+
*/
|
|
135
|
+
isSupported(locale) {
|
|
136
|
+
return this.supported.includes(locale);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=negotiator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"negotiator.js","sourceRoot":"","sources":["../../src/i18n/negotiator.ts"],"names":[],"mappings":"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"}
|