@warlock.js/core 5.31.0 → 5.32.0
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/CHANGELOG.md +23 -0
- package/esm/application/app.d.mts +3 -3
- package/esm/application/app.d.mts.map +1 -1
- package/esm/application/application-config-types.d.mts +1 -2
- package/esm/application/application-config-types.d.mts.map +1 -1
- package/esm/application/application.d.mts +5 -7
- package/esm/application/application.d.mts.map +1 -1
- package/esm/application/application.mjs +3 -1
- package/esm/application/application.mjs.map +1 -1
- package/esm/application/boot-signal.d.mts +14 -12
- package/esm/application/boot-signal.d.mts.map +1 -1
- package/esm/application/index.d.mts +2 -1
- package/esm/application/index.mjs +1 -1
- package/esm/application/public-url.d.mts +1 -2
- package/esm/application/public-url.d.mts.map +1 -1
- package/esm/application/roles.d.mts +10 -11
- package/esm/application/roles.d.mts.map +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts +1 -3
- package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
- package/esm/benchmark/benchmark.d.mts +1 -3
- package/esm/benchmark/benchmark.d.mts.map +1 -1
- package/esm/benchmark/channels/console.channel.d.mts +1 -3
- package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts +1 -3
- package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
- package/esm/benchmark/index.mjs +1 -1
- package/esm/benchmark/profiler.d.mts +1 -3
- package/esm/benchmark/profiler.d.mts.map +1 -1
- package/esm/benchmark/profiler.mjs +2 -1
- package/esm/benchmark/profiler.mjs.map +1 -1
- package/esm/benchmark/types.d.mts +22 -17
- package/esm/benchmark/types.d.mts.map +1 -1
- package/esm/bootstrap/setup.d.mts +1 -2
- package/esm/bootstrap/setup.d.mts.map +1 -1
- package/esm/bootstrap.d.mts +1 -2
- package/esm/bootstrap.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.d.mts +3 -5
- package/esm/cache/database-cache-driver.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.mjs +1 -1
- package/esm/cache/index.d.mts +2 -1
- package/esm/cache/index.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs +6 -3
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/commands/agents-md/agents-md-command.action.mjs +3 -2
- package/esm/cli/commands/agents-md/agents-md-command.action.mjs.map +1 -1
- package/esm/cli/commands/board/board-command.action.mjs +1 -1
- package/esm/cli/commands/check/check-command.action.mjs +1 -1
- package/esm/cli/commands/check/child-typecheck.mjs +1 -1
- package/esm/cli/commands/check/child-typecheck.mjs.map +1 -1
- package/esm/cli/commands/check/format-problems.mjs +1 -1
- package/esm/cli/commands/dev-server.command.mjs +3 -2
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/cli/commands/doctor/check.types.d.mts +29 -16
- package/esm/cli/commands/doctor/check.types.d.mts.map +1 -1
- package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +22 -27
- package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs +2 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
- package/esm/cli/commands/explain/explain-command.action.mjs +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs +5 -2
- package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs +5 -3
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs +3 -2
- package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs +3 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs +3 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs +3 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/templates/endpoint-stubs.mjs +2 -2
- package/esm/cli/commands/generate/templates/endpoint-stubs.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/endpoint-schema.mjs +1 -2
- package/esm/cli/commands/generate/utils/endpoint-schema.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
- package/esm/cli/commands/inspect/inspect-command.action.mjs +3 -2
- package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -1
- package/esm/cli/commands/issue/collect-environment.mjs +187 -0
- package/esm/cli/commands/issue/collect-environment.mjs.map +1 -0
- package/esm/cli/commands/issue/issue-command.action.mjs +70 -0
- package/esm/cli/commands/issue/issue-command.action.mjs.map +1 -0
- package/esm/cli/commands/issue.command.mjs +31 -0
- package/esm/cli/commands/issue.command.mjs.map +1 -0
- package/esm/cli/commands/mcp/mcp-command.action.mjs +15 -14
- package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -1
- package/esm/cli/commands/openapi-generator.action.mjs +1 -1
- package/esm/cli/commands/postman-generator.action.mjs +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
- package/esm/cli/commands/routes/route-row.mjs +1 -1
- package/esm/cli/commands/routes/routes-diff.action.mjs +2 -2
- package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
- package/esm/cli/commands/test.command.mjs +1 -1
- package/esm/cli/commands/trace/trace-command.action.mjs +1 -1
- package/esm/cli/commands-loader.mjs +1 -1
- package/esm/cli/framework-cli-commands.mjs +2 -0
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/cli/parse-cli-args.mjs +2 -2
- package/esm/cli/parse-cli-args.mjs.map +1 -1
- package/esm/cli/start.d.mts +1 -1
- package/esm/cli/string-similarity.mjs +1 -1
- package/esm/commands/cli-command.d.mts +2 -4
- package/esm/commands/cli-command.d.mts.map +1 -1
- package/esm/commands/index.d.mts +2 -1
- package/esm/commands/index.mjs +1 -1
- package/esm/commands/types.d.mts +8 -8
- package/esm/commands/types.d.mts.map +1 -1
- package/esm/config/config-getter.d.mts +2 -3
- package/esm/config/config-getter.d.mts.map +1 -1
- package/esm/config/config-getter.mjs +5 -5
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-handlers.d.mts +1 -3
- package/esm/config/config-handlers.d.mts.map +1 -1
- package/esm/config/config-loader.d.mts +1 -2
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +3 -3
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/config-manager.mjs +1 -1
- package/esm/config/config-schema.d.mts +19 -16
- package/esm/config/config-schema.d.mts.map +1 -1
- package/esm/config/config-setter.d.mts +2 -4
- package/esm/config/config-setter.d.mts.map +1 -1
- package/esm/config/config-setter.mjs +2 -2
- package/esm/config/config-setter.mjs.map +1 -1
- package/esm/config/config-special-handlers.d.mts +2 -4
- package/esm/config/config-special-handlers.d.mts.map +1 -1
- package/esm/config/index.d.mts +2 -1
- package/esm/config/index.mjs +1 -1
- package/esm/config/types.d.mts +4 -5
- package/esm/config/types.d.mts.map +1 -1
- package/esm/connectors/access-connector.d.mts +1 -3
- package/esm/connectors/access-connector.d.mts.map +1 -1
- package/esm/connectors/access-connector.mjs +2 -2
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.d.mts +1 -3
- package/esm/connectors/ai-connector.d.mts.map +1 -1
- package/esm/connectors/ai-connector.mjs +2 -2
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -3
- package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-unique-connector-names.d.mts +1 -3
- package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-unique-connector-names.mjs +2 -1
- package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
- package/esm/connectors/base-connector.d.mts +1 -3
- package/esm/connectors/base-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.d.mts +1 -3
- package/esm/connectors/cache-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.mjs +3 -3
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/connectors-manager.d.mts +2 -4
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +2 -2
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/database-connector.d.mts +1 -3
- package/esm/connectors/database-connector.d.mts.map +1 -1
- package/esm/connectors/database-connector.mjs +2 -2
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/describe-server-address.mjs +4 -4
- package/esm/connectors/describe-server-address.mjs.map +1 -1
- package/esm/connectors/herald-connector.d.mts +1 -3
- package/esm/connectors/herald-connector.d.mts.map +1 -1
- package/esm/connectors/herald-connector.mjs +2 -2
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts +1 -3
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +8 -7
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/index.d.mts +2 -1
- package/esm/connectors/index.mjs +1 -1
- package/esm/connectors/logger-connector.d.mts +1 -3
- package/esm/connectors/logger-connector.d.mts.map +1 -1
- package/esm/connectors/logger-connector.mjs +2 -2
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.d.mts +1 -3
- package/esm/connectors/mail-connector.d.mts.map +1 -1
- package/esm/connectors/mail-connector.mjs +2 -2
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.d.mts +1 -3
- package/esm/connectors/notifications-connector.d.mts.map +1 -1
- package/esm/connectors/notifications-connector.mjs +2 -2
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/register-configured-connectors.d.mts +2 -4
- package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
- package/esm/connectors/socket-connector.d.mts +1 -3
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +12 -10
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/connectors/storage.connector.d.mts +1 -3
- package/esm/connectors/storage.connector.d.mts.map +1 -1
- package/esm/connectors/storage.connector.mjs +2 -2
- package/esm/connectors/storage.connector.mjs.map +1 -1
- package/esm/connectors/types.d.mts +17 -14
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/container/container-instance-registry.mjs.map +1 -1
- package/esm/container/development-app-modules.d.mts +7 -5
- package/esm/container/development-app-modules.d.mts.map +1 -1
- package/esm/container/development-model-modules.d.mts +6 -5
- package/esm/container/development-model-modules.d.mts.map +1 -1
- package/esm/container/index.d.mts +4 -4
- package/esm/container/index.d.mts.map +1 -1
- package/esm/database/index.d.mts +3 -1
- package/esm/database/index.mjs +1 -1
- package/esm/database/migrate-action.mjs +1 -1
- package/esm/database/models/database-log/database-log.d.mts +2 -3
- package/esm/database/models/database-log/database-log.d.mts.map +1 -1
- package/esm/database/models/database-log/index.d.mts +2 -1
- package/esm/database/models/database-log/index.mjs +1 -1
- package/esm/database/seed-command-action.mjs +1 -1
- package/esm/database/seeds/seeder.d.mts +2 -4
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +2 -3
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +2 -1
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +7 -8
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/utils.d.mts +4 -5
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/dev-server/app-module-registry.mjs +1 -1
- package/esm/dev-server/create-worker.mjs +5 -3
- package/esm/dev-server/create-worker.mjs.map +1 -1
- package/esm/dev-server/dependency-graph.d.mts +1 -3
- package/esm/dev-server/dependency-graph.d.mts.map +1 -1
- package/esm/dev-server/dependency-graph.mjs +1 -1
- package/esm/dev-server/dependency-graph.mjs.map +1 -1
- package/esm/dev-server/extract-translation-keys.mjs +16 -17
- package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +3 -7
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-operations.d.mts +1 -3
- package/esm/dev-server/file-operations.d.mts.map +1 -1
- package/esm/dev-server/files-watcher.mjs +12 -11
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +36 -115
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +5 -5
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts +2 -2
- package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -0
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
- package/esm/dev-server/health-checker/oxlint-runner.mjs +6 -5
- package/esm/dev-server/health-checker/oxlint-runner.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +1 -1
- package/esm/dev-server/health-checker/workers/oxlint-health.worker.d.mts +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.d.mts +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +40 -174
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts +4 -8
- package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.d.mts +10 -6
- package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.mjs +4 -3
- package/esm/dev-server/loader/load-hook.mjs.map +1 -1
- package/esm/dev-server/loader/own-resolver.mjs +1 -1
- package/esm/dev-server/loader/register-loader.mjs +3 -2
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts +2 -2
- package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs +2 -1
- package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs +2 -1
- package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
- package/esm/dev-server/manifest-manager.d.mts +1 -3
- package/esm/dev-server/manifest-manager.d.mts.map +1 -1
- package/esm/dev-server/model-module-registry.mjs +3 -3
- package/esm/dev-server/model-module-registry.mjs.map +1 -1
- package/esm/dev-server/model-resource-typings.mjs +40 -47
- package/esm/dev-server/model-resource-typings.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs +2 -2
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/package-json-manager.mjs +1 -1
- package/esm/dev-server/parse-imports.mjs +6 -38
- package/esm/dev-server/parse-imports.mjs.map +1 -1
- package/esm/dev-server/read-config-ast.mjs +3 -33
- package/esm/dev-server/read-config-ast.mjs.map +1 -1
- package/esm/dev-server/ready-block.mjs +1 -1
- package/esm/dev-server/shortcuts.mjs +1 -1
- package/esm/dev-server/special-files-collector.d.mts +2 -4
- package/esm/dev-server/special-files-collector.d.mts.map +1 -1
- package/esm/dev-server/supervisor.mjs +1 -1
- package/esm/dev-server/tsconfig-manager.mjs +3 -3
- package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs +28 -35
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/dev-server/types.d.mts +3 -4
- package/esm/dev-server/types.d.mts.map +1 -1
- package/esm/dev-server/update-check-cache.mjs +2 -2
- package/esm/dev-server/update-check-cache.mjs.map +1 -1
- package/esm/encryption/encrypt.d.mts +2 -3
- package/esm/encryption/encrypt.d.mts.map +1 -1
- package/esm/encryption/hash.d.mts +1 -2
- package/esm/encryption/hash.d.mts.map +1 -1
- package/esm/encryption/index.mjs +1 -1
- package/esm/encryption/password.d.mts +2 -3
- package/esm/encryption/password.d.mts.map +1 -1
- package/esm/encryption/types.d.mts +2 -3
- package/esm/encryption/types.d.mts.map +1 -1
- package/esm/errors/error-codes.d.mts +29 -22
- package/esm/errors/error-codes.d.mts.map +1 -1
- package/esm/errors/warlock-error.d.mts +1 -3
- package/esm/errors/warlock-error.d.mts.map +1 -1
- package/esm/generations/add-command.action.mjs +3 -2
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/features/bull-board.feature.mjs +2 -1
- package/esm/generations/features/bull-board.feature.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs +2 -1
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/shared/merge-web-sitemap-config.mjs +16 -23
- package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
- package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
- package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
- package/esm/generations/features/sitemap.feature.mjs +2 -1
- package/esm/generations/features/sitemap.feature.mjs.map +1 -1
- package/esm/generations/generation-fs.mjs +1 -1
- package/esm/generations/generation-run.mjs +1 -1
- package/esm/generations/stubs.mjs +1 -1
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/boot-port-preflight.d.mts +4 -5
- package/esm/http/boot-port-preflight.d.mts.map +1 -1
- package/esm/http/boot-port-preflight.mjs +2 -2
- package/esm/http/boot-port-preflight.mjs.map +1 -1
- package/esm/http/bounded-stream-queue.d.mts +4 -4
- package/esm/http/bounded-stream-queue.d.mts.map +1 -1
- package/esm/http/bounded-stream-queue.mjs +1 -1
- package/esm/http/bounded-stream-queue.mjs.map +1 -1
- package/esm/http/build-cors-options.mjs +2 -2
- package/esm/http/build-cors-options.mjs.map +1 -1
- package/esm/http/build-rate-limit-options.d.mts +2 -3
- package/esm/http/build-rate-limit-options.d.mts.map +1 -1
- package/esm/http/build-rate-limit-options.mjs +1 -1
- package/esm/http/build-rate-limit-options.mjs.map +1 -1
- package/esm/http/conditional-request.d.mts +14 -13
- package/esm/http/conditional-request.d.mts.map +1 -1
- package/esm/http/config.d.mts +2 -4
- package/esm/http/config.d.mts.map +1 -1
- package/esm/http/config.mjs +2 -2
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/context/request-context.d.mts +6 -7
- package/esm/http/context/request-context.d.mts.map +1 -1
- package/esm/http/context/request-memo.d.mts +1 -2
- package/esm/http/context/request-memo.d.mts.map +1 -1
- package/esm/http/createHttpApplication.d.mts +2 -3
- package/esm/http/createHttpApplication.d.mts.map +1 -1
- package/esm/http/createHttpApplication.mjs +2 -2
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/csp.d.mts +10 -12
- package/esm/http/csp.d.mts.map +1 -1
- package/esm/http/csp.mjs +2 -2
- package/esm/http/csp.mjs.map +1 -1
- package/esm/http/csrf-default-guard.d.mts +2 -4
- package/esm/http/csrf-default-guard.d.mts.map +1 -1
- package/esm/http/csrf-default-guard.mjs +1 -1
- package/esm/http/csrf-default-guard.mjs.map +1 -1
- package/esm/http/csrf-origin-policy.d.mts +7 -9
- package/esm/http/csrf-origin-policy.d.mts.map +1 -1
- package/esm/http/csrf-origin-policy.mjs +2 -2
- package/esm/http/csrf-origin-policy.mjs.map +1 -1
- package/esm/http/database/RequestLog.d.mts +2 -3
- package/esm/http/database/RequestLog.d.mts.map +1 -1
- package/esm/http/error-codes.d.mts +1 -2
- package/esm/http/error-codes.d.mts.map +1 -1
- package/esm/http/error-mapper.d.mts +2 -4
- package/esm/http/error-mapper.d.mts.map +1 -1
- package/esm/http/error-mapper.mjs +2 -2
- package/esm/http/error-mapper.mjs.map +1 -1
- package/esm/http/errors/errors.d.mts +28 -29
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/escape-header-value.d.mts +1 -2
- package/esm/http/escape-header-value.d.mts.map +1 -1
- package/esm/http/events.d.mts +2 -4
- package/esm/http/events.d.mts.map +1 -1
- package/esm/http/health.d.mts +4 -4
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/index.d.mts +4 -1
- package/esm/http/index.mjs +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts +2 -4
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts +3 -3
- package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts +3 -3
- package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +6 -6
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/index.d.mts +3 -1
- package/esm/http/middleware/index.mjs +1 -1
- package/esm/http/middleware/inject-request-context.d.mts +2 -4
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +3 -3
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts +3 -3
- package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts +3 -3
- package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +4 -4
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts +2 -2
- package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
- package/esm/http/middleware/middleware-list.d.mts +1 -3
- package/esm/http/middleware/middleware-list.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts +3 -3
- package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs +2 -2
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts +2 -3
- package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts +3 -5
- package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
- package/esm/http/middleware/utils/index.d.mts +2 -1
- package/esm/http/middleware/utils/parse-size.d.mts +1 -2
- package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
- package/esm/http/middleware/utils/parse-size.mjs +2 -2
- package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
- package/esm/http/plugins.d.mts +2 -4
- package/esm/http/plugins.d.mts.map +1 -1
- package/esm/http/plugins.mjs +10 -10
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/port-preflight.d.mts +3 -4
- package/esm/http/port-preflight.d.mts.map +1 -1
- package/esm/http/rate-limit-cache-store.mjs +4 -3
- package/esm/http/rate-limit-cache-store.mjs.map +1 -1
- package/esm/http/ready-report.d.mts +15 -10
- package/esm/http/ready-report.d.mts.map +1 -1
- package/esm/http/request-controller.d.mts +1 -3
- package/esm/http/request-controller.d.mts.map +1 -1
- package/esm/http/request-log-snapshot.d.mts +20 -16
- package/esm/http/request-log-snapshot.d.mts.map +1 -1
- package/esm/http/request-log-snapshot.mjs +3 -3
- package/esm/http/request-log-snapshot.mjs.map +1 -1
- package/esm/http/request.d.mts +8 -7
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +8 -7
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/response.d.mts +12 -11
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +7 -7
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/safe-redirect.d.mts +3 -4
- package/esm/http/safe-redirect.d.mts.map +1 -1
- package/esm/http/serialized.d.mts +12 -13
- package/esm/http/serialized.d.mts.map +1 -1
- package/esm/http/server-rebuilt.d.mts +3 -5
- package/esm/http/server-rebuilt.d.mts.map +1 -1
- package/esm/http/server.d.mts +9 -9
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +4 -4
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/stream-react-response.d.mts +7 -7
- package/esm/http/stream-react-response.d.mts.map +1 -1
- package/esm/http/tracing/index.mjs +1 -1
- package/esm/http/tracing/trace-id.d.mts +2 -3
- package/esm/http/tracing/trace-id.d.mts.map +1 -1
- package/esm/http/tracing/tracing-dispatcher.d.mts +10 -11
- package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
- package/esm/http/tracing/tracing-dispatcher.mjs +2 -2
- package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
- package/esm/http/tracing/tracing.type.d.mts +11 -9
- package/esm/http/tracing/tracing.type.d.mts.map +1 -1
- package/esm/http/types.d.mts +49 -43
- package/esm/http/types.d.mts.map +1 -1
- package/esm/http/uploaded-file.d.mts +6 -5
- package/esm/http/uploaded-file.d.mts.map +1 -1
- package/esm/http/uploads/generate-image-variants.d.mts +6 -6
- package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
- package/esm/http/uploads/generate-image-variants.mjs +1 -1
- package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
- package/esm/http/uploads/image-variant-cache-entries.mjs +1 -1
- package/esm/http/uploads/image-variant-cache.mjs +8 -8
- package/esm/http/uploads/image-variant-cache.mjs.map +1 -1
- package/esm/http/uploads/image-variant-types.d.mts +7 -9
- package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
- package/esm/http/uploads/image-variants-config-error.d.mts +1 -2
- package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
- package/esm/http/uploads/index.d.mts +2 -1
- package/esm/http/uploads/index.mjs +1 -1
- package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
- package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
- package/esm/http/uploads/purge-image-variants.d.mts +2 -4
- package/esm/http/uploads/purge-image-variants.d.mts.map +1 -1
- package/esm/http/uploads/resolve-image-variant.d.mts +3 -5
- package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -1
- package/esm/http/uploads/resolve-image-variants-config.mjs +4 -4
- package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
- package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
- package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
- package/esm/http/uploads/trim-image-variant-cache.mjs +3 -3
- package/esm/http/uploads/trim-image-variant-cache.mjs.map +1 -1
- package/esm/http/uploads/uploaded-file.controller.d.mts +6 -5
- package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
- package/esm/http/uploads/uploaded-file.controller.mjs +2 -1
- package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
- package/esm/http/uploads/variant-cache-key.mjs +1 -1
- package/esm/http/uploads-config.d.mts +2 -4
- package/esm/http/uploads-config.d.mts.map +1 -1
- package/esm/http/uploads-types.d.mts +19 -17
- package/esm/http/uploads-types.d.mts.map +1 -1
- package/esm/http/xmlable.d.mts +1 -2
- package/esm/http/xmlable.d.mts.map +1 -1
- package/esm/image/image.d.mts +6 -7
- package/esm/image/image.d.mts.map +1 -1
- package/esm/image/image.mjs.map +1 -1
- package/esm/image/index.d.mts +2 -1
- package/esm/image/index.mjs +1 -1
- package/esm/index.d.mts +21 -0
- package/esm/loader/app-module-importer.d.mts +1 -2
- package/esm/loader/app-module-importer.d.mts.map +1 -1
- package/esm/localization/index.mjs +1 -1
- package/esm/localization/parse-locale-dictionary.d.mts +4 -5
- package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/parse-locale-dictionary.mjs +1 -1
- package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
- package/esm/localization/register-locale-dictionary.d.mts +3 -4
- package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/register-locale-dictionary.mjs +2 -2
- package/esm/localization/register-locale-dictionary.mjs.map +1 -1
- package/esm/logger/fatal-visibility.d.mts +1 -2
- package/esm/logger/fatal-visibility.d.mts.map +1 -1
- package/esm/logger/index.d.mts +2 -1
- package/esm/logger/index.mjs +1 -1
- package/esm/logger/logger.d.mts +1 -3
- package/esm/logger/logger.d.mts.map +1 -1
- package/esm/logger/types.d.mts +2 -3
- package/esm/logger/types.d.mts.map +1 -1
- package/esm/mail/config.d.mts +12 -14
- package/esm/mail/config.d.mts.map +1 -1
- package/esm/mail/events.d.mts +4 -6
- package/esm/mail/events.d.mts.map +1 -1
- package/esm/mail/index.d.mts +2 -1
- package/esm/mail/index.mjs +1 -1
- package/esm/mail/mail.d.mts +1 -3
- package/esm/mail/mail.d.mts.map +1 -1
- package/esm/mail/mailer-pool.d.mts +5 -7
- package/esm/mail/mailer-pool.d.mts.map +1 -1
- package/esm/mail/react-mail.d.mts +1 -3
- package/esm/mail/react-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.d.mts +1 -3
- package/esm/mail/send-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.mjs +2 -1
- package/esm/mail/send-mail.mjs.map +1 -1
- package/esm/mail/test-mailbox.d.mts +11 -13
- package/esm/mail/test-mailbox.d.mts.map +1 -1
- package/esm/mail/types.d.mts +17 -18
- package/esm/mail/types.d.mts.map +1 -1
- package/esm/manifest/manifest-manager.mjs +1 -1
- package/esm/openapi/build-openapi-document.d.mts +2 -4
- package/esm/openapi/build-openapi-document.d.mts.map +1 -1
- package/esm/openapi/cast-schema.mjs +1 -1
- package/esm/openapi/development-openapi-provider.d.mts +5 -6
- package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
- package/esm/openapi/index.d.mts +3 -1
- package/esm/openapi/index.mjs +1 -1
- package/esm/openapi/openapi-child-output.mjs +2 -2
- package/esm/openapi/openapi-child-output.mjs.map +1 -1
- package/esm/openapi/postman/build-request-url.mjs +1 -1
- package/esm/openapi/postman/example-from-schema.d.mts +1 -3
- package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
- package/esm/openapi/postman/index.d.mts +2 -1
- package/esm/openapi/postman/openapi-to-postman-collection.d.mts +3 -5
- package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
- package/esm/openapi/postman/postman-types.d.mts +19 -18
- package/esm/openapi/postman/postman-types.d.mts.map +1 -1
- package/esm/openapi/postman/schema-refs.d.mts +1 -3
- package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
- package/esm/openapi/postman/uuid-v5.mjs +1 -1
- package/esm/openapi/schema-registry.d.mts +1 -1
- package/esm/openapi/security.mjs +1 -1
- package/esm/openapi/types.d.mts +23 -21
- package/esm/openapi/types.d.mts.map +1 -1
- package/esm/production/assert-generated-imports.mjs +1 -1
- package/esm/production/build-contributions.mjs +1 -1
- package/esm/production/bundle-framework-dependencies.mjs +1 -1
- package/esm/production/dist-build-manifest.mjs +1 -1
- package/esm/production/esbuild-plugins.mjs.map +1 -1
- package/esm/production/esbuild-preflight.mjs +1 -1
- package/esm/production/production-builder.mjs +2 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/production-supervisor.mjs +1 -1
- package/esm/production/registration-child-runner.mjs +4 -3
- package/esm/production/registration-child-runner.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +4 -4
- package/esm/production/resolve-build-config.d.mts.map +1 -1
- package/esm/production/resolve-build-config.mjs +1 -1
- package/esm/production/route-registration-child.d.mts +1 -1
- package/esm/production/route-registration-child.mjs +8 -7
- package/esm/production/route-registration-child.mjs.map +1 -1
- package/esm/production/tsconfig-path-aliases.mjs +1 -1
- package/esm/react/index.d.mts +1 -3
- package/esm/react/index.d.mts.map +1 -1
- package/esm/react/index.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +3 -4
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +2 -3
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs +10 -9
- package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/index.d.mts +2 -1
- package/esm/repositories/adapters/cascade/index.mjs +1 -1
- package/esm/repositories/contracts/index.d.mts +2 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +4 -6
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -3
- package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/types.d.mts +23 -25
- package/esm/repositories/contracts/types.d.mts.map +1 -1
- package/esm/repositories/index.d.mts +4 -1
- package/esm/repositories/index.mjs +1 -1
- package/esm/repositories/repository.manager.d.mts +2 -3
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +2 -2
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/resource/define-resource.d.mts +3 -5
- package/esm/resource/define-resource.d.mts.map +1 -1
- package/esm/resource/index.d.mts +2 -1
- package/esm/resource/index.mjs +1 -1
- package/esm/resource/nullable-resource.d.mts +5 -7
- package/esm/resource/nullable-resource.d.mts.map +1 -1
- package/esm/resource/register-resource.d.mts +1 -3
- package/esm/resource/register-resource.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.d.mts +1 -3
- package/esm/resource/resource-field-builder.d.mts.map +1 -1
- package/esm/resource/resource.d.mts +3 -5
- package/esm/resource/resource.d.mts.map +1 -1
- package/esm/resource/resource.mjs +4 -2
- package/esm/resource/resource.mjs.map +1 -1
- package/esm/resource/types.d.mts +21 -21
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/restful/index.d.mts +2 -1
- package/esm/restful/index.mjs +1 -1
- package/esm/restful/restful.d.mts +12 -32
- package/esm/restful/restful.d.mts.map +1 -1
- package/esm/router/index.d.mts +2 -1
- package/esm/router/index.mjs +1 -1
- package/esm/router/named-api-routes-with-responses.mjs +2 -1
- package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
- package/esm/router/normalize-request-path.d.mts +1 -2
- package/esm/router/normalize-request-path.d.mts.map +1 -1
- package/esm/router/normalize-route-path.d.mts +1 -2
- package/esm/router/normalize-route-path.d.mts.map +1 -1
- package/esm/router/positional-handler-diagnostics.d.mts +15 -13
- package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
- package/esm/router/resolve-route-rate-limit.mjs +3 -3
- package/esm/router/resolve-route-rate-limit.mjs.map +1 -1
- package/esm/router/route-builder.d.mts +1 -3
- package/esm/router/route-builder.d.mts.map +1 -1
- package/esm/router/route-guard-names.mjs +1 -1
- package/esm/router/route-guard-names.mjs.map +1 -1
- package/esm/router/route-name-method-suffix.d.mts +2 -3
- package/esm/router/route-name-method-suffix.d.mts.map +1 -1
- package/esm/router/route-name-taken-error.d.mts +1 -3
- package/esm/router/route-name-taken-error.d.mts.map +1 -1
- package/esm/router/route-registry.d.mts +1 -3
- package/esm/router/route-registry.d.mts.map +1 -1
- package/esm/router/router.d.mts +2 -4
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +8 -6
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts +25 -26
- package/esm/router/types.d.mts.map +1 -1
- package/esm/router/unguarded-route-diagnostics.d.mts +6 -8
- package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -1
- package/esm/socket/index.d.mts +2 -1
- package/esm/socket/index.mjs +1 -1
- package/esm/socket/types.d.mts +2 -4
- package/esm/socket/types.d.mts.map +1 -1
- package/esm/socket/utils.d.mts +1 -3
- package/esm/socket/utils.d.mts.map +1 -1
- package/esm/storage/config.d.mts +4 -6
- package/esm/storage/config.d.mts.map +1 -1
- package/esm/storage/context/storage-driver-context.d.mts +3 -4
- package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts +2 -4
- package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts +1 -3
- package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.d.mts +2 -3
- package/esm/storage/drivers/local-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.mjs +8 -3
- package/esm/storage/drivers/local-driver.mjs.map +1 -1
- package/esm/storage/drivers/r2-driver.d.mts +1 -3
- package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
- package/esm/storage/drivers/s3-driver.d.mts +1 -3
- package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
- package/esm/storage/index.d.mts +2 -1
- package/esm/storage/index.mjs +1 -1
- package/esm/storage/local-disk-roots.mjs +2 -2
- package/esm/storage/local-disk-roots.mjs.map +1 -1
- package/esm/storage/scoped-storage.d.mts +2 -3
- package/esm/storage/scoped-storage.d.mts.map +1 -1
- package/esm/storage/storage-file.d.mts +1 -3
- package/esm/storage/storage-file.d.mts.map +1 -1
- package/esm/storage/storage.d.mts +3 -4
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/types.d.mts +36 -36
- package/esm/storage/types.d.mts.map +1 -1
- package/esm/storage/utils/classify-ip-address.d.mts +1 -2
- package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.d.mts +1 -2
- package/esm/storage/utils/contain-path.d.mts.map +1 -1
- package/esm/storage/utils/mime.d.mts +2 -3
- package/esm/storage/utils/mime.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts +6 -6
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs +3 -3
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/storage/utils/storage-capability-error.d.mts +1 -3
- package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-error.d.mts +2 -3
- package/esm/storage/utils/storage-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-not-initialized-error.d.mts +1 -2
- package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
- package/esm/tests/authenticated-test-client.d.mts +5 -6
- package/esm/tests/authenticated-test-client.d.mts.map +1 -1
- package/esm/tests/factories.d.mts +38 -23
- package/esm/tests/factories.d.mts.map +1 -1
- package/esm/tests/fakes/cache-fake.d.mts +14 -9
- package/esm/tests/fakes/cache-fake.d.mts.map +1 -1
- package/esm/tests/fakes/clock-fake.d.mts +13 -8
- package/esm/tests/fakes/clock-fake.d.mts.map +1 -1
- package/esm/tests/fakes/fake-assertion-error.d.mts +2 -3
- package/esm/tests/fakes/fake-assertion-error.d.mts.map +1 -1
- package/esm/tests/fakes/ids-fake.d.mts +5 -4
- package/esm/tests/fakes/ids-fake.d.mts.map +1 -1
- package/esm/tests/fakes/index.d.mts +2 -1
- package/esm/tests/fakes/index.mjs +1 -1
- package/esm/tests/fakes/mail-fake.d.mts +21 -13
- package/esm/tests/fakes/mail-fake.d.mts.map +1 -1
- package/esm/tests/fakes/queue-fake.d.mts +21 -13
- package/esm/tests/fakes/queue-fake.d.mts.map +1 -1
- package/esm/tests/fakes/storage-fake.d.mts +12 -8
- package/esm/tests/fakes/storage-fake.d.mts.map +1 -1
- package/esm/tests/fakes/storage-fake.mjs +1 -1
- package/esm/tests/fakes/test-fakes.d.mts +8 -9
- package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
- package/esm/tests/fakes/test-fakes.mjs +1 -1
- package/esm/tests/fakes/test-fakes.mjs.map +1 -1
- package/esm/tests/index.d.mts +1 -0
- package/esm/tests/snapshot-response.d.mts +4 -5
- package/esm/tests/snapshot-response.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.d.mts +4 -6
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +5 -5
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-connectors-selection.d.mts +2 -2
- package/esm/tests/test-connectors-selection.d.mts.map +1 -1
- package/esm/tests/test-connectors-selection.mjs +1 -1
- package/esm/tests/test-helpers.d.mts +11 -12
- package/esm/tests/test-helpers.d.mts.map +1 -1
- package/esm/tests/test-http-server.d.mts +14 -10
- package/esm/tests/test-http-server.d.mts.map +1 -1
- package/esm/tests/test-lifecycle-state.mjs +1 -1
- package/esm/tests/vitest-setup.d.mts +6 -7
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tooling/agents-md/agents-md-markers.d.mts +4 -5
- package/esm/tooling/agents-md/agents-md-markers.d.mts.map +1 -1
- package/esm/tooling/agents-md/agents-md-markers.mjs +2 -1
- package/esm/tooling/agents-md/agents-md-markers.mjs.map +1 -1
- package/esm/tooling/agents-md/agents-md-refresher.d.mts +19 -12
- package/esm/tooling/agents-md/agents-md-refresher.d.mts.map +1 -1
- package/esm/tooling/agents-md/installed-skills.d.mts +13 -9
- package/esm/tooling/agents-md/installed-skills.d.mts.map +1 -1
- package/esm/tooling/agents-md/render-agents-md.d.mts +8 -7
- package/esm/tooling/agents-md/render-agents-md.d.mts.map +1 -1
- package/esm/tooling/agents-md/render-agents-md.mjs +2 -2
- package/esm/tooling/agents-md/render-agents-md.mjs.map +1 -1
- package/esm/tooling/agents-md/write-agents-md.d.mts +17 -12
- package/esm/tooling/agents-md/write-agents-md.d.mts.map +1 -1
- package/esm/tooling/board/board-message.d.mts +4 -6
- package/esm/tooling/board/board-message.d.mts.map +1 -1
- package/esm/tooling/board/board.d.mts +50 -38
- package/esm/tooling/board/board.d.mts.map +1 -1
- package/esm/tooling/board/board.mjs +4 -3
- package/esm/tooling/board/board.mjs.map +1 -1
- package/esm/tooling/board/board.types.d.mts +32 -23
- package/esm/tooling/board/board.types.d.mts.map +1 -1
- package/esm/tooling/check/changed-files.d.mts +4 -6
- package/esm/tooling/check/changed-files.d.mts.map +1 -1
- package/esm/tooling/check/changed-files.mjs +2 -2
- package/esm/tooling/check/changed-files.mjs.map +1 -1
- package/esm/tooling/check/check-report.types.d.mts +22 -17
- package/esm/tooling/check/check-report.types.d.mts.map +1 -1
- package/esm/tooling/check/code-style-conventions.mjs +25 -25
- package/esm/tooling/check/code-style-conventions.mjs.map +1 -1
- package/esm/tooling/check/conventions-step.d.mts +4 -6
- package/esm/tooling/check/conventions-step.d.mts.map +1 -1
- package/esm/tooling/check/conventions-step.mjs +7 -18
- package/esm/tooling/check/conventions-step.mjs.map +1 -1
- package/esm/tooling/check/environment-step.d.mts +2 -4
- package/esm/tooling/check/environment-step.d.mts.map +1 -1
- package/esm/tooling/check/environment-step.mjs +1 -1
- package/esm/tooling/check/index.mjs +1 -1
- package/esm/tooling/check/lint-step.d.mts +4 -5
- package/esm/tooling/check/lint-step.d.mts.map +1 -1
- package/esm/tooling/check/lint-step.mjs +2 -1
- package/esm/tooling/check/lint-step.mjs.map +1 -1
- package/esm/tooling/check/request-input.mjs +15 -15
- package/esm/tooling/check/request-input.mjs.map +1 -1
- package/esm/tooling/check/run-check.d.mts +22 -14
- package/esm/tooling/check/run-check.d.mts.map +1 -1
- package/esm/tooling/check/run-tests.d.mts +22 -15
- package/esm/tooling/check/run-tests.d.mts.map +1 -1
- package/esm/tooling/check/security-conventions.mjs +133 -131
- package/esm/tooling/check/security-conventions.mjs.map +1 -1
- package/esm/tooling/check/source-ast.mjs +92 -132
- package/esm/tooling/check/source-ast.mjs.map +1 -1
- package/esm/tooling/check/tests-step.d.mts +7 -8
- package/esm/tooling/check/tests-step.d.mts.map +1 -1
- package/esm/tooling/check/tests-step.mjs +3 -3
- package/esm/tooling/check/tests-step.mjs.map +1 -1
- package/esm/tooling/dev-state/dev-server-state.d.mts +17 -13
- package/esm/tooling/dev-state/dev-server-state.d.mts.map +1 -1
- package/esm/tooling/devtools/devtools-client.d.mts +29 -20
- package/esm/tooling/devtools/devtools-client.d.mts.map +1 -1
- package/esm/tooling/generate/generation.d.mts +34 -22
- package/esm/tooling/generate/generation.d.mts.map +1 -1
- package/esm/tooling/generate/generation.mjs +9 -5
- package/esm/tooling/generate/generation.mjs.map +1 -1
- package/esm/tooling/generate/generator-spec.d.mts +9 -9
- package/esm/tooling/generate/generator-spec.d.mts.map +1 -1
- package/esm/tooling/generate/index.mjs +1 -1
- package/esm/tooling/generate/project-files.mjs +3 -3
- package/esm/tooling/generate/project-files.mjs.map +1 -1
- package/esm/tooling/generate/run-cli.d.mts +14 -11
- package/esm/tooling/generate/run-cli.d.mts.map +1 -1
- package/esm/tooling/generate/run-cli.mjs +2 -2
- package/esm/tooling/generate/run-cli.mjs.map +1 -1
- package/esm/tooling/generate/unified-diff.d.mts +10 -7
- package/esm/tooling/generate/unified-diff.d.mts.map +1 -1
- package/esm/tooling/index.d.mts +1 -0
- package/esm/tooling/inspect/boot-for-inspect.d.mts +7 -7
- package/esm/tooling/inspect/boot-for-inspect.d.mts.map +1 -1
- package/esm/tooling/inspect/collect-config.mjs +3 -3
- package/esm/tooling/inspect/collect-config.mjs.map +1 -1
- package/esm/tooling/inspect/collect-models.d.mts +4 -3
- package/esm/tooling/inspect/collect-models.d.mts.map +1 -1
- package/esm/tooling/inspect/collect-models.mjs +1 -1
- package/esm/tooling/inspect/collect-packages.d.mts +1 -2
- package/esm/tooling/inspect/collect-packages.d.mts.map +1 -1
- package/esm/tooling/inspect/collect-pages.mjs +10 -10
- package/esm/tooling/inspect/collect-pages.mjs.map +1 -1
- package/esm/tooling/inspect/collect-routes.mjs +1 -1
- package/esm/tooling/inspect/event-recorder.d.mts +7 -7
- package/esm/tooling/inspect/event-recorder.d.mts.map +1 -1
- package/esm/tooling/inspect/index.d.mts +2 -1
- package/esm/tooling/inspect/index.mjs +1 -1
- package/esm/tooling/inspect/inspect-app.d.mts +25 -16
- package/esm/tooling/inspect/inspect-app.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-report.schema.d.mts +1 -2
- package/esm/tooling/inspect/inspect-report.schema.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-report.types.d.mts +86 -54
- package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -1
- package/esm/tooling/mcp/create-mcp-context.d.mts +11 -8
- package/esm/tooling/mcp/create-mcp-context.d.mts.map +1 -1
- package/esm/tooling/mcp/db-schema.d.mts +10 -9
- package/esm/tooling/mcp/db-schema.d.mts.map +1 -1
- package/esm/tooling/mcp/docs-search.d.mts +20 -15
- package/esm/tooling/mcp/docs-search.d.mts.map +1 -1
- package/esm/tooling/mcp/index.mjs +1 -1
- package/esm/tooling/mcp/load-ai-tools.d.mts +7 -8
- package/esm/tooling/mcp/load-ai-tools.d.mts.map +1 -1
- package/esm/tooling/mcp/load-ai-tools.mjs +2 -1
- package/esm/tooling/mcp/load-ai-tools.mjs.map +1 -1
- package/esm/tooling/mcp/mcp-tools.d.mts +29 -19
- package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -1
- package/esm/tooling/mcp/mcp-tools.mjs +3 -2
- package/esm/tooling/mcp/mcp-tools.mjs.map +1 -1
- package/esm/tooling/mcp/start-mcp-server.d.mts +24 -17
- package/esm/tooling/mcp/start-mcp-server.d.mts.map +1 -1
- package/esm/tooling/mcp/start-mcp-server.mjs +1 -1
- package/esm/tooling/mcp/start-mcp-server.mjs.map +1 -1
- package/esm/tooling/mcp/tool-input.d.mts +7 -7
- package/esm/tooling/mcp/tool-input.d.mts.map +1 -1
- package/esm/tooling/problem.d.mts +27 -17
- package/esm/tooling/problem.d.mts.map +1 -1
- package/esm/tooling/syntax/ast.mjs +230 -0
- package/esm/tooling/syntax/ast.mjs.map +1 -0
- package/esm/tooling/syntax/imports.mjs +34 -0
- package/esm/tooling/syntax/imports.mjs.map +1 -0
- package/esm/tooling/trace/trace-report.types.d.mts +36 -22
- package/esm/tooling/trace/trace-report.types.d.mts.map +1 -1
- package/esm/tooling/trace/trace-request.d.mts +27 -20
- package/esm/tooling/trace/trace-request.d.mts.map +1 -1
- package/esm/tooling/trace/trace-request.mjs +2 -2
- package/esm/tooling/trace/trace-request.mjs.map +1 -1
- package/esm/tooling/typecheck/index.mjs +1 -1
- package/esm/tooling/typecheck/run-typecheck.d.mts +15 -48
- package/esm/tooling/typecheck/run-typecheck.d.mts.map +1 -1
- package/esm/tooling/typecheck/run-typecheck.mjs +42 -105
- package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -1
- package/esm/tooling/typescript/compiler.d.mts +31 -0
- package/esm/tooling/typescript/compiler.d.mts.map +1 -0
- package/esm/tooling/typescript/compiler.mjs +120 -0
- package/esm/tooling/typescript/compiler.mjs.map +1 -0
- package/esm/updater/update-warlock-packages.mjs +3 -2
- package/esm/updater/update-warlock-packages.mjs.map +1 -1
- package/esm/upgrade/codemods/index.mjs +1 -1
- package/esm/upgrade/codemods/logger-sync-calls.mjs +1 -1
- package/esm/upgrade/codemods/logger-sync-calls.mjs.map +1 -1
- package/esm/upgrade/codemods/request-log-snapshot.mjs +1 -1
- package/esm/upgrade/codemods/request-log-snapshot.mjs.map +1 -1
- package/esm/upgrade/diff.mjs +1 -1
- package/esm/upgrade/diff.mjs.map +1 -1
- package/esm/upgrade/load-ts-morph.mjs +3 -2
- package/esm/upgrade/load-ts-morph.mjs.map +1 -1
- package/esm/upgrade/run-upgrade.mjs +1 -1
- package/esm/use-cases/index.d.mts +2 -1
- package/esm/use-cases/index.mjs +1 -1
- package/esm/use-cases/types.d.mts +116 -63
- package/esm/use-cases/types.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts +1 -3
- package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
- package/esm/use-cases/use-case-events.d.mts +3 -5
- package/esm/use-cases/use-case-events.d.mts.map +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts +6 -6
- package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
- package/esm/use-cases/use-case.d.mts +2 -4
- package/esm/use-cases/use-case.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.d.mts +1 -3
- package/esm/use-cases/use-case.errors.d.mts.map +1 -1
- package/esm/use-cases/use-cases-registry.d.mts +8 -10
- package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
- package/esm/utils/app-log.d.mts +1 -2
- package/esm/utils/app-log.d.mts.map +1 -1
- package/esm/utils/clock.d.mts +8 -6
- package/esm/utils/clock.d.mts.map +1 -1
- package/esm/utils/database-log.d.mts +3 -4
- package/esm/utils/database-log.d.mts.map +1 -1
- package/esm/utils/environment.d.mts +4 -5
- package/esm/utils/environment.d.mts.map +1 -1
- package/esm/utils/framework-vesion.mjs.map +1 -1
- package/esm/utils/get-localized.d.mts +2 -3
- package/esm/utils/get-localized.d.mts.map +1 -1
- package/esm/utils/ids.d.mts +9 -6
- package/esm/utils/ids.d.mts.map +1 -1
- package/esm/utils/index.d.mts +2 -1
- package/esm/utils/index.mjs +1 -1
- package/esm/utils/normalized-path.d.mts +1 -2
- package/esm/utils/normalized-path.d.mts.map +1 -1
- package/esm/utils/npm-registry.d.mts +1 -2
- package/esm/utils/npm-registry.d.mts.map +1 -1
- package/esm/utils/paths.d.mts +13 -14
- package/esm/utils/paths.d.mts.map +1 -1
- package/esm/utils/paths.mjs +2 -2
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/utils/promise-all-object.d.mts +1 -2
- package/esm/utils/promise-all-object.d.mts.map +1 -1
- package/esm/utils/queue.d.mts +1 -2
- package/esm/utils/queue.d.mts.map +1 -1
- package/esm/utils/runtime.d.mts +11 -10
- package/esm/utils/runtime.d.mts.map +1 -1
- package/esm/utils/sleep.d.mts +1 -2
- package/esm/utils/sleep.d.mts.map +1 -1
- package/esm/utils/sluggable.d.mts +1 -3
- package/esm/utils/sluggable.d.mts.map +1 -1
- package/esm/utils/to-json.d.mts +1 -2
- package/esm/utils/to-json.d.mts.map +1 -1
- package/esm/utils/types.d.mts +1 -2
- package/esm/utils/types.d.mts.map +1 -1
- package/esm/utils/urls.d.mts +5 -6
- package/esm/utils/urls.d.mts.map +1 -1
- package/esm/utils/version-compare.d.mts +1 -2
- package/esm/utils/version-compare.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts +2 -3
- package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts +2 -3
- package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/index.d.mts +2 -1
- package/esm/validation/database/index.mjs +1 -1
- package/esm/validation/database/types.d.mts +14 -10
- package/esm/validation/database/types.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts +2 -3
- package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts +2 -3
- package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
- package/esm/validation/file/file.d.mts +4 -6
- package/esm/validation/file/file.d.mts.map +1 -1
- package/esm/validation/file/index.d.mts +2 -1
- package/esm/validation/file/index.mjs +1 -1
- package/esm/validation/index.d.mts +5 -1
- package/esm/validation/index.mjs +1 -1
- package/esm/validation/plugins/index.mjs +1 -1
- package/esm/validation/types.d.mts +6 -4
- package/esm/validation/types.d.mts.map +1 -1
- package/esm/validation/validateAll.mjs +2 -2
- package/esm/validation/validateAll.mjs.map +1 -1
- package/esm/validation/validation-failure-status.mjs +2 -2
- package/esm/validation/validation-failure-status.mjs.map +1 -1
- package/esm/validation/validators/file-validator.d.mts +2 -4
- package/esm/validation/validators/file-validator.d.mts.map +1 -1
- package/esm/validation/validators/index.d.mts +2 -1
- package/esm/validation/validators/index.mjs +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts +2 -3
- package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
- package/esm/warlock-config/define-config.d.mts +1 -3
- package/esm/warlock-config/define-config.d.mts.map +1 -1
- package/esm/warlock-config/define-config.mjs +3 -2
- package/esm/warlock-config/define-config.mjs.map +1 -1
- package/esm/warlock-config/index.d.mts +2 -1
- package/esm/warlock-config/index.mjs +1 -1
- package/esm/warlock-config/types.d.mts +6 -5
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts +5 -7
- package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs +2 -1
- package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
- package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
- package/llms-full.txt +55 -5
- package/package.json +17 -15
- package/skills/create-module/SKILL.md +7 -0
- package/skills/index.md +2 -0
- package/skills/report-framework-issue.md +154 -0
- package/skills/run-app/SKILL.md +6 -5
- package/skills/upgrade-from-5-29/SKILL.md +41 -0
- package/skills/warlock-check/SKILL.md +1 -0
- package/esm/tooling/check/index.d.mts +0 -8
- package/esm/tooling/typecheck/index.d.mts +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit-cache-store.mjs","names":[],"sources":["../../../../../../../../packages/core/src/http/rate-limit-cache-store.ts"],"sourcesContent":["import type { FastifyRateLimitOptions, FastifyRateLimitStore } from \"@fastify/rate-limit\";\nimport { cache } from \"@warlock.js/cache\";\nimport { log } from \"@warlock.js/logger\";\nimport { createHash } from \"node:crypto\";\n\n/**\n * Rate-limit counting shared through `@warlock.js/cache`, so every process\n * that uses the same cache driver (Redis, Postgres) counts into the same\n * buckets. With a memory driver (`memory`, `lru`, `memoryExtended`) the\n * counts stay in the process, like the in-memory limiter.\n *\n * Windows are fixed and aligned to the clock: a 60 s window resets on the\n * minute, whichever process saw the first request. Each window has its own\n * key, created atomically with a TTL of two windows and incremented with the\n * driver's atomic increment, so a key cannot expire while its window counts.\n *\n * Two drivers are refused, with {@link UnsupportedRateLimitDriverError}:\n *\n * - `null` stores nothing, so every request would count as the first and the\n * limit would never trip.\n * - `file` has no expiry sweeper, so every past window would stay on disk\n * forever, and its increment is only serialized within one process, so\n * workers sharing the directory would lose counts.\n */\n\nconst KEY_PREFIX = \"rate-limit\";\n\n/**\n * Cache drivers that cannot back a shared limiter (see the module comment).\n */\nconst UNSUPPORTED_DRIVERS = new Set([\"null\", \"file\"]);\n\n/**\n * Thrown when `store: \"cache\"` runs on a cache driver that cannot count.\n */\nexport class UnsupportedRateLimitDriverError extends Error {\n /** Stable Warlock error code; `warlock explain WL1003` prints the fix. */\n public readonly code = \"WL1003\";\n\n public constructor(driverName: string) {\n super(\n `Rate limiting with store: \"cache\" cannot use the \"${driverName}\" cache driver: ` +\n (driverName === \"null\"\n ? \"it stores nothing, so the limit would never trip. \"\n : \"it never removes expired windows and its increment is not shared between processes. \") +\n 'Use redis or pg (or a memory driver for a single process), or set store: \"memory\".',\n );\n\n this.name = \"UnsupportedRateLimitDriverError\";\n }\n}\n\nfunction assertSupportedDriver(): void {\n const driverName = cache.currentDriver?.name;\n\n if (driverName && UNSUPPORTED_DRIVERS.has(driverName)) {\n throw new UnsupportedRateLimitDriverError(driverName);\n }\n}\n\n/**\n * Hash used for group keys and route namespaces before they reach the cache.\n */\nfunction shortHash(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 32);\n}\n\n/**\n * The group key (an IP, a user id, whatever `keyGenerator` returned) is\n * hashed before it reaches the cache: cache drivers log their keys, and a raw\n * IP or email in a key is personal data in a log line.\n *\n * The namespace (it carries a route path) is hashed as well: flattening\n * `/users/:id` and `/users/id` to one safe string merged their counters, and\n * the file driver would turn `/` into directories. A readable, flattened\n * prefix stays in front of the hash for debugging.\n */\nfunction windowKey(namespace: string, group: string, windowIndex: number): string {\n const readable = namespace.replace(/[^A-Za-z0-9_-]+/g, \"_\").slice(0, 40);\n\n return `${KEY_PREFIX}.${readable}-${shortHash(namespace).slice(0, 16)}.${shortHash(group)}.${windowIndex}`;\n}\n\n/**\n * Count one request for `group` in the current window.\n *\n * @returns the count so far in this window and when the window resets (epoch ms)\n * @throws {UnsupportedRateLimitDriverError} on the `null` or `file` driver\n */\nexport async function incrementSharedRateLimit(\n namespace: string,\n group: string,\n windowMs: number,\n now: number = Date.now(),\n): Promise<{ current: number; resetAt: number }> {\n assertSupportedDriver();\n\n const windowIndex = Math.floor(now / windowMs);\n const key = windowKey(namespace, group, windowIndex);\n const ttlSeconds = Math.max(1, Math.ceil((2 * windowMs) / 1000));\n\n await cache.set(key, 0, { ttl: ttlSeconds, onConflict: \"create\" });\n\n const current = await cache.increment(key, 1, { ttl: ttlSeconds });\n\n return { current, resetAt: (windowIndex + 1) * windowMs };\n}\n\n/**\n * Read the count for `group` in the current window without counting a request\n */\nexport async function readSharedRateLimit(\n namespace: string,\n group: string,\n windowMs: number,\n now: number = Date.now(),\n): Promise<{ current: number; resetAt: number }> {\n assertSupportedDriver();\n\n const windowIndex = Math.floor(now / windowMs);\n const value = await cache.get(windowKey(namespace, group, windowIndex));\n\n return {\n current: typeof value === \"number\" ? value : 0,\n resetAt: (windowIndex + 1) * windowMs,\n };\n}\n\n/**\n * How often a failing shared store is reported. A cache outage fails every\n * request, so logging each one would flood the log.\n */\nconst ERROR_LOG_INTERVAL_MS = 60_000;\n\nlet lastErrorLogAt = 0;\n\n/**\n * Log a shared rate-limit store failure, at most once per minute.\n */\nexport function logSharedRateLimitError(error: unknown, now: number = Date.now()): void {\n if (now - lastErrorLogAt < ERROR_LOG_INTERVAL_MS) return;\n\n lastErrorLogAt = now;\n log.error(\"http\", \"rate-limit\", error);\n}\n\n/**\n * Forget when the last store error was logged (tests).\n */\nexport function resetSharedRateLimitErrorLog(): void {\n lastErrorLogAt = 0;\n}\n\n/**\n * Route data `@fastify/rate-limit` passes to `child()`: the route's options\n * under `routeInfo` (`fastify.rateLimit()` hooks pass an empty one).\n */\ntype ChildRouteOptions = {\n routeInfo?: { method?: unknown; url?: string; path?: string };\n};\n\n/**\n * `fastify.rateLimit()` hooks have no route; told apart by creation order,\n * which matches across processes running the same code.\n */\nlet nextHookNamespace = 0;\n\n/**\n * `@fastify/rate-limit` store backed by `@warlock.js/cache`. Selected with\n * `http.rateLimit.store: \"cache\"`; each route with its own `rateLimit` gets\n * its own namespace through `child()`.\n *\n * A failure (cache outage, unsupported driver) is logged at most once a\n * minute and passed to the plugin, which lets the request through because\n * Warlock registers it with `skipOnError: true` for this store.\n */\nexport class CacheRateLimitStore implements FastifyRateLimitStore {\n public constructor(\n _options?: FastifyRateLimitOptions,\n protected readonly namespace: string = \"global\",\n ) {}\n\n public incr(\n key: string,\n callback: (error: Error | null, result?: { current: number; ttl: number }) => void,\n timeWindow: number,\n ): void {\n incrementSharedRateLimit(this.namespace, key, timeWindow).then(\n ({ current, resetAt }) => callback(null, { current, ttl: Math.max(0, resetAt - Date.now()) }),\n (error: unknown) => {\n logSharedRateLimitError(error);\n callback(error instanceof Error ? error : new Error(String(error)));\n },\n );\n }\n\n public read(\n key: string,\n callback: (error: Error | null, result?: { current: number; ttl: number }) => void,\n timeWindow: number,\n ): void {\n readSharedRateLimit(this.namespace, key, timeWindow).then(\n ({ current, resetAt }) =>\n callback(null, { current, ttl: current === 0 ? 0 : Math.max(0, resetAt - Date.now()) }),\n (error: unknown) => {\n logSharedRateLimitError(error);\n callback(error instanceof Error ? error : new Error(String(error)));\n },\n );\n }\n\n public child(routeOptions: Parameters<FastifyRateLimitStore[\"child\"]>[0]): FastifyRateLimitStore {\n // The plugin's declared type names the route options directly, but at\n // runtime (11.x) it passes them merged under `routeInfo`.\n const routeInfo = (routeOptions as unknown as ChildRouteOptions).routeInfo ?? {};\n const method = Array.isArray(routeInfo.method)\n ? routeInfo.method.join(\",\")\n : String(routeInfo.method ?? \"\");\n const url = routeInfo.url ?? routeInfo.path ?? \"\";\n\n if (!method && !url) {\n return new CacheRateLimitStore(undefined, `hook.${nextHookNamespace++}`);\n }\n\n return new CacheRateLimitStore(undefined, `route.${method} ${url}`);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rate-limit-cache-store.mjs","names":[],"sources":["../../../../../../../../packages/core/src/http/rate-limit-cache-store.ts"],"sourcesContent":["import type { FastifyRateLimitOptions, FastifyRateLimitStore } from \"@fastify/rate-limit\";\nimport { cache } from \"@warlock.js/cache\";\nimport { log } from \"@warlock.js/logger\";\nimport { createHash } from \"node:crypto\";\n\n/**\n * Rate-limit counting shared through `@warlock.js/cache`, so every process\n * that uses the same cache driver (Redis, Postgres) counts into the same\n * buckets. With a memory driver (`memory`, `lru`, `memoryExtended`) the\n * counts stay in the process, like the in-memory limiter.\n *\n * Windows are fixed and aligned to the clock: a 60 s window resets on the\n * minute, whichever process saw the first request. Each window has its own\n * key, created atomically with a TTL of two windows and incremented with the\n * driver's atomic increment, so a key cannot expire while its window counts.\n *\n * Two drivers are refused, with {@link UnsupportedRateLimitDriverError}:\n *\n * - `null` stores nothing, so every request would count as the first and the\n * limit would never trip.\n * - `file` has no expiry sweeper, so every past window would stay on disk\n * forever, and its increment is only serialized within one process, so\n * workers sharing the directory would lose counts.\n */\n\nconst KEY_PREFIX = \"rate-limit\";\n\n/**\n * Cache drivers that cannot back a shared limiter (see the module comment).\n */\nconst UNSUPPORTED_DRIVERS = new Set([\"null\", \"file\"]);\n\n/**\n * Thrown when `store: \"cache\"` runs on a cache driver that cannot count.\n */\nexport class UnsupportedRateLimitDriverError extends Error {\n /** Stable Warlock error code; `warlock explain WL1003` prints the fix. */\n public readonly code = \"WL1003\";\n\n public constructor(driverName: string) {\n super(\n `Rate limiting with store: \"cache\" cannot use the \"${driverName}\" cache driver: ` +\n (driverName === \"null\"\n ? \"it stores nothing, so the limit would never trip. \"\n : \"it never removes expired windows and its increment is not shared between processes. \") +\n 'Use redis or pg (or a memory driver for a single process), or set store: \"memory\".',\n );\n\n this.name = \"UnsupportedRateLimitDriverError\";\n }\n}\n\nfunction assertSupportedDriver(): void {\n const driverName = cache.currentDriver?.name;\n\n if (driverName && UNSUPPORTED_DRIVERS.has(driverName)) {\n throw new UnsupportedRateLimitDriverError(driverName);\n }\n}\n\n/**\n * Hash used for group keys and route namespaces before they reach the cache.\n */\nfunction shortHash(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 32);\n}\n\n/**\n * The group key (an IP, a user id, whatever `keyGenerator` returned) is\n * hashed before it reaches the cache: cache drivers log their keys, and a raw\n * IP or email in a key is personal data in a log line.\n *\n * The namespace (it carries a route path) is hashed as well: flattening\n * `/users/:id` and `/users/id` to one safe string merged their counters, and\n * the file driver would turn `/` into directories. A readable, flattened\n * prefix stays in front of the hash for debugging.\n */\nfunction windowKey(namespace: string, group: string, windowIndex: number): string {\n const readable = namespace.replace(/[^A-Za-z0-9_-]+/g, \"_\").slice(0, 40);\n\n return `${KEY_PREFIX}.${readable}-${shortHash(namespace).slice(0, 16)}.${shortHash(group)}.${windowIndex}`;\n}\n\n/**\n * Count one request for `group` in the current window.\n *\n * @returns the count so far in this window and when the window resets (epoch ms)\n * @throws {UnsupportedRateLimitDriverError} on the `null` or `file` driver\n */\nexport async function incrementSharedRateLimit(\n namespace: string,\n group: string,\n windowMs: number,\n now: number = Date.now(),\n): Promise<{ current: number; resetAt: number }> {\n assertSupportedDriver();\n\n const windowIndex = Math.floor(now / windowMs);\n const key = windowKey(namespace, group, windowIndex);\n const ttlSeconds = Math.max(1, Math.ceil((2 * windowMs) / 1000));\n\n await cache.set(key, 0, { ttl: ttlSeconds, onConflict: \"create\" });\n\n const current = await cache.increment(key, 1, { ttl: ttlSeconds });\n\n return { current, resetAt: (windowIndex + 1) * windowMs };\n}\n\n/**\n * Read the count for `group` in the current window without counting a request\n */\nexport async function readSharedRateLimit(\n namespace: string,\n group: string,\n windowMs: number,\n now: number = Date.now(),\n): Promise<{ current: number; resetAt: number }> {\n assertSupportedDriver();\n\n const windowIndex = Math.floor(now / windowMs);\n const value = await cache.get(windowKey(namespace, group, windowIndex));\n\n return {\n current: typeof value === \"number\" ? value : 0,\n resetAt: (windowIndex + 1) * windowMs,\n };\n}\n\n/**\n * How often a failing shared store is reported. A cache outage fails every\n * request, so logging each one would flood the log.\n */\nconst ERROR_LOG_INTERVAL_MS = 60_000;\n\nlet lastErrorLogAt = 0;\n\n/**\n * Log a shared rate-limit store failure, at most once per minute.\n */\nexport function logSharedRateLimitError(error: unknown, now: number = Date.now()): void {\n if (now - lastErrorLogAt < ERROR_LOG_INTERVAL_MS) return;\n\n lastErrorLogAt = now;\n log.error(\"http\", \"rate-limit\", error);\n}\n\n/**\n * Forget when the last store error was logged (tests).\n */\nexport function resetSharedRateLimitErrorLog(): void {\n lastErrorLogAt = 0;\n}\n\n/**\n * Route data `@fastify/rate-limit` passes to `child()`: the route's options\n * under `routeInfo` (`fastify.rateLimit()` hooks pass an empty one).\n */\ntype ChildRouteOptions = {\n routeInfo?: { method?: unknown; url?: string; path?: string };\n};\n\n/**\n * `fastify.rateLimit()` hooks have no route; told apart by creation order,\n * which matches across processes running the same code.\n */\nlet nextHookNamespace = 0;\n\n/**\n * `@fastify/rate-limit` store backed by `@warlock.js/cache`. Selected with\n * `http.rateLimit.store: \"cache\"`; each route with its own `rateLimit` gets\n * its own namespace through `child()`.\n *\n * A failure (cache outage, unsupported driver) is logged at most once a\n * minute and passed to the plugin, which lets the request through because\n * Warlock registers it with `skipOnError: true` for this store.\n */\nexport class CacheRateLimitStore implements FastifyRateLimitStore {\n public constructor(\n _options?: FastifyRateLimitOptions,\n protected readonly namespace: string = \"global\",\n ) {}\n\n public incr(\n key: string,\n callback: (error: Error | null, result?: { current: number; ttl: number }) => void,\n timeWindow: number,\n ): void {\n incrementSharedRateLimit(this.namespace, key, timeWindow).then(\n ({ current, resetAt }) => callback(null, { current, ttl: Math.max(0, resetAt - Date.now()) }),\n (error: unknown) => {\n logSharedRateLimitError(error);\n callback(error instanceof Error ? error : new Error(String(error)));\n },\n );\n }\n\n public read(\n key: string,\n callback: (error: Error | null, result?: { current: number; ttl: number }) => void,\n timeWindow: number,\n ): void {\n readSharedRateLimit(this.namespace, key, timeWindow).then(\n ({ current, resetAt }) =>\n callback(null, { current, ttl: current === 0 ? 0 : Math.max(0, resetAt - Date.now()) }),\n (error: unknown) => {\n logSharedRateLimitError(error);\n callback(error instanceof Error ? error : new Error(String(error)));\n },\n );\n }\n\n public child(routeOptions: Parameters<FastifyRateLimitStore[\"child\"]>[0]): FastifyRateLimitStore {\n // The plugin's declared type names the route options directly, but at\n // runtime (11.x) it passes them merged under `routeInfo`.\n const routeInfo = (routeOptions as unknown as ChildRouteOptions).routeInfo ?? {};\n const method = Array.isArray(routeInfo.method)\n ? routeInfo.method.join(\",\")\n : String(routeInfo.method ?? \"\");\n const url = routeInfo.url ?? routeInfo.path ?? \"\";\n\n if (!method && !url) {\n return new CacheRateLimitStore(undefined, `hook.${nextHookNamespace++}`);\n }\n\n return new CacheRateLimitStore(undefined, `route.${method} ${url}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,aAAa;;;;AAKnB,MAAM,sCAAsB,IAAI,IAAI,CAAC,QAAQ,MAAM,CAAC;;;;AAKpD,IAAa,kCAAb,cAAqD,MAAM;CAIzD,AAAO,YAAY,YAAoB;EACrC,MACE,qDAAqD,WAAW,qBAC7D,eAAe,SACZ,uDACA,0FACJ,sFACJ;cATqB;EAWrB,KAAK,OAAO;CACd;AACF;AAEA,SAAS,wBAA8B;CACrC,MAAM,aAAa,MAAM,eAAe;CAExC,IAAI,cAAc,oBAAoB,IAAI,UAAU,GAClD,MAAM,IAAI,gCAAgC,UAAU;AAExD;;;;AAKA,SAAS,UAAU,OAAuB;CACxC,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;AACrE;;;;;;;;;;;AAYA,SAAS,UAAU,WAAmB,OAAe,aAA6B;CAChF,MAAM,WAAW,UAAU,QAAQ,oBAAoB,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE;CAEvE,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,SAAS,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,GAAG,UAAU,KAAK,EAAE,GAAG;AAC/F;;;;;;;AAQA,eAAsB,yBACpB,WACA,OACA,UACA,MAAc,KAAK,IAAI,GACwB;CAC/C,sBAAsB;CAEtB,MAAM,cAAc,KAAK,MAAM,MAAM,QAAQ;CAC7C,MAAM,MAAM,UAAU,WAAW,OAAO,WAAW;CACnD,MAAM,aAAa,KAAK,IAAI,GAAG,KAAK,KAAM,IAAI,WAAY,GAAI,CAAC;CAE/D,MAAM,MAAM,IAAI,KAAK,GAAG;EAAE,KAAK;EAAY,YAAY;CAAS,CAAC;CAIjE,OAAO;EAAE,eAFa,MAAM,UAAU,KAAK,GAAG,EAAE,KAAK,WAAW,CAAC;EAE/C,UAAU,cAAc,KAAK;CAAS;AAC1D;;;;AAKA,eAAsB,oBACpB,WACA,OACA,UACA,MAAc,KAAK,IAAI,GACwB;CAC/C,sBAAsB;CAEtB,MAAM,cAAc,KAAK,MAAM,MAAM,QAAQ;CAC7C,MAAM,QAAQ,MAAM,MAAM,IAAI,UAAU,WAAW,OAAO,WAAW,CAAC;CAEtE,OAAO;EACL,SAAS,OAAO,UAAU,WAAW,QAAQ;EAC7C,UAAU,cAAc,KAAK;CAC/B;AACF;;;;;AAMA,MAAM,wBAAwB;AAE9B,IAAI,iBAAiB;;;;AAKrB,SAAgB,wBAAwB,OAAgB,MAAc,KAAK,IAAI,GAAS;CACtF,IAAI,MAAM,iBAAiB,uBAAuB;CAElD,iBAAiB;CACjB,IAAI,MAAM,QAAQ,cAAc,KAAK;AACvC;;;;;AAqBA,IAAI,oBAAoB;;;;;;;;;;AAWxB,IAAa,sBAAb,MAAa,oBAAqD;CAChE,AAAO,YACL,UACA,AAAmB,YAAoB,UACvC;EADmB;CAClB;CAEH,AAAO,KACL,KACA,UACA,YACM;EACN,yBAAyB,KAAK,WAAW,KAAK,UAAU,CAAC,CAAC,MACvD,EAAE,SAAS,cAAc,SAAS,MAAM;GAAE;GAAS,KAAK,KAAK,IAAI,GAAG,UAAU,KAAK,IAAI,CAAC;EAAE,CAAC,IAC3F,UAAmB;GAClB,wBAAwB,KAAK;GAC7B,SAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;EACpE,CACF;CACF;CAEA,AAAO,KACL,KACA,UACA,YACM;EACN,oBAAoB,KAAK,WAAW,KAAK,UAAU,CAAC,CAAC,MAClD,EAAE,SAAS,cACV,SAAS,MAAM;GAAE;GAAS,KAAK,YAAY,IAAI,IAAI,KAAK,IAAI,GAAG,UAAU,KAAK,IAAI,CAAC;EAAE,CAAC,IACvF,UAAmB;GAClB,wBAAwB,KAAK;GAC7B,SAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;EACpE,CACF;CACF;CAEA,AAAO,MAAM,cAAoF;EAG/F,MAAM,YAAa,aAA8C,aAAa,CAAC;EAC/E,MAAM,SAAS,MAAM,QAAQ,UAAU,MAAM,IACzC,UAAU,OAAO,KAAK,GAAG,IACzB,OAAO,UAAU,UAAU,EAAE;EACjC,MAAM,MAAM,UAAU,OAAO,UAAU,QAAQ;EAE/C,IAAI,CAAC,UAAU,CAAC,KACd,OAAO,IAAI,oBAAoB,QAAW,QAAQ,qBAAqB;EAGzE,OAAO,IAAI,oBAAoB,QAAW,SAAS,OAAO,GAAG,KAAK;CACpE;AACF"}
|
|
@@ -31,26 +31,31 @@
|
|
|
31
31
|
* hands its stdout to a supervisor that greps for known lines, so the existing
|
|
32
32
|
* per-fact log lines stay exactly as they are outside development.
|
|
33
33
|
*/
|
|
34
|
-
type HttpReadyReport = {
|
|
35
|
-
/** Exactly what `listen()` returned — the bind, not its presentation. */
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
export type HttpReadyReport = {
|
|
35
|
+
/** Exactly what `listen()` returned — the bind, not its presentation. */
|
|
36
|
+
boundAddress?: string;
|
|
37
|
+
/** The address spelled for a human; safe to paste into a browser. */
|
|
38
|
+
url: string;
|
|
39
|
+
/** Whether the bind covers more than loopback. */
|
|
40
|
+
wildcardBind: boolean;
|
|
41
|
+
/** The port actually bound. */
|
|
42
|
+
port: number;
|
|
43
|
+
/** Routes on the app router at the moment the server started listening. */
|
|
44
|
+
routeCount: number;
|
|
45
|
+
/** `app.baseUrl`, when it is a deployment address rather than a local one. */
|
|
40
46
|
publicUrl?: string;
|
|
41
47
|
};
|
|
42
48
|
/**
|
|
43
49
|
* @internal Called by `HttpConnector.start()` right after a successful listen.
|
|
44
50
|
*/
|
|
45
|
-
declare function setHttpReadyReport(next: HttpReadyReport): void;
|
|
51
|
+
export declare function setHttpReadyReport(next: HttpReadyReport): void;
|
|
46
52
|
/**
|
|
47
53
|
* The last recorded bind, or `undefined` for a process with no HTTP surface —
|
|
48
54
|
* a queue worker still boots, and the ready block must render without an app
|
|
49
55
|
* URL rather than invent one.
|
|
50
56
|
*/
|
|
51
|
-
declare function getHttpReadyReport(): HttpReadyReport | undefined;
|
|
57
|
+
export declare function getHttpReadyReport(): HttpReadyReport | undefined;
|
|
52
58
|
/** @internal Test seam — a module-level singleton needs a way back to empty. */
|
|
53
|
-
declare function resetHttpReadyReport(): void;
|
|
59
|
+
export declare function resetHttpReadyReport(): void;
|
|
54
60
|
//#endregion
|
|
55
|
-
export { HttpReadyReport, getHttpReadyReport, resetHttpReadyReport, setHttpReadyReport };
|
|
56
61
|
//# sourceMappingURL=ready-report.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ready-report.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/ready-report.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"ready-report.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/ready-report.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAiCY;;EAEV;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;;wBAQc,mBAAmB,MAAM;;;;;;wBASzB,sBAAsB;;wBAKtB"}
|
|
@@ -2,14 +2,12 @@ import { Response } from "./response.mjs";
|
|
|
2
2
|
import { Request } from "./request.mjs";
|
|
3
3
|
import { ReturnedResponse } from "./types.mjs";
|
|
4
4
|
import { RequestControllerContract } from "../router/types.mjs";
|
|
5
|
-
|
|
6
5
|
//#region ../../packages/core/src/http/request-controller.d.ts
|
|
7
|
-
declare abstract class RequestController implements RequestControllerContract {
|
|
6
|
+
export declare abstract class RequestController implements RequestControllerContract {
|
|
8
7
|
readonly request: Request;
|
|
9
8
|
readonly response: Response;
|
|
10
9
|
constructor(request: Request, response: Response);
|
|
11
10
|
abstract execute(): Promise<ReturnedResponse>;
|
|
12
11
|
}
|
|
13
12
|
//#endregion
|
|
14
|
-
export { RequestController };
|
|
15
13
|
//# sourceMappingURL=request-controller.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-controller.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/request-controller.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"request-controller.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/request-controller.ts"],"mappings":";;;;;8BAKsB,6BAA6B;WAE/B,SAAS;WACT,UAAU;EAF5B,YACkB,SAAS,SACT,UAAU;WAKZ,WAAW,QAAQ"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* logging: { body: false, query: false },
|
|
11
11
|
* });
|
|
12
12
|
*/
|
|
13
|
-
type RequestLoggingOptions = {
|
|
13
|
+
export type RequestLoggingOptions = {
|
|
14
14
|
/**
|
|
15
15
|
* Include the request body in log entries.
|
|
16
16
|
*
|
|
@@ -30,8 +30,9 @@ type RequestLoggingOptions = {
|
|
|
30
30
|
query?: boolean;
|
|
31
31
|
};
|
|
32
32
|
/** A URL policy that can only remove input from snapshots, even on unmatched requests. */
|
|
33
|
-
type PrivateRequestLoggingRule = {
|
|
34
|
-
/** Path prefix at a segment boundary, or a regular expression over the normalized path. */
|
|
33
|
+
export type PrivateRequestLoggingRule = {
|
|
34
|
+
/** Path prefix at a segment boundary, or a regular expression over the normalized path. */
|
|
35
|
+
path: string | RegExp;
|
|
35
36
|
body?: false;
|
|
36
37
|
query?: false;
|
|
37
38
|
};
|
|
@@ -39,13 +40,14 @@ type PrivateRequestLoggingRule = {
|
|
|
39
40
|
* `http.logging`: the app-wide defaults for {@link RequestLoggingOptions},
|
|
40
41
|
* plus query parameter names whose values are masked in logged URLs.
|
|
41
42
|
*/
|
|
42
|
-
type HttpLoggingConfig = RequestLoggingOptions & {
|
|
43
|
+
export type HttpLoggingConfig = RequestLoggingOptions & {
|
|
43
44
|
/**
|
|
44
45
|
* Extra query parameter names to mask in logged URLs, on top of the
|
|
45
46
|
* logger's default secret-key denylist and {@link URL_CREDENTIAL_PARAMS}.
|
|
46
47
|
* Matched like the logger's keys: case, `-` and `_` are ignored.
|
|
47
48
|
*/
|
|
48
|
-
redactQueryParams?: string[];
|
|
49
|
+
redactQueryParams?: string[];
|
|
50
|
+
/** URL policies applied before route logging; matching rules cannot be overridden by a route. */
|
|
49
51
|
private?: PrivateRequestLoggingRule[];
|
|
50
52
|
};
|
|
51
53
|
/**
|
|
@@ -53,11 +55,14 @@ type HttpLoggingConfig = RequestLoggingOptions & {
|
|
|
53
55
|
* place of the `Request`/`Response` instances, whose native request, reply
|
|
54
56
|
* and socket graphs reach every sink otherwise.
|
|
55
57
|
*/
|
|
56
|
-
type RequestLogSnapshot = {
|
|
58
|
+
export type RequestLogSnapshot = {
|
|
57
59
|
id: string;
|
|
58
|
-
method: string;
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
method: string;
|
|
61
|
+
/** Path and query string, with credential-bearing parameter values masked. */
|
|
62
|
+
url: string;
|
|
63
|
+
/** The matched route pattern, e.g. `/users/:id`. */
|
|
64
|
+
route?: string;
|
|
65
|
+
/** The route name, when it has one. */
|
|
61
66
|
name?: string;
|
|
62
67
|
ip?: string;
|
|
63
68
|
userAgent?: string;
|
|
@@ -69,7 +74,7 @@ type RequestLogSnapshot = {
|
|
|
69
74
|
* are too generic for the logger's key denylist: signed-URL signatures,
|
|
70
75
|
* pre-signed cloud credentials and OAuth authorization codes.
|
|
71
76
|
*/
|
|
72
|
-
declare const URL_CREDENTIAL_PARAMS: readonly string[];
|
|
77
|
+
export declare const URL_CREDENTIAL_PARAMS: readonly string[];
|
|
73
78
|
/**
|
|
74
79
|
* Mask the values of credential-bearing query parameters in a URL (absolute,
|
|
75
80
|
* or a path with a query string). A parameter is credential-bearing when its
|
|
@@ -81,7 +86,7 @@ declare const URL_CREDENTIAL_PARAMS: readonly string[];
|
|
|
81
86
|
* @example
|
|
82
87
|
* redactUrlCredentials("/hooks?secret=abc&page=2") // "/hooks?secret=[REDACTED]&page=2"
|
|
83
88
|
*/
|
|
84
|
-
declare function redactUrlCredentials(url: string, extraParams?: readonly string[]): string;
|
|
89
|
+
export declare function redactUrlCredentials(url: string, extraParams?: readonly string[]): string;
|
|
85
90
|
/**
|
|
86
91
|
* Mask the values of credential-bearing parameters in a parsed query object,
|
|
87
92
|
* with the same names {@link redactUrlCredentials} masks in the URL. Nested
|
|
@@ -90,19 +95,19 @@ declare function redactUrlCredentials(url: string, extraParams?: readonly string
|
|
|
90
95
|
* @example
|
|
91
96
|
* redactQueryCredentials({ code: "abc", page: "2" }) // { code: "[REDACTED]", page: "2" }
|
|
92
97
|
*/
|
|
93
|
-
declare function redactQueryCredentials(query: Record<string, unknown>, extraParams?: readonly string[]): Record<string, unknown>;
|
|
98
|
+
export declare function redactQueryCredentials(query: Record<string, unknown>, extraParams?: readonly string[]): Record<string, unknown>;
|
|
94
99
|
/**
|
|
95
100
|
* The effective logging options for a request: `http.logging` overlaid by the
|
|
96
101
|
* route's own `logging` option, then restricted by matching private URL policies.
|
|
97
102
|
*/
|
|
98
|
-
declare function resolveRequestLoggingOptions(routeOptions: RequestLoggingOptions | undefined, url?: string, routePath?: string): Required<RequestLoggingOptions> & {
|
|
103
|
+
export declare function resolveRequestLoggingOptions(routeOptions: RequestLoggingOptions | undefined, url?: string, routePath?: string): Required<RequestLoggingOptions> & {
|
|
99
104
|
redactQueryParams: string[];
|
|
100
105
|
};
|
|
101
106
|
/**
|
|
102
107
|
* The fields of a request the snapshot reads. Structural, so the snapshot can
|
|
103
108
|
* be built (and tested) without a live Fastify request.
|
|
104
109
|
*/
|
|
105
|
-
type RequestLogSource = {
|
|
110
|
+
export type RequestLogSource = {
|
|
106
111
|
id: string;
|
|
107
112
|
method: string;
|
|
108
113
|
url: string;
|
|
@@ -124,7 +129,6 @@ type RequestLogSource = {
|
|
|
124
129
|
*
|
|
125
130
|
* Uploaded files are summarised (`{ file, mimeType }`) rather than walked.
|
|
126
131
|
*/
|
|
127
|
-
declare function buildRequestLogSnapshot(source: RequestLogSource): RequestLogSnapshot;
|
|
132
|
+
export declare function buildRequestLogSnapshot(source: RequestLogSource): RequestLogSnapshot;
|
|
128
133
|
//#endregion
|
|
129
|
-
export { HttpLoggingConfig, PrivateRequestLoggingRule, RequestLogSnapshot, RequestLogSource, RequestLoggingOptions, URL_CREDENTIAL_PARAMS, buildRequestLogSnapshot, redactQueryCredentials, redactUrlCredentials, resolveRequestLoggingOptions };
|
|
130
134
|
//# sourceMappingURL=request-log-snapshot.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-log-snapshot.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/request-log-snapshot.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"request-log-snapshot.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/request-log-snapshot.ts"],"mappings":";;;;;;;;;;;;YAeY;;;;;;;;;;EAUV;;;;;;;EAOA;;;YAIU;;EAEV,eAAe;EACf;EACA;;;;;;YAOU,oBAAoB;;;;;;EAM9B;;EAEA,UAAU;;;;;;;YAQA;EACV;EACA;;EAEA;;EAEA;;EAEA;EACA;EACA;EACA,QAAQ;EACR,OAAO;;;;;;;qBAQI;;;;;;;;;;;;wBA4BG,qBAAqB,aAAa;;;;;;;;;wBA4DlC,uBACd,OAAO,yBACP,kCACC;;;;;wBAmCa,6BACd,cAAc,mCACd,cACA,qBACC,SAAS;EAA2B;;;;;;YAuG3B;EACV;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR,OAAO;EACP;IAAU;IAAe;IAAe,UAAU;;;;;;;;;;;wBAWpC,wBAAwB,QAAQ,mBAAmB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UploadedFile } from "./uploaded-file.mjs";
|
|
2
|
-
import
|
|
2
|
+
import baseConfig from "@mongez/config";
|
|
3
3
|
import { DEFAULT_REDACT_KEY_SET, normalizeRedactKey } from "@warlock.js/logger";
|
|
4
4
|
|
|
5
5
|
//#region ../../packages/core/src/http/request-log-snapshot.ts
|
|
@@ -87,7 +87,7 @@ function redactQueryValue(value, isCredential) {
|
|
|
87
87
|
* route's own `logging` option, then restricted by matching private URL policies.
|
|
88
88
|
*/
|
|
89
89
|
function resolveRequestLoggingOptions(routeOptions, url, routePath) {
|
|
90
|
-
const global =
|
|
90
|
+
const global = baseConfig.get("http.logging") ?? {};
|
|
91
91
|
const options = {
|
|
92
92
|
body: routeOptions?.body ?? global.body ?? true,
|
|
93
93
|
query: routeOptions?.query ?? global.query ?? true,
|
|
@@ -164,7 +164,7 @@ function loggingPathCandidates(url) {
|
|
|
164
164
|
const segments = [];
|
|
165
165
|
for (const segment of decoded.split("/")) if (segment === "..") segments.pop();
|
|
166
166
|
else if (segment && segment !== ".") segments.push(segment);
|
|
167
|
-
return [
|
|
167
|
+
return [.../* @__PURE__ */ new Set([
|
|
168
168
|
raw,
|
|
169
169
|
decoded,
|
|
170
170
|
`/${segments.join("/")}`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-log-snapshot.mjs","names":[],"sources":["../../../../../../../../packages/core/src/http/request-log-snapshot.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { DEFAULT_REDACT_KEY_SET, normalizeRedactKey } from \"@warlock.js/logger\";\nimport { UploadedFile } from \"./uploaded-file\";\n\n/**\n * What a request's log entries carry of its input. Set globally under\n * `http.logging` and per route with the route's `logging` option; the route\n * wins key by key, unless a private URL policy suppresses that field.\n *\n * @example\n * // never log the body or the query string of this route, not even redacted\n * router.post(\"/accounts/credentials\", controller, {\n * logging: { body: false, query: false },\n * });\n */\nexport type RequestLoggingOptions = {\n /**\n * Include the request body in log entries.\n *\n * The body is logged as RECEIVED, before validation, so fields the schema\n * later rejects are part of it. Turn it off on routes that accept secrets\n * or arbitrary user text.\n *\n * @default true\n */\n body?: boolean;\n /**\n * Include the parsed query string in log entries. The logged URL keeps its\n * path either way; with `query: false` its query string is dropped too.\n *\n * @default true\n */\n query?: boolean;\n};\n\n/** A URL policy that can only remove input from snapshots, even on unmatched requests. */\nexport type PrivateRequestLoggingRule = {\n /** Path prefix at a segment boundary, or a regular expression over the normalized path. */\n path: string | RegExp;\n body?: false;\n query?: false;\n};\n\n/**\n * `http.logging`: the app-wide defaults for {@link RequestLoggingOptions},\n * plus query parameter names whose values are masked in logged URLs.\n */\nexport type HttpLoggingConfig = RequestLoggingOptions & {\n /**\n * Extra query parameter names to mask in logged URLs, on top of the\n * logger's default secret-key denylist and {@link URL_CREDENTIAL_PARAMS}.\n * Matched like the logger's keys: case, `-` and `_` are ignored.\n */\n redactQueryParams?: string[];\n /** URL policies applied before route logging; matching rules cannot be overridden by a route. */\n private?: PrivateRequestLoggingRule[];\n};\n\n/**\n * The bounded, plain-data view of a request that Core puts in log entries in\n * place of the `Request`/`Response` instances, whose native request, reply\n * and socket graphs reach every sink otherwise.\n */\nexport type RequestLogSnapshot = {\n id: string;\n method: string;\n /** Path and query string, with credential-bearing parameter values masked. */\n url: string;\n /** The matched route pattern, e.g. `/users/:id`. */\n route?: string;\n /** The route name, when it has one. */\n name?: string;\n ip?: string;\n userAgent?: string;\n query?: Record<string, unknown>;\n body?: Record<string, unknown>;\n};\n\n/**\n * Query parameters that carry a credential in a URL even though their names\n * are too generic for the logger's key denylist: signed-URL signatures,\n * pre-signed cloud credentials and OAuth authorization codes.\n */\nexport const URL_CREDENTIAL_PARAMS: readonly string[] = [\n \"signature\",\n \"sig\",\n \"code\",\n \"x-amz-signature\",\n \"x-amz-credential\",\n \"x-amz-security-token\",\n \"x-goog-signature\",\n \"x-goog-credential\",\n];\n\nconst URL_CREDENTIAL_PARAM_SET: ReadonlySet<string> = new Set(\n URL_CREDENTIAL_PARAMS.map(normalizeRedactKey),\n);\n\nconst REDACTED = \"[REDACTED]\";\n\n/**\n * Mask the values of credential-bearing query parameters in a URL (absolute,\n * or a path with a query string). A parameter is credential-bearing when its\n * normalized name is in the logger's default secret-key denylist (`secret`,\n * `token`, `apiKey`, …), in {@link URL_CREDENTIAL_PARAMS}, or in `extraParams`.\n *\n * The path and the other parameters are kept as written.\n *\n * @example\n * redactUrlCredentials(\"/hooks?secret=abc&page=2\") // \"/hooks?secret=[REDACTED]&page=2\"\n */\nexport function redactUrlCredentials(url: string, extraParams: readonly string[] = []): string {\n const queryStart = url.indexOf(\"?\");\n\n if (queryStart === -1) return url;\n\n const hashStart = url.indexOf(\"#\", queryStart);\n const queryEnd = hashStart === -1 ? url.length : hashStart;\n const isCredential = credentialParamMatcher(extraParams);\n\n const query = url\n .slice(queryStart + 1, queryEnd)\n .split(\"&\")\n .map((pair) => {\n const separator = pair.indexOf(\"=\");\n const rawName = separator === -1 ? pair : pair.slice(0, separator);\n\n let name = rawName;\n\n try {\n name = decodeURIComponent(rawName.replace(/\\+/g, \" \"));\n } catch {\n // A malformed escape is logged under its raw name.\n }\n\n if (separator !== -1 && isCredential(name)) {\n return `${rawName}=${REDACTED}`;\n }\n\n return pair;\n })\n .join(\"&\");\n\n // A fragment never reaches the server, but a URL handed in by app code may\n // carry one; it is dropped rather than risk logging a token in it.\n return `${url.slice(0, queryStart)}?${query}`;\n}\n\n/**\n * A predicate telling whether a query parameter name carries a credential:\n * its normalized name is in the logger's default secret-key denylist, in\n * {@link URL_CREDENTIAL_PARAMS}, or in `extraParams`.\n */\nfunction credentialParamMatcher(extraParams: readonly string[]): (name: string) => boolean {\n const extra = new Set(extraParams.map(normalizeRedactKey));\n\n return (name) => {\n const key = normalizeRedactKey(name);\n\n return DEFAULT_REDACT_KEY_SET.has(key) || URL_CREDENTIAL_PARAM_SET.has(key) || extra.has(key);\n };\n}\n\n/**\n * Mask the values of credential-bearing parameters in a parsed query object,\n * with the same names {@link redactUrlCredentials} masks in the URL. Nested\n * objects and arrays (`a[b]=…` parsing) are walked; the input is not mutated.\n *\n * @example\n * redactQueryCredentials({ code: \"abc\", page: \"2\" }) // { code: \"[REDACTED]\", page: \"2\" }\n */\nexport function redactQueryCredentials(\n query: Record<string, unknown>,\n extraParams: readonly string[] = [],\n): Record<string, unknown> {\n return redactQueryObject(query, credentialParamMatcher(extraParams));\n}\n\nfunction redactQueryObject(\n query: Record<string, unknown>,\n isCredential: (name: string) => boolean,\n): Record<string, unknown> {\n const output: Record<string, unknown> = {};\n\n for (const [name, value] of Object.entries(query)) {\n output[name] = isCredential(name) ? REDACTED : redactQueryValue(value, isCredential);\n }\n\n return output;\n}\n\nfunction redactQueryValue(value: unknown, isCredential: (name: string) => boolean): unknown {\n if (Array.isArray(value)) return value.map((item) => redactQueryValue(item, isCredential));\n\n if (\n value !== null &&\n typeof value === \"object\" &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n return redactQueryObject(value as Record<string, unknown>, isCredential);\n }\n\n return value;\n}\n\n/**\n * The effective logging options for a request: `http.logging` overlaid by the\n * route's own `logging` option, then restricted by matching private URL policies.\n */\nexport function resolveRequestLoggingOptions(\n routeOptions: RequestLoggingOptions | undefined,\n url?: string,\n routePath?: string,\n): Required<RequestLoggingOptions> & { redactQueryParams: string[] } {\n const global = (config.get(\"http.logging\") ?? {}) as HttpLoggingConfig;\n\n const options = {\n body: routeOptions?.body ?? global.body ?? true,\n query: routeOptions?.query ?? global.query ?? true,\n redactQueryParams: global.redactQueryParams ?? [],\n };\n if (!global.private?.length || url === undefined) return options;\n const candidates = loggingPathCandidates(url);\n if (candidates === undefined) return { ...options, body: false, query: false };\n if (routePath) {\n const routeCandidates = loggingPathCandidates(routePath);\n if (!routeCandidates) return { ...options, body: false, query: false };\n candidates.push(...routeCandidates);\n }\n\n for (const rule of compiledPrivateRules(global.private)) {\n let matches: boolean;\n if (rule.type === \"regex\") {\n const { regex, needsClone } = rule;\n matches = candidates.some((candidate) =>\n (needsClone ? new RegExp(regex.source, regex.flags) : regex).test(candidate),\n );\n } else {\n const { prefixes } = rule;\n // A malformed configured prefix must never silently disable privacy.\n matches =\n prefixes === undefined ||\n prefixes.some((prefix) =>\n candidates.some(\n (candidate) =>\n prefix === \"/\" || candidate === prefix || candidate.startsWith(`${prefix}/`),\n ),\n );\n }\n if (!matches) continue;\n if (rule.body === false) options.body = false;\n if (rule.query === false) options.query = false;\n }\n return options;\n}\n\n/** A private rule with its path matcher prepared once. */\ntype CompiledPrivateRule = Pick<PrivateRequestLoggingRule, \"body\" | \"query\"> &\n (\n | { type: \"regex\"; regex: RegExp; needsClone: boolean }\n // `undefined` prefixes: the configured path does not decode, so it matches every request.\n | { type: \"prefix\"; prefixes: string[] | undefined }\n );\n\n/**\n * Compiled rules per configured `http.logging.private` array. Snapshots are\n * built several times per request, so each array's prefixes are normalised\n * once; replacing the array (a new config value) compiles the new one.\n */\nconst compiledRulesCache = new WeakMap<\n readonly PrivateRequestLoggingRule[],\n CompiledPrivateRule[]\n>();\n\nfunction compiledPrivateRules(rules: readonly PrivateRequestLoggingRule[]): CompiledPrivateRule[] {\n let compiled = compiledRulesCache.get(rules);\n if (compiled) return compiled;\n compiled = rules.map((rule): CompiledPrivateRule => {\n const { path, body, query } = rule;\n if (path instanceof RegExp) {\n // A global or sticky regex keeps `lastIndex` between tests; use a fresh copy.\n return { type: \"regex\", regex: path, needsClone: path.global || path.sticky, body, query };\n }\n return { type: \"prefix\", prefixes: loggingPathCandidates(path), body, query };\n });\n compiledRulesCache.set(rules, compiled);\n return compiled;\n}\n\n/** Backslashes to slashes, repeated slashes collapsed, no trailing slash. */\nfunction collapseLoggingPath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/\\/+/g, \"/\").replace(/\\/$/, \"\") || \"/\";\n}\n\nfunction loggingPathCandidates(url: string): string[] | undefined {\n try {\n // Preserve raw dot segments in absolute-form requests; URL() would erase them.\n const pathname = url.replace(/^[a-z][a-z\\d+.-]*:\\/\\/[^/?#]*/i, \"\").split(/[?#]/u)[0] || \"/\";\n const raw = collapseLoggingPath(pathname);\n const decoded = collapseLoggingPath(decodeURIComponent(pathname));\n const segments: string[] = [];\n for (const segment of decoded.split(\"/\")) {\n if (segment === \"..\") segments.pop();\n else if (segment && segment !== \".\") segments.push(segment);\n }\n return [...new Set([raw, decoded, `/${segments.join(\"/\")}`])];\n } catch {\n // With a private-path policy, undecodable input is withheld rather than guessed.\n return undefined;\n }\n}\n\n/**\n * The fields of a request the snapshot reads. Structural, so the snapshot can\n * be built (and tested) without a live Fastify request.\n */\nexport type RequestLogSource = {\n id: string;\n method: string;\n url: string;\n ip?: string;\n userAgent?: string;\n query?: Record<string, unknown>;\n body?: Record<string, unknown>;\n route?: { path?: string; name?: string; logging?: RequestLoggingOptions };\n};\n\n/**\n * Build the {@link RequestLogSnapshot} for a request, applying the route's\n * logging policy BEFORE anything reaches a log entry: an omitted body or\n * query is never copied, so no sink, channel or redaction setting can expose it.\n * Credential-bearing query parameters are masked in both `url` and `query`.\n *\n * Uploaded files are summarised (`{ file, mimeType }`) rather than walked.\n */\nexport function buildRequestLogSnapshot(source: RequestLogSource): RequestLogSnapshot {\n const options = resolveRequestLoggingOptions(\n source.route?.logging,\n source.url,\n source.route?.path,\n );\n const url = options.query ? source.url : stripQuery(source.url);\n\n const snapshot: RequestLogSnapshot = {\n id: source.id,\n method: source.method,\n url: redactUrlCredentials(url ?? \"\", options.redactQueryParams),\n };\n\n if (source.route?.path) snapshot.route = source.route.path;\n if (source.route?.name) snapshot.name = source.route.name;\n if (source.ip) snapshot.ip = source.ip;\n if (source.userAgent) snapshot.userAgent = source.userAgent;\n\n if (options.query && source.query && Object.keys(source.query).length > 0) {\n snapshot.query = redactQueryCredentials(source.query, options.redactQueryParams);\n }\n\n if (options.body && source.body && Object.keys(source.body).length > 0) {\n snapshot.body = summariseFiles(source.body);\n }\n\n return snapshot;\n}\n\nfunction stripQuery(url: string | undefined): string | undefined {\n if (!url) return url;\n\n const queryStart = url.indexOf(\"?\");\n\n return queryStart === -1 ? url : url.slice(0, queryStart);\n}\n\nfunction summariseFiles(body: Record<string, unknown>): Record<string, unknown> {\n const output: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(body)) {\n output[key] = Array.isArray(value) ? value.map(summariseFile) : summariseFile(value);\n }\n\n return output;\n}\n\nfunction summariseFile(value: unknown): unknown {\n if (!(value instanceof UploadedFile)) return value;\n\n return { file: value.name, mimeType: value.mimeType };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"request-log-snapshot.mjs","names":["config"],"sources":["../../../../../../../../packages/core/src/http/request-log-snapshot.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { DEFAULT_REDACT_KEY_SET, normalizeRedactKey } from \"@warlock.js/logger\";\nimport { UploadedFile } from \"./uploaded-file\";\n\n/**\n * What a request's log entries carry of its input. Set globally under\n * `http.logging` and per route with the route's `logging` option; the route\n * wins key by key, unless a private URL policy suppresses that field.\n *\n * @example\n * // never log the body or the query string of this route, not even redacted\n * router.post(\"/accounts/credentials\", controller, {\n * logging: { body: false, query: false },\n * });\n */\nexport type RequestLoggingOptions = {\n /**\n * Include the request body in log entries.\n *\n * The body is logged as RECEIVED, before validation, so fields the schema\n * later rejects are part of it. Turn it off on routes that accept secrets\n * or arbitrary user text.\n *\n * @default true\n */\n body?: boolean;\n /**\n * Include the parsed query string in log entries. The logged URL keeps its\n * path either way; with `query: false` its query string is dropped too.\n *\n * @default true\n */\n query?: boolean;\n};\n\n/** A URL policy that can only remove input from snapshots, even on unmatched requests. */\nexport type PrivateRequestLoggingRule = {\n /** Path prefix at a segment boundary, or a regular expression over the normalized path. */\n path: string | RegExp;\n body?: false;\n query?: false;\n};\n\n/**\n * `http.logging`: the app-wide defaults for {@link RequestLoggingOptions},\n * plus query parameter names whose values are masked in logged URLs.\n */\nexport type HttpLoggingConfig = RequestLoggingOptions & {\n /**\n * Extra query parameter names to mask in logged URLs, on top of the\n * logger's default secret-key denylist and {@link URL_CREDENTIAL_PARAMS}.\n * Matched like the logger's keys: case, `-` and `_` are ignored.\n */\n redactQueryParams?: string[];\n /** URL policies applied before route logging; matching rules cannot be overridden by a route. */\n private?: PrivateRequestLoggingRule[];\n};\n\n/**\n * The bounded, plain-data view of a request that Core puts in log entries in\n * place of the `Request`/`Response` instances, whose native request, reply\n * and socket graphs reach every sink otherwise.\n */\nexport type RequestLogSnapshot = {\n id: string;\n method: string;\n /** Path and query string, with credential-bearing parameter values masked. */\n url: string;\n /** The matched route pattern, e.g. `/users/:id`. */\n route?: string;\n /** The route name, when it has one. */\n name?: string;\n ip?: string;\n userAgent?: string;\n query?: Record<string, unknown>;\n body?: Record<string, unknown>;\n};\n\n/**\n * Query parameters that carry a credential in a URL even though their names\n * are too generic for the logger's key denylist: signed-URL signatures,\n * pre-signed cloud credentials and OAuth authorization codes.\n */\nexport const URL_CREDENTIAL_PARAMS: readonly string[] = [\n \"signature\",\n \"sig\",\n \"code\",\n \"x-amz-signature\",\n \"x-amz-credential\",\n \"x-amz-security-token\",\n \"x-goog-signature\",\n \"x-goog-credential\",\n];\n\nconst URL_CREDENTIAL_PARAM_SET: ReadonlySet<string> = new Set(\n URL_CREDENTIAL_PARAMS.map(normalizeRedactKey),\n);\n\nconst REDACTED = \"[REDACTED]\";\n\n/**\n * Mask the values of credential-bearing query parameters in a URL (absolute,\n * or a path with a query string). A parameter is credential-bearing when its\n * normalized name is in the logger's default secret-key denylist (`secret`,\n * `token`, `apiKey`, …), in {@link URL_CREDENTIAL_PARAMS}, or in `extraParams`.\n *\n * The path and the other parameters are kept as written.\n *\n * @example\n * redactUrlCredentials(\"/hooks?secret=abc&page=2\") // \"/hooks?secret=[REDACTED]&page=2\"\n */\nexport function redactUrlCredentials(url: string, extraParams: readonly string[] = []): string {\n const queryStart = url.indexOf(\"?\");\n\n if (queryStart === -1) return url;\n\n const hashStart = url.indexOf(\"#\", queryStart);\n const queryEnd = hashStart === -1 ? url.length : hashStart;\n const isCredential = credentialParamMatcher(extraParams);\n\n const query = url\n .slice(queryStart + 1, queryEnd)\n .split(\"&\")\n .map((pair) => {\n const separator = pair.indexOf(\"=\");\n const rawName = separator === -1 ? pair : pair.slice(0, separator);\n\n let name = rawName;\n\n try {\n name = decodeURIComponent(rawName.replace(/\\+/g, \" \"));\n } catch {\n // A malformed escape is logged under its raw name.\n }\n\n if (separator !== -1 && isCredential(name)) {\n return `${rawName}=${REDACTED}`;\n }\n\n return pair;\n })\n .join(\"&\");\n\n // A fragment never reaches the server, but a URL handed in by app code may\n // carry one; it is dropped rather than risk logging a token in it.\n return `${url.slice(0, queryStart)}?${query}`;\n}\n\n/**\n * A predicate telling whether a query parameter name carries a credential:\n * its normalized name is in the logger's default secret-key denylist, in\n * {@link URL_CREDENTIAL_PARAMS}, or in `extraParams`.\n */\nfunction credentialParamMatcher(extraParams: readonly string[]): (name: string) => boolean {\n const extra = new Set(extraParams.map(normalizeRedactKey));\n\n return (name) => {\n const key = normalizeRedactKey(name);\n\n return DEFAULT_REDACT_KEY_SET.has(key) || URL_CREDENTIAL_PARAM_SET.has(key) || extra.has(key);\n };\n}\n\n/**\n * Mask the values of credential-bearing parameters in a parsed query object,\n * with the same names {@link redactUrlCredentials} masks in the URL. Nested\n * objects and arrays (`a[b]=…` parsing) are walked; the input is not mutated.\n *\n * @example\n * redactQueryCredentials({ code: \"abc\", page: \"2\" }) // { code: \"[REDACTED]\", page: \"2\" }\n */\nexport function redactQueryCredentials(\n query: Record<string, unknown>,\n extraParams: readonly string[] = [],\n): Record<string, unknown> {\n return redactQueryObject(query, credentialParamMatcher(extraParams));\n}\n\nfunction redactQueryObject(\n query: Record<string, unknown>,\n isCredential: (name: string) => boolean,\n): Record<string, unknown> {\n const output: Record<string, unknown> = {};\n\n for (const [name, value] of Object.entries(query)) {\n output[name] = isCredential(name) ? REDACTED : redactQueryValue(value, isCredential);\n }\n\n return output;\n}\n\nfunction redactQueryValue(value: unknown, isCredential: (name: string) => boolean): unknown {\n if (Array.isArray(value)) return value.map((item) => redactQueryValue(item, isCredential));\n\n if (\n value !== null &&\n typeof value === \"object\" &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n return redactQueryObject(value as Record<string, unknown>, isCredential);\n }\n\n return value;\n}\n\n/**\n * The effective logging options for a request: `http.logging` overlaid by the\n * route's own `logging` option, then restricted by matching private URL policies.\n */\nexport function resolveRequestLoggingOptions(\n routeOptions: RequestLoggingOptions | undefined,\n url?: string,\n routePath?: string,\n): Required<RequestLoggingOptions> & { redactQueryParams: string[] } {\n const global = (config.get(\"http.logging\") ?? {}) as HttpLoggingConfig;\n\n const options = {\n body: routeOptions?.body ?? global.body ?? true,\n query: routeOptions?.query ?? global.query ?? true,\n redactQueryParams: global.redactQueryParams ?? [],\n };\n if (!global.private?.length || url === undefined) return options;\n const candidates = loggingPathCandidates(url);\n if (candidates === undefined) return { ...options, body: false, query: false };\n if (routePath) {\n const routeCandidates = loggingPathCandidates(routePath);\n if (!routeCandidates) return { ...options, body: false, query: false };\n candidates.push(...routeCandidates);\n }\n\n for (const rule of compiledPrivateRules(global.private)) {\n let matches: boolean;\n if (rule.type === \"regex\") {\n const { regex, needsClone } = rule;\n matches = candidates.some((candidate) =>\n (needsClone ? new RegExp(regex.source, regex.flags) : regex).test(candidate),\n );\n } else {\n const { prefixes } = rule;\n // A malformed configured prefix must never silently disable privacy.\n matches =\n prefixes === undefined ||\n prefixes.some((prefix) =>\n candidates.some(\n (candidate) =>\n prefix === \"/\" || candidate === prefix || candidate.startsWith(`${prefix}/`),\n ),\n );\n }\n if (!matches) continue;\n if (rule.body === false) options.body = false;\n if (rule.query === false) options.query = false;\n }\n return options;\n}\n\n/** A private rule with its path matcher prepared once. */\ntype CompiledPrivateRule = Pick<PrivateRequestLoggingRule, \"body\" | \"query\"> &\n (\n | { type: \"regex\"; regex: RegExp; needsClone: boolean }\n // `undefined` prefixes: the configured path does not decode, so it matches every request.\n | { type: \"prefix\"; prefixes: string[] | undefined }\n );\n\n/**\n * Compiled rules per configured `http.logging.private` array. Snapshots are\n * built several times per request, so each array's prefixes are normalised\n * once; replacing the array (a new config value) compiles the new one.\n */\nconst compiledRulesCache = new WeakMap<\n readonly PrivateRequestLoggingRule[],\n CompiledPrivateRule[]\n>();\n\nfunction compiledPrivateRules(rules: readonly PrivateRequestLoggingRule[]): CompiledPrivateRule[] {\n let compiled = compiledRulesCache.get(rules);\n if (compiled) return compiled;\n compiled = rules.map((rule): CompiledPrivateRule => {\n const { path, body, query } = rule;\n if (path instanceof RegExp) {\n // A global or sticky regex keeps `lastIndex` between tests; use a fresh copy.\n return { type: \"regex\", regex: path, needsClone: path.global || path.sticky, body, query };\n }\n return { type: \"prefix\", prefixes: loggingPathCandidates(path), body, query };\n });\n compiledRulesCache.set(rules, compiled);\n return compiled;\n}\n\n/** Backslashes to slashes, repeated slashes collapsed, no trailing slash. */\nfunction collapseLoggingPath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/\\/+/g, \"/\").replace(/\\/$/, \"\") || \"/\";\n}\n\nfunction loggingPathCandidates(url: string): string[] | undefined {\n try {\n // Preserve raw dot segments in absolute-form requests; URL() would erase them.\n const pathname = url.replace(/^[a-z][a-z\\d+.-]*:\\/\\/[^/?#]*/i, \"\").split(/[?#]/u)[0] || \"/\";\n const raw = collapseLoggingPath(pathname);\n const decoded = collapseLoggingPath(decodeURIComponent(pathname));\n const segments: string[] = [];\n for (const segment of decoded.split(\"/\")) {\n if (segment === \"..\") segments.pop();\n else if (segment && segment !== \".\") segments.push(segment);\n }\n return [...new Set([raw, decoded, `/${segments.join(\"/\")}`])];\n } catch {\n // With a private-path policy, undecodable input is withheld rather than guessed.\n return undefined;\n }\n}\n\n/**\n * The fields of a request the snapshot reads. Structural, so the snapshot can\n * be built (and tested) without a live Fastify request.\n */\nexport type RequestLogSource = {\n id: string;\n method: string;\n url: string;\n ip?: string;\n userAgent?: string;\n query?: Record<string, unknown>;\n body?: Record<string, unknown>;\n route?: { path?: string; name?: string; logging?: RequestLoggingOptions };\n};\n\n/**\n * Build the {@link RequestLogSnapshot} for a request, applying the route's\n * logging policy BEFORE anything reaches a log entry: an omitted body or\n * query is never copied, so no sink, channel or redaction setting can expose it.\n * Credential-bearing query parameters are masked in both `url` and `query`.\n *\n * Uploaded files are summarised (`{ file, mimeType }`) rather than walked.\n */\nexport function buildRequestLogSnapshot(source: RequestLogSource): RequestLogSnapshot {\n const options = resolveRequestLoggingOptions(\n source.route?.logging,\n source.url,\n source.route?.path,\n );\n const url = options.query ? source.url : stripQuery(source.url);\n\n const snapshot: RequestLogSnapshot = {\n id: source.id,\n method: source.method,\n url: redactUrlCredentials(url ?? \"\", options.redactQueryParams),\n };\n\n if (source.route?.path) snapshot.route = source.route.path;\n if (source.route?.name) snapshot.name = source.route.name;\n if (source.ip) snapshot.ip = source.ip;\n if (source.userAgent) snapshot.userAgent = source.userAgent;\n\n if (options.query && source.query && Object.keys(source.query).length > 0) {\n snapshot.query = redactQueryCredentials(source.query, options.redactQueryParams);\n }\n\n if (options.body && source.body && Object.keys(source.body).length > 0) {\n snapshot.body = summariseFiles(source.body);\n }\n\n return snapshot;\n}\n\nfunction stripQuery(url: string | undefined): string | undefined {\n if (!url) return url;\n\n const queryStart = url.indexOf(\"?\");\n\n return queryStart === -1 ? url : url.slice(0, queryStart);\n}\n\nfunction summariseFiles(body: Record<string, unknown>): Record<string, unknown> {\n const output: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(body)) {\n output[key] = Array.isArray(value) ? value.map(summariseFile) : summariseFile(value);\n }\n\n return output;\n}\n\nfunction summariseFile(value: unknown): unknown {\n if (!(value instanceof UploadedFile)) return value;\n\n return { file: value.name, mimeType: value.mimeType };\n}\n"],"mappings":"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"}
|
package/esm/http/request.d.mts
CHANGED
|
@@ -3,17 +3,18 @@ import { Response } from "./response.mjs";
|
|
|
3
3
|
import { UploadedFile } from "./uploaded-file.mjs";
|
|
4
4
|
import { DecodedAccessToken, RequestEvent, RequestLocals } from "./types.mjs";
|
|
5
5
|
import { Middleware, RequestHandler, Route } from "../router/types.mjs";
|
|
6
|
+
import "../router/index.mjs";
|
|
7
|
+
import "../index.mjs";
|
|
6
8
|
import { BaseValidator } from "@warlock.js/seal";
|
|
7
9
|
import { LogLevel } from "@warlock.js/logger";
|
|
8
10
|
import { FastifyRequest } from "fastify";
|
|
9
11
|
import { IncomingHttpHeaders } from "node:http2";
|
|
10
|
-
|
|
11
12
|
//#region ../../packages/core/src/http/request.d.ts
|
|
12
|
-
type StandardHeaders = { [K in keyof IncomingHttpHeaders as string extends K ? never : number extends K ? never : K]: IncomingHttpHeaders[K] };
|
|
13
|
+
type StandardHeaders = { [K in keyof IncomingHttpHeaders as string extends K ? never : number extends K ? never : K]: IncomingHttpHeaders[K]; };
|
|
13
14
|
type HeaderKeys = keyof StandardHeaders;
|
|
14
15
|
/** A request-bound translator: keyword in, translated string out. */
|
|
15
|
-
type RequestTranslator = (keyword: string, placeholders?: Record<string, unknown>) => string;
|
|
16
|
-
declare class Request<RequestValidation = any> {
|
|
16
|
+
export type RequestTranslator = (keyword: string, placeholders?: Record<string, unknown>) => string;
|
|
17
|
+
export declare class Request<RequestValidation = any> {
|
|
17
18
|
/**
|
|
18
19
|
* Underlying Fastify request — a public escape hatch to capabilities the
|
|
19
20
|
* framework's high-level helpers don't yet cover.
|
|
@@ -424,14 +425,14 @@ declare class Request<RequestValidation = any> {
|
|
|
424
425
|
* @internal Framework orchestration — do not call from app code. Wired
|
|
425
426
|
* from the Fastify route handler in `router.scan()`.
|
|
426
427
|
*/
|
|
427
|
-
execute(): Promise<any[] |
|
|
428
|
+
execute(): Promise<any[] | Record<string, any> | Response>;
|
|
428
429
|
/**
|
|
429
430
|
* Iterate the collected middlewares in order; return the first short-circuit
|
|
430
431
|
* value or `undefined` when every middleware passes through.
|
|
431
432
|
*
|
|
432
433
|
* @internal Framework orchestration — do not call from app code.
|
|
433
434
|
*/
|
|
434
|
-
protected executeMiddleware(): Promise<any[] |
|
|
435
|
+
protected executeMiddleware(): Promise<any[] | Record<string, any> | Response | undefined>;
|
|
435
436
|
/**
|
|
436
437
|
* Gather the middleware list for the current route — today just the
|
|
437
438
|
* route-level array; future extraction may merge group + app-wide layers.
|
|
@@ -633,5 +634,5 @@ declare class Request<RequestValidation = any> {
|
|
|
633
634
|
setHeader(key: HeaderKeys, value: string): this;
|
|
634
635
|
}
|
|
635
636
|
//#endregion
|
|
636
|
-
export {
|
|
637
|
+
export {};
|
|
637
638
|
//# sourceMappingURL=request.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/http/request.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"request.d.mts","names":["_$_warlock_js_core0.RequestHandler"],"sources":["../../../../../../../../packages/core/src/http/request.ts"],"mappings":";;;;;;;;;;;;KAkCK,qBAID,WAAW,sCAAsC,2BAA2B,YAAY,IACvF,oBAAoB;KAGpB,mBAAmB;;YAGZ,qBAAqB,iBAAiB,eAAe;qBAEpD,QAAQ;;;;;;;;;;;;;;;;;EAiBZ,aAAc;;;;EAKd,UAAW;;;;EAKX,OAAQ;;;;;UAMP;;;;;;;;;;;;;;;;;;;;MAqBG,UAAU;;;;YAmCX;;;;UAKF;;;;;;;;MASG,sBAAsB;MAItB,mBAAmB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC9B,QAAQ;;;;;YAML;;;;;;;;;;;;;;;;;;;;;;;MAwBC;;;;SAWG,SAAS;;;;;EAMhB,OAAO;;;;EAKP,GAAG;;;;YAeA;;;;YAKA,gBAAgB;;;;EAKnB;;;;;;EAOA;;;;EAKA;;;;EAKA;;;;EAKA,WAAW,SAAS;;;;;;;;;;YA6BjB;;;;;;;;YA0BA;;;;;;mBAYO,iBAAiB,iBAAiB;;;;EAY5C,UAAU,oBAAoB,iBAAiB;;;;;;;;;YAY5C,YAAY;;;;;YAoBZ;;;;MA0BC;;;;MASA,OAAO;;;;EAOX,cAAc;;;;;;EAWd,cAAc;;;;MAOV;;;;EAOE,SAAS,YAAY,eAAe,4BAAyB,mCAAA;;;;EAOnE,OAAO,+BAA+B,YAC3C,MAAM,gBAAgB,YACtB;;;;MAQS,WAAW;;;;;;;;UAWd;;;;EASD,OAAO,cAAc;;;;EAerB,UAAU;;;;MASN;;;;MAOA;;;;MAOA;;;;MAOA;;;;MAoBA;;;;;;MAiBA;;;;MAeA;;;;MAOA;;;;;;;;;;;YAcD,iBAAiB;;;;;;YASjB,iBAAiB;;;;;;;;;;YAkBjB,cAAc,YAAY,qBAAqB,QAAQ;YAMvD;;;;;YAmBA;;;;YASA,UAAU;;;;YAkLV,WAAW;;;;EAsBd,SAAS,OAAO;;;;EAYhB,QAAQ,WAAW,iBAAiB;;;;EAOpC,GAAG,WAAW,cAAc,yCAAa;;;;EAOzC,IAAI,cAAc,QAAO;;;;;;;;;;;;;EA0BzB,iBAAiB;;;;MAkBb;;;;MAOA;;;;MAOA;;;;;;;;;EAYE,iBAAa,QAAA;;;;;;EAuCnB,cAAUA,eAAA;;;;;EAQV,UAAU,SAAS,mBAAmB,gBAAgB,4BAA4B;;;;EAalF,mBAAmB,mBAAmB;;;;EAOtC,iBAAiB,MAAM;;;;;;;;EAWjB,WAAO,gBAAA,sBAAA;;;;;;;YAoBJ,qBAAiB,gBAAA,sBAAA;;;;;;;YA4DvB,sBAAsB;;;;EAiCzB,MAAM,aAAa;;;;EAOnB,MAAM,cAAuB;;;;EAO7B,IAAI,aAAa;;;;EAOjB,IAAI;;;;EAOJ,IAAI,aAAa;;;;EASjB,WAAW,aAAa;;;;EAWxB,SAAS;;;;MASL;;;;EAOJ,QAAQ,aAAa;;;;MASjB;;;;EAmBJ,KAAK,cAAc;;;;;EAUnB,MAAM,eAAe;;;;MAOjB;;;;;;;;;;;EAcJ,SAAS,aAAa;;;;MAUlB;;;;EAOJ,SAAS,aAAa;;;;EAStB;;;;EAOA;;;;EAUA;;;;EAmBA;;;;EAmBA,KAAK;;;;EAOL,MAAM;;;;EAWN,OAAO;;;;EAOP,KAAK,aAAa;;;;EAqBlB,IAAI,aAAa;;;;MAWb;;;;EAOJ,OAAO,aAAa;;;;EASpB,MAAM,aAAa;;;;EASnB,OAAO,aAAa;;;;;;;;;;MAehB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCJ;;;;MAoCI;;;;MAOA;;;;MAOA;;;;MAOA;;;;MAOA,uBAAuB,YAAY;;;;EAOvC,UAAU,KAAK,YAAY"}
|
package/esm/http/request.mjs
CHANGED
|
@@ -438,12 +438,13 @@ var Request = class Request {
|
|
|
438
438
|
continue;
|
|
439
439
|
}
|
|
440
440
|
if (Array.isArray(value)) set(body, key, value.map(this.parseValue.bind(this)));
|
|
441
|
-
else if (isArrayKey)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
441
|
+
else if (isArrayKey) {
|
|
442
|
+
if (body[key]) body[key].push(this.parseValue(value));
|
|
443
|
+
else {
|
|
444
|
+
body[key] = [this.parseValue(value)];
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
} else set(body, key, this.parseValue(value));
|
|
447
448
|
}
|
|
448
449
|
for (const key in arrayOfObjectValues) body[key] = arrayOfObjectValues[key];
|
|
449
450
|
return body;
|
|
@@ -661,7 +662,7 @@ var Request = class Request {
|
|
|
661
662
|
const global = [...configured?.all || []];
|
|
662
663
|
if (matchesRoute(configured?.only)) global.push(...configured?.only?.middleware || []);
|
|
663
664
|
const excluded = matchesRoute(configured?.except) ? configured?.except?.middleware || [] : [];
|
|
664
|
-
return [
|
|
665
|
+
return [.../* @__PURE__ */ new Set([...global.filter((middleware) => !excluded.includes(middleware)), ...route.middleware || []])];
|
|
665
666
|
}
|
|
666
667
|
/**
|
|
667
668
|
* Get request input value from query string, params or body
|