@warlock.js/core 5.2.0 → 5.2.1
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 +9 -0
- package/esm/application/app.d.mts +1 -1
- package/esm/application/app.d.mts.map +1 -1
- package/esm/application/app.mjs +1 -1
- package/esm/application/app.mjs.map +1 -1
- package/esm/application/application-config-types.d.mts +1 -1
- package/esm/application/application-config-types.d.mts.map +1 -1
- package/esm/application/application.d.mts +1 -1
- package/esm/application/application.d.mts.map +1 -1
- package/esm/application/application.mjs +1 -1
- package/esm/application/application.mjs.map +1 -1
- package/esm/application/boot-signal.d.mts +1 -1
- package/esm/application/boot-signal.d.mts.map +1 -1
- package/esm/application/boot-signal.mjs +1 -1
- package/esm/application/boot-signal.mjs.map +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
- package/esm/benchmark/benchmark-snapshots.mjs +1 -1
- package/esm/benchmark/benchmark-snapshots.mjs.map +1 -1
- package/esm/benchmark/benchmark.d.mts +1 -1
- package/esm/benchmark/benchmark.d.mts.map +1 -1
- package/esm/benchmark/benchmark.mjs +1 -1
- package/esm/benchmark/benchmark.mjs.map +1 -1
- package/esm/benchmark/channels/console.channel.d.mts +1 -1
- package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/console.channel.mjs +1 -1
- package/esm/benchmark/channels/console.channel.mjs.map +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/noop.channel.mjs +1 -1
- package/esm/benchmark/channels/noop.channel.mjs.map +1 -1
- package/esm/benchmark/profiler.d.mts +1 -1
- package/esm/benchmark/profiler.d.mts.map +1 -1
- package/esm/benchmark/profiler.mjs +1 -1
- package/esm/benchmark/profiler.mjs.map +1 -1
- package/esm/benchmark/types.d.mts +1 -1
- package/esm/benchmark/types.d.mts.map +1 -1
- package/esm/bootstrap/setup.d.mts +1 -1
- package/esm/bootstrap/setup.d.mts.map +1 -1
- package/esm/bootstrap/setup.mjs +1 -1
- package/esm/bootstrap/setup.mjs.map +1 -1
- package/esm/bootstrap.d.mts +1 -1
- package/esm/bootstrap.d.mts.map +1 -1
- package/esm/bootstrap.mjs +1 -1
- package/esm/bootstrap.mjs.map +1 -1
- package/esm/cache/database-cache-driver.d.mts +1 -1
- package/esm/cache/database-cache-driver.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.mjs +1 -1
- package/esm/cache/database-cache-driver.mjs.map +1 -1
- package/esm/cache/index.mjs +1 -1
- package/esm/cache/index.mjs.map +1 -1
- package/esm/cli/cli-commands.manager.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/cli-commands.utils.mjs +1 -1
- package/esm/cli/cli-commands.utils.mjs.map +1 -1
- package/esm/cli/commands/add.command.mjs +1 -1
- package/esm/cli/commands/add.command.mjs.map +1 -1
- package/esm/cli/commands/build.command.mjs +1 -1
- package/esm/cli/commands/build.command.mjs.map +1 -1
- package/esm/cli/commands/create-database.command.mjs +1 -1
- package/esm/cli/commands/create-database.command.mjs.map +1 -1
- package/esm/cli/commands/dev-server.command.mjs +1 -1
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/cli/commands/doctor/boot-for-diagnostics.mjs +1 -1
- package/esm/cli/commands/doctor/boot-for-diagnostics.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/config.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/connectors.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/handler-signature.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/handler-signature.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/health.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/index.mjs +1 -1
- package/esm/cli/commands/doctor/checks/index.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/routes.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
- package/esm/cli/commands/doctor/format-report.mjs +1 -1
- package/esm/cli/commands/doctor/format-report.mjs.map +1 -1
- package/esm/cli/commands/doctor/run-checks.mjs +1 -1
- package/esm/cli/commands/doctor/run-checks.mjs.map +1 -1
- package/esm/cli/commands/doctor.command.mjs +1 -1
- package/esm/cli/commands/doctor.command.mjs.map +1 -1
- package/esm/cli/commands/drop-tables.command.mjs +1 -1
- package/esm/cli/commands/drop-tables.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generate.command.mjs +1 -1
- package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/templates/stubs.mjs +1 -1
- package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/prompt.mjs +1 -1
- package/esm/cli/commands/generate/utils/prompt.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/writer.mjs +1 -1
- package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
- package/esm/cli/commands/migrate.command.mjs +1 -1
- package/esm/cli/commands/migrate.command.mjs.map +1 -1
- package/esm/cli/commands/routes/diff-page-routes.mjs +1 -1
- package/esm/cli/commands/routes/diff-page-routes.mjs.map +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -1
- package/esm/cli/commands/routes/route-row.mjs +1 -1
- package/esm/cli/commands/routes/route-row.mjs.map +1 -1
- package/esm/cli/commands/routes/routes-command.action.mjs +1 -1
- package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -1
- package/esm/cli/commands/routes/routes-diff.action.mjs +1 -1
- package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
- package/esm/cli/commands/routes.command.mjs +1 -1
- package/esm/cli/commands/routes.command.mjs.map +1 -1
- package/esm/cli/commands/seed.command.mjs +1 -1
- package/esm/cli/commands/seed.command.mjs.map +1 -1
- package/esm/cli/commands/start-production.command.mjs +1 -1
- package/esm/cli/commands/start-production.command.mjs.map +1 -1
- package/esm/cli/commands/storage-put.action.mjs +1 -1
- package/esm/cli/commands/storage-put.action.mjs.map +1 -1
- package/esm/cli/commands/storage-put.command.mjs +1 -1
- package/esm/cli/commands/storage-put.command.mjs.map +1 -1
- package/esm/cli/commands/typings-generator.command.mjs +1 -1
- package/esm/cli/commands/typings-generator.command.mjs.map +1 -1
- package/esm/cli/commands/update.command.mjs +1 -1
- package/esm/cli/commands/update.command.mjs.map +1 -1
- package/esm/cli/commands-loader.mjs +1 -1
- package/esm/cli/commands-loader.mjs.map +1 -1
- package/esm/cli/framework-cli-commands.mjs +1 -1
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/cli/parse-cli-args.mjs +1 -1
- package/esm/cli/parse-cli-args.mjs.map +1 -1
- package/esm/cli/start.mjs +1 -1
- package/esm/cli/start.mjs.map +1 -1
- package/esm/cli/string-similarity.mjs +1 -1
- package/esm/cli/string-similarity.mjs.map +1 -1
- package/esm/commands/cli-command.d.mts +1 -1
- package/esm/commands/cli-command.d.mts.map +1 -1
- package/esm/commands/cli-command.mjs +1 -1
- package/esm/commands/cli-command.mjs.map +1 -1
- package/esm/commands/types.d.mts +1 -1
- package/esm/commands/types.d.mts.map +1 -1
- package/esm/config/config-getter.d.mts +1 -1
- package/esm/config/config-getter.d.mts.map +1 -1
- package/esm/config/config-getter.mjs +1 -1
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-handlers.d.mts +1 -1
- package/esm/config/config-handlers.d.mts.map +1 -1
- package/esm/config/config-handlers.mjs +1 -1
- package/esm/config/config-handlers.mjs.map +1 -1
- package/esm/config/config-loader.d.mts +1 -1
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +1 -1
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/config-manager.mjs +1 -1
- package/esm/config/config-manager.mjs.map +1 -1
- package/esm/config/config-setter.d.mts +1 -1
- package/esm/config/config-setter.d.mts.map +1 -1
- package/esm/config/config-setter.mjs +1 -1
- package/esm/config/config-setter.mjs.map +1 -1
- package/esm/config/config-special-handlers.d.mts +1 -1
- package/esm/config/config-special-handlers.d.mts.map +1 -1
- package/esm/config/config-special-handlers.mjs +1 -1
- package/esm/config/config-special-handlers.mjs.map +1 -1
- package/esm/config/load-config-files.mjs +1 -1
- package/esm/config/load-config-files.mjs.map +1 -1
- package/esm/config/locale-configuration.mjs +1 -1
- package/esm/config/locale-configuration.mjs.map +1 -1
- package/esm/config/types.d.mts +1 -1
- package/esm/config/types.d.mts.map +1 -1
- package/esm/connectors/access-connector.d.mts +1 -1
- package/esm/connectors/access-connector.d.mts.map +1 -1
- package/esm/connectors/access-connector.mjs +1 -1
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.d.mts +1 -1
- package/esm/connectors/ai-connector.d.mts.map +1 -1
- package/esm/connectors/ai-connector.mjs +1 -1
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.mjs +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.mjs.map +1 -1
- package/esm/connectors/assert-unique-connector-names.d.mts +1 -1
- package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-unique-connector-names.mjs +1 -1
- package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
- package/esm/connectors/base-connector.d.mts +1 -1
- package/esm/connectors/base-connector.d.mts.map +1 -1
- package/esm/connectors/base-connector.mjs +1 -1
- package/esm/connectors/base-connector.mjs.map +1 -1
- package/esm/connectors/cache-connector.d.mts +1 -1
- package/esm/connectors/cache-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.mjs +1 -1
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/connectors-manager.d.mts +1 -1
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +1 -1
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/database-connector.d.mts +1 -1
- package/esm/connectors/database-connector.d.mts.map +1 -1
- package/esm/connectors/database-connector.mjs +1 -1
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/describe-server-address.mjs +1 -1
- package/esm/connectors/describe-server-address.mjs.map +1 -1
- package/esm/connectors/herald-connector.d.mts +1 -1
- package/esm/connectors/herald-connector.d.mts.map +1 -1
- package/esm/connectors/herald-connector.mjs +1 -1
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts +1 -1
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +1 -1
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/logger-connector.d.mts +1 -1
- package/esm/connectors/logger-connector.d.mts.map +1 -1
- package/esm/connectors/logger-connector.mjs +1 -1
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.d.mts +1 -1
- package/esm/connectors/mail-connector.d.mts.map +1 -1
- package/esm/connectors/mail-connector.mjs +1 -1
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.d.mts +1 -1
- package/esm/connectors/notifications-connector.d.mts.map +1 -1
- package/esm/connectors/notifications-connector.mjs +1 -1
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/register-configured-connectors.d.mts +1 -1
- package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
- package/esm/connectors/register-configured-connectors.mjs +1 -1
- package/esm/connectors/register-configured-connectors.mjs.map +1 -1
- package/esm/connectors/socket-connector.d.mts +1 -1
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +1 -1
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/connectors/storage.connector.d.mts +1 -1
- package/esm/connectors/storage.connector.d.mts.map +1 -1
- package/esm/connectors/storage.connector.mjs +1 -1
- package/esm/connectors/storage.connector.mjs.map +1 -1
- package/esm/connectors/types.d.mts +1 -1
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/connectors/types.mjs +1 -1
- package/esm/connectors/types.mjs.map +1 -1
- package/esm/container/index.d.mts +1 -1
- package/esm/container/index.d.mts.map +1 -1
- package/esm/container/index.mjs +1 -1
- package/esm/container/index.mjs.map +1 -1
- package/esm/database/create-database-action.mjs +1 -1
- package/esm/database/create-database-action.mjs.map +1 -1
- package/esm/database/drop-tables-action.mjs +1 -1
- package/esm/database/drop-tables-action.mjs.map +1 -1
- package/esm/database/migrate-action.mjs +1 -1
- package/esm/database/migrate-action.mjs.map +1 -1
- package/esm/database/models/database-log/database-log.d.mts +1 -1
- package/esm/database/models/database-log/database-log.d.mts.map +1 -1
- package/esm/database/models/database-log/database-log.mjs +1 -1
- package/esm/database/models/database-log/database-log.mjs.map +1 -1
- package/esm/database/pending-exit-code.mjs +1 -1
- package/esm/database/pending-exit-code.mjs.map +1 -1
- package/esm/database/resolve-pending-migrations.mjs +1 -1
- package/esm/database/resolve-pending-migrations.mjs.map +1 -1
- package/esm/database/seed-command-action.mjs +1 -1
- package/esm/database/seed-command-action.mjs.map +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -1
- package/esm/database/seeds/seeder.d.mts +1 -1
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +1 -1
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.mjs +1 -1
- package/esm/database/seeds/seeder.errors.mjs.map +1 -1
- package/esm/database/seeds/seeder.mjs +1 -1
- package/esm/database/seeds/seeder.mjs.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +1 -1
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/seeds-table-migration.mjs +1 -1
- package/esm/database/seeds/seeds-table-migration.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +1 -1
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/seeds/utils.mjs +1 -1
- package/esm/database/seeds/utils.mjs.map +1 -1
- package/esm/database/utils.d.mts +1 -1
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/database/utils.mjs +1 -1
- package/esm/database/utils.mjs.map +1 -1
- package/esm/dev-server/check-for-updates.mjs +1 -1
- package/esm/dev-server/check-for-updates.mjs.map +1 -1
- package/esm/dev-server/create-worker.mjs +1 -1
- package/esm/dev-server/create-worker.mjs.map +1 -1
- package/esm/dev-server/dependency-graph.d.mts +1 -1
- 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/dev-logger.mjs +1 -1
- package/esm/dev-server/dev-logger.mjs.map +1 -1
- package/esm/dev-server/development-server.mjs +1 -1
- package/esm/dev-server/development-server.mjs.map +1 -1
- package/esm/dev-server/events.mjs +1 -1
- package/esm/dev-server/events.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs +1 -1
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +1 -1
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-manager.mjs +1 -1
- package/esm/dev-server/file-manager.mjs.map +1 -1
- package/esm/dev-server/file-operations.d.mts +1 -1
- package/esm/dev-server/file-operations.d.mts.map +1 -1
- package/esm/dev-server/file-operations.mjs +1 -1
- package/esm/dev-server/file-operations.mjs.map +1 -1
- package/esm/dev-server/files-orchestrator.mjs +1 -1
- package/esm/dev-server/files-orchestrator.mjs.map +1 -1
- package/esm/dev-server/files-watcher.mjs +1 -1
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/flags.mjs +1 -1
- package/esm/dev-server/flags.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +1 -1
- 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 +1 -1
- 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 +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs.map +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
- package/esm/dev-server/layer-executor.mjs +1 -1
- package/esm/dev-server/layer-executor.mjs.map +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs.map +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
- package/esm/dev-server/loader/hook-thread.mjs +1 -1
- package/esm/dev-server/loader/hook-thread.mjs.map +1 -1
- package/esm/dev-server/loader/load-hook.d.mts +1 -1
- package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.mjs +1 -1
- 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/own-resolver.mjs.map +1 -1
- package/esm/dev-server/loader/register-loader.mjs +1 -1
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-capture.mjs +1 -1
- package/esm/dev-server/loader/resolve-capture.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
- package/esm/dev-server/loader/source-slug.mjs +1 -1
- package/esm/dev-server/loader/source-slug.mjs.map +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
- package/esm/dev-server/loader/version-registry.mjs +1 -1
- package/esm/dev-server/loader/version-registry.mjs.map +1 -1
- package/esm/dev-server/manifest-manager.d.mts +1 -1
- package/esm/dev-server/manifest-manager.d.mts.map +1 -1
- package/esm/dev-server/manifest-manager.mjs +1 -1
- package/esm/dev-server/manifest-manager.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs +1 -1
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/package-json-manager.mjs +1 -1
- package/esm/dev-server/package-json-manager.mjs.map +1 -1
- package/esm/dev-server/parse-imports.mjs +1 -1
- package/esm/dev-server/parse-imports.mjs.map +1 -1
- package/esm/dev-server/read-config-ast.mjs +1 -1
- package/esm/dev-server/read-config-ast.mjs.map +1 -1
- package/esm/dev-server/ready-block.mjs +1 -1
- package/esm/dev-server/ready-block.mjs.map +1 -1
- package/esm/dev-server/register-dev-shortcuts.mjs +1 -1
- package/esm/dev-server/register-dev-shortcuts.mjs.map +1 -1
- package/esm/dev-server/restart-dev-server.mjs +1 -1
- package/esm/dev-server/restart-dev-server.mjs.map +1 -1
- package/esm/dev-server/run-typings-generation.mjs +1 -1
- package/esm/dev-server/run-typings-generation.mjs.map +1 -1
- package/esm/dev-server/shortcuts.mjs +1 -1
- package/esm/dev-server/shortcuts.mjs.map +1 -1
- package/esm/dev-server/special-files-collector.d.mts +1 -1
- package/esm/dev-server/special-files-collector.d.mts.map +1 -1
- package/esm/dev-server/special-files-collector.mjs +1 -1
- package/esm/dev-server/special-files-collector.mjs.map +1 -1
- package/esm/dev-server/start-development-server.mjs +1 -1
- package/esm/dev-server/start-development-server.mjs.map +1 -1
- package/esm/dev-server/supervisor.mjs +1 -1
- package/esm/dev-server/supervisor.mjs.map +1 -1
- package/esm/dev-server/tsconfig-manager.mjs +1 -1
- package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs +1 -1
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/dev-server/types.d.mts +1 -1
- package/esm/dev-server/types.d.mts.map +1 -1
- package/esm/dev-server/update-check-cache.mjs +1 -1
- package/esm/dev-server/update-check-cache.mjs.map +1 -1
- package/esm/dev-server/utils.mjs +1 -1
- package/esm/dev-server/utils.mjs.map +1 -1
- package/esm/encryption/encrypt.d.mts +1 -1
- package/esm/encryption/encrypt.d.mts.map +1 -1
- package/esm/encryption/encrypt.mjs +1 -1
- package/esm/encryption/encrypt.mjs.map +1 -1
- package/esm/encryption/hash.d.mts +1 -1
- package/esm/encryption/hash.d.mts.map +1 -1
- package/esm/encryption/hash.mjs +1 -1
- package/esm/encryption/hash.mjs.map +1 -1
- package/esm/encryption/password.d.mts +1 -1
- package/esm/encryption/password.d.mts.map +1 -1
- package/esm/encryption/password.mjs +1 -1
- package/esm/encryption/password.mjs.map +1 -1
- package/esm/encryption/types.d.mts +1 -1
- package/esm/encryption/types.d.mts.map +1 -1
- package/esm/generations/add-command.action.mjs +1 -1
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/features/access.feature.mjs +1 -1
- package/esm/generations/features/access.feature.mjs.map +1 -1
- package/esm/generations/features/ai-anthropic.feature.mjs +1 -1
- package/esm/generations/features/ai-anthropic.feature.mjs.map +1 -1
- package/esm/generations/features/ai-bedrock.feature.mjs +1 -1
- package/esm/generations/features/ai-bedrock.feature.mjs.map +1 -1
- package/esm/generations/features/ai-google.feature.mjs +1 -1
- package/esm/generations/features/ai-google.feature.mjs.map +1 -1
- package/esm/generations/features/ai-ollama.feature.mjs +1 -1
- package/esm/generations/features/ai-ollama.feature.mjs.map +1 -1
- package/esm/generations/features/ai-openai.feature.mjs +1 -1
- package/esm/generations/features/ai-openai.feature.mjs.map +1 -1
- package/esm/generations/features/ai-panoptic.feature.mjs +1 -1
- package/esm/generations/features/ai-panoptic.feature.mjs.map +1 -1
- package/esm/generations/features/ai-tools.feature.mjs +1 -1
- package/esm/generations/features/ai-tools.feature.mjs.map +1 -1
- package/esm/generations/features/ai-workspace.feature.mjs +1 -1
- package/esm/generations/features/ai-workspace.feature.mjs.map +1 -1
- package/esm/generations/features/ai.feature.mjs +1 -1
- package/esm/generations/features/ai.feature.mjs.map +1 -1
- package/esm/generations/features/herald.feature.mjs +1 -1
- package/esm/generations/features/herald.feature.mjs.map +1 -1
- package/esm/generations/features/image.feature.mjs +1 -1
- package/esm/generations/features/image.feature.mjs.map +1 -1
- package/esm/generations/features/index.mjs +1 -1
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/mail.feature.mjs +1 -1
- package/esm/generations/features/mail.feature.mjs.map +1 -1
- package/esm/generations/features/mongodb.feature.mjs +1 -1
- package/esm/generations/features/mongodb.feature.mjs.map +1 -1
- package/esm/generations/features/mysql.feature.mjs +1 -1
- package/esm/generations/features/mysql.feature.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs +1 -1
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/postgres.feature.mjs +1 -1
- package/esm/generations/features/postgres.feature.mjs.map +1 -1
- package/esm/generations/features/react-email.feature.mjs +1 -1
- package/esm/generations/features/react-email.feature.mjs.map +1 -1
- package/esm/generations/features/react.feature.mjs +1 -1
- package/esm/generations/features/react.feature.mjs.map +1 -1
- package/esm/generations/features/redis.feature.mjs +1 -1
- package/esm/generations/features/redis.feature.mjs.map +1 -1
- package/esm/generations/features/s3.feature.mjs +1 -1
- package/esm/generations/features/s3.feature.mjs.map +1 -1
- package/esm/generations/features/scheduler.feature.mjs +1 -1
- package/esm/generations/features/scheduler.feature.mjs.map +1 -1
- package/esm/generations/features/ses.feature.mjs +1 -1
- package/esm/generations/features/ses.feature.mjs.map +1 -1
- package/esm/generations/features/shadcn.feature.mjs +1 -1
- package/esm/generations/features/shadcn.feature.mjs.map +1 -1
- package/esm/generations/features/shared/link-ai-package-import.mjs +1 -1
- package/esm/generations/features/shared/link-ai-package-import.mjs.map +1 -1
- package/esm/generations/features/shared/migration-timestamp.mjs +1 -1
- package/esm/generations/features/shared/migration-timestamp.mjs.map +1 -1
- package/esm/generations/features/socket.feature.mjs +1 -1
- package/esm/generations/features/socket.feature.mjs.map +1 -1
- package/esm/generations/features/tailwind.feature.mjs +1 -1
- package/esm/generations/features/tailwind.feature.mjs.map +1 -1
- package/esm/generations/features/test.feature.mjs +1 -1
- package/esm/generations/features/test.feature.mjs.map +1 -1
- package/esm/generations/features/types.mjs +1 -1
- package/esm/generations/features/types.mjs.map +1 -1
- package/esm/generations/features/web.feature.mjs +1 -1
- package/esm/generations/features/web.feature.mjs.map +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 +1 -1
- package/esm/http/boot-port-preflight.d.mts.map +1 -1
- package/esm/http/boot-port-preflight.mjs +1 -1
- package/esm/http/boot-port-preflight.mjs.map +1 -1
- package/esm/http/build-cors-options.mjs +1 -1
- package/esm/http/build-cors-options.mjs.map +1 -1
- package/esm/http/config.d.mts +1 -1
- package/esm/http/config.d.mts.map +1 -1
- package/esm/http/config.mjs +1 -1
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/context/request-context.d.mts +1 -1
- package/esm/http/context/request-context.d.mts.map +1 -1
- package/esm/http/context/request-context.mjs +1 -1
- package/esm/http/context/request-context.mjs.map +1 -1
- package/esm/http/context/request-memo.d.mts +1 -1
- package/esm/http/context/request-memo.d.mts.map +1 -1
- package/esm/http/context/request-memo.mjs +1 -1
- package/esm/http/context/request-memo.mjs.map +1 -1
- package/esm/http/createHttpApplication.d.mts +1 -1
- package/esm/http/createHttpApplication.d.mts.map +1 -1
- package/esm/http/createHttpApplication.mjs +1 -1
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/database/RequestLog.d.mts +1 -1
- package/esm/http/database/RequestLog.d.mts.map +1 -1
- package/esm/http/database/RequestLog.mjs +1 -1
- package/esm/http/database/RequestLog.mjs.map +1 -1
- package/esm/http/error-codes.d.mts +1 -1
- package/esm/http/error-codes.d.mts.map +1 -1
- package/esm/http/error-codes.mjs +1 -1
- package/esm/http/error-codes.mjs.map +1 -1
- package/esm/http/errors/errors.d.mts +1 -1
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/errors/errors.mjs +1 -1
- package/esm/http/errors/errors.mjs.map +1 -1
- package/esm/http/events.d.mts +1 -1
- package/esm/http/events.d.mts.map +1 -1
- package/esm/http/events.mjs +1 -1
- package/esm/http/events.mjs.map +1 -1
- package/esm/http/health.d.mts +1 -1
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/health.mjs +1 -1
- package/esm/http/health.mjs.map +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/inject-request-context.d.mts +1 -1
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +1 -1
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
- package/esm/http/middleware/middleware-list.d.mts +1 -1
- package/esm/http/middleware/middleware-list.d.mts.map +1 -1
- package/esm/http/middleware/middleware-list.mjs +1 -1
- package/esm/http/middleware/middleware-list.mjs.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
- package/esm/http/middleware/utils/cidr-match.mjs +1 -1
- package/esm/http/middleware/utils/cidr-match.mjs.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs.map +1 -1
- package/esm/http/middleware/utils/parse-size.d.mts +1 -1
- package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
- package/esm/http/middleware/utils/parse-size.mjs +1 -1
- package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
- package/esm/http/plugins.d.mts +1 -1
- package/esm/http/plugins.d.mts.map +1 -1
- package/esm/http/plugins.mjs +1 -1
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/port-preflight.d.mts +1 -1
- package/esm/http/port-preflight.d.mts.map +1 -1
- package/esm/http/port-preflight.mjs +1 -1
- package/esm/http/port-preflight.mjs.map +1 -1
- package/esm/http/ready-report.d.mts +1 -1
- package/esm/http/ready-report.d.mts.map +1 -1
- package/esm/http/ready-report.mjs +1 -1
- package/esm/http/ready-report.mjs.map +1 -1
- package/esm/http/request-controller.d.mts +1 -1
- package/esm/http/request-controller.d.mts.map +1 -1
- package/esm/http/request-controller.mjs +1 -1
- package/esm/http/request-controller.mjs.map +1 -1
- package/esm/http/request.d.mts +1 -1
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +1 -1
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/response.d.mts +1 -1
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +1 -1
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.d.mts +1 -1
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +1 -1
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/types.d.mts +1 -1
- package/esm/http/types.d.mts.map +1 -1
- package/esm/http/uploaded-file.d.mts +1 -1
- package/esm/http/uploaded-file.d.mts.map +1 -1
- package/esm/http/uploaded-file.mjs +1 -1
- package/esm/http/uploaded-file.mjs.map +1 -1
- package/esm/http/uploads-config.d.mts +1 -1
- package/esm/http/uploads-config.d.mts.map +1 -1
- package/esm/http/uploads-config.mjs +1 -1
- package/esm/http/uploads-config.mjs.map +1 -1
- package/esm/http/uploads-types.d.mts +1 -1
- package/esm/http/uploads-types.d.mts.map +1 -1
- package/esm/image/image.d.mts +1 -1
- package/esm/image/image.d.mts.map +1 -1
- package/esm/image/image.mjs +1 -1
- package/esm/image/image.mjs.map +1 -1
- package/esm/logger/fatal-visibility.d.mts +1 -1
- package/esm/logger/fatal-visibility.d.mts.map +1 -1
- package/esm/logger/fatal-visibility.mjs +1 -1
- package/esm/logger/fatal-visibility.mjs.map +1 -1
- package/esm/logger/logger.d.mts +1 -1
- package/esm/logger/logger.d.mts.map +1 -1
- package/esm/logger/logger.mjs +1 -1
- package/esm/logger/logger.mjs.map +1 -1
- package/esm/logger/types.d.mts +1 -1
- package/esm/logger/types.d.mts.map +1 -1
- package/esm/mail/config.d.mts +1 -1
- package/esm/mail/config.d.mts.map +1 -1
- package/esm/mail/config.mjs +1 -1
- package/esm/mail/config.mjs.map +1 -1
- package/esm/mail/events.d.mts +1 -1
- package/esm/mail/events.d.mts.map +1 -1
- package/esm/mail/events.mjs +1 -1
- package/esm/mail/events.mjs.map +1 -1
- package/esm/mail/mail.d.mts +1 -1
- package/esm/mail/mail.d.mts.map +1 -1
- package/esm/mail/mail.mjs +1 -1
- package/esm/mail/mail.mjs.map +1 -1
- package/esm/mail/mailer-pool.d.mts +1 -1
- package/esm/mail/mailer-pool.d.mts.map +1 -1
- package/esm/mail/mailer-pool.mjs +1 -1
- package/esm/mail/mailer-pool.mjs.map +1 -1
- package/esm/mail/react-mail.d.mts +1 -1
- package/esm/mail/react-mail.d.mts.map +1 -1
- package/esm/mail/react-mail.mjs +1 -1
- package/esm/mail/react-mail.mjs.map +1 -1
- package/esm/mail/send-mail.d.mts +1 -1
- package/esm/mail/send-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.mjs +1 -1
- package/esm/mail/send-mail.mjs.map +1 -1
- package/esm/mail/test-mailbox.d.mts +1 -1
- package/esm/mail/test-mailbox.d.mts.map +1 -1
- package/esm/mail/test-mailbox.mjs +1 -1
- package/esm/mail/test-mailbox.mjs.map +1 -1
- package/esm/mail/types.d.mts +1 -1
- package/esm/mail/types.d.mts.map +1 -1
- package/esm/mail/types.mjs +1 -1
- package/esm/mail/types.mjs.map +1 -1
- package/esm/manifest/manifest-manager.mjs +1 -1
- package/esm/manifest/manifest-manager.mjs.map +1 -1
- package/esm/production/assert-dist-ready-to-start.mjs +1 -1
- package/esm/production/assert-dist-ready-to-start.mjs.map +1 -1
- package/esm/production/assert-generated-imports.mjs +1 -1
- package/esm/production/assert-generated-imports.mjs.map +1 -1
- package/esm/production/build-app-production.mjs +1 -1
- package/esm/production/build-app-production.mjs.map +1 -1
- package/esm/production/build-contributions.mjs +1 -1
- package/esm/production/build-contributions.mjs.map +1 -1
- package/esm/production/dist-build-manifest.mjs +1 -1
- package/esm/production/dist-build-manifest.mjs.map +1 -1
- package/esm/production/esbuild-plugins.mjs +1 -1
- package/esm/production/esbuild-plugins.mjs.map +1 -1
- package/esm/production/production-builder.mjs +1 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/production-supervisor.mjs +1 -1
- package/esm/production/production-supervisor.mjs.map +1 -1
- package/esm/production/promote-dist.mjs +1 -1
- package/esm/production/promote-dist.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +1 -1
- package/esm/production/resolve-build-config.d.mts.map +1 -1
- package/esm/production/resolve-build-config.mjs +1 -1
- package/esm/production/resolve-build-config.mjs.map +1 -1
- package/esm/react/index.d.mts +1 -1
- package/esm/react/index.d.mts.map +1 -1
- package/esm/react/index.mjs +1 -1
- package/esm/react/index.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.mjs +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/types.d.mts +1 -1
- package/esm/repositories/contracts/types.d.mts.map +1 -1
- package/esm/repositories/repository.manager.d.mts +1 -1
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +1 -1
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/resource/define-resource.d.mts +1 -1
- package/esm/resource/define-resource.d.mts.map +1 -1
- package/esm/resource/define-resource.mjs +1 -1
- package/esm/resource/define-resource.mjs.map +1 -1
- package/esm/resource/register-resource.d.mts +1 -1
- package/esm/resource/register-resource.d.mts.map +1 -1
- package/esm/resource/register-resource.mjs +1 -1
- package/esm/resource/register-resource.mjs.map +1 -1
- package/esm/resource/resource-field-builder.d.mts +1 -1
- package/esm/resource/resource-field-builder.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.mjs +1 -1
- package/esm/resource/resource-field-builder.mjs.map +1 -1
- package/esm/resource/resource.d.mts +1 -1
- package/esm/resource/resource.d.mts.map +1 -1
- package/esm/resource/resource.mjs +1 -1
- package/esm/resource/resource.mjs.map +1 -1
- package/esm/resource/types.d.mts +1 -1
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/restful/restful.d.mts +1 -1
- package/esm/restful/restful.d.mts.map +1 -1
- package/esm/restful/restful.mjs +1 -1
- package/esm/restful/restful.mjs.map +1 -1
- package/esm/router/describe-route-for-log.mjs +1 -1
- package/esm/router/describe-route-for-log.mjs.map +1 -1
- package/esm/router/log-request-lifecycle.mjs +1 -1
- package/esm/router/log-request-lifecycle.mjs.map +1 -1
- package/esm/router/normalize-request-path.d.mts +1 -1
- package/esm/router/normalize-request-path.d.mts.map +1 -1
- package/esm/router/normalize-request-path.mjs +1 -1
- package/esm/router/normalize-request-path.mjs.map +1 -1
- package/esm/router/normalize-route-path.d.mts +1 -1
- package/esm/router/normalize-route-path.d.mts.map +1 -1
- package/esm/router/normalize-route-path.mjs +1 -1
- package/esm/router/normalize-route-path.mjs.map +1 -1
- package/esm/router/positional-handler-diagnostics.d.mts +1 -1
- package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
- package/esm/router/positional-handler-diagnostics.mjs +1 -1
- package/esm/router/positional-handler-diagnostics.mjs.map +1 -1
- package/esm/router/route-builder.d.mts +1 -1
- package/esm/router/route-builder.d.mts.map +1 -1
- package/esm/router/route-builder.mjs +1 -1
- package/esm/router/route-builder.mjs.map +1 -1
- package/esm/router/route-name-method-suffix.d.mts +1 -1
- package/esm/router/route-name-method-suffix.d.mts.map +1 -1
- package/esm/router/route-name-method-suffix.mjs +1 -1
- package/esm/router/route-name-method-suffix.mjs.map +1 -1
- package/esm/router/route-registry.d.mts +1 -1
- package/esm/router/route-registry.d.mts.map +1 -1
- package/esm/router/route-registry.mjs +1 -1
- package/esm/router/route-registry.mjs.map +1 -1
- package/esm/router/router.d.mts +1 -1
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +1 -1
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts +1 -1
- package/esm/router/types.d.mts.map +1 -1
- package/esm/socket/types.d.mts +1 -1
- package/esm/socket/types.d.mts.map +1 -1
- package/esm/socket/utils.d.mts +1 -1
- package/esm/socket/utils.d.mts.map +1 -1
- package/esm/socket/utils.mjs +1 -1
- package/esm/socket/utils.mjs.map +1 -1
- package/esm/storage/config.d.mts +1 -1
- package/esm/storage/config.d.mts.map +1 -1
- package/esm/storage/config.mjs +1 -1
- package/esm/storage/config.mjs.map +1 -1
- package/esm/storage/context/storage-driver-context.d.mts +1 -1
- package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
- package/esm/storage/context/storage-driver-context.mjs +1 -1
- package/esm/storage/context/storage-driver-context.mjs.map +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.mjs +1 -1
- package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.mjs +1 -1
- package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
- package/esm/storage/drivers/local-driver.d.mts +1 -1
- package/esm/storage/drivers/local-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.mjs +1 -1
- package/esm/storage/drivers/local-driver.mjs.map +1 -1
- package/esm/storage/drivers/r2-driver.d.mts +1 -1
- package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
- package/esm/storage/drivers/r2-driver.mjs +1 -1
- package/esm/storage/drivers/r2-driver.mjs.map +1 -1
- package/esm/storage/drivers/s3-driver.d.mts +1 -1
- package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
- package/esm/storage/drivers/s3-driver.mjs +1 -1
- package/esm/storage/drivers/s3-driver.mjs.map +1 -1
- package/esm/storage/scoped-storage.d.mts +1 -1
- package/esm/storage/scoped-storage.d.mts.map +1 -1
- package/esm/storage/scoped-storage.mjs +1 -1
- package/esm/storage/scoped-storage.mjs.map +1 -1
- package/esm/storage/storage-file.d.mts +1 -1
- package/esm/storage/storage-file.d.mts.map +1 -1
- package/esm/storage/storage-file.mjs +1 -1
- package/esm/storage/storage-file.mjs.map +1 -1
- package/esm/storage/storage.d.mts +1 -1
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/storage.mjs +1 -1
- package/esm/storage/storage.mjs.map +1 -1
- package/esm/storage/types.d.mts +1 -1
- package/esm/storage/types.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.d.mts +1 -1
- package/esm/storage/utils/contain-path.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.mjs +1 -1
- package/esm/storage/utils/contain-path.mjs.map +1 -1
- package/esm/storage/utils/mime.d.mts +1 -1
- package/esm/storage/utils/mime.d.mts.map +1 -1
- package/esm/storage/utils/mime.mjs +1 -1
- package/esm/storage/utils/mime.mjs.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts +1 -1
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs +1 -1
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/storage/utils/storage-error.d.mts +1 -1
- package/esm/storage/utils/storage-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-error.mjs +1 -1
- package/esm/storage/utils/storage-error.mjs.map +1 -1
- package/esm/tests/start-http-development-server.d.mts +1 -1
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +1 -1
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-connectors-selection.d.mts +1 -1
- package/esm/tests/test-connectors-selection.d.mts.map +1 -1
- package/esm/tests/test-connectors-selection.mjs +1 -1
- package/esm/tests/test-connectors-selection.mjs.map +1 -1
- package/esm/tests/test-helpers.d.mts +1 -1
- package/esm/tests/test-helpers.d.mts.map +1 -1
- package/esm/tests/test-helpers.mjs +1 -1
- package/esm/tests/test-helpers.mjs.map +1 -1
- package/esm/tests/test-lifecycle-state.mjs +1 -1
- package/esm/tests/test-lifecycle-state.mjs.map +1 -1
- package/esm/tests/test-server-port-channel.mjs +1 -1
- package/esm/tests/test-server-port-channel.mjs.map +1 -1
- package/esm/tests/test-setup-timeout.mjs +1 -1
- package/esm/tests/test-setup-timeout.mjs.map +1 -1
- package/esm/tests/vitest-setup.d.mts +1 -1
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs +1 -1
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/updater/package-manager.mjs +1 -1
- package/esm/updater/package-manager.mjs.map +1 -1
- package/esm/updater/update-warlock-packages.mjs +1 -1
- package/esm/updater/update-warlock-packages.mjs.map +1 -1
- package/esm/use-cases/types.d.mts +1 -1
- package/esm/use-cases/types.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.mjs +1 -1
- package/esm/use-cases/use-case-broadcast.mjs.map +1 -1
- package/esm/use-cases/use-case-events.d.mts +1 -1
- package/esm/use-cases/use-case-events.d.mts.map +1 -1
- package/esm/use-cases/use-case-events.mjs +1 -1
- package/esm/use-cases/use-case-events.mjs.map +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
- package/esm/use-cases/use-case-pipeline.mjs +1 -1
- package/esm/use-cases/use-case-pipeline.mjs.map +1 -1
- package/esm/use-cases/use-case.d.mts +1 -1
- package/esm/use-cases/use-case.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.d.mts +1 -1
- package/esm/use-cases/use-case.errors.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.mjs +1 -1
- package/esm/use-cases/use-case.errors.mjs.map +1 -1
- package/esm/use-cases/use-case.mjs +1 -1
- package/esm/use-cases/use-case.mjs.map +1 -1
- package/esm/use-cases/use-cases-registry.d.mts +1 -1
- package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
- package/esm/use-cases/use-cases-registry.mjs +1 -1
- package/esm/use-cases/use-cases-registry.mjs.map +1 -1
- package/esm/utils/app-log.d.mts +1 -1
- package/esm/utils/app-log.d.mts.map +1 -1
- package/esm/utils/app-log.mjs +1 -1
- package/esm/utils/app-log.mjs.map +1 -1
- package/esm/utils/database-log.d.mts +1 -1
- package/esm/utils/database-log.d.mts.map +1 -1
- package/esm/utils/database-log.mjs +1 -1
- package/esm/utils/database-log.mjs.map +1 -1
- package/esm/utils/environment.d.mts +1 -1
- package/esm/utils/environment.d.mts.map +1 -1
- package/esm/utils/environment.mjs +1 -1
- package/esm/utils/environment.mjs.map +1 -1
- package/esm/utils/framework-vesion.mjs +1 -1
- package/esm/utils/framework-vesion.mjs.map +1 -1
- package/esm/utils/get-localized.d.mts +1 -1
- package/esm/utils/get-localized.d.mts.map +1 -1
- package/esm/utils/get-localized.mjs +1 -1
- package/esm/utils/get-localized.mjs.map +1 -1
- package/esm/utils/load-environment.mjs +1 -1
- package/esm/utils/load-environment.mjs.map +1 -1
- package/esm/utils/normalized-path.d.mts +1 -1
- package/esm/utils/normalized-path.d.mts.map +1 -1
- package/esm/utils/normalized-path.mjs +1 -1
- package/esm/utils/normalized-path.mjs.map +1 -1
- package/esm/utils/npm-registry.d.mts +1 -1
- package/esm/utils/npm-registry.d.mts.map +1 -1
- package/esm/utils/npm-registry.mjs +1 -1
- package/esm/utils/npm-registry.mjs.map +1 -1
- package/esm/utils/paths.d.mts +1 -1
- package/esm/utils/paths.d.mts.map +1 -1
- package/esm/utils/paths.mjs +1 -1
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/utils/promise-all-object.d.mts +1 -1
- package/esm/utils/promise-all-object.d.mts.map +1 -1
- package/esm/utils/promise-all-object.mjs +1 -1
- package/esm/utils/promise-all-object.mjs.map +1 -1
- package/esm/utils/queue.d.mts +1 -1
- package/esm/utils/queue.d.mts.map +1 -1
- package/esm/utils/queue.mjs +1 -1
- package/esm/utils/queue.mjs.map +1 -1
- package/esm/utils/sleep.d.mts +1 -1
- package/esm/utils/sleep.d.mts.map +1 -1
- package/esm/utils/sleep.mjs +1 -1
- package/esm/utils/sleep.mjs.map +1 -1
- package/esm/utils/sluggable.d.mts +1 -1
- package/esm/utils/sluggable.d.mts.map +1 -1
- package/esm/utils/sluggable.mjs +1 -1
- package/esm/utils/sluggable.mjs.map +1 -1
- package/esm/utils/to-json.d.mts +1 -1
- package/esm/utils/to-json.d.mts.map +1 -1
- package/esm/utils/to-json.mjs +1 -1
- package/esm/utils/to-json.mjs.map +1 -1
- package/esm/utils/types.d.mts +1 -1
- package/esm/utils/types.d.mts.map +1 -1
- package/esm/utils/urls.d.mts +1 -1
- package/esm/utils/urls.d.mts.map +1 -1
- package/esm/utils/urls.mjs +1 -1
- package/esm/utils/urls.mjs.map +1 -1
- package/esm/utils/version-compare.d.mts +1 -1
- package/esm/utils/version-compare.d.mts.map +1 -1
- package/esm/utils/version-compare.mjs +1 -1
- package/esm/utils/version-compare.mjs.map +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-id.mjs +1 -1
- package/esm/validation/database/exists-except-current-id.mjs.map +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-user.mjs +1 -1
- package/esm/validation/database/exists-except-current-user.mjs.map +1 -1
- package/esm/validation/database/types.d.mts +1 -1
- package/esm/validation/database/types.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.mjs +1 -1
- package/esm/validation/database/unique-except-current-id.mjs.map +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-user.mjs +1 -1
- package/esm/validation/database/unique-except-current-user.mjs.map +1 -1
- package/esm/validation/file/file.d.mts +1 -1
- package/esm/validation/file/file.d.mts.map +1 -1
- package/esm/validation/file/file.mjs +1 -1
- package/esm/validation/file/file.mjs.map +1 -1
- package/esm/validation/init.mjs +1 -1
- package/esm/validation/init.mjs.map +1 -1
- package/esm/validation/plugins/database-plugin.mjs +1 -1
- package/esm/validation/plugins/database-plugin.mjs.map +1 -1
- package/esm/validation/plugins/file-plugin.mjs +1 -1
- package/esm/validation/plugins/file-plugin.mjs.map +1 -1
- package/esm/validation/plugins/localized-plugin.mjs +1 -1
- package/esm/validation/plugins/localized-plugin.mjs.map +1 -1
- package/esm/validation/types.d.mts +1 -1
- package/esm/validation/types.d.mts.map +1 -1
- package/esm/validation/validateAll.mjs +1 -1
- package/esm/validation/validateAll.mjs.map +1 -1
- package/esm/validation/validators/file-validator.d.mts +1 -1
- package/esm/validation/validators/file-validator.d.mts.map +1 -1
- package/esm/validation/validators/file-validator.mjs +1 -1
- package/esm/validation/validators/file-validator.mjs.map +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
- package/esm/vite/lower-stage3-decorators.mjs +1 -1
- package/esm/vite/lower-stage3-decorators.mjs.map +1 -1
- package/esm/warlock-config/default-configurations.mjs +1 -1
- package/esm/warlock-config/default-configurations.mjs.map +1 -1
- package/esm/warlock-config/define-config.d.mts +1 -1
- package/esm/warlock-config/define-config.d.mts.map +1 -1
- package/esm/warlock-config/define-config.mjs +1 -1
- package/esm/warlock-config/define-config.mjs.map +1 -1
- package/esm/warlock-config/normalize-build-config.mjs +1 -1
- package/esm/warlock-config/normalize-build-config.mjs.map +1 -1
- package/esm/warlock-config/types.d.mts +1 -1
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contain-path.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"contain-path.d.mts","names":[],"sources":["../../../../../../../../core/src/storage/utils/contain-path.ts"],"mappings":";;AAqBA;;;;AAAgE;;;;;;;;;;;;;iBAAhD,iBAAA,CAAkB,IAAA,UAAc,QAAgB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StorageError } from "./storage-error.mjs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
//#region core/src/storage/utils/contain-path.ts
|
|
4
|
+
//#region ../core/src/storage/utils/contain-path.ts
|
|
5
5
|
/**
|
|
6
6
|
* Resolve `location` against `root` and assert the result stays *inside*
|
|
7
7
|
* `root` — the local-storage path-traversal guard.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contain-path.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"contain-path.mjs","names":[],"sources":["../../../../../../../../core/src/storage/utils/contain-path.ts"],"sourcesContent":["import path from \"path\";\nimport { StorageError } from \"./storage-error\";\n\n/**\n * Resolve `location` against `root` and assert the result stays *inside*\n * `root` — the local-storage path-traversal guard.\n *\n * Without this, a `location` like `../../etc/passwd`, `..\\..\\windows\\...`,\n * an absolute path (`/etc/passwd`, `C:\\secret`), or a prefix breakout could\n * escape the configured storage root and read or clobber arbitrary files on\n * the host.\n *\n * The check compares the relative path from `root` to the resolved target:\n * if it climbs out (`..` prefix) or is itself absolute (different drive /\n * root on Windows), the location is rejected.\n *\n * @param root - Absolute, normalized storage root.\n * @param location - Caller-supplied (already prefix-applied) location.\n * @returns The absolute, contained filesystem path.\n * @throws {StorageError} When the location escapes `root`.\n */\nexport function resolveWithinRoot(root: string, location: string): string {\n const resolved = path.resolve(root, location);\n const rel = path.relative(root, resolved);\n\n if (rel !== \"\" && (rel.startsWith(\"..\") || path.isAbsolute(rel))) {\n throw new StorageError(\n `Storage location escapes the storage root: \"${location}\"`,\n { context: { location, root } },\n );\n }\n\n return resolved;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,kBAAkB,MAAc,UAA0B;CACxE,MAAM,WAAW,KAAK,QAAQ,MAAM,QAAQ;CAC5C,MAAM,MAAM,KAAK,SAAS,MAAM,QAAQ;CAExC,IAAI,QAAQ,OAAO,IAAI,WAAW,IAAI,KAAK,KAAK,WAAW,GAAG,IAC5D,MAAM,IAAI,aACR,+CAA+C,SAAS,IACxD,EAAE,SAAS;EAAE;EAAU;CAAK,EAAE,CAChC;CAGF,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mime.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"mime.d.mts","names":[],"sources":["../../../../../../../../core/src/storage/utils/mime.ts"],"mappings":";;AAcA;;;;AAAwC;iBAAxB,WAAA,CAAY,IAAY;;;;cAO3B,SAAA;EAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mime.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"mime.mjs","names":[],"sources":["../../../../../../../../core/src/storage/utils/mime.ts"],"sourcesContent":["/**\n * MIME type utilities\n *\n * This module wraps the mime package to avoid type conflicts\n * with @types/send which has its own @types/mime dependency.\n */\nimport mime from \"mime\";\n\n/**\n * Get MIME type from file path or extension\n *\n * @param path - File path or extension\n * @returns MIME type or \"application/octet-stream\" if unknown\n */\nexport function getMimeType(path: string): string {\n return mime.getType(path) || \"application/octet-stream\";\n}\n\n/**\n * Common MIME type constants\n */\nexport const MimeTypes = {\n // Images\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n\n // Documents\n pdf: \"application/pdf\",\n txt: \"text/plain\",\n html: \"text/html\",\n css: \"text/css\",\n js: \"application/javascript\",\n json: \"application/json\",\n xml: \"application/xml\",\n\n // Archives\n zip: \"application/zip\",\n gzip: \"application/gzip\",\n\n // Media\n mp3: \"audio/mpeg\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n ogg: \"audio/ogg\",\n\n // Binary\n binary: \"application/octet-stream\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAgB,YAAY,MAAsB;CAChD,OAAO,KAAK,QAAQ,IAAI,KAAK;AAC/B;;;;AAKA,MAAa,YAAY;CAEvB,MAAM;CACN,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;CACL,KAAK;CAGL,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;CACL,IAAI;CACJ,MAAM;CACN,KAAK;CAGL,KAAK;CACL,MAAM;CAGN,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;CAGL,QAAQ;AACV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-fetch.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"safe-fetch.d.mts","names":[],"sources":["../../../../../../../../core/src/storage/utils/safe-fetch.ts"],"mappings":";;AAmCA;;;;;;KAAY,gBAAA;EAkBV;;;;EAbA,iBAAA;EA2Hc;;;;AAAgC;EArH9C,QAAA,WAgNyB;EA9MzB,SAAA;EA+Mc;;;;EA1Md,cAAA;EA6MA;;;AACE;EAzMF,KAAA,UAAe,KAAK;AAAA;;;;;;;;;;;iBAyGN,qBAAA,CAAsB,EAAU;;AAyHtB;;;;KA9Bd,eAAA;EACV,MAAA,EAAQ,MAAM;EACd,WAAA;EACA,MAAA;EACA,UAAA;EACA,EAAA;AAAA;;;;;;;;;;;;;;;;;;;;iBAsBoB,iBAAA,CACpB,MAAA,UACA,OAAA,GAAS,gBAAA,GACR,OAAA,CAAQ,eAAA"}
|
|
@@ -2,7 +2,7 @@ import { StorageError } from "./storage-error.mjs";
|
|
|
2
2
|
import { isIP } from "@warlock.js/seal";
|
|
3
3
|
import { lookup } from "node:dns/promises";
|
|
4
4
|
|
|
5
|
-
//#region core/src/storage/utils/safe-fetch.ts
|
|
5
|
+
//#region ../core/src/storage/utils/safe-fetch.ts
|
|
6
6
|
/**
|
|
7
7
|
* SSRF / resource-exhaustion guard for storage's outbound downloads
|
|
8
8
|
* (`putFromUrl`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-fetch.mjs","names":[],"sources":["C:/Work/Warlock.js/core/src/storage/utils/safe-fetch.ts"],"sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport { isIP } from \"@warlock.js/seal\";\nimport { StorageError } from \"./storage-error\";\n\n/**\n * SSRF / resource-exhaustion guard for storage's outbound downloads\n * (`putFromUrl`).\n *\n * NOTE: this MIRRORS `@warlock.js/ai`'s `src/security/private-ip.ts` and\n * `src/security/outbound-policy.ts`. It is duplicated here intentionally\n * because `@warlock.js/core` cannot depend on `@warlock.js/ai`. Pending\n * extraction of a shared security package, keep the two copies in sync.\n */\n\n/** 50 MiB — default cap on a downloaded body (storage files run larger than AI payloads). */\nconst DEFAULT_MAX_BYTES = 50 * 1024 * 1024;\n/** 30s — default per-request timeout. */\nconst DEFAULT_TIMEOUT_MS = 30_000;\n/**\n * Cap on the number of re-validated redirect hops. Mirrors\n * `@warlock.js/ai`'s `DEFAULT_MAX_REDIRECTS`\n * (ai/src/security/outbound-policy.ts:15).\n */\nconst DEFAULT_MAX_REDIRECTS = 5;\n\n/** 3xx statuses whose `Location` a follow re-issues — mirrors ai/src/security/outbound-policy.ts:18. */\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n\n/**\n * Options controlling a guarded outbound fetch. Every field is optional;\n * {@link resolveFetchPolicy} fills safe defaults. The defaults are\n * deliberately strict (https+http, private-IP deny ON, 30s timeout,\n * 50 MiB cap) so a caller that does not tune them still gets a hardened\n * request.\n */\nexport type SafeFetchOptions = {\n /**\n * Whether to ALLOW private / loopback / link-local / metadata hosts.\n * Default `false` — the SSRF guard is on (private hosts are denied).\n */\n allowPrivateHosts?: boolean;\n /**\n * Maximum response body size in bytes. A declared `content-length` over\n * this fails fast; otherwise the body is read with a running cap and the\n * stream is aborted on overflow. Default `52_428_800` (50 MiB).\n */\n maxBytes?: number;\n /** Per-request timeout in milliseconds. Default `30_000`. */\n timeoutMs?: number;\n /**\n * URL schemes permitted for the request, compared case-insensitively.\n * Default `[\"https\", \"http\"]`.\n */\n allowedSchemes?: string[];\n /**\n * Injected `fetch` implementation (for tests or proxies). Defaults to the\n * global `fetch`.\n */\n fetch?: typeof fetch;\n};\n\n/** {@link SafeFetchOptions} with every default resolved — never partial. */\ntype ResolvedFetchPolicy = {\n allowPrivateHosts: boolean;\n maxBytes: number;\n timeoutMs: number;\n allowedSchemes: string[];\n fetch: typeof fetch;\n};\n\n/**\n * Fill a {@link SafeFetchOptions} with strict defaults: https+http,\n * private-IP deny on, 30s timeout, 50 MiB cap, global `fetch`.\n */\nfunction resolveFetchPolicy(options: SafeFetchOptions = {}): ResolvedFetchPolicy {\n return {\n allowPrivateHosts: options.allowPrivateHosts ?? false,\n maxBytes: options.maxBytes ?? DEFAULT_MAX_BYTES,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n allowedSchemes: options.allowedSchemes ?? [\"https\", \"http\"],\n fetch: options.fetch ?? globalThis.fetch,\n };\n}\n\n/** Parse a dotted-quad into four octets, or `null` if malformed. */\nfunction parseIpv4(ip: string): [number, number, number, number] | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) {\n return null;\n }\n\n const octets = parts.map((part) => Number(part));\n if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) {\n return null;\n }\n\n return octets as [number, number, number, number];\n}\n\nfunction isPrivateIpv4(ip: string): boolean {\n const octets = parseIpv4(ip);\n if (!octets) {\n return true; // unparseable → refuse, fail closed\n }\n\n const [a, b] = octets;\n\n return (\n a === 0 || // 0.0.0.0/8 \"this network\"\n a === 10 || // 10.0.0.0/8 private\n a === 127 || // 127.0.0.0/8 loopback\n (a === 100 && b >= 64 && b <= 127) || // 100.64.0.0/10 CGNAT\n (a === 169 && b === 254) || // 169.254.0.0/16 link-local + metadata\n (a === 172 && b >= 16 && b <= 31) || // 172.16.0.0/12 private\n (a === 192 && b === 168) || // 192.168.0.0/16 private\n (a === 192 && b === 0) || // 192.0.0.0/24 + 192.0.2.0/24 (IETF/test)\n (a === 198 && (b === 18 || b === 19)) || // 198.18.0.0/15 benchmarking\n (a === 198 && b === 51) || // 198.51.100.0/24 test-net-2\n (a === 203 && b === 0) || // 203.0.113.0/24 test-net-3\n a >= 224 // 224.0.0.0/4 multicast + 240.0.0.0/4 reserved + 255.255.255.255\n );\n}\n\nfunction isPrivateIpv6(ip: string): boolean {\n const normalized = ip.toLowerCase().split(\"%\")[0]; // drop zone id\n\n // IPv4-mapped / -embedded (::ffff:a.b.c.d, ::a.b.c.d) — defer to the v4\n // check on the trailing dotted-quad so an inward-mapped address is caught.\n const v4 = normalized.match(/(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/);\n if (v4) {\n return isPrivateIpv4(v4[1]);\n }\n\n if (normalized === \"::1\" || normalized === \"::\") {\n return true; // loopback / unspecified\n }\n\n // Expand only the leading group enough to classify the reserved blocks.\n const firstGroup = normalized.split(\":\")[0];\n const head = firstGroup === \"\" ? 0 : Number.parseInt(firstGroup, 16);\n\n // fc00::/7 unique-local (fc.. / fd..)\n if ((head & 0xfe00) === 0xfc00) {\n return true;\n }\n // fe80::/10 link-local\n if ((head & 0xffc0) === 0xfe80) {\n return true;\n }\n\n return false;\n}\n\n/**\n * True when `ip` is a private, loopback, link-local, unique-local,\n * carrier-grade-NAT, unspecified, or otherwise non-public address — the set\n * an SSRF guard must refuse. Accepts IPv4 and IPv6 literals (including\n * IPv4-mapped IPv6 like `::ffff:169.254.169.254`). A non-IP string returns\n * `false` (the caller resolves hostnames via DNS first).\n *\n * The cloud-metadata endpoint `169.254.169.254` is covered by the IPv4\n * link-local range `169.254.0.0/16`.\n */\nexport function isPrivateOrReservedIp(ip: string): boolean {\n const family = isIP(ip);\n if (family === 4) {\n return isPrivateIpv4(ip);\n }\n if (family === 6) {\n return isPrivateIpv6(ip);\n }\n return false;\n}\n\n/** Strip the `[ ]` IPv6 brackets `URL.hostname` keeps. */\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n\n/**\n * Reject when `host` is — or resolves to — a private / reserved address.\n * IP literals are checked directly; hostnames are resolved via DNS and every\n * returned address is checked (a public name pointing inward is caught). A\n * resolution failure fails closed.\n */\nasync function assertHostNotPrivate(host: string, rawUrl: string): Promise<void> {\n if (isIP(host) !== 0) {\n if (isPrivateOrReservedIp(host)) {\n throw new StorageError(\n `outbound request blocked — \"${host}\" is a private/reserved address`,\n { context: { url: rawUrl, address: host } },\n );\n }\n return;\n }\n\n let addresses: Array<{ address: string }>;\n try {\n addresses = await lookup(host, { all: true });\n } catch (cause) {\n throw new StorageError(\n `outbound request blocked — could not resolve host \"${host}\" to verify it is public`,\n { cause, context: { url: rawUrl, host } },\n );\n }\n\n for (const { address } of addresses) {\n if (isPrivateOrReservedIp(address)) {\n throw new StorageError(\n `outbound request blocked — host \"${host}\" resolves to a private/reserved address (${address})`,\n { context: { url: rawUrl, host, address } },\n );\n }\n }\n}\n\n/**\n * Validate a URL against the policy BEFORE any network call: scheme\n * allowlist and (when private hosts are not allowed) a DNS resolution that\n * rejects private / loopback / link-local / metadata addresses — the SSRF\n * guard. Returns the parsed `URL` on success; throws {@link StorageError}\n * otherwise.\n */\nasync function assertUrlAllowed(rawUrl: string, policy: ResolvedFetchPolicy): Promise<URL> {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new StorageError(`outbound request blocked — invalid URL: ${rawUrl}`, {\n context: { url: rawUrl },\n });\n }\n\n const scheme = url.protocol.replace(/:$/, \"\").toLowerCase();\n if (!policy.allowedSchemes.some((s) => s.toLowerCase() === scheme)) {\n throw new StorageError(\n `outbound request blocked — scheme \"${scheme}\" is not allowed (allowed: ${policy.allowedSchemes.join(\", \")})`,\n { context: { url: rawUrl, scheme } },\n );\n }\n\n if (!policy.allowPrivateHosts) {\n const host = stripBrackets(url.hostname);\n await assertHostNotPrivate(host, rawUrl);\n }\n\n return url;\n}\n\n/**\n * Result of {@link safeFetchToBuffer}: the (capped) body plus the response's\n * content-type, so callers can derive a MIME type and enforce a non-empty\n * content-type check.\n */\nexport type SafeFetchResult = {\n buffer: Buffer;\n contentType: string | null;\n status: number;\n statusText: string;\n ok: boolean;\n};\n\n/**\n * SSRF-guarded download: validates the URL (scheme allowlist + post-DNS\n * private-IP deny), performs the request with a timeout via\n * `AbortController`, then streams the body with a hard byte cap — aborting\n * the moment the running total exceeds `maxBytes`. A declared\n * `content-length` over the cap fails fast.\n *\n * Redirects are NEVER delegated to the platform: every hop is issued with\n * `redirect: \"manual\"` and its `Location` is re-run through\n * {@link assertUrlAllowed} — including the DNS-resolution private-IP check\n * — before being followed (capped at {@link DEFAULT_MAX_REDIRECTS}), so a\n * 3xx from an allowed host cannot smuggle the request to a private /\n * metadata target. Mirrors `@warlock.js/ai`'s `guardedFetch`\n * (ai/src/security/outbound-policy.ts:188-284); duplicated per this\n * module's file-header note since core cannot depend on ai.\n *\n * @throws {StorageError} On a blocked URL (initial or redirect target),\n * a redirect-hop bound overflow, timeout, or oversized body.\n */\nexport async function safeFetchToBuffer(\n rawUrl: string,\n options: SafeFetchOptions = {},\n): Promise<SafeFetchResult> {\n const policy = resolveFetchPolicy(options);\n let url = await assertUrlAllowed(rawUrl, policy);\n\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(\n new StorageError(`outbound request timed out after ${policy.timeoutMs}ms`, {\n context: { url: rawUrl, timeoutMs: policy.timeoutMs },\n }),\n );\n }, policy.timeoutMs);\n\n try {\n let response: Response;\n\n for (let hop = 0; ; hop++) {\n response = await policy.fetch(url, { signal: controller.signal, redirect: \"manual\" });\n\n const location = response.headers.get(\"location\");\n if (!REDIRECT_STATUSES.has(response.status) || location === null) {\n break;\n }\n\n if (hop >= DEFAULT_MAX_REDIRECTS) {\n throw new StorageError(\n `outbound request blocked — more than ${DEFAULT_MAX_REDIRECTS} redirects`,\n { context: { url: rawUrl, maxRedirects: DEFAULT_MAX_REDIRECTS } },\n );\n }\n\n let target: URL;\n try {\n target = new URL(location, url);\n } catch {\n throw new StorageError(`outbound request blocked — invalid redirect Location: ${location}`, {\n context: { url: url.toString(), location },\n });\n }\n\n // Discard the interim body so the connection can be reused.\n if (response.body) {\n await response.body.cancel().catch(() => undefined);\n }\n\n // The redirect target gets the SAME scheme + private-IP validation\n // (incl. DNS resolution) as the initial URL — this is what closes\n // the redirect-based SSRF bypass: a 302 from an allowed host to\n // 169.254.169.254 is re-validated here, not blindly followed.\n url = await assertUrlAllowed(target.toString(), policy);\n }\n\n const declared = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(declared) && declared > policy.maxBytes) {\n throw new StorageError(\n `outbound response body too large — declared ${declared} bytes exceeds the ${policy.maxBytes}-byte cap`,\n { context: { url: rawUrl, declared, maxBytes: policy.maxBytes } },\n );\n }\n\n const buffer = await readBodyCapped(response, policy.maxBytes, rawUrl);\n\n return {\n buffer,\n contentType: response.headers.get(\"content-type\"),\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Read a response body into a Buffer with a hard byte cap. The stream is\n * read chunk-by-chunk and cancelled the moment the running total exceeds\n * `maxBytes`. Throws {@link StorageError} on overflow.\n */\nasync function readBodyCapped(\n response: Response,\n maxBytes: number,\n rawUrl: string,\n): Promise<Buffer> {\n if (!response.body) {\n const arrayBuffer = await response.arrayBuffer();\n if (arrayBuffer.byteLength > maxBytes) {\n throw new StorageError(\n `outbound response body exceeded the ${maxBytes}-byte cap`,\n { context: { url: rawUrl, maxBytes } },\n );\n }\n return Buffer.from(arrayBuffer);\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel();\n throw new StorageError(\n `outbound response body exceeded the ${maxBytes}-byte cap`,\n { context: { url: rawUrl, maxBytes } },\n );\n }\n chunks.push(value);\n }\n\n return Buffer.concat(chunks);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"safe-fetch.mjs","names":[],"sources":["../../../../../../../../core/src/storage/utils/safe-fetch.ts"],"sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport { isIP } from \"@warlock.js/seal\";\nimport { StorageError } from \"./storage-error\";\n\n/**\n * SSRF / resource-exhaustion guard for storage's outbound downloads\n * (`putFromUrl`).\n *\n * NOTE: this MIRRORS `@warlock.js/ai`'s `src/security/private-ip.ts` and\n * `src/security/outbound-policy.ts`. It is duplicated here intentionally\n * because `@warlock.js/core` cannot depend on `@warlock.js/ai`. Pending\n * extraction of a shared security package, keep the two copies in sync.\n */\n\n/** 50 MiB — default cap on a downloaded body (storage files run larger than AI payloads). */\nconst DEFAULT_MAX_BYTES = 50 * 1024 * 1024;\n/** 30s — default per-request timeout. */\nconst DEFAULT_TIMEOUT_MS = 30_000;\n/**\n * Cap on the number of re-validated redirect hops. Mirrors\n * `@warlock.js/ai`'s `DEFAULT_MAX_REDIRECTS`\n * (ai/src/security/outbound-policy.ts:15).\n */\nconst DEFAULT_MAX_REDIRECTS = 5;\n\n/** 3xx statuses whose `Location` a follow re-issues — mirrors ai/src/security/outbound-policy.ts:18. */\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n\n/**\n * Options controlling a guarded outbound fetch. Every field is optional;\n * {@link resolveFetchPolicy} fills safe defaults. The defaults are\n * deliberately strict (https+http, private-IP deny ON, 30s timeout,\n * 50 MiB cap) so a caller that does not tune them still gets a hardened\n * request.\n */\nexport type SafeFetchOptions = {\n /**\n * Whether to ALLOW private / loopback / link-local / metadata hosts.\n * Default `false` — the SSRF guard is on (private hosts are denied).\n */\n allowPrivateHosts?: boolean;\n /**\n * Maximum response body size in bytes. A declared `content-length` over\n * this fails fast; otherwise the body is read with a running cap and the\n * stream is aborted on overflow. Default `52_428_800` (50 MiB).\n */\n maxBytes?: number;\n /** Per-request timeout in milliseconds. Default `30_000`. */\n timeoutMs?: number;\n /**\n * URL schemes permitted for the request, compared case-insensitively.\n * Default `[\"https\", \"http\"]`.\n */\n allowedSchemes?: string[];\n /**\n * Injected `fetch` implementation (for tests or proxies). Defaults to the\n * global `fetch`.\n */\n fetch?: typeof fetch;\n};\n\n/** {@link SafeFetchOptions} with every default resolved — never partial. */\ntype ResolvedFetchPolicy = {\n allowPrivateHosts: boolean;\n maxBytes: number;\n timeoutMs: number;\n allowedSchemes: string[];\n fetch: typeof fetch;\n};\n\n/**\n * Fill a {@link SafeFetchOptions} with strict defaults: https+http,\n * private-IP deny on, 30s timeout, 50 MiB cap, global `fetch`.\n */\nfunction resolveFetchPolicy(options: SafeFetchOptions = {}): ResolvedFetchPolicy {\n return {\n allowPrivateHosts: options.allowPrivateHosts ?? false,\n maxBytes: options.maxBytes ?? DEFAULT_MAX_BYTES,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n allowedSchemes: options.allowedSchemes ?? [\"https\", \"http\"],\n fetch: options.fetch ?? globalThis.fetch,\n };\n}\n\n/** Parse a dotted-quad into four octets, or `null` if malformed. */\nfunction parseIpv4(ip: string): [number, number, number, number] | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) {\n return null;\n }\n\n const octets = parts.map((part) => Number(part));\n if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) {\n return null;\n }\n\n return octets as [number, number, number, number];\n}\n\nfunction isPrivateIpv4(ip: string): boolean {\n const octets = parseIpv4(ip);\n if (!octets) {\n return true; // unparseable → refuse, fail closed\n }\n\n const [a, b] = octets;\n\n return (\n a === 0 || // 0.0.0.0/8 \"this network\"\n a === 10 || // 10.0.0.0/8 private\n a === 127 || // 127.0.0.0/8 loopback\n (a === 100 && b >= 64 && b <= 127) || // 100.64.0.0/10 CGNAT\n (a === 169 && b === 254) || // 169.254.0.0/16 link-local + metadata\n (a === 172 && b >= 16 && b <= 31) || // 172.16.0.0/12 private\n (a === 192 && b === 168) || // 192.168.0.0/16 private\n (a === 192 && b === 0) || // 192.0.0.0/24 + 192.0.2.0/24 (IETF/test)\n (a === 198 && (b === 18 || b === 19)) || // 198.18.0.0/15 benchmarking\n (a === 198 && b === 51) || // 198.51.100.0/24 test-net-2\n (a === 203 && b === 0) || // 203.0.113.0/24 test-net-3\n a >= 224 // 224.0.0.0/4 multicast + 240.0.0.0/4 reserved + 255.255.255.255\n );\n}\n\nfunction isPrivateIpv6(ip: string): boolean {\n const normalized = ip.toLowerCase().split(\"%\")[0]; // drop zone id\n\n // IPv4-mapped / -embedded (::ffff:a.b.c.d, ::a.b.c.d) — defer to the v4\n // check on the trailing dotted-quad so an inward-mapped address is caught.\n const v4 = normalized.match(/(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/);\n if (v4) {\n return isPrivateIpv4(v4[1]);\n }\n\n if (normalized === \"::1\" || normalized === \"::\") {\n return true; // loopback / unspecified\n }\n\n // Expand only the leading group enough to classify the reserved blocks.\n const firstGroup = normalized.split(\":\")[0];\n const head = firstGroup === \"\" ? 0 : Number.parseInt(firstGroup, 16);\n\n // fc00::/7 unique-local (fc.. / fd..)\n if ((head & 0xfe00) === 0xfc00) {\n return true;\n }\n // fe80::/10 link-local\n if ((head & 0xffc0) === 0xfe80) {\n return true;\n }\n\n return false;\n}\n\n/**\n * True when `ip` is a private, loopback, link-local, unique-local,\n * carrier-grade-NAT, unspecified, or otherwise non-public address — the set\n * an SSRF guard must refuse. Accepts IPv4 and IPv6 literals (including\n * IPv4-mapped IPv6 like `::ffff:169.254.169.254`). A non-IP string returns\n * `false` (the caller resolves hostnames via DNS first).\n *\n * The cloud-metadata endpoint `169.254.169.254` is covered by the IPv4\n * link-local range `169.254.0.0/16`.\n */\nexport function isPrivateOrReservedIp(ip: string): boolean {\n const family = isIP(ip);\n if (family === 4) {\n return isPrivateIpv4(ip);\n }\n if (family === 6) {\n return isPrivateIpv6(ip);\n }\n return false;\n}\n\n/** Strip the `[ ]` IPv6 brackets `URL.hostname` keeps. */\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n\n/**\n * Reject when `host` is — or resolves to — a private / reserved address.\n * IP literals are checked directly; hostnames are resolved via DNS and every\n * returned address is checked (a public name pointing inward is caught). A\n * resolution failure fails closed.\n */\nasync function assertHostNotPrivate(host: string, rawUrl: string): Promise<void> {\n if (isIP(host) !== 0) {\n if (isPrivateOrReservedIp(host)) {\n throw new StorageError(\n `outbound request blocked — \"${host}\" is a private/reserved address`,\n { context: { url: rawUrl, address: host } },\n );\n }\n return;\n }\n\n let addresses: Array<{ address: string }>;\n try {\n addresses = await lookup(host, { all: true });\n } catch (cause) {\n throw new StorageError(\n `outbound request blocked — could not resolve host \"${host}\" to verify it is public`,\n { cause, context: { url: rawUrl, host } },\n );\n }\n\n for (const { address } of addresses) {\n if (isPrivateOrReservedIp(address)) {\n throw new StorageError(\n `outbound request blocked — host \"${host}\" resolves to a private/reserved address (${address})`,\n { context: { url: rawUrl, host, address } },\n );\n }\n }\n}\n\n/**\n * Validate a URL against the policy BEFORE any network call: scheme\n * allowlist and (when private hosts are not allowed) a DNS resolution that\n * rejects private / loopback / link-local / metadata addresses — the SSRF\n * guard. Returns the parsed `URL` on success; throws {@link StorageError}\n * otherwise.\n */\nasync function assertUrlAllowed(rawUrl: string, policy: ResolvedFetchPolicy): Promise<URL> {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new StorageError(`outbound request blocked — invalid URL: ${rawUrl}`, {\n context: { url: rawUrl },\n });\n }\n\n const scheme = url.protocol.replace(/:$/, \"\").toLowerCase();\n if (!policy.allowedSchemes.some((s) => s.toLowerCase() === scheme)) {\n throw new StorageError(\n `outbound request blocked — scheme \"${scheme}\" is not allowed (allowed: ${policy.allowedSchemes.join(\", \")})`,\n { context: { url: rawUrl, scheme } },\n );\n }\n\n if (!policy.allowPrivateHosts) {\n const host = stripBrackets(url.hostname);\n await assertHostNotPrivate(host, rawUrl);\n }\n\n return url;\n}\n\n/**\n * Result of {@link safeFetchToBuffer}: the (capped) body plus the response's\n * content-type, so callers can derive a MIME type and enforce a non-empty\n * content-type check.\n */\nexport type SafeFetchResult = {\n buffer: Buffer;\n contentType: string | null;\n status: number;\n statusText: string;\n ok: boolean;\n};\n\n/**\n * SSRF-guarded download: validates the URL (scheme allowlist + post-DNS\n * private-IP deny), performs the request with a timeout via\n * `AbortController`, then streams the body with a hard byte cap — aborting\n * the moment the running total exceeds `maxBytes`. A declared\n * `content-length` over the cap fails fast.\n *\n * Redirects are NEVER delegated to the platform: every hop is issued with\n * `redirect: \"manual\"` and its `Location` is re-run through\n * {@link assertUrlAllowed} — including the DNS-resolution private-IP check\n * — before being followed (capped at {@link DEFAULT_MAX_REDIRECTS}), so a\n * 3xx from an allowed host cannot smuggle the request to a private /\n * metadata target. Mirrors `@warlock.js/ai`'s `guardedFetch`\n * (ai/src/security/outbound-policy.ts:188-284); duplicated per this\n * module's file-header note since core cannot depend on ai.\n *\n * @throws {StorageError} On a blocked URL (initial or redirect target),\n * a redirect-hop bound overflow, timeout, or oversized body.\n */\nexport async function safeFetchToBuffer(\n rawUrl: string,\n options: SafeFetchOptions = {},\n): Promise<SafeFetchResult> {\n const policy = resolveFetchPolicy(options);\n let url = await assertUrlAllowed(rawUrl, policy);\n\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(\n new StorageError(`outbound request timed out after ${policy.timeoutMs}ms`, {\n context: { url: rawUrl, timeoutMs: policy.timeoutMs },\n }),\n );\n }, policy.timeoutMs);\n\n try {\n let response: Response;\n\n for (let hop = 0; ; hop++) {\n response = await policy.fetch(url, { signal: controller.signal, redirect: \"manual\" });\n\n const location = response.headers.get(\"location\");\n if (!REDIRECT_STATUSES.has(response.status) || location === null) {\n break;\n }\n\n if (hop >= DEFAULT_MAX_REDIRECTS) {\n throw new StorageError(\n `outbound request blocked — more than ${DEFAULT_MAX_REDIRECTS} redirects`,\n { context: { url: rawUrl, maxRedirects: DEFAULT_MAX_REDIRECTS } },\n );\n }\n\n let target: URL;\n try {\n target = new URL(location, url);\n } catch {\n throw new StorageError(`outbound request blocked — invalid redirect Location: ${location}`, {\n context: { url: url.toString(), location },\n });\n }\n\n // Discard the interim body so the connection can be reused.\n if (response.body) {\n await response.body.cancel().catch(() => undefined);\n }\n\n // The redirect target gets the SAME scheme + private-IP validation\n // (incl. DNS resolution) as the initial URL — this is what closes\n // the redirect-based SSRF bypass: a 302 from an allowed host to\n // 169.254.169.254 is re-validated here, not blindly followed.\n url = await assertUrlAllowed(target.toString(), policy);\n }\n\n const declared = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(declared) && declared > policy.maxBytes) {\n throw new StorageError(\n `outbound response body too large — declared ${declared} bytes exceeds the ${policy.maxBytes}-byte cap`,\n { context: { url: rawUrl, declared, maxBytes: policy.maxBytes } },\n );\n }\n\n const buffer = await readBodyCapped(response, policy.maxBytes, rawUrl);\n\n return {\n buffer,\n contentType: response.headers.get(\"content-type\"),\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Read a response body into a Buffer with a hard byte cap. The stream is\n * read chunk-by-chunk and cancelled the moment the running total exceeds\n * `maxBytes`. Throws {@link StorageError} on overflow.\n */\nasync function readBodyCapped(\n response: Response,\n maxBytes: number,\n rawUrl: string,\n): Promise<Buffer> {\n if (!response.body) {\n const arrayBuffer = await response.arrayBuffer();\n if (arrayBuffer.byteLength > maxBytes) {\n throw new StorageError(\n `outbound response body exceeded the ${maxBytes}-byte cap`,\n { context: { url: rawUrl, maxBytes } },\n );\n }\n return Buffer.from(arrayBuffer);\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel();\n throw new StorageError(\n `outbound response body exceeded the ${maxBytes}-byte cap`,\n { context: { url: rawUrl, maxBytes } },\n );\n }\n chunks.push(value);\n }\n\n return Buffer.concat(chunks);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-error.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"storage-error.d.mts","names":[],"sources":["../../../../../../../../core/src/storage/utils/storage-error.ts"],"mappings":";;AAYA;;;;;;;;AAEkB;AAOlB;;KATY,mBAAA;EACV,KAAA;EACA,OAAA,GAAU,MAAM;AAAA;;;;;cAOL,YAAA,SAAqB,KAAA;EASN;;;EAAA,SALV,KAAA;EAOoB;;AAA6B;EAA7B,SAFpB,OAAA,GAAU,MAAA;cAEP,OAAA,UAAiB,OAAA,GAAU,mBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-error.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"storage-error.mjs","names":[],"sources":["../../../../../../../../core/src/storage/utils/storage-error.ts"],"sourcesContent":["/**\n * Base error for the storage subsystem.\n *\n * The storage drivers historically threw bare `Error`s. The security\n * guards added to the local and cloud drivers (path-traversal containment,\n * SSRF-guarded `putFromUrl`) need a named, catchable error so callers can\n * branch on `instanceof StorageError` instead of string-matching messages.\n *\n * `context` is a free-form diagnostic bag (offending location, host, URL)\n * mirroring the convention used by `@warlock.js/ai`'s error classes — it is\n * for logs and telemetry, treated as opaque by consumers.\n */\nexport type StorageErrorOptions = {\n cause?: unknown;\n context?: Record<string, unknown>;\n};\n\n/**\n * Error thrown by storage drivers for refused or invalid operations\n * (path-traversal attempts, blocked outbound fetches, oversized downloads).\n */\nexport class StorageError extends Error {\n /**\n * Optional original thrown value preserved through re-wrapping.\n */\n public readonly cause?: unknown;\n\n /**\n * Optional free-form diagnostic bag (location, host, url, …).\n */\n public readonly context?: Record<string, unknown>;\n\n public constructor(message: string, options?: StorageErrorOptions) {\n super(message);\n this.name = \"StorageError\";\n this.cause = options?.cause;\n this.context = options?.context;\n }\n}\n"],"mappings":";;;;;AAqBA,IAAa,eAAb,cAAkC,MAAM;CAWtC,AAAO,YAAY,SAAiB,SAA+B;EACjE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,QAAQ,SAAS;EACtB,KAAK,UAAU,SAAS;CAC1B;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-http-development-server.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"start-http-development-server.d.mts","names":[],"sources":["../../../../../../../core/src/tests/start-http-development-server.ts"],"mappings":";KAwBY,0BAAA;EAAA;;;;AAON;AA4EN;EA5EE,IAAI;AAAA;;;;;;AA8EI;AAoFV;;iBAtFsB,mBAAA,CACpB,OAAA,GAAS,0BAAA,GACR,OAAO;;AAoFyC;AA6BnD;;iBA7BsB,kBAAA,CAAA,GAAsB,OAAO;;AA6BhB;;iBAAnB,mBAAA,CAAA"}
|
|
@@ -10,7 +10,7 @@ import { loadConfigFiles } from "../config/load-config-files.mjs";
|
|
|
10
10
|
import { publishTestServerPort, withdrawTestServerPort } from "./test-server-port-channel.mjs";
|
|
11
11
|
import config from "@mongez/config";
|
|
12
12
|
|
|
13
|
-
//#region core/src/tests/start-http-development-server.ts
|
|
13
|
+
//#region ../core/src/tests/start-http-development-server.ts
|
|
14
14
|
/**
|
|
15
15
|
* HTTP Test Server
|
|
16
16
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-http-development-server.mjs","names":[],"sources":["C:/Work/Warlock.js/core/src/tests/start-http-development-server.ts"],"sourcesContent":["/**\n * HTTP Test Server\n *\n * Starts a minimal HTTP server for testing.\n * Unlike the full DevelopmentServer, this:\n * - Does NOT watch files\n * - Does NOT do HMR\n * - Only starts connectors needed for HTTP requests\n *\n * Used in Vitest's globalSetup to start server once for all test workers.\n */\nimport config from \"@mongez/config\";\nimport { Application } from \"../application\";\nimport { bootstrap } from \"../bootstrap\";\nimport { loadConfigFiles } from \"../config/load-config-files\";\nimport { connectorsManager } from \"../connectors/connectors-manager\";\nimport { ConnectorLifecyclePhase } from \"../connectors/types\";\nimport { filesOrchestrator } from \"../dev-server/files-orchestrator\";\nimport { assertPortIsAvailable } from \"../http/port-preflight\";\nimport { warlockConfigManager } from \"../warlock-config/warlock-config.manager\";\nimport { publishTestServerPort, withdrawTestServerPort } from \"./test-server-port-channel\";\n\nlet isServerRunning = false;\n\nexport type StartHttpTestServerOptions = {\n /**\n * Port the test server binds to, overriding `http.port`.\n *\n * Needed because the server cannot be moved from outside: this function\n * bootstraps the app itself, and that bootstrap re-reads `.env`.\n */\n port?: number;\n};\n\n/**\n * Apply the caller's port and preflight the bind.\n *\n * Called at the last moment before the HTTP connector binds, and that timing is\n * the fix: `bootstrap()` re-reads `.env` through `loadEnv()` (dotenv overrides\n * by default), and `src/config/http.ts` then resolves its port from that store,\n * so anything the caller set earlier is gone by the time the port is read.\n * Writing into `config` here is also the only channel that works — assigning\n * `process.env.HTTP_PORT` has no effect, since `env()` reads dotenv's own store\n * and never falls back to `process.env`.\n */\nasync function applyTestServerPort(port?: number): Promise<void> {\n const httpConfig = config.get(\"http\");\n\n if (!httpConfig) {\n if (port !== undefined) {\n throw new Error(\n `startHttpTestServer({ port: ${port} }) was given a port, but this app has no \\`http\\` config, so no HTTP server is started. Add \\`src/config/http.ts\\` first.`,\n );\n }\n\n return;\n }\n\n if (port !== undefined) {\n config.set(\"http.port\", port);\n }\n\n const resolvedPort = config.get(\"http.port\");\n\n // No configured port at all is fine: Fastify falls back to its own default and\n // the workers resolve the same one from their own config, so both ends agree\n // without the channel.\n //\n // A non-numeric port is NOT fine, and must fail loudly rather than skip the\n // preflight silently. `env()` coerces a value only when it round-trips exactly\n // (`String(Number(v)) === v`), so `HTTP_PORT=3999` and `HTTP_PORT=0` arrive as\n // numbers, but `03999`, `+3999`, `1e3` and anything with stray whitespace stay\n // strings. Letting those through used to reach `HttpConnector.start()`'s\n // `listen({ port })` unchanged — no preflight, no published port, and every\n // test worker resolving a URL from a channel nothing ever wrote to.\n if (typeof resolvedPort !== \"number\") {\n throw new Error(\n `startHttpTestServer() cannot use \\`http.port\\` value ${JSON.stringify(resolvedPort)} — it did not round-trip through Number() (env() only coerces a value when \\`String(Number(v)) === v\\`, so \"03999\", \"+3999\", \"1e3\", and values with stray whitespace stay strings). Fix \\`HTTP_PORT\\` in .env, or pass an explicit numeric port: startHttpTestServer({ port: 3999 }).`,\n );\n }\n\n // `0` is the OS's \"pick a free one for me\" idiom, and the test server cannot\n // support it. Preflighting 0 would bind some unrelated ephemeral port and pass\n // without proving anything, and there is nothing meaningful to publish: the\n // port Fastify ends up binding is never recorded — `HttpConnector.start()`\n // stores the port it ASKED for, not the one it got. Accepting 0 silently is\n // what left `getTestServerUrl()` resolving to `http://host:0` through its own\n // config fallback, so every worker request went to a port nothing listens on.\n if (resolvedPort <= 0) {\n throw new Error(\n `startHttpTestServer() cannot run on port ${resolvedPort}. Pass an explicit port — e.g. startHttpTestServer({ port: 3999 }) — or set \\`http.port\\` in your config. Test workers are separate processes that resolve the server's URL from the port published at startup, and an OS-assigned port is not knowable to them.`,\n );\n }\n\n await assertPortIsAvailable(resolvedPort, config.get(\"http.host\") || \"localhost\");\n\n publishTestServerPort(resolvedPort);\n}\n\n/**\n * Start the HTTP test server (minimal - no file watching)\n * Call this in Vitest's globalSetup\n *\n * @example\n * // run this suite on its own port, whatever `.env` says\n * await startHttpTestServer({ port: 3999 });\n */\nexport async function startHttpTestServer(\n options: StartHttpTestServerOptions = {},\n): Promise<void> {\n if (isServerRunning) {\n console.log(\"[test-server] Server already running, skipping start\");\n return;\n }\n\n console.log(\"[test-server] Starting HTTP test server...\");\n\n try {\n // Set environment\n Application.setRuntimeStrategy(\"development\");\n Application.setEnvironment(\"test\");\n\n // Bootstrap (env, etc.)\n await warlockConfigManager.load();\n await bootstrap();\n\n // Initialize file orchestrator (but don't watch)\n await filesOrchestrator.init();\n await filesOrchestrator.initializeAll();\n\n // Load config files\n await loadConfigFiles(true);\n\n // Early-phase connectors (database, cache, logger, storage, mailer,\n // herald) must start BEFORE app modules load: a module's `main.ts` boot\n // side-effect can query the DB at import time, so the data source has to\n // be registered first. This mirrors the dev/prod boot order (see\n // `cli-commands.manager`, `production-builder`, and `DevelopmentServer`).\n await connectorsManager.startPhase(ConnectorLifecyclePhase.Early);\n\n // Load application modules (their boot side-effects now see a live DB).\n await filesOrchestrator.moduleLoader.loadAll();\n\n await applyTestServerPort(options.port);\n\n // A rejecting validator (Application.onValidateBoot) must abort boot\n // before late-phase connectors bind a port — same slot as\n // `DevelopmentServer.start()` and the generated production `app.ts`.\n await Application.runStartupValidators();\n\n // Late-phase connectors (http, socket) bind after app code has\n // registered its routes and listeners.\n await connectorsManager.startPhase(ConnectorLifecyclePhase.Late);\n\n isServerRunning = true;\n } catch (error) {\n // This function owns the connectors it starts, so a failure part-way\n // through has to leave nothing behind. Without this, `isServerRunning` was\n // still `false` — it is only set on the last line — so `globalTeardown`'s\n // `stopHttpTestServer()` reported \"No server to stop\" and walked away from\n // live early-phase connectors and a published port that outlived them.\n await unwindPartialStartup();\n\n // Rethrown unchanged: the startup failure is the one the caller needs to\n // read. A cleanup failure that replaced it would hide the actual cause.\n throw error;\n }\n}\n\n/**\n * Best-effort teardown of whatever a failed {@link startHttpTestServer} managed\n * to start.\n *\n * Every step is independent and none may throw: this runs while an error is\n * already in flight, and the caller is about to rethrow it.\n */\nasync function unwindPartialStartup(): Promise<void> {\n try {\n await connectorsManager.shutdown();\n } catch (shutdownError) {\n // Reported, not thrown — it is secondary to the startup error being\n // rethrown, and losing that one to this would be the worse outcome.\n console.error(\"[test-server] Cleanup after a failed start did not complete:\", shutdownError);\n }\n\n withdrawTestServerPort();\n isServerRunning = false;\n}\n\n/**\n * Stop the HTTP test server\n * Call this in Vitest's globalTeardown\n */\nexport async function stopHttpTestServer(): Promise<void> {\n if (!isServerRunning) {\n console.log(\"[test-server] No server to stop\");\n return;\n }\n\n try {\n await connectorsManager.shutdown();\n\n console.log(\"[test-server] HTTP test server stopped\");\n } catch (error) {\n // Surfaced, never swallowed — cleaning up is not the same as the shutdown\n // having succeeded, and a suite whose teardown failed should say so.\n console.error(\"[test-server] Error stopping HTTP server:\", error);\n\n throw error;\n } finally {\n // In a `finally` rather than after the `await`: when `shutdown()` threw,\n // the published port survived the server it pointed at, so the next run in\n // the same process inherited a stale one and sent every request to it.\n withdrawTestServerPort();\n\n isServerRunning = false;\n }\n}\n\n/**\n * Check if test server is running\n */\nexport function isTestServerRunning(): boolean {\n return isServerRunning;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsBA,IAAI,kBAAkB;;;;;;;;;;;;AAuBtB,eAAe,oBAAoB,MAA8B;CAG/D,IAAI,CAFe,OAAO,IAAI,MAEhB,GAAG;EACf,IAAI,SAAS,QACX,MAAM,IAAI,MACR,+BAA+B,KAAK,2HACtC;EAGF;CACF;CAEA,IAAI,SAAS,QACX,OAAO,IAAI,aAAa,IAAI;CAG9B,MAAM,eAAe,OAAO,IAAI,WAAW;CAa3C,IAAI,OAAO,iBAAiB,UAC1B,MAAM,IAAI,MACR,wDAAwD,KAAK,UAAU,YAAY,EAAE,sRACvF;CAUF,IAAI,gBAAgB,GAClB,MAAM,IAAI,MACR,4CAA4C,aAAa,iQAC3D;CAGF,MAAM,sBAAsB,cAAc,OAAO,IAAI,WAAW,KAAK,WAAW;CAEhF,sBAAsB,YAAY;AACpC;;;;;;;;;AAUA,eAAsB,oBACpB,UAAsC,CAAC,GACxB;CACf,IAAI,iBAAiB;EACnB,QAAQ,IAAI,sDAAsD;EAClE;CACF;CAEA,QAAQ,IAAI,4CAA4C;CAExD,IAAI;EAEF,YAAY,mBAAmB,aAAa;EAC5C,YAAY,eAAe,MAAM;EAGjC,MAAM,qBAAqB,KAAK;EAChC,MAAM,UAAU;EAGhB,MAAM,kBAAkB,KAAK;EAC7B,MAAM,kBAAkB,cAAc;EAGtC,MAAM,gBAAgB,IAAI;EAO1B,MAAM,kBAAkB,kBAAwC;EAGhE,MAAM,kBAAkB,aAAa,QAAQ;EAE7C,MAAM,oBAAoB,QAAQ,IAAI;EAKtC,MAAM,YAAY,qBAAqB;EAIvC,MAAM,kBAAkB,iBAAuC;EAE/D,kBAAkB;CACpB,SAAS,OAAO;EAMd,MAAM,qBAAqB;EAI3B,MAAM;CACR;AACF;;;;;;;;AASA,eAAe,uBAAsC;CACnD,IAAI;EACF,MAAM,kBAAkB,SAAS;CACnC,SAAS,eAAe;EAGtB,QAAQ,MAAM,gEAAgE,aAAa;CAC7F;CAEA,uBAAuB;CACvB,kBAAkB;AACpB;;;;;AAMA,eAAsB,qBAAoC;CACxD,IAAI,CAAC,iBAAiB;EACpB,QAAQ,IAAI,iCAAiC;EAC7C;CACF;CAEA,IAAI;EACF,MAAM,kBAAkB,SAAS;EAEjC,QAAQ,IAAI,wCAAwC;CACtD,SAAS,OAAO;EAGd,QAAQ,MAAM,6CAA6C,KAAK;EAEhE,MAAM;CACR,UAAU;EAIR,uBAAuB;EAEvB,kBAAkB;CACpB;AACF;;;;AAKA,SAAgB,sBAA+B;CAC7C,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"start-http-development-server.mjs","names":[],"sources":["../../../../../../../core/src/tests/start-http-development-server.ts"],"sourcesContent":["/**\n * HTTP Test Server\n *\n * Starts a minimal HTTP server for testing.\n * Unlike the full DevelopmentServer, this:\n * - Does NOT watch files\n * - Does NOT do HMR\n * - Only starts connectors needed for HTTP requests\n *\n * Used in Vitest's globalSetup to start server once for all test workers.\n */\nimport config from \"@mongez/config\";\nimport { Application } from \"../application\";\nimport { bootstrap } from \"../bootstrap\";\nimport { loadConfigFiles } from \"../config/load-config-files\";\nimport { connectorsManager } from \"../connectors/connectors-manager\";\nimport { ConnectorLifecyclePhase } from \"../connectors/types\";\nimport { filesOrchestrator } from \"../dev-server/files-orchestrator\";\nimport { assertPortIsAvailable } from \"../http/port-preflight\";\nimport { warlockConfigManager } from \"../warlock-config/warlock-config.manager\";\nimport { publishTestServerPort, withdrawTestServerPort } from \"./test-server-port-channel\";\n\nlet isServerRunning = false;\n\nexport type StartHttpTestServerOptions = {\n /**\n * Port the test server binds to, overriding `http.port`.\n *\n * Needed because the server cannot be moved from outside: this function\n * bootstraps the app itself, and that bootstrap re-reads `.env`.\n */\n port?: number;\n};\n\n/**\n * Apply the caller's port and preflight the bind.\n *\n * Called at the last moment before the HTTP connector binds, and that timing is\n * the fix: `bootstrap()` re-reads `.env` through `loadEnv()` (dotenv overrides\n * by default), and `src/config/http.ts` then resolves its port from that store,\n * so anything the caller set earlier is gone by the time the port is read.\n * Writing into `config` here is also the only channel that works — assigning\n * `process.env.HTTP_PORT` has no effect, since `env()` reads dotenv's own store\n * and never falls back to `process.env`.\n */\nasync function applyTestServerPort(port?: number): Promise<void> {\n const httpConfig = config.get(\"http\");\n\n if (!httpConfig) {\n if (port !== undefined) {\n throw new Error(\n `startHttpTestServer({ port: ${port} }) was given a port, but this app has no \\`http\\` config, so no HTTP server is started. Add \\`src/config/http.ts\\` first.`,\n );\n }\n\n return;\n }\n\n if (port !== undefined) {\n config.set(\"http.port\", port);\n }\n\n const resolvedPort = config.get(\"http.port\");\n\n // No configured port at all is fine: Fastify falls back to its own default and\n // the workers resolve the same one from their own config, so both ends agree\n // without the channel.\n //\n // A non-numeric port is NOT fine, and must fail loudly rather than skip the\n // preflight silently. `env()` coerces a value only when it round-trips exactly\n // (`String(Number(v)) === v`), so `HTTP_PORT=3999` and `HTTP_PORT=0` arrive as\n // numbers, but `03999`, `+3999`, `1e3` and anything with stray whitespace stay\n // strings. Letting those through used to reach `HttpConnector.start()`'s\n // `listen({ port })` unchanged — no preflight, no published port, and every\n // test worker resolving a URL from a channel nothing ever wrote to.\n if (typeof resolvedPort !== \"number\") {\n throw new Error(\n `startHttpTestServer() cannot use \\`http.port\\` value ${JSON.stringify(resolvedPort)} — it did not round-trip through Number() (env() only coerces a value when \\`String(Number(v)) === v\\`, so \"03999\", \"+3999\", \"1e3\", and values with stray whitespace stay strings). Fix \\`HTTP_PORT\\` in .env, or pass an explicit numeric port: startHttpTestServer({ port: 3999 }).`,\n );\n }\n\n // `0` is the OS's \"pick a free one for me\" idiom, and the test server cannot\n // support it. Preflighting 0 would bind some unrelated ephemeral port and pass\n // without proving anything, and there is nothing meaningful to publish: the\n // port Fastify ends up binding is never recorded — `HttpConnector.start()`\n // stores the port it ASKED for, not the one it got. Accepting 0 silently is\n // what left `getTestServerUrl()` resolving to `http://host:0` through its own\n // config fallback, so every worker request went to a port nothing listens on.\n if (resolvedPort <= 0) {\n throw new Error(\n `startHttpTestServer() cannot run on port ${resolvedPort}. Pass an explicit port — e.g. startHttpTestServer({ port: 3999 }) — or set \\`http.port\\` in your config. Test workers are separate processes that resolve the server's URL from the port published at startup, and an OS-assigned port is not knowable to them.`,\n );\n }\n\n await assertPortIsAvailable(resolvedPort, config.get(\"http.host\") || \"localhost\");\n\n publishTestServerPort(resolvedPort);\n}\n\n/**\n * Start the HTTP test server (minimal - no file watching)\n * Call this in Vitest's globalSetup\n *\n * @example\n * // run this suite on its own port, whatever `.env` says\n * await startHttpTestServer({ port: 3999 });\n */\nexport async function startHttpTestServer(\n options: StartHttpTestServerOptions = {},\n): Promise<void> {\n if (isServerRunning) {\n console.log(\"[test-server] Server already running, skipping start\");\n return;\n }\n\n console.log(\"[test-server] Starting HTTP test server...\");\n\n try {\n // Set environment\n Application.setRuntimeStrategy(\"development\");\n Application.setEnvironment(\"test\");\n\n // Bootstrap (env, etc.)\n await warlockConfigManager.load();\n await bootstrap();\n\n // Initialize file orchestrator (but don't watch)\n await filesOrchestrator.init();\n await filesOrchestrator.initializeAll();\n\n // Load config files\n await loadConfigFiles(true);\n\n // Early-phase connectors (database, cache, logger, storage, mailer,\n // herald) must start BEFORE app modules load: a module's `main.ts` boot\n // side-effect can query the DB at import time, so the data source has to\n // be registered first. This mirrors the dev/prod boot order (see\n // `cli-commands.manager`, `production-builder`, and `DevelopmentServer`).\n await connectorsManager.startPhase(ConnectorLifecyclePhase.Early);\n\n // Load application modules (their boot side-effects now see a live DB).\n await filesOrchestrator.moduleLoader.loadAll();\n\n await applyTestServerPort(options.port);\n\n // A rejecting validator (Application.onValidateBoot) must abort boot\n // before late-phase connectors bind a port — same slot as\n // `DevelopmentServer.start()` and the generated production `app.ts`.\n await Application.runStartupValidators();\n\n // Late-phase connectors (http, socket) bind after app code has\n // registered its routes and listeners.\n await connectorsManager.startPhase(ConnectorLifecyclePhase.Late);\n\n isServerRunning = true;\n } catch (error) {\n // This function owns the connectors it starts, so a failure part-way\n // through has to leave nothing behind. Without this, `isServerRunning` was\n // still `false` — it is only set on the last line — so `globalTeardown`'s\n // `stopHttpTestServer()` reported \"No server to stop\" and walked away from\n // live early-phase connectors and a published port that outlived them.\n await unwindPartialStartup();\n\n // Rethrown unchanged: the startup failure is the one the caller needs to\n // read. A cleanup failure that replaced it would hide the actual cause.\n throw error;\n }\n}\n\n/**\n * Best-effort teardown of whatever a failed {@link startHttpTestServer} managed\n * to start.\n *\n * Every step is independent and none may throw: this runs while an error is\n * already in flight, and the caller is about to rethrow it.\n */\nasync function unwindPartialStartup(): Promise<void> {\n try {\n await connectorsManager.shutdown();\n } catch (shutdownError) {\n // Reported, not thrown — it is secondary to the startup error being\n // rethrown, and losing that one to this would be the worse outcome.\n console.error(\"[test-server] Cleanup after a failed start did not complete:\", shutdownError);\n }\n\n withdrawTestServerPort();\n isServerRunning = false;\n}\n\n/**\n * Stop the HTTP test server\n * Call this in Vitest's globalTeardown\n */\nexport async function stopHttpTestServer(): Promise<void> {\n if (!isServerRunning) {\n console.log(\"[test-server] No server to stop\");\n return;\n }\n\n try {\n await connectorsManager.shutdown();\n\n console.log(\"[test-server] HTTP test server stopped\");\n } catch (error) {\n // Surfaced, never swallowed — cleaning up is not the same as the shutdown\n // having succeeded, and a suite whose teardown failed should say so.\n console.error(\"[test-server] Error stopping HTTP server:\", error);\n\n throw error;\n } finally {\n // In a `finally` rather than after the `await`: when `shutdown()` threw,\n // the published port survived the server it pointed at, so the next run in\n // the same process inherited a stale one and sent every request to it.\n withdrawTestServerPort();\n\n isServerRunning = false;\n }\n}\n\n/**\n * Check if test server is running\n */\nexport function isTestServerRunning(): boolean {\n return isServerRunning;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsBA,IAAI,kBAAkB;;;;;;;;;;;;AAuBtB,eAAe,oBAAoB,MAA8B;CAG/D,IAAI,CAFe,OAAO,IAAI,MAEhB,GAAG;EACf,IAAI,SAAS,QACX,MAAM,IAAI,MACR,+BAA+B,KAAK,2HACtC;EAGF;CACF;CAEA,IAAI,SAAS,QACX,OAAO,IAAI,aAAa,IAAI;CAG9B,MAAM,eAAe,OAAO,IAAI,WAAW;CAa3C,IAAI,OAAO,iBAAiB,UAC1B,MAAM,IAAI,MACR,wDAAwD,KAAK,UAAU,YAAY,EAAE,sRACvF;CAUF,IAAI,gBAAgB,GAClB,MAAM,IAAI,MACR,4CAA4C,aAAa,iQAC3D;CAGF,MAAM,sBAAsB,cAAc,OAAO,IAAI,WAAW,KAAK,WAAW;CAEhF,sBAAsB,YAAY;AACpC;;;;;;;;;AAUA,eAAsB,oBACpB,UAAsC,CAAC,GACxB;CACf,IAAI,iBAAiB;EACnB,QAAQ,IAAI,sDAAsD;EAClE;CACF;CAEA,QAAQ,IAAI,4CAA4C;CAExD,IAAI;EAEF,YAAY,mBAAmB,aAAa;EAC5C,YAAY,eAAe,MAAM;EAGjC,MAAM,qBAAqB,KAAK;EAChC,MAAM,UAAU;EAGhB,MAAM,kBAAkB,KAAK;EAC7B,MAAM,kBAAkB,cAAc;EAGtC,MAAM,gBAAgB,IAAI;EAO1B,MAAM,kBAAkB,kBAAwC;EAGhE,MAAM,kBAAkB,aAAa,QAAQ;EAE7C,MAAM,oBAAoB,QAAQ,IAAI;EAKtC,MAAM,YAAY,qBAAqB;EAIvC,MAAM,kBAAkB,iBAAuC;EAE/D,kBAAkB;CACpB,SAAS,OAAO;EAMd,MAAM,qBAAqB;EAI3B,MAAM;CACR;AACF;;;;;;;;AASA,eAAe,uBAAsC;CACnD,IAAI;EACF,MAAM,kBAAkB,SAAS;CACnC,SAAS,eAAe;EAGtB,QAAQ,MAAM,gEAAgE,aAAa;CAC7F;CAEA,uBAAuB;CACvB,kBAAkB;AACpB;;;;;AAMA,eAAsB,qBAAoC;CACxD,IAAI,CAAC,iBAAiB;EACpB,QAAQ,IAAI,iCAAiC;EAC7C;CACF;CAEA,IAAI;EACF,MAAM,kBAAkB,SAAS;EAEjC,QAAQ,IAAI,wCAAwC;CACtD,SAAS,OAAO;EAGd,QAAQ,MAAM,6CAA6C,KAAK;EAEhE,MAAM;CACR,UAAU;EAIR,uBAAuB;EAEvB,kBAAkB;CACpB;AACF;;;;AAKA,SAAgB,sBAA+B;CAC7C,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-connectors-selection.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-connectors-selection.d.mts","names":[],"sources":["../../../../../../../core/src/tests/test-connectors-selection.ts"],"mappings":";;;;;AAqBA;;;;AAA6D;KAAjD,uBAAA,aAAoC,aAAa"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { config } from "../config/config-getter.mjs";
|
|
2
2
|
import "../config/index.mjs";
|
|
3
3
|
|
|
4
|
-
//#region core/src/tests/test-connectors-selection.ts
|
|
4
|
+
//#region ../core/src/tests/test-connectors-selection.ts
|
|
5
5
|
/**
|
|
6
6
|
* Classify the caller's `connectors` option as explicit or deferred.
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-connectors-selection.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-connectors-selection.mjs","names":[],"sources":["../../../../../../../core/src/tests/test-connectors-selection.ts"],"sourcesContent":["/**\n * Effective connector selection for the worker test lifecycle.\n *\n * Owns one decision: given what the caller passed and what the project\n * configured, which connectors does `setupTest` actually start? The precedence\n * is ratified in `contracts/2026-08-12-test-worker-lifecycle.md`:\n *\n * explicit non-`undefined` setupTest option > tests.connectors config > true\n */\nimport type { GenericObject } from \"@mongez/reinforcements\";\nimport { config } from \"../config\";\nimport type { ConnectorName } from \"../connectors\";\n\n/**\n * What a test runtime was asked to start.\n *\n * - `false` — bootstrap the runtime, start no connectors.\n * - `true` — start the framework's default connector set.\n * - an array — start exactly those. Order is not promised; lifecycle priority\n * decides the real boot/shutdown order.\n */\nexport type TestConnectorsSelection = boolean | ConnectorName[];\n\n/**\n * A caller's request, before the lower precedence layers are consulted.\n *\n * The distinction that matters is \"did the caller supply a value at all\", not\n * \"what value\" — `setupTest({ connectors: undefined })` must fall through to\n * project config exactly like `setupTest()` does, so an optional variable\n * holding `undefined` can never silently erase a project's configuration.\n */\nexport type RequestedTestConnectors =\n | { readonly isExplicit: true; readonly selection: TestConnectorsSelection }\n | { readonly isExplicit: false };\n\n/**\n * Classify the caller's `connectors` option as explicit or deferred.\n */\nexport function readRequestedConnectors(\n selection: TestConnectorsSelection | undefined,\n): RequestedTestConnectors {\n if (selection === undefined) {\n return { isExplicit: false };\n }\n\n return { isExplicit: true, selection };\n}\n\n/**\n * Read the `tests.connectors` config layer, or `undefined` when the project has\n * not configured one.\n *\n * Only meaningful once config files are loaded — before that, every project\n * looks like a project without a `tests` config.\n */\nexport function readConfiguredConnectors(): TestConnectorsSelection | undefined {\n // The default matters: `config.get` resolves an absent key to its default, and\n // ITS default is `null` — not `{}`. `warlock add test` does not generate\n // `src/config/tests.ts`, so reading `.connectors` off the result threw\n // \"Cannot read properties of null\" on the generated default path.\n const testsConfig = config.get<GenericObject>(\"tests\", {});\n\n // Cast at the config boundary: `GenericObject` values are untyped, and this is\n // the one place the untyped value becomes a typed selection.\n return testsConfig?.connectors as TestConnectorsSelection | undefined;\n}\n\n/**\n * Apply the ratified precedence:\n *\n * explicit non-`undefined` setupTest option > tests.connectors config > true\n *\n * ⚠ This is the reverse of 4.13, where config won over the parameter. Explicit\n * call-site intent beats a project default; a call that supplied nothing is not\n * intent, which is why \"omitted\" and \"explicitly `undefined`\" both defer.\n */\nexport function resolveEffectiveConnectors(\n requested: RequestedTestConnectors,\n): TestConnectorsSelection {\n if (requested.isExplicit) {\n return requested.selection;\n }\n\n const configured = readConfiguredConnectors();\n\n if (configured !== undefined) {\n return configured;\n }\n\n return true;\n}\n\n/**\n * Deduplicate a connector list and put it in a stable order.\n *\n * Two callers naming the same connectors in a different order asked for the same\n * thing, so the lifecycle must not treat them as a conflict.\n */\nexport function normalizeConnectorNames(names: ConnectorName[]): ConnectorName[] {\n return [...new Set(names)].sort();\n}\n\n/**\n * Compare two selections by normalized semantics — arrays as deduplicated sets,\n * never by caller order.\n */\nexport function isSameConnectorsSelection(\n left: TestConnectorsSelection,\n right: TestConnectorsSelection,\n): boolean {\n if (Array.isArray(left) && Array.isArray(right)) {\n const normalizedLeft = normalizeConnectorNames(left);\n const normalizedRight = normalizeConnectorNames(right);\n\n return (\n normalizedLeft.length === normalizedRight.length &&\n normalizedLeft.every((name, index) => name === normalizedRight[index])\n );\n }\n\n return left === right;\n}\n\n/**\n * Render a selection for an error message a caller can act on.\n */\nexport function describeConnectorsSelection(selection: TestConnectorsSelection): string {\n if (selection === true) {\n return \"the default connector set (`connectors: true`)\";\n }\n\n if (selection === false) {\n return \"no connectors (`connectors: false`)\";\n }\n\n const names = normalizeConnectorNames(selection)\n .map((name) => `\"${name}\"`)\n .join(\", \");\n\n return `\\`connectors: [${names}]\\``;\n}\n"],"mappings":";;;;;;;AAsCA,SAAgB,wBACd,WACyB;CACzB,IAAI,cAAc,QAChB,OAAO,EAAE,YAAY,MAAM;CAG7B,OAAO;EAAE,YAAY;EAAM;CAAU;AACvC;;;;;;;;AASA,SAAgB,2BAAgE;CAS9E,OAJoB,OAAO,IAAmB,SAAS,CAAC,CAIvC,GAAG;AACtB;;;;;;;;;;AAWA,SAAgB,2BACd,WACyB;CACzB,IAAI,UAAU,YACZ,OAAO,UAAU;CAGnB,MAAM,aAAa,yBAAyB;CAE5C,IAAI,eAAe,QACjB,OAAO;CAGT,OAAO;AACT;;;;;;;AAQA,SAAgB,wBAAwB,OAAyC;CAC/E,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,EAAE,KAAK;AAClC;;;;;AAMA,SAAgB,0BACd,MACA,OACS;CACT,IAAI,MAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK,GAAG;EAC/C,MAAM,iBAAiB,wBAAwB,IAAI;EACnD,MAAM,kBAAkB,wBAAwB,KAAK;EAErD,OACE,eAAe,WAAW,gBAAgB,UAC1C,eAAe,OAAO,MAAM,UAAU,SAAS,gBAAgB,MAAM;CAEzE;CAEA,OAAO,SAAS;AAClB;;;;AAKA,SAAgB,4BAA4B,WAA4C;CACtF,IAAI,cAAc,MAChB,OAAO;CAGT,IAAI,cAAc,OAChB,OAAO;CAOT,OAAO,kBAJO,wBAAwB,SAAS,EAC5C,KAAK,SAAS,IAAI,KAAK,EAAE,EACzB,KAAK,IAEqB,EAAE;AACjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-helpers.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-helpers.d.mts","names":[],"sources":["../../../../../../../core/src/tests/test-helpers.ts"],"mappings":";;AAYA;;;;AAAgC;AAehC;;AAfgC,iBAAhB,gBAAA,CAAA;;;;;iBAeM,WAAA,CAAY,IAAA,UAAc,OAAA,GAAS,WAAA,GAAmB,OAAA,CAAQ,QAAA;;;;iBAgD9D,OAAA,CAAQ,IAAA,UAAc,OAAA,GAAS,WAAA,GAAmB,OAAA,CAAQ,QAAA;;;AAhDY;iBAuDtE,QAAA,CACpB,IAAA,UACA,IAAA,YACA,OAAA,GAAS,WAAA,GACR,OAAA,CAAQ,QAAA;;;;iBAOW,OAAA,CACpB,IAAA,UACA,IAAA,YACA,OAAA,GAAS,WAAA,GACR,OAAA,CAAQ,QAAA;;;;iBAOW,UAAA,CAAW,IAAA,UAAc,OAAA,GAAS,WAAA,GAAmB,OAAA,CAAQ,QAAA;;;;iBAO7D,SAAA,CACpB,IAAA,UACA,IAAA,YACA,OAAA,GAAS,WAAA,GACR,OAAA,CAAQ,QAAA;;AAxC6E;AAOxF;iBAwCsB,iBAAA,GAAA,CAAqB,QAAA,EAAU,QAAA,GAAW,OAAA,CAAQ,CAAA;;;;iBAOlD,UAAA,GAAA,CAAc,QAAA,EAAU,QAAA,EAAU,cAAA,YAAuB,OAAA,CAAQ,CAAA"}
|
|
@@ -2,7 +2,7 @@ import { config } from "../config/config-getter.mjs";
|
|
|
2
2
|
import "../config/index.mjs";
|
|
3
3
|
import { TEST_SERVER_PORT_ENV_KEY } from "./test-server-port-channel.mjs";
|
|
4
4
|
|
|
5
|
-
//#region core/src/tests/test-helpers.ts
|
|
5
|
+
//#region ../core/src/tests/test-helpers.ts
|
|
6
6
|
/**
|
|
7
7
|
* Warlock.js Test Helpers
|
|
8
8
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-helpers.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-helpers.mjs","names":[],"sources":["../../../../../../../core/src/tests/test-helpers.ts"],"sourcesContent":["/**\n * Warlock.js Test Helpers\n *\n * Utilities for testing Warlock.js applications.\n */\n\nimport { config } from \"../config\";\nimport { TEST_SERVER_PORT_ENV_KEY } from \"./test-server-port-channel\";\n\n/**\n * Get the test server base URL\n */\nexport function getTestServerUrl(): string {\n // `startHttpTestServer` publishes the port it actually bound. Test workers are\n // separate processes whose own config resolves `http.port` from `.env`, so\n // without this a suite started on an explicit port would send every request to\n // the `.env` port instead of the one the server is listening on.\n const publishedPort = process.env[TEST_SERVER_PORT_ENV_KEY];\n const port = publishedPort || config.key(\"http.port\", 2031);\n const host = config.key(\"http.host\", \"localhost\");\n return `http://${host}:${port}`;\n}\n\n/**\n * Simple HTTP request helper for test server\n * Uses native fetch - lightweight, no extra dependencies\n */\nexport async function testRequest(path: string, options: RequestInit = {}): Promise<Response> {\n return sendRequest(path, options, false);\n}\n\n/**\n * The single place a request is actually built.\n *\n * `serializedJson` says whether THIS module turned the caller's value into a\n * JSON string. It is the only thing that justifies setting a JSON content type:\n * a `FormData` body carries a multipart boundary the runtime generates, and\n * labelling it `application/json` produces a request no server can parse.\n */\nasync function sendRequest(\n path: string,\n options: RequestInit,\n serializedJson: boolean,\n): Promise<Response> {\n const baseUrl = getTestServerUrl();\n const url = path.startsWith(\"/\") ? `${baseUrl}${path}` : `${baseUrl}/${path}`;\n\n // Normalised through `Headers` rather than object-spread: `RequestInit.headers`\n // may be a record, a `Headers` instance, or a list of `[name, value]` tuples,\n // and spreading the last two silently produces an object with numeric keys —\n // the header is simply lost, with no error anywhere.\n const headers = new Headers(options.headers);\n\n if (serializedJson && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n\n return fetch(url, { ...options, headers });\n}\n\n/**\n * Serialize a body for a JSON request.\n *\n * `undefined` means the caller omitted the argument; every other value —\n * including `false`, `0`, `\"\"` and `null` — is a legal JSON document and must\n * be sent. The old check was `body ? JSON.stringify(body) : undefined`, which\n * dropped all four.\n */\nfunction jsonBody(body: unknown): string | undefined {\n return body === undefined ? undefined : JSON.stringify(body);\n}\n\n/**\n * GET request helper\n */\nexport async function testGet(path: string, options: RequestInit = {}): Promise<Response> {\n return testRequest(path, { ...options, method: \"GET\" });\n}\n\n/**\n * POST request helper\n */\nexport async function testPost(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n): Promise<Response> {\n return sendRequest(path, { ...options, method: \"POST\", body: jsonBody(body) }, body !== undefined);\n}\n\n/**\n * PUT request helper\n */\nexport async function testPut(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n): Promise<Response> {\n return sendRequest(path, { ...options, method: \"PUT\", body: jsonBody(body) }, body !== undefined);\n}\n\n/**\n * DELETE request helper\n */\nexport async function testDelete(path: string, options: RequestInit = {}): Promise<Response> {\n return testRequest(path, { ...options, method: \"DELETE\" });\n}\n\n/**\n * PATCH request helper\n */\nexport async function testPatch(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n): Promise<Response> {\n return sendRequest(path, { ...options, method: \"PATCH\", body: jsonBody(body) }, body !== undefined);\n}\n\n/**\n * Parse JSON response with type safety\n */\nexport async function parseJsonResponse<T>(response: Response): Promise<T> {\n return response.json() as Promise<T>;\n}\n\n/**\n * Assert response status and return parsed JSON\n */\nexport async function expectJson<T>(response: Response, expectedStatus = 200): Promise<T> {\n if (response.status !== expectedStatus) {\n const text = await response.text();\n throw new Error(`Expected status ${expectedStatus}, got ${response.status}. Body: ${text}`);\n }\n return parseJsonResponse<T>(response);\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,mBAA2B;CAMzC,MAAM,OADgB,QAAQ,mCACA,OAAO,IAAI,aAAa,IAAI;CAE1D,OAAO,UADM,OAAO,IAAI,aAAa,WACjB,EAAE,GAAG;AAC3B;;;;;AAMA,eAAsB,YAAY,MAAc,UAAuB,CAAC,GAAsB;CAC5F,OAAO,YAAY,MAAM,SAAS,KAAK;AACzC;;;;;;;;;AAUA,eAAe,YACb,MACA,SACA,gBACmB;CACnB,MAAM,UAAU,iBAAiB;CACjC,MAAM,MAAM,KAAK,WAAW,GAAG,IAAI,GAAG,UAAU,SAAS,GAAG,QAAQ,GAAG;CAMvE,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;CAE3C,IAAI,kBAAkB,CAAC,QAAQ,IAAI,cAAc,GAC/C,QAAQ,IAAI,gBAAgB,kBAAkB;CAGhD,OAAO,MAAM,KAAK;EAAE,GAAG;EAAS;CAAQ,CAAC;AAC3C;;;;;;;;;AAUA,SAAS,SAAS,MAAmC;CACnD,OAAO,SAAS,SAAY,SAAY,KAAK,UAAU,IAAI;AAC7D;;;;AAKA,eAAsB,QAAQ,MAAc,UAAuB,CAAC,GAAsB;CACxF,OAAO,YAAY,MAAM;EAAE,GAAG;EAAS,QAAQ;CAAM,CAAC;AACxD;;;;AAKA,eAAsB,SACpB,MACA,MACA,UAAuB,CAAC,GACL;CACnB,OAAO,YAAY,MAAM;EAAE,GAAG;EAAS,QAAQ;EAAQ,MAAM,SAAS,IAAI;CAAE,GAAG,SAAS,MAAS;AACnG;;;;AAKA,eAAsB,QACpB,MACA,MACA,UAAuB,CAAC,GACL;CACnB,OAAO,YAAY,MAAM;EAAE,GAAG;EAAS,QAAQ;EAAO,MAAM,SAAS,IAAI;CAAE,GAAG,SAAS,MAAS;AAClG;;;;AAKA,eAAsB,WAAW,MAAc,UAAuB,CAAC,GAAsB;CAC3F,OAAO,YAAY,MAAM;EAAE,GAAG;EAAS,QAAQ;CAAS,CAAC;AAC3D;;;;AAKA,eAAsB,UACpB,MACA,MACA,UAAuB,CAAC,GACL;CACnB,OAAO,YAAY,MAAM;EAAE,GAAG;EAAS,QAAQ;EAAS,MAAM,SAAS,IAAI;CAAE,GAAG,SAAS,MAAS;AACpG;;;;AAKA,eAAsB,kBAAqB,UAAgC;CACzE,OAAO,SAAS,KAAK;AACvB;;;;AAKA,eAAsB,WAAc,UAAoB,iBAAiB,KAAiB;CACxF,IAAI,SAAS,WAAW,gBAAgB;EACtC,MAAM,OAAO,MAAM,SAAS,KAAK;EACjC,MAAM,IAAI,MAAM,mBAAmB,eAAe,QAAQ,SAAS,OAAO,UAAU,MAAM;CAC5F;CACA,OAAO,kBAAqB,QAAQ;AACtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-lifecycle-state.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-lifecycle-state.mjs","names":[],"sources":["../../../../../../../core/src/tests/test-lifecycle-state.ts"],"sourcesContent":["/**\n * Lifecycle bookkeeping for the worker test runtime.\n *\n * Owns one thing: WHERE the state lives. `setupTest` / `teardownTest` own what\n * the transitions mean.\n *\n * The storage rule is the defect this module exists to fix. A module-scoped\n * `let` is rebuilt for every test file — measured across `forks|threads` ×\n * `isolate true|false` in `proofs/2026-08-12-nova-vitest-setupfiles-lifetime.md`\n * — while the worker itself, and every socket, pool and timer it holds, can\n * survive that rebuild. State that resets precisely where live resources do not\n * is not a guard; it is a lie about what is running.\n *\n * `globalThis` is the right scope for it: one per process for a fork worker, one\n * per thread for a thread worker, never shared between distinct workers — which\n * is exactly the boundary the resources themselves live inside.\n */\nimport type {\n RequestedTestConnectors,\n TestConnectorsSelection,\n} from \"./test-connectors-selection\";\nimport type { TestTimeoutScheduler } from \"./test-setup-timeout\";\n\n/**\n * The transitions the lifecycle serializes through.\n *\n * ```\n * idle -> starting -> ready -> stopping -> idle\n * \\-> poisoned\n * ```\n *\n * `poisoned` is reached when the shutdown layer reports a failure: the runtime\n * is neither up nor provably down, so the next `setupTest` must refuse rather\n * than stack a second runtime on top of leaked resources.\n *\n * @internal No state API is public.\n */\nexport type TestLifecycleState = \"idle\" | \"starting\" | \"ready\" | \"stopping\" | \"poisoned\";\n\n/**\n * The single in-flight setup attempt that concurrent `setupTest` callers share.\n *\n * @internal\n */\nexport type TestSetupAttempt = {\n /**\n * What the caller that opened the attempt asked for, before config was read.\n */\n readonly requested: RequestedTestConnectors;\n\n /**\n * Settles once the attempt has consulted project config, and therefore doubles\n * as the \"config is readable now\" barrier a later caller needs before it can\n * resolve its own config-derived selection and compare the two. Rejects with\n * the startup error when the attempt fails before reaching that point.\n */\n readonly effectiveSelection: Promise<TestConnectorsSelection>;\n\n /**\n * The attempt itself. Resolves when the runtime is ready, rejects with the\n * original startup error.\n */\n readonly completion: Promise<void>;\n};\n\n/**\n * @internal\n */\nexport type TestLifecycleRegistry = {\n state: TestLifecycleState;\n activeSelection?: TestConnectorsSelection;\n setupAttempt?: TestSetupAttempt;\n teardownAttempt?: Promise<void>;\n\n /**\n * How the setup bound is scheduled. Specs replace it to prove the guard in\n * milliseconds rather than outliving a real two-minute timeout; production\n * leaves it unset and gets {@link scheduleRealTimeout}.\n *\n * It lives here, on the runtime-context registry, for the same reason the\n * state does: a spec that could only reach a module-level slot would be\n * relying on the very rebuild this module exists to survive.\n */\n scheduleTimeout?: TestTimeoutScheduler;\n\n /**\n * Overrides `tests.setupTimeout` and the default. Internal, for specs — the\n * public surface stays the `setupTest` / `teardownTest` pair.\n */\n setupTimeoutOverride?: number;\n};\n\n/**\n * Where the registry hangs off the runtime context.\n *\n * @internal Exported for specs, which must be able to reach the same slot the\n * implementation uses — a spec that could only reset module state would be\n * testing the very assumption this module rejects. Deliberately not re-exported\n * from `src/tests/index.ts`.\n */\nexport const TEST_LIFECYCLE_REGISTRY_KEY = Symbol.for(\"@warlock.js/core:tests:lifecycle\");\n\ntype TestLifecycleHost = typeof globalThis & {\n [TEST_LIFECYCLE_REGISTRY_KEY]?: TestLifecycleRegistry;\n};\n\n/**\n * Read the runtime context's lifecycle registry, creating it on first use.\n *\n * @internal\n */\nexport function getTestLifecycleRegistry(): TestLifecycleRegistry {\n const host = globalThis as TestLifecycleHost;\n const registry = host[TEST_LIFECYCLE_REGISTRY_KEY];\n\n if (registry) {\n return registry;\n }\n\n const freshRegistry: TestLifecycleRegistry = { state: \"idle\" };\n\n host[TEST_LIFECYCLE_REGISTRY_KEY] = freshRegistry;\n\n return freshRegistry;\n}\n"],"mappings":";;;;;;;;;AAoGA,MAAa,8BAA8B,OAAO,IAAI,kCAAkC;;;;;;AAWxF,SAAgB,2BAAkD;CAChE,MAAM,OAAO;CACb,MAAM,WAAW,KAAK;CAEtB,IAAI,UACF,OAAO;CAGT,MAAM,gBAAuC,EAAE,OAAO,OAAO;CAE7D,KAAK,+BAA+B;CAEpC,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-server-port-channel.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-server-port-channel.mjs","names":[],"sources":["../../../../../../../core/src/tests/test-server-port-channel.ts"],"sourcesContent":["/**\n * The channel `startHttpTestServer` uses to tell test workers which port it\n * bound.\n *\n * Vitest runs `globalSetup` in the main process and each test file in its own\n * worker, so the workers do not share the main process's resolved config — they\n * re-resolve `http.port` from `.env`. An environment variable is the one thing a\n * worker inherits from the process that spawned it, which makes it the only\n * channel an explicit port can travel through.\n *\n * This is process plumbing between two of our own processes, not application\n * configuration — app code still reads its port through `config`.\n */\nexport const TEST_SERVER_PORT_ENV_KEY = \"WARLOCK_TEST_SERVER_PORT\";\n\n/**\n * Publish the port the test server bound, for the workers to read.\n */\nexport function publishTestServerPort(port: number): void {\n process.env[TEST_SERVER_PORT_ENV_KEY] = String(port);\n}\n\n/**\n * Withdraw the published port on shutdown, so a later run in the same process\n * can't inherit a stale one.\n */\nexport function withdrawTestServerPort(): void {\n delete process.env[TEST_SERVER_PORT_ENV_KEY];\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,2BAA2B;;;;AAKxC,SAAgB,sBAAsB,MAAoB;CACxD,QAAQ,IAAI,4BAA4B,OAAO,IAAI;AACrD;;;;;AAMA,SAAgB,yBAA+B;CAC7C,OAAO,QAAQ,IAAI;AACrB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { config } from "../config/config-getter.mjs";
|
|
2
2
|
import "../config/index.mjs";
|
|
3
3
|
|
|
4
|
-
//#region core/src/tests/test-setup-timeout.ts
|
|
4
|
+
//#region ../core/src/tests/test-setup-timeout.ts
|
|
5
5
|
/**
|
|
6
6
|
* Two minutes. Chosen to sit far above any healthy bootstrap and far below the
|
|
7
7
|
* point where a human stops watching — a stuck worker should announce itself
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-setup-timeout.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"test-setup-timeout.mjs","names":[],"sources":["../../../../../../../core/src/tests/test-setup-timeout.ts"],"sourcesContent":["/**\n * The setup bound for the worker test lifecycle.\n *\n * Owns one decision: how long a `setupTest` attempt may run before the\n * lifecycle gives up on it. `vitest-setup.ts` owns what giving up MEANS.\n *\n * This is a HANG GUARD, not a startup-performance deadline. A cold database, a\n * container that has just been started, a first-run migration — all of those are\n * legitimately slow and none of them are a stuck lifecycle. The default is\n * therefore generous on purpose: it exists so that a setup which will never\n * finish fails with a sentence a caller can act on, instead of stranding the\n * lifecycle in `starting` where `teardownTest`'s wait-then-re-enter path spins\n * until the worker dies of heap exhaustion.\n */\nimport type { GenericObject } from \"@mongez/reinforcements\";\nimport { config } from \"../config\";\n\n/**\n * Two minutes. Chosen to sit far above any healthy bootstrap and far below the\n * point where a human stops watching — a stuck worker should announce itself\n * while someone is still looking at the terminal.\n */\nexport const DEFAULT_TEST_SETUP_TIMEOUT = 120_000;\n\n/**\n * A scheduled expiry the lifecycle can cancel when the attempt settles first.\n *\n * @internal\n */\nexport type TestTimeoutHandle = {\n cancel: () => void;\n};\n\n/**\n * How the lifecycle schedules its expiry.\n *\n * Injectable so a spec can prove the bound in milliseconds instead of outliving\n * a real one — see {@link TestLifecycleRegistry.scheduleTimeout}. Deliberately\n * internal: the public API stays the `setupTest` / `teardownTest` pair.\n *\n * @internal\n */\nexport type TestTimeoutScheduler = (\n timeout: number,\n onExpiry: () => void,\n) => TestTimeoutHandle;\n\n/**\n * The real scheduler.\n *\n * `unref` matters: a pending hang guard must never be the reason a worker stays\n * alive after its tests have finished.\n *\n * @internal\n */\nexport const scheduleRealTimeout: TestTimeoutScheduler = (timeout, onExpiry) => {\n const timer = setTimeout(onExpiry, timeout);\n\n timer.unref?.();\n\n return { cancel: () => clearTimeout(timer) };\n};\n\n/**\n * Read `tests.setupTimeout`, or `undefined` when the project has not set one.\n *\n * Only meaningful once config files are loaded — before that, every project\n * looks like a project without a `tests` config.\n *\n * @throws when the key is present but is not a positive finite number of\n * milliseconds. Falling back to the default would silently erase a project's\n * configuration, which is the same defect the connector precedence rules out.\n */\nexport function readConfiguredSetupTimeout(): number | undefined {\n // `config.get` resolves an absent key to its default, and ITS default is\n // `null` — not `{}` — so the explicit `{}` is what keeps this from throwing\n // \"Cannot read properties of null\" on a project with no `src/config/tests.ts`.\n const testsConfig = config.get<GenericObject>(\"tests\", {});\n const configured = testsConfig?.setupTimeout as unknown;\n\n if (configured === undefined) {\n return undefined;\n }\n\n if (typeof configured !== \"number\" || !Number.isFinite(configured) || configured <= 0) {\n throw new Error(\n `tests.setupTimeout must be a positive number of milliseconds, but it is ${JSON.stringify(configured)}. Remove the key to use the default of ${DEFAULT_TEST_SETUP_TIMEOUT}ms.`,\n );\n }\n\n return configured;\n}\n\n/**\n * The message a caller sees when the bound expires.\n *\n * Names three things, because a hang guard that only says \"timed out\" sends the\n * reader to the framework's source: what state the lifecycle is stuck in, what\n * bound it exceeded, and how to raise that bound.\n */\nexport function describeExpiredSetup(timeout: number): string {\n return (\n `setupTest() did not finish within ${timeout}ms and is stuck in the \"starting\" state. ` +\n \"The lifecycle is now poisoned: whatever that attempt had already started is not known to be \" +\n \"closed, so later setupTest() calls refuse until the Vitest worker is recycled. \" +\n `If your cold start is legitimately slower than this, raise the bound with \\`tests.setupTimeout\\` ` +\n `in \\`src/config/tests.ts\\` — milliseconds, default ${DEFAULT_TEST_SETUP_TIMEOUT}.`\n );\n}\n"],"mappings":";;;;;;;;;AAsBA,MAAa,6BAA6B;;;;;;;;;AAiC1C,MAAa,uBAA6C,SAAS,aAAa;CAC9E,MAAM,QAAQ,WAAW,UAAU,OAAO;CAE1C,MAAM,QAAQ;CAEd,OAAO,EAAE,cAAc,aAAa,KAAK,EAAE;AAC7C;;;;;;;;;;;AAYA,SAAgB,6BAAiD;CAK/D,MAAM,aADc,OAAO,IAAmB,SAAS,CAAC,CAC3B,GAAG;CAEhC,IAAI,eAAe,QACjB;CAGF,IAAI,OAAO,eAAe,YAAY,CAAC,OAAO,SAAS,UAAU,KAAK,cAAc,GAClF,MAAM,IAAI,MACR,2EAA2E,KAAK,UAAU,UAAU,EAAE,yCAAyC,2BAA2B,IAC5K;CAGF,OAAO;AACT;;;;;;;;AASA,SAAgB,qBAAqB,SAAyB;CAC5D,OACE,qCAAqC,QAAQ,0WAIS,2BAA2B;AAErF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-setup.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"vitest-setup.d.mts","names":[],"sources":["../../../../../../../core/src/tests/vitest-setup.ts"],"mappings":";;;KAoDY,gBAAA;EAAA;;;;AAS0B;AAOtC;;;EAPE,UAAA,GAAa,uBAAuB;AAAA;;;;AAQF;cADvB,kBAAA,SAA2B,KAAK;cACxB,OAAA;AAAA;;;;;;AAqC+C;AAgDpE;;;;AAA6C;;;;;;;;;;;;;;;;;iBAhDvB,SAAA,CAAU,OAAA,GAAU,gBAAA,GAAmB,OAAO;;;;;;;;;;;;;;;;;;iBAgD9C,YAAA,CAAA,GAAgB,OAAO"}
|
|
@@ -9,7 +9,7 @@ import { describeConnectorsSelection, isSameConnectorsSelection, normalizeConnec
|
|
|
9
9
|
import { getTestLifecycleRegistry } from "./test-lifecycle-state.mjs";
|
|
10
10
|
import { DEFAULT_TEST_SETUP_TIMEOUT, describeExpiredSetup, readConfiguredSetupTimeout, scheduleRealTimeout } from "./test-setup-timeout.mjs";
|
|
11
11
|
|
|
12
|
-
//#region core/src/tests/vitest-setup.ts
|
|
12
|
+
//#region ../core/src/tests/vitest-setup.ts
|
|
13
13
|
/**
|
|
14
14
|
* Worker test lifecycle — `setupTest` / `teardownTest`.
|
|
15
15
|
*
|