@warlock.js/core 5.31.0 → 5.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/esm/application/app.d.mts +3 -3
- package/esm/application/app.d.mts.map +1 -1
- package/esm/application/application-config-types.d.mts +9 -2
- package/esm/application/application-config-types.d.mts.map +1 -1
- package/esm/application/application.d.mts +5 -7
- package/esm/application/application.d.mts.map +1 -1
- package/esm/application/application.mjs +3 -1
- package/esm/application/application.mjs.map +1 -1
- package/esm/application/boot-signal.d.mts +22 -20
- package/esm/application/boot-signal.d.mts.map +1 -1
- package/esm/application/boot-signal.mjs +15 -9
- package/esm/application/boot-signal.mjs.map +1 -1
- package/esm/application/index.d.mts +2 -1
- package/esm/application/index.mjs +1 -1
- package/esm/application/public-url.d.mts +1 -2
- package/esm/application/public-url.d.mts.map +1 -1
- package/esm/application/roles.d.mts +10 -11
- package/esm/application/roles.d.mts.map +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts +1 -3
- package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
- package/esm/benchmark/benchmark.d.mts +1 -3
- package/esm/benchmark/benchmark.d.mts.map +1 -1
- package/esm/benchmark/channels/console.channel.d.mts +1 -3
- package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts +1 -3
- package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
- package/esm/benchmark/index.mjs +1 -1
- package/esm/benchmark/profiler.d.mts +1 -3
- package/esm/benchmark/profiler.d.mts.map +1 -1
- package/esm/benchmark/profiler.mjs +2 -1
- package/esm/benchmark/profiler.mjs.map +1 -1
- package/esm/benchmark/types.d.mts +22 -17
- package/esm/benchmark/types.d.mts.map +1 -1
- package/esm/bootstrap/setup.d.mts +1 -2
- package/esm/bootstrap/setup.d.mts.map +1 -1
- package/esm/bootstrap.d.mts +1 -2
- package/esm/bootstrap.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.d.mts +3 -5
- package/esm/cache/database-cache-driver.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.mjs +1 -1
- package/esm/cache/index.d.mts +2 -1
- package/esm/cache/index.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs +6 -3
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/commands/agents-md/agents-md-command.action.mjs +3 -2
- package/esm/cli/commands/agents-md/agents-md-command.action.mjs.map +1 -1
- package/esm/cli/commands/ai/ai-command.action.mjs +140 -0
- package/esm/cli/commands/ai/ai-command.action.mjs.map +1 -0
- package/esm/cli/commands/ai.command.mjs +50 -0
- package/esm/cli/commands/ai.command.mjs.map +1 -0
- package/esm/cli/commands/board/board-command.action.mjs +1 -1
- package/esm/cli/commands/check/check-command.action.mjs +4 -1
- package/esm/cli/commands/check/check-command.action.mjs.map +1 -1
- package/esm/cli/commands/check/child-typecheck.mjs +1 -1
- package/esm/cli/commands/check/child-typecheck.mjs.map +1 -1
- package/esm/cli/commands/check/format-problems.mjs +1 -1
- package/esm/cli/commands/check.command.mjs +6 -1
- package/esm/cli/commands/check.command.mjs.map +1 -1
- package/esm/cli/commands/dev-server.command.mjs +3 -2
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/cli/commands/doctor/check.types.d.mts +29 -16
- package/esm/cli/commands/doctor/check.types.d.mts.map +1 -1
- package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +22 -27
- package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs +2 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
- package/esm/cli/commands/explain/explain-command.action.mjs +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs +5 -2
- package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs +5 -3
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs +3 -2
- package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs +3 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs +3 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs +3 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/templates/endpoint-stubs.mjs +2 -2
- package/esm/cli/commands/generate/templates/endpoint-stubs.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/endpoint-schema.mjs +1 -2
- package/esm/cli/commands/generate/utils/endpoint-schema.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
- package/esm/cli/commands/inspect/inspect-command.action.mjs +3 -2
- package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -1
- package/esm/cli/commands/issue/collect-environment.mjs +187 -0
- package/esm/cli/commands/issue/collect-environment.mjs.map +1 -0
- package/esm/cli/commands/issue/issue-command.action.mjs +70 -0
- package/esm/cli/commands/issue/issue-command.action.mjs.map +1 -0
- package/esm/cli/commands/issue.command.mjs +31 -0
- package/esm/cli/commands/issue.command.mjs.map +1 -0
- package/esm/cli/commands/mcp/mcp-command.action.mjs +15 -14
- package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -1
- package/esm/cli/commands/openapi-generator.action.mjs +1 -1
- package/esm/cli/commands/pm2/pm2-command.action.mjs +91 -0
- package/esm/cli/commands/pm2/pm2-command.action.mjs.map +1 -0
- package/esm/cli/commands/pm2/pm2-config.mjs +115 -0
- package/esm/cli/commands/pm2/pm2-config.mjs.map +1 -0
- package/esm/cli/commands/pm2.command.mjs +53 -0
- package/esm/cli/commands/pm2.command.mjs.map +1 -0
- package/esm/cli/commands/postman-generator.action.mjs +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
- package/esm/cli/commands/routes/route-row.mjs +1 -1
- package/esm/cli/commands/routes/routes-diff.action.mjs +2 -2
- package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
- package/esm/cli/commands/test.command.mjs +1 -1
- package/esm/cli/commands/trace/trace-command.action.mjs +1 -1
- package/esm/cli/commands-loader.mjs +1 -1
- package/esm/cli/framework-cli-commands.mjs +6 -0
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/cli/parse-cli-args.mjs +2 -2
- package/esm/cli/parse-cli-args.mjs.map +1 -1
- package/esm/cli/start.d.mts +1 -1
- package/esm/cli/string-similarity.mjs +1 -1
- package/esm/commands/cli-command.d.mts +2 -4
- package/esm/commands/cli-command.d.mts.map +1 -1
- package/esm/commands/index.d.mts +2 -1
- package/esm/commands/index.mjs +1 -1
- package/esm/commands/types.d.mts +8 -8
- package/esm/commands/types.d.mts.map +1 -1
- package/esm/config/config-getter.d.mts +2 -3
- package/esm/config/config-getter.d.mts.map +1 -1
- package/esm/config/config-getter.mjs +5 -5
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-handlers.d.mts +1 -3
- package/esm/config/config-handlers.d.mts.map +1 -1
- package/esm/config/config-loader.d.mts +1 -2
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +3 -3
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/config-manager.mjs +1 -1
- package/esm/config/config-schema.d.mts +19 -16
- package/esm/config/config-schema.d.mts.map +1 -1
- package/esm/config/config-setter.d.mts +2 -4
- package/esm/config/config-setter.d.mts.map +1 -1
- package/esm/config/config-setter.mjs +2 -2
- package/esm/config/config-setter.mjs.map +1 -1
- package/esm/config/config-special-handlers.d.mts +2 -4
- package/esm/config/config-special-handlers.d.mts.map +1 -1
- package/esm/config/index.d.mts +2 -1
- package/esm/config/index.mjs +1 -1
- package/esm/config/types.d.mts +4 -5
- package/esm/config/types.d.mts.map +1 -1
- package/esm/connectors/access-connector.d.mts +1 -3
- package/esm/connectors/access-connector.d.mts.map +1 -1
- package/esm/connectors/access-connector.mjs +2 -2
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.d.mts +1 -3
- package/esm/connectors/ai-connector.d.mts.map +1 -1
- package/esm/connectors/ai-connector.mjs +2 -2
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -3
- package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-unique-connector-names.d.mts +1 -3
- package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-unique-connector-names.mjs +2 -1
- package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
- package/esm/connectors/base-connector.d.mts +1 -3
- package/esm/connectors/base-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.d.mts +1 -3
- package/esm/connectors/cache-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.mjs +3 -3
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/connectors-manager.d.mts +2 -4
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +3 -6
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/database-connector.d.mts +1 -3
- package/esm/connectors/database-connector.d.mts.map +1 -1
- package/esm/connectors/database-connector.mjs +2 -2
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/describe-server-address.mjs +4 -4
- package/esm/connectors/describe-server-address.mjs.map +1 -1
- package/esm/connectors/herald-connector.d.mts +1 -3
- package/esm/connectors/herald-connector.d.mts.map +1 -1
- package/esm/connectors/herald-connector.mjs +2 -2
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts +1 -3
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +8 -7
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/index.d.mts +2 -1
- package/esm/connectors/index.mjs +1 -1
- package/esm/connectors/logger-connector.d.mts +1 -3
- package/esm/connectors/logger-connector.d.mts.map +1 -1
- package/esm/connectors/logger-connector.mjs +2 -2
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.d.mts +1 -3
- package/esm/connectors/mail-connector.d.mts.map +1 -1
- package/esm/connectors/mail-connector.mjs +2 -2
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.d.mts +1 -3
- package/esm/connectors/notifications-connector.d.mts.map +1 -1
- package/esm/connectors/notifications-connector.mjs +2 -2
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/register-configured-connectors.d.mts +2 -4
- package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
- package/esm/connectors/shutdown-timeout.mjs +7 -0
- package/esm/connectors/shutdown-timeout.mjs.map +1 -0
- package/esm/connectors/socket-connector.d.mts +1 -3
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +20 -11
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/connectors/storage.connector.d.mts +1 -3
- package/esm/connectors/storage.connector.d.mts.map +1 -1
- package/esm/connectors/storage.connector.mjs +2 -2
- package/esm/connectors/storage.connector.mjs.map +1 -1
- package/esm/connectors/types.d.mts +17 -14
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/container/container-instance-registry.mjs.map +1 -1
- package/esm/container/development-app-modules.d.mts +7 -5
- package/esm/container/development-app-modules.d.mts.map +1 -1
- package/esm/container/development-model-modules.d.mts +6 -5
- package/esm/container/development-model-modules.d.mts.map +1 -1
- package/esm/container/index.d.mts +4 -4
- package/esm/container/index.d.mts.map +1 -1
- package/esm/database/index.d.mts +3 -1
- package/esm/database/index.mjs +1 -1
- package/esm/database/migrate-action.mjs +1 -1
- package/esm/database/models/database-log/database-log.d.mts +2 -3
- package/esm/database/models/database-log/database-log.d.mts.map +1 -1
- package/esm/database/models/database-log/index.d.mts +2 -1
- package/esm/database/models/database-log/index.mjs +1 -1
- package/esm/database/seed-command-action.mjs +1 -1
- package/esm/database/seeds/seeder.d.mts +2 -4
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +2 -3
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +2 -1
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +7 -8
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/utils.d.mts +4 -5
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/dev-server/app-module-registry.mjs +1 -1
- package/esm/dev-server/create-worker.mjs +5 -3
- package/esm/dev-server/create-worker.mjs.map +1 -1
- package/esm/dev-server/dependency-graph.d.mts +1 -3
- package/esm/dev-server/dependency-graph.d.mts.map +1 -1
- package/esm/dev-server/dependency-graph.mjs +1 -1
- package/esm/dev-server/dependency-graph.mjs.map +1 -1
- package/esm/dev-server/extract-translation-keys.mjs +16 -17
- package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +3 -7
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-operations.d.mts +1 -3
- package/esm/dev-server/file-operations.d.mts.map +1 -1
- package/esm/dev-server/files-watcher.mjs +12 -11
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +6 -8
- 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 +36 -115
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/default-health-checkers.mjs +6 -15
- package/esm/dev-server/health-checker/default-health-checkers.mjs.map +1 -1
- package/esm/dev-server/health-checker/eslint-support.mjs +27 -0
- package/esm/dev-server/health-checker/eslint-support.mjs.map +1 -0
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +7 -6
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts +2 -2
- package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -0
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
- package/esm/dev-server/health-checker/oxlint-runner.mjs +6 -5
- package/esm/dev-server/health-checker/oxlint-runner.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +2 -11
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/oxlint-health.worker.d.mts +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.d.mts +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +40 -174
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts +4 -8
- package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.d.mts +10 -6
- package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.mjs +4 -3
- package/esm/dev-server/loader/load-hook.mjs.map +1 -1
- package/esm/dev-server/loader/own-resolver.mjs +1 -1
- package/esm/dev-server/loader/register-loader.mjs +3 -2
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts +2 -2
- package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs +2 -1
- package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs +2 -1
- package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
- package/esm/dev-server/manifest-manager.d.mts +1 -3
- package/esm/dev-server/manifest-manager.d.mts.map +1 -1
- package/esm/dev-server/model-module-registry.mjs +3 -3
- package/esm/dev-server/model-module-registry.mjs.map +1 -1
- package/esm/dev-server/model-resource-typings.mjs +40 -47
- package/esm/dev-server/model-resource-typings.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs +2 -2
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/package-json-manager.mjs +1 -1
- package/esm/dev-server/parse-imports.mjs +6 -38
- package/esm/dev-server/parse-imports.mjs.map +1 -1
- package/esm/dev-server/read-config-ast.mjs +3 -33
- package/esm/dev-server/read-config-ast.mjs.map +1 -1
- package/esm/dev-server/ready-block.mjs +1 -1
- package/esm/dev-server/shortcuts.mjs +1 -1
- package/esm/dev-server/special-files-collector.d.mts +2 -4
- package/esm/dev-server/special-files-collector.d.mts.map +1 -1
- package/esm/dev-server/supervisor.mjs +1 -1
- package/esm/dev-server/tsconfig-manager.mjs +3 -3
- package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs +28 -35
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/dev-server/types.d.mts +3 -4
- package/esm/dev-server/types.d.mts.map +1 -1
- package/esm/dev-server/update-check-cache.mjs +2 -2
- package/esm/dev-server/update-check-cache.mjs.map +1 -1
- package/esm/encryption/encrypt.d.mts +2 -3
- package/esm/encryption/encrypt.d.mts.map +1 -1
- package/esm/encryption/hash.d.mts +1 -2
- package/esm/encryption/hash.d.mts.map +1 -1
- package/esm/encryption/index.mjs +1 -1
- package/esm/encryption/password.d.mts +2 -3
- package/esm/encryption/password.d.mts.map +1 -1
- package/esm/encryption/types.d.mts +2 -3
- package/esm/encryption/types.d.mts.map +1 -1
- package/esm/errors/error-codes.d.mts +29 -22
- package/esm/errors/error-codes.d.mts.map +1 -1
- package/esm/errors/warlock-error.d.mts +1 -3
- package/esm/errors/warlock-error.d.mts.map +1 -1
- package/esm/generations/add-command.action.mjs +3 -2
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/features/bull-board.feature.mjs +2 -1
- package/esm/generations/features/bull-board.feature.mjs.map +1 -1
- package/esm/generations/features/index.mjs +2 -0
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs +2 -1
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/process.feature.mjs +65 -0
- package/esm/generations/features/process.feature.mjs.map +1 -0
- package/esm/generations/features/shared/merge-web-sitemap-config.mjs +16 -23
- package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
- package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
- package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
- package/esm/generations/features/sitemap.feature.mjs +2 -1
- package/esm/generations/features/sitemap.feature.mjs.map +1 -1
- package/esm/generations/generation-fs.mjs +1 -1
- package/esm/generations/generation-run.mjs +1 -1
- package/esm/generations/stubs.mjs +1 -1
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/boot-port-preflight.d.mts +4 -5
- package/esm/http/boot-port-preflight.d.mts.map +1 -1
- package/esm/http/boot-port-preflight.mjs +2 -2
- package/esm/http/boot-port-preflight.mjs.map +1 -1
- package/esm/http/bounded-stream-queue.d.mts +4 -4
- package/esm/http/bounded-stream-queue.d.mts.map +1 -1
- package/esm/http/bounded-stream-queue.mjs +1 -1
- package/esm/http/bounded-stream-queue.mjs.map +1 -1
- package/esm/http/build-cors-options.mjs +2 -2
- package/esm/http/build-cors-options.mjs.map +1 -1
- package/esm/http/build-rate-limit-options.d.mts +2 -3
- package/esm/http/build-rate-limit-options.d.mts.map +1 -1
- package/esm/http/build-rate-limit-options.mjs +1 -1
- package/esm/http/build-rate-limit-options.mjs.map +1 -1
- package/esm/http/conditional-request.d.mts +14 -13
- package/esm/http/conditional-request.d.mts.map +1 -1
- package/esm/http/config.d.mts +2 -4
- package/esm/http/config.d.mts.map +1 -1
- package/esm/http/config.mjs +2 -2
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/context/request-context.d.mts +6 -7
- package/esm/http/context/request-context.d.mts.map +1 -1
- package/esm/http/context/request-memo.d.mts +1 -2
- package/esm/http/context/request-memo.d.mts.map +1 -1
- package/esm/http/createHttpApplication.d.mts +2 -3
- package/esm/http/createHttpApplication.d.mts.map +1 -1
- package/esm/http/createHttpApplication.mjs +2 -2
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/csp.d.mts +10 -12
- package/esm/http/csp.d.mts.map +1 -1
- package/esm/http/csp.mjs +2 -2
- package/esm/http/csp.mjs.map +1 -1
- package/esm/http/csrf-default-guard.d.mts +2 -4
- package/esm/http/csrf-default-guard.d.mts.map +1 -1
- package/esm/http/csrf-default-guard.mjs +1 -1
- package/esm/http/csrf-default-guard.mjs.map +1 -1
- package/esm/http/csrf-origin-policy.d.mts +7 -9
- package/esm/http/csrf-origin-policy.d.mts.map +1 -1
- package/esm/http/csrf-origin-policy.mjs +2 -2
- package/esm/http/csrf-origin-policy.mjs.map +1 -1
- package/esm/http/database/RequestLog.d.mts +2 -3
- package/esm/http/database/RequestLog.d.mts.map +1 -1
- package/esm/http/error-codes.d.mts +1 -2
- package/esm/http/error-codes.d.mts.map +1 -1
- package/esm/http/error-mapper.d.mts +2 -4
- package/esm/http/error-mapper.d.mts.map +1 -1
- package/esm/http/error-mapper.mjs +2 -2
- package/esm/http/error-mapper.mjs.map +1 -1
- package/esm/http/errors/errors.d.mts +28 -29
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/escape-header-value.d.mts +1 -2
- package/esm/http/escape-header-value.d.mts.map +1 -1
- package/esm/http/events.d.mts +2 -4
- package/esm/http/events.d.mts.map +1 -1
- package/esm/http/health.d.mts +4 -4
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/index.d.mts +4 -1
- package/esm/http/index.mjs +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts +2 -4
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts +3 -3
- package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts +3 -3
- package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +6 -6
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/index.d.mts +3 -1
- package/esm/http/middleware/index.mjs +1 -1
- package/esm/http/middleware/inject-request-context.d.mts +2 -4
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +3 -3
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts +3 -3
- package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts +3 -3
- package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +4 -4
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts +2 -2
- package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
- package/esm/http/middleware/middleware-list.d.mts +1 -3
- package/esm/http/middleware/middleware-list.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts +3 -3
- package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs +2 -2
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts +2 -3
- package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts +3 -5
- package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
- package/esm/http/middleware/utils/index.d.mts +2 -1
- package/esm/http/middleware/utils/parse-size.d.mts +1 -2
- package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
- package/esm/http/middleware/utils/parse-size.mjs +2 -2
- package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
- package/esm/http/plugins.d.mts +2 -4
- package/esm/http/plugins.d.mts.map +1 -1
- package/esm/http/plugins.mjs +10 -10
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/port-preflight.d.mts +3 -4
- package/esm/http/port-preflight.d.mts.map +1 -1
- package/esm/http/port-preflight.mjs +2 -0
- package/esm/http/port-preflight.mjs.map +1 -1
- package/esm/http/rate-limit-cache-store.mjs +4 -3
- package/esm/http/rate-limit-cache-store.mjs.map +1 -1
- package/esm/http/ready-report.d.mts +15 -10
- package/esm/http/ready-report.d.mts.map +1 -1
- package/esm/http/request-controller.d.mts +1 -3
- package/esm/http/request-controller.d.mts.map +1 -1
- package/esm/http/request-log-snapshot.d.mts +20 -16
- package/esm/http/request-log-snapshot.d.mts.map +1 -1
- package/esm/http/request-log-snapshot.mjs +3 -3
- package/esm/http/request-log-snapshot.mjs.map +1 -1
- package/esm/http/request.d.mts +8 -7
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +8 -7
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/response.d.mts +12 -11
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +7 -7
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/safe-redirect.d.mts +3 -4
- package/esm/http/safe-redirect.d.mts.map +1 -1
- package/esm/http/serialized.d.mts +12 -13
- package/esm/http/serialized.d.mts.map +1 -1
- package/esm/http/server-rebuilt.d.mts +3 -5
- package/esm/http/server-rebuilt.d.mts.map +1 -1
- package/esm/http/server.d.mts +9 -9
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +4 -4
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/stream-react-response.d.mts +7 -7
- package/esm/http/stream-react-response.d.mts.map +1 -1
- package/esm/http/tracing/index.mjs +1 -1
- package/esm/http/tracing/trace-id.d.mts +2 -3
- package/esm/http/tracing/trace-id.d.mts.map +1 -1
- package/esm/http/tracing/tracing-dispatcher.d.mts +10 -11
- package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
- package/esm/http/tracing/tracing-dispatcher.mjs +2 -2
- package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
- package/esm/http/tracing/tracing.type.d.mts +11 -9
- package/esm/http/tracing/tracing.type.d.mts.map +1 -1
- package/esm/http/types.d.mts +49 -43
- package/esm/http/types.d.mts.map +1 -1
- package/esm/http/uploaded-file.d.mts +6 -5
- package/esm/http/uploaded-file.d.mts.map +1 -1
- package/esm/http/uploads/generate-image-variants.d.mts +6 -6
- package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
- package/esm/http/uploads/generate-image-variants.mjs +1 -1
- package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
- package/esm/http/uploads/image-variant-cache-entries.mjs +1 -1
- package/esm/http/uploads/image-variant-cache.mjs +8 -8
- package/esm/http/uploads/image-variant-cache.mjs.map +1 -1
- package/esm/http/uploads/image-variant-types.d.mts +7 -9
- package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
- package/esm/http/uploads/image-variants-config-error.d.mts +1 -2
- package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
- package/esm/http/uploads/index.d.mts +2 -1
- package/esm/http/uploads/index.mjs +1 -1
- package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
- package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
- package/esm/http/uploads/purge-image-variants.d.mts +2 -4
- package/esm/http/uploads/purge-image-variants.d.mts.map +1 -1
- package/esm/http/uploads/resolve-image-variant.d.mts +3 -5
- package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -1
- package/esm/http/uploads/resolve-image-variants-config.mjs +4 -4
- package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
- package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
- package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
- package/esm/http/uploads/trim-image-variant-cache.mjs +3 -3
- package/esm/http/uploads/trim-image-variant-cache.mjs.map +1 -1
- package/esm/http/uploads/uploaded-file.controller.d.mts +6 -5
- package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
- package/esm/http/uploads/uploaded-file.controller.mjs +2 -1
- package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
- package/esm/http/uploads/variant-cache-key.mjs +1 -1
- package/esm/http/uploads-config.d.mts +2 -4
- package/esm/http/uploads-config.d.mts.map +1 -1
- package/esm/http/uploads-types.d.mts +19 -17
- package/esm/http/uploads-types.d.mts.map +1 -1
- package/esm/http/xmlable.d.mts +1 -2
- package/esm/http/xmlable.d.mts.map +1 -1
- package/esm/image/image.d.mts +6 -7
- package/esm/image/image.d.mts.map +1 -1
- package/esm/image/image.mjs.map +1 -1
- package/esm/image/index.d.mts +2 -1
- package/esm/image/index.mjs +1 -1
- package/esm/index.d.mts +28 -2
- package/esm/index.mjs +7 -2
- package/esm/loader/app-module-importer.d.mts +1 -2
- package/esm/loader/app-module-importer.d.mts.map +1 -1
- package/esm/localization/index.mjs +1 -1
- package/esm/localization/parse-locale-dictionary.d.mts +4 -5
- package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/parse-locale-dictionary.mjs +1 -1
- package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
- package/esm/localization/register-locale-dictionary.d.mts +3 -4
- package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/register-locale-dictionary.mjs +2 -2
- package/esm/localization/register-locale-dictionary.mjs.map +1 -1
- package/esm/logger/fatal-visibility.d.mts +1 -2
- package/esm/logger/fatal-visibility.d.mts.map +1 -1
- package/esm/logger/index.d.mts +2 -1
- package/esm/logger/index.mjs +1 -1
- package/esm/logger/logger.d.mts +1 -3
- package/esm/logger/logger.d.mts.map +1 -1
- package/esm/logger/types.d.mts +2 -3
- package/esm/logger/types.d.mts.map +1 -1
- package/esm/mail/config.d.mts +12 -14
- package/esm/mail/config.d.mts.map +1 -1
- package/esm/mail/events.d.mts +4 -6
- package/esm/mail/events.d.mts.map +1 -1
- package/esm/mail/index.d.mts +2 -1
- package/esm/mail/index.mjs +1 -1
- package/esm/mail/mail.d.mts +1 -3
- package/esm/mail/mail.d.mts.map +1 -1
- package/esm/mail/mailer-pool.d.mts +5 -7
- package/esm/mail/mailer-pool.d.mts.map +1 -1
- package/esm/mail/react-mail.d.mts +1 -3
- package/esm/mail/react-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.d.mts +1 -3
- package/esm/mail/send-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.mjs +2 -1
- package/esm/mail/send-mail.mjs.map +1 -1
- package/esm/mail/test-mailbox.d.mts +11 -13
- package/esm/mail/test-mailbox.d.mts.map +1 -1
- package/esm/mail/types.d.mts +17 -18
- package/esm/mail/types.d.mts.map +1 -1
- package/esm/manifest/manifest-manager.mjs +1 -1
- package/esm/openapi/build-openapi-document.d.mts +2 -4
- package/esm/openapi/build-openapi-document.d.mts.map +1 -1
- package/esm/openapi/cast-schema.mjs +1 -1
- package/esm/openapi/development-openapi-provider.d.mts +5 -6
- package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
- package/esm/openapi/index.d.mts +3 -1
- package/esm/openapi/index.mjs +1 -1
- package/esm/openapi/openapi-child-output.mjs +2 -2
- package/esm/openapi/openapi-child-output.mjs.map +1 -1
- package/esm/openapi/postman/build-request-url.mjs +1 -1
- package/esm/openapi/postman/example-from-schema.d.mts +1 -3
- package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
- package/esm/openapi/postman/index.d.mts +2 -1
- package/esm/openapi/postman/openapi-to-postman-collection.d.mts +3 -5
- package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
- package/esm/openapi/postman/postman-types.d.mts +19 -18
- package/esm/openapi/postman/postman-types.d.mts.map +1 -1
- package/esm/openapi/postman/schema-refs.d.mts +1 -3
- package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
- package/esm/openapi/postman/uuid-v5.mjs +1 -1
- package/esm/openapi/schema-registry.d.mts +1 -1
- package/esm/openapi/security.mjs +1 -1
- package/esm/openapi/types.d.mts +23 -21
- package/esm/openapi/types.d.mts.map +1 -1
- package/esm/production/assert-generated-imports.mjs +1 -1
- package/esm/production/build-contributions.mjs +1 -1
- package/esm/production/bundle-framework-dependencies.mjs +1 -1
- package/esm/production/dist-build-manifest.mjs +1 -1
- package/esm/production/esbuild-plugins.mjs.map +1 -1
- package/esm/production/esbuild-preflight.mjs +1 -1
- package/esm/production/production-builder.mjs +2 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/production-supervisor.mjs +1 -1
- package/esm/production/registration-child-runner.mjs +4 -3
- package/esm/production/registration-child-runner.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +4 -4
- package/esm/production/resolve-build-config.d.mts.map +1 -1
- package/esm/production/resolve-build-config.mjs +1 -1
- package/esm/production/route-registration-child.d.mts +1 -1
- package/esm/production/route-registration-child.mjs +8 -7
- package/esm/production/route-registration-child.mjs.map +1 -1
- package/esm/production/tsconfig-path-aliases.mjs +1 -1
- package/esm/react/index.d.mts +1 -3
- package/esm/react/index.d.mts.map +1 -1
- package/esm/react/index.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +3 -4
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +2 -3
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs +10 -9
- package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/index.d.mts +2 -1
- package/esm/repositories/adapters/cascade/index.mjs +1 -1
- package/esm/repositories/contracts/index.d.mts +2 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +4 -6
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -3
- package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/types.d.mts +23 -25
- package/esm/repositories/contracts/types.d.mts.map +1 -1
- package/esm/repositories/index.d.mts +4 -1
- package/esm/repositories/index.mjs +1 -1
- package/esm/repositories/repository.manager.d.mts +2 -3
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +2 -2
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/resource/define-resource.d.mts +3 -5
- package/esm/resource/define-resource.d.mts.map +1 -1
- package/esm/resource/index.d.mts +2 -1
- package/esm/resource/index.mjs +1 -1
- package/esm/resource/nullable-resource.d.mts +5 -7
- package/esm/resource/nullable-resource.d.mts.map +1 -1
- package/esm/resource/register-resource.d.mts +1 -3
- package/esm/resource/register-resource.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.d.mts +1 -3
- package/esm/resource/resource-field-builder.d.mts.map +1 -1
- package/esm/resource/resource.d.mts +3 -5
- package/esm/resource/resource.d.mts.map +1 -1
- package/esm/resource/resource.mjs +4 -2
- package/esm/resource/resource.mjs.map +1 -1
- package/esm/resource/types.d.mts +21 -21
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/restful/index.d.mts +2 -1
- package/esm/restful/index.mjs +1 -1
- package/esm/restful/restful.d.mts +12 -32
- package/esm/restful/restful.d.mts.map +1 -1
- package/esm/router/index.d.mts +2 -1
- package/esm/router/index.mjs +1 -1
- package/esm/router/named-api-routes-with-responses.mjs +2 -1
- package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
- package/esm/router/normalize-request-path.d.mts +1 -2
- package/esm/router/normalize-request-path.d.mts.map +1 -1
- package/esm/router/normalize-route-path.d.mts +1 -2
- package/esm/router/normalize-route-path.d.mts.map +1 -1
- package/esm/router/positional-handler-diagnostics.d.mts +15 -13
- package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
- package/esm/router/resolve-route-rate-limit.mjs +3 -3
- package/esm/router/resolve-route-rate-limit.mjs.map +1 -1
- package/esm/router/route-builder.d.mts +1 -3
- package/esm/router/route-builder.d.mts.map +1 -1
- package/esm/router/route-guard-names.mjs +1 -1
- package/esm/router/route-guard-names.mjs.map +1 -1
- package/esm/router/route-name-method-suffix.d.mts +2 -3
- package/esm/router/route-name-method-suffix.d.mts.map +1 -1
- package/esm/router/route-name-taken-error.d.mts +1 -3
- package/esm/router/route-name-taken-error.d.mts.map +1 -1
- package/esm/router/route-registry.d.mts +1 -3
- package/esm/router/route-registry.d.mts.map +1 -1
- package/esm/router/router.d.mts +2 -4
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +8 -6
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts +25 -26
- package/esm/router/types.d.mts.map +1 -1
- package/esm/router/unguarded-route-diagnostics.d.mts +6 -8
- package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -1
- package/esm/secrets/errors.d.mts +9 -0
- package/esm/secrets/errors.d.mts.map +1 -0
- package/esm/secrets/errors.mjs +22 -0
- package/esm/secrets/errors.mjs.map +1 -0
- package/esm/secrets/file-backend.mjs +167 -0
- package/esm/secrets/file-backend.mjs.map +1 -0
- package/esm/secrets/index.d.mts +6 -0
- package/esm/secrets/index.mjs +6 -0
- package/esm/secrets/keyring-backend.mjs +50 -0
- package/esm/secrets/keyring-backend.mjs.map +1 -0
- package/esm/secrets/memory-backend.d.mts +12 -0
- package/esm/secrets/memory-backend.d.mts.map +1 -0
- package/esm/secrets/memory-backend.mjs +28 -0
- package/esm/secrets/memory-backend.mjs.map +1 -0
- package/esm/secrets/secret-store.d.mts +25 -0
- package/esm/secrets/secret-store.d.mts.map +1 -0
- package/esm/secrets/secret-store.mjs +117 -0
- package/esm/secrets/secret-store.mjs.map +1 -0
- package/esm/secrets/secrets.d.mts +11 -0
- package/esm/secrets/secrets.d.mts.map +1 -0
- package/esm/secrets/secrets.mjs +63 -0
- package/esm/secrets/secrets.mjs.map +1 -0
- package/esm/secrets/types.d.mts +22 -0
- package/esm/secrets/types.d.mts.map +1 -0
- package/esm/socket/index.d.mts +2 -1
- package/esm/socket/index.mjs +2 -2
- package/esm/socket/types.d.mts +2 -4
- package/esm/socket/types.d.mts.map +1 -1
- package/esm/socket/utils.d.mts +8 -3
- package/esm/socket/utils.d.mts.map +1 -1
- package/esm/socket/utils.mjs +12 -1
- package/esm/socket/utils.mjs.map +1 -1
- package/esm/storage/config.d.mts +4 -6
- package/esm/storage/config.d.mts.map +1 -1
- package/esm/storage/context/storage-driver-context.d.mts +3 -4
- package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts +2 -4
- package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts +1 -3
- package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.d.mts +2 -3
- package/esm/storage/drivers/local-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.mjs +8 -3
- package/esm/storage/drivers/local-driver.mjs.map +1 -1
- package/esm/storage/drivers/r2-driver.d.mts +1 -3
- package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
- package/esm/storage/drivers/s3-driver.d.mts +1 -3
- package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
- package/esm/storage/index.d.mts +2 -1
- package/esm/storage/index.mjs +1 -1
- package/esm/storage/local-disk-roots.mjs +2 -2
- package/esm/storage/local-disk-roots.mjs.map +1 -1
- package/esm/storage/scoped-storage.d.mts +2 -3
- package/esm/storage/scoped-storage.d.mts.map +1 -1
- package/esm/storage/storage-file.d.mts +1 -3
- package/esm/storage/storage-file.d.mts.map +1 -1
- package/esm/storage/storage.d.mts +3 -4
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/types.d.mts +36 -36
- package/esm/storage/types.d.mts.map +1 -1
- package/esm/storage/utils/classify-ip-address.d.mts +1 -2
- package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.d.mts +1 -2
- package/esm/storage/utils/contain-path.d.mts.map +1 -1
- package/esm/storage/utils/mime.d.mts +2 -3
- package/esm/storage/utils/mime.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts +6 -6
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs +3 -3
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/storage/utils/storage-capability-error.d.mts +1 -3
- package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-error.d.mts +2 -3
- package/esm/storage/utils/storage-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-not-initialized-error.d.mts +1 -2
- package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
- package/esm/tests/authenticated-test-client.d.mts +5 -6
- package/esm/tests/authenticated-test-client.d.mts.map +1 -1
- package/esm/tests/factories.d.mts +38 -23
- package/esm/tests/factories.d.mts.map +1 -1
- package/esm/tests/fakes/cache-fake.d.mts +14 -9
- package/esm/tests/fakes/cache-fake.d.mts.map +1 -1
- package/esm/tests/fakes/clock-fake.d.mts +13 -8
- package/esm/tests/fakes/clock-fake.d.mts.map +1 -1
- package/esm/tests/fakes/fake-assertion-error.d.mts +2 -3
- package/esm/tests/fakes/fake-assertion-error.d.mts.map +1 -1
- package/esm/tests/fakes/ids-fake.d.mts +5 -4
- package/esm/tests/fakes/ids-fake.d.mts.map +1 -1
- package/esm/tests/fakes/index.d.mts +3 -1
- package/esm/tests/fakes/index.mjs +2 -1
- package/esm/tests/fakes/mail-fake.d.mts +21 -13
- package/esm/tests/fakes/mail-fake.d.mts.map +1 -1
- package/esm/tests/fakes/queue-fake.d.mts +21 -13
- package/esm/tests/fakes/queue-fake.d.mts.map +1 -1
- package/esm/tests/fakes/secrets-fake.d.mts +13 -0
- package/esm/tests/fakes/secrets-fake.d.mts.map +1 -0
- package/esm/tests/fakes/secrets-fake.mjs +50 -0
- package/esm/tests/fakes/secrets-fake.mjs.map +1 -0
- package/esm/tests/fakes/storage-fake.d.mts +12 -8
- package/esm/tests/fakes/storage-fake.d.mts.map +1 -1
- package/esm/tests/fakes/storage-fake.mjs +1 -1
- package/esm/tests/fakes/test-fakes.d.mts +9 -10
- package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
- package/esm/tests/fakes/test-fakes.mjs +6 -3
- package/esm/tests/fakes/test-fakes.mjs.map +1 -1
- package/esm/tests/index.d.mts +3 -1
- package/esm/tests/index.mjs +2 -1
- package/esm/tests/snapshot-response.d.mts +4 -5
- package/esm/tests/snapshot-response.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.d.mts +4 -6
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +5 -5
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-connectors-selection.d.mts +2 -2
- package/esm/tests/test-connectors-selection.d.mts.map +1 -1
- package/esm/tests/test-connectors-selection.mjs +1 -1
- package/esm/tests/test-helpers.d.mts +11 -12
- package/esm/tests/test-helpers.d.mts.map +1 -1
- package/esm/tests/test-http-server.d.mts +14 -10
- package/esm/tests/test-http-server.d.mts.map +1 -1
- package/esm/tests/test-lifecycle-state.mjs +1 -1
- package/esm/tests/vitest-setup.d.mts +7 -8
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/tooling/agents-md/agents-md-markers.d.mts +4 -5
- package/esm/tooling/agents-md/agents-md-markers.d.mts.map +1 -1
- package/esm/tooling/agents-md/agents-md-markers.mjs +2 -1
- package/esm/tooling/agents-md/agents-md-markers.mjs.map +1 -1
- package/esm/tooling/agents-md/agents-md-refresher.d.mts +19 -12
- package/esm/tooling/agents-md/agents-md-refresher.d.mts.map +1 -1
- package/esm/tooling/agents-md/installed-skills.d.mts +13 -9
- package/esm/tooling/agents-md/installed-skills.d.mts.map +1 -1
- package/esm/tooling/agents-md/render-agents-md.d.mts +8 -7
- package/esm/tooling/agents-md/render-agents-md.d.mts.map +1 -1
- package/esm/tooling/agents-md/render-agents-md.mjs +2 -2
- package/esm/tooling/agents-md/render-agents-md.mjs.map +1 -1
- package/esm/tooling/agents-md/write-agents-md.d.mts +17 -12
- package/esm/tooling/agents-md/write-agents-md.d.mts.map +1 -1
- package/esm/tooling/board/board-message.d.mts +4 -6
- package/esm/tooling/board/board-message.d.mts.map +1 -1
- package/esm/tooling/board/board.d.mts +50 -38
- package/esm/tooling/board/board.d.mts.map +1 -1
- package/esm/tooling/board/board.mjs +4 -3
- package/esm/tooling/board/board.mjs.map +1 -1
- package/esm/tooling/board/board.types.d.mts +32 -23
- package/esm/tooling/board/board.types.d.mts.map +1 -1
- package/esm/tooling/check/changed-files.d.mts +4 -6
- package/esm/tooling/check/changed-files.d.mts.map +1 -1
- package/esm/tooling/check/changed-files.mjs +2 -2
- package/esm/tooling/check/changed-files.mjs.map +1 -1
- package/esm/tooling/check/check-report.types.d.mts +22 -17
- package/esm/tooling/check/check-report.types.d.mts.map +1 -1
- package/esm/tooling/check/code-style-conventions.mjs +25 -25
- package/esm/tooling/check/code-style-conventions.mjs.map +1 -1
- package/esm/tooling/check/conventions-step.d.mts +4 -6
- package/esm/tooling/check/conventions-step.d.mts.map +1 -1
- package/esm/tooling/check/conventions-step.mjs +7 -18
- package/esm/tooling/check/conventions-step.mjs.map +1 -1
- package/esm/tooling/check/environment-step.d.mts +2 -4
- package/esm/tooling/check/environment-step.d.mts.map +1 -1
- package/esm/tooling/check/environment-step.mjs +1 -1
- package/esm/tooling/check/index.mjs +1 -1
- package/esm/tooling/check/lint-step.d.mts +5 -12
- package/esm/tooling/check/lint-step.d.mts.map +1 -1
- package/esm/tooling/check/lint-step.mjs +16 -12
- package/esm/tooling/check/lint-step.mjs.map +1 -1
- package/esm/tooling/check/request-input.mjs +15 -15
- package/esm/tooling/check/request-input.mjs.map +1 -1
- package/esm/tooling/check/run-check.d.mts +24 -14
- package/esm/tooling/check/run-check.d.mts.map +1 -1
- package/esm/tooling/check/run-check.mjs +2 -2
- package/esm/tooling/check/run-check.mjs.map +1 -1
- package/esm/tooling/check/run-tests.d.mts +22 -15
- package/esm/tooling/check/run-tests.d.mts.map +1 -1
- package/esm/tooling/check/security-conventions.mjs +133 -131
- package/esm/tooling/check/security-conventions.mjs.map +1 -1
- package/esm/tooling/check/source-ast.mjs +92 -132
- package/esm/tooling/check/source-ast.mjs.map +1 -1
- package/esm/tooling/check/tests-step.d.mts +7 -8
- package/esm/tooling/check/tests-step.d.mts.map +1 -1
- package/esm/tooling/check/tests-step.mjs +3 -3
- package/esm/tooling/check/tests-step.mjs.map +1 -1
- package/esm/tooling/dev-state/dev-server-state.d.mts +17 -13
- package/esm/tooling/dev-state/dev-server-state.d.mts.map +1 -1
- package/esm/tooling/devtools/devtools-client.d.mts +29 -20
- package/esm/tooling/devtools/devtools-client.d.mts.map +1 -1
- package/esm/tooling/generate/generation.d.mts +34 -22
- package/esm/tooling/generate/generation.d.mts.map +1 -1
- package/esm/tooling/generate/generation.mjs +9 -5
- package/esm/tooling/generate/generation.mjs.map +1 -1
- package/esm/tooling/generate/generator-spec.d.mts +9 -9
- package/esm/tooling/generate/generator-spec.d.mts.map +1 -1
- package/esm/tooling/generate/index.mjs +1 -1
- package/esm/tooling/generate/project-files.mjs +3 -3
- package/esm/tooling/generate/project-files.mjs.map +1 -1
- package/esm/tooling/generate/run-cli.d.mts +14 -11
- package/esm/tooling/generate/run-cli.d.mts.map +1 -1
- package/esm/tooling/generate/run-cli.mjs +2 -2
- package/esm/tooling/generate/run-cli.mjs.map +1 -1
- package/esm/tooling/generate/unified-diff.d.mts +10 -7
- package/esm/tooling/generate/unified-diff.d.mts.map +1 -1
- package/esm/tooling/index.d.mts +1 -0
- package/esm/tooling/inspect/boot-for-inspect.d.mts +7 -7
- package/esm/tooling/inspect/boot-for-inspect.d.mts.map +1 -1
- package/esm/tooling/inspect/collect-config.mjs +3 -3
- package/esm/tooling/inspect/collect-config.mjs.map +1 -1
- package/esm/tooling/inspect/collect-models.d.mts +4 -3
- package/esm/tooling/inspect/collect-models.d.mts.map +1 -1
- package/esm/tooling/inspect/collect-models.mjs +1 -1
- package/esm/tooling/inspect/collect-packages.d.mts +1 -2
- package/esm/tooling/inspect/collect-packages.d.mts.map +1 -1
- package/esm/tooling/inspect/collect-pages.mjs +10 -10
- package/esm/tooling/inspect/collect-pages.mjs.map +1 -1
- package/esm/tooling/inspect/collect-routes.mjs +1 -1
- package/esm/tooling/inspect/event-recorder.d.mts +7 -7
- package/esm/tooling/inspect/event-recorder.d.mts.map +1 -1
- package/esm/tooling/inspect/index.d.mts +2 -1
- package/esm/tooling/inspect/index.mjs +1 -1
- package/esm/tooling/inspect/inspect-app.d.mts +25 -16
- package/esm/tooling/inspect/inspect-app.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-report.schema.d.mts +1 -2
- package/esm/tooling/inspect/inspect-report.schema.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-report.types.d.mts +86 -54
- package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -1
- package/esm/tooling/mcp/create-mcp-context.d.mts +11 -8
- package/esm/tooling/mcp/create-mcp-context.d.mts.map +1 -1
- package/esm/tooling/mcp/db-schema.d.mts +10 -9
- package/esm/tooling/mcp/db-schema.d.mts.map +1 -1
- package/esm/tooling/mcp/docs-search.d.mts +20 -15
- package/esm/tooling/mcp/docs-search.d.mts.map +1 -1
- package/esm/tooling/mcp/index.mjs +1 -1
- package/esm/tooling/mcp/load-ai-tools.d.mts +7 -8
- package/esm/tooling/mcp/load-ai-tools.d.mts.map +1 -1
- package/esm/tooling/mcp/load-ai-tools.mjs +2 -1
- package/esm/tooling/mcp/load-ai-tools.mjs.map +1 -1
- package/esm/tooling/mcp/mcp-tools.d.mts +29 -19
- package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -1
- package/esm/tooling/mcp/mcp-tools.mjs +3 -2
- package/esm/tooling/mcp/mcp-tools.mjs.map +1 -1
- package/esm/tooling/mcp/start-mcp-server.d.mts +24 -17
- package/esm/tooling/mcp/start-mcp-server.d.mts.map +1 -1
- package/esm/tooling/mcp/start-mcp-server.mjs +1 -1
- package/esm/tooling/mcp/start-mcp-server.mjs.map +1 -1
- package/esm/tooling/mcp/tool-input.d.mts +7 -7
- package/esm/tooling/mcp/tool-input.d.mts.map +1 -1
- package/esm/tooling/problem.d.mts +27 -17
- package/esm/tooling/problem.d.mts.map +1 -1
- package/esm/tooling/syntax/ast.mjs +230 -0
- package/esm/tooling/syntax/ast.mjs.map +1 -0
- package/esm/tooling/syntax/imports.mjs +34 -0
- package/esm/tooling/syntax/imports.mjs.map +1 -0
- package/esm/tooling/trace/trace-report.types.d.mts +36 -22
- package/esm/tooling/trace/trace-report.types.d.mts.map +1 -1
- package/esm/tooling/trace/trace-request.d.mts +27 -20
- package/esm/tooling/trace/trace-request.d.mts.map +1 -1
- package/esm/tooling/trace/trace-request.mjs +2 -2
- package/esm/tooling/trace/trace-request.mjs.map +1 -1
- package/esm/tooling/typecheck/index.mjs +1 -1
- package/esm/tooling/typecheck/run-typecheck.d.mts +15 -48
- package/esm/tooling/typecheck/run-typecheck.d.mts.map +1 -1
- package/esm/tooling/typecheck/run-typecheck.mjs +42 -105
- package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -1
- package/esm/tooling/typescript/compiler.d.mts +31 -0
- package/esm/tooling/typescript/compiler.d.mts.map +1 -0
- package/esm/tooling/typescript/compiler.mjs +120 -0
- package/esm/tooling/typescript/compiler.mjs.map +1 -0
- package/esm/updater/update-warlock-packages.mjs +3 -2
- package/esm/updater/update-warlock-packages.mjs.map +1 -1
- package/esm/upgrade/codemods/index.mjs +3 -1
- package/esm/upgrade/codemods/index.mjs.map +1 -1
- package/esm/upgrade/codemods/logger-sync-calls.mjs +1 -1
- package/esm/upgrade/codemods/logger-sync-calls.mjs.map +1 -1
- package/esm/upgrade/codemods/oxc-toolchain.mjs +142 -0
- package/esm/upgrade/codemods/oxc-toolchain.mjs.map +1 -0
- package/esm/upgrade/codemods/request-log-snapshot.mjs +1 -1
- package/esm/upgrade/codemods/request-log-snapshot.mjs.map +1 -1
- package/esm/upgrade/codemods/toolchain-templates.mjs +244 -0
- package/esm/upgrade/codemods/toolchain-templates.mjs.map +1 -0
- package/esm/upgrade/diff.mjs +1 -1
- package/esm/upgrade/diff.mjs.map +1 -1
- package/esm/upgrade/load-ts-morph.mjs +3 -2
- package/esm/upgrade/load-ts-morph.mjs.map +1 -1
- package/esm/upgrade/run-upgrade.mjs +26 -7
- package/esm/upgrade/run-upgrade.mjs.map +1 -1
- package/esm/use-cases/index.d.mts +2 -1
- package/esm/use-cases/index.mjs +1 -1
- package/esm/use-cases/types.d.mts +116 -63
- package/esm/use-cases/types.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts +1 -3
- package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
- package/esm/use-cases/use-case-events.d.mts +3 -5
- package/esm/use-cases/use-case-events.d.mts.map +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts +6 -6
- package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
- package/esm/use-cases/use-case.d.mts +2 -4
- package/esm/use-cases/use-case.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.d.mts +1 -3
- package/esm/use-cases/use-case.errors.d.mts.map +1 -1
- package/esm/use-cases/use-cases-registry.d.mts +8 -10
- package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
- package/esm/utils/app-log.d.mts +1 -2
- package/esm/utils/app-log.d.mts.map +1 -1
- package/esm/utils/clock.d.mts +8 -6
- package/esm/utils/clock.d.mts.map +1 -1
- package/esm/utils/database-log.d.mts +3 -4
- package/esm/utils/database-log.d.mts.map +1 -1
- package/esm/utils/environment.d.mts +4 -5
- package/esm/utils/environment.d.mts.map +1 -1
- package/esm/utils/framework-vesion.mjs.map +1 -1
- package/esm/utils/get-localized.d.mts +2 -3
- package/esm/utils/get-localized.d.mts.map +1 -1
- package/esm/utils/ids.d.mts +9 -6
- package/esm/utils/ids.d.mts.map +1 -1
- package/esm/utils/index.d.mts +2 -1
- package/esm/utils/index.mjs +1 -1
- package/esm/utils/normalized-path.d.mts +1 -2
- package/esm/utils/normalized-path.d.mts.map +1 -1
- package/esm/utils/npm-registry.d.mts +1 -2
- package/esm/utils/npm-registry.d.mts.map +1 -1
- package/esm/utils/paths.d.mts +13 -14
- package/esm/utils/paths.d.mts.map +1 -1
- package/esm/utils/paths.mjs +2 -2
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/utils/promise-all-object.d.mts +1 -2
- package/esm/utils/promise-all-object.d.mts.map +1 -1
- package/esm/utils/queue.d.mts +1 -2
- package/esm/utils/queue.d.mts.map +1 -1
- package/esm/utils/runtime.d.mts +11 -10
- package/esm/utils/runtime.d.mts.map +1 -1
- package/esm/utils/sleep.d.mts +1 -2
- package/esm/utils/sleep.d.mts.map +1 -1
- package/esm/utils/sluggable.d.mts +1 -3
- package/esm/utils/sluggable.d.mts.map +1 -1
- package/esm/utils/to-json.d.mts +1 -2
- package/esm/utils/to-json.d.mts.map +1 -1
- package/esm/utils/types.d.mts +1 -2
- package/esm/utils/types.d.mts.map +1 -1
- package/esm/utils/urls.d.mts +5 -6
- package/esm/utils/urls.d.mts.map +1 -1
- package/esm/utils/version-compare.d.mts +1 -2
- package/esm/utils/version-compare.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts +2 -3
- package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts +2 -3
- package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/index.d.mts +2 -1
- package/esm/validation/database/index.mjs +1 -1
- package/esm/validation/database/types.d.mts +14 -10
- package/esm/validation/database/types.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts +2 -3
- package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts +2 -3
- package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
- package/esm/validation/file/file.d.mts +4 -6
- package/esm/validation/file/file.d.mts.map +1 -1
- package/esm/validation/file/index.d.mts +2 -1
- package/esm/validation/file/index.mjs +1 -1
- package/esm/validation/index.d.mts +5 -1
- package/esm/validation/index.mjs +1 -1
- package/esm/validation/plugins/index.mjs +1 -1
- package/esm/validation/types.d.mts +6 -4
- package/esm/validation/types.d.mts.map +1 -1
- package/esm/validation/validateAll.mjs +2 -2
- package/esm/validation/validateAll.mjs.map +1 -1
- package/esm/validation/validation-failure-status.mjs +2 -2
- package/esm/validation/validation-failure-status.mjs.map +1 -1
- package/esm/validation/validators/file-validator.d.mts +2 -4
- package/esm/validation/validators/file-validator.d.mts.map +1 -1
- package/esm/validation/validators/index.d.mts +2 -1
- package/esm/validation/validators/index.mjs +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts +2 -3
- package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
- package/esm/warlock-config/define-config.d.mts +1 -3
- package/esm/warlock-config/define-config.d.mts.map +1 -1
- package/esm/warlock-config/define-config.mjs +3 -2
- package/esm/warlock-config/define-config.mjs.map +1 -1
- package/esm/warlock-config/index.d.mts +2 -1
- package/esm/warlock-config/index.mjs +1 -1
- package/esm/warlock-config/types.d.mts +8 -6
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts +5 -7
- package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs +2 -1
- package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
- package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
- package/llms-full.txt +379 -22
- package/llms.txt +3 -2
- package/package.json +27 -15
- package/skills/README.md +2 -1
- package/skills/create-module/SKILL.md +7 -0
- package/skills/index.md +3 -1
- package/skills/report-framework-issue.md +154 -0
- package/skills/run-app/SKILL.md +120 -10
- package/skills/store-secrets/SKILL.md +102 -0
- package/skills/test-fakes/SKILL.md +13 -11
- package/skills/upgrade-from-5-29/SKILL.md +78 -0
- package/skills/warlock-check/SKILL.md +6 -1
- package/skills/warlock-doctor/SKILL.md +9 -0
- package/skills/wire-socket/SKILL.md +19 -0
- package/skills/write-cli-command/SKILL.md +21 -0
- package/esm/tooling/check/index.d.mts +0 -8
- package/esm/tooling/typecheck/index.d.mts +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-hook.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/load-hook.ts"],"sourcesContent":["import { transformSync } from \"esbuild\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { sourceSlug } from \"./source-slug.js\";\nimport { cacheKey, TranspileCache } from \"./transpile-cache.js\";\n\ntype LoadContext = {\n format?: string;\n importAttributes?: Record<string, string>;\n};\n\ntype LoadResult = {\n format: string;\n source: string | Buffer;\n shortCircuit?: boolean;\n};\n\ntype NextLoad = (url: string, context?: LoadContext) => Promise<LoadResult>;\n\n/**\n * Everything the transpile path needs, computed once on the main thread and\n * shipped into the hook worker via `initialize()`. Always present — esbuild\n * transpile is unconditional now (tsx is no longer in the TS path).\n */\nexport type TranspileInit = {\n /** Absolute `.warlock/transpile` directory. */\n cacheDir: string;\n /** Source-content key salt: esbuild version + epoch + tsconfig blob. */\n fingerprint: string;\n /** esbuild `target` (e.g. `\"node22\"` — must match the prod builder). */\n target: string;\n /** JSON string of `{ compilerOptions }` handed to esbuild as tsconfigRaw. */\n tsconfigRaw: string;\n /**\n * Debug-only: name cache files `<slug>.<hash>.js` and append a trailing\n * `// @source <path>` marker so entries are eyeball-identifiable. Off by\n * default (opaque `<hash>.js`). Cosmetic — never affects keys or lookup.\n */\n debugNames: boolean;\n};\n\nconst VERSION_QUERY = /\\?v=\\d+$/;\nconst TS_FILE = /\\.(ts|tsx|mts|cts)$/;\n\nlet transpile: TranspileInit;\nlet cache: TranspileCache;\n\n/**\n * Called once from the hook worker's `initialize()`. Wires the persisted\n * transpile cache and runs one opportunistic GC pass at boot — cheap, off\n * the hot path, single directory scan.\n */\nexport function configureTranspile(init: TranspileInit): void {\n transpile = init;\n cache = new TranspileCache(init.cacheDir);\n\n // Boot-time eviction so the cache can't grow unbounded across weeks of\n // dev. Bounds are generous; correctness never depends on GC (content\n // hashing already guarantees that) — this is purely disk hygiene.\n cache.gc({\n maxBytes: 256 * 1024 * 1024,\n maxAgeMs: 14 * 24 * 60 * 60 * 1000,\n });\n}\n\n/**\n * ESM loader `load()` hook.\n *\n * Owns the transpile for **every** TypeScript file — project `src/`,\n * `@warlock.js/*` framework source, and `warlock.config.ts` alike. There\n * is no tsx in the TypeScript path any more: we read the source, key it by\n * a content hash + options fingerprint, serve the cached JS on a hit, and\n * otherwise transform it with esbuild directly and persist. Non-TypeScript\n * URLs (npm `.js`/`.cjs`/`.mjs`, `node:` builtins, JSON) are not ours —\n * they fall through to the next loader (Node's default).\n *\n * The `?v=<N>` query drives Node's module identity (HMR) for `src/` files\n * and is **never** part of the cache key — the cache is keyed purely by\n * source content, so the two mechanisms are fully orthogonal. Framework\n * and config `.ts` carry no `?v` (no HMR) but are transpiled and cached\n * exactly the same way.\n *\n * The source map esbuild emits is inline base64 with `sourcefile` set to\n * the clean absolute `.ts` path, so V8 (run with source maps enabled)\n * reports stack frames at the original TypeScript location.\n *\n * @example\n * // load(\"file:///src/user.model.ts?v=3\") → esbuild transpile + cache\n * // load(\"file:///@warlock.js/core/src/x.ts\") → esbuild transpile + cache\n * // load(\"file:///node_modules/ms/index.js\") → nextLoad (Node default)\n */\nexport async function load(\n url: string,\n context: LoadContext,\n nextLoad: NextLoad,\n): Promise<LoadResult> {\n const cleanUrl = url.replace(VERSION_QUERY, \"\");\n\n // Not TypeScript → not ours. npm packages, node: builtins, JSON, etc.\n if (!TS_FILE.test(cleanUrl)) {\n return nextLoad(url, context);\n }\n\n const absolutePath = fileURLToPath(cleanUrl);\n const source = readFileSync(absolutePath, \"utf8\");\n const key = cacheKey(source, transpile.fingerprint);\n\n // Cosmetic filename label; undefined keeps opaque <hash>.js names.\n const label = transpile.debugNames ? sourceSlug(absolutePath) : undefined;\n\n const hit = cache.get(key, label);\n if (hit) {\n return { format: \"module\", source: hit.code, shortCircuit: true };\n }\n\n const loader = absolutePath.endsWith(\".tsx\") ? \"tsx\" : \"ts\";\n\n const result = transformSync(source, {\n loader,\n format: \"esm\",\n target: transpile.target,\n sourcefile: absolutePath,\n // Inline base64 map, self-contained (sourcesContent on by default), so\n // it survives the ?v=N URL with no extra resolution step.\n sourcemap: \"inline\",\n tsconfigRaw: transpile.tsconfigRaw,\n });\n\n // result.code already carries the inline //# sourceMappingURL. The\n // marker goes AFTER that line: a trailing comment can't shift earlier\n // generated lines, so the inline map (and therefore stack-frame line\n // numbers) stays exact. A leading marker would desync it by one line.\n const code = label ? `${result.code}\\n// @source ${absolutePath}\\n` : result.code;\n\n cache.put(key, { code, map: \"\" }, label);\n\n return { format: \"module\", source: code, shortCircuit: true };\n}\n"],"mappings":";;;;;;;AAyCA,MAAM,gBAAgB;AACtB,MAAM,UAAU;AAEhB,IAAI;AACJ,IAAI;;;;;;AAOJ,SAAgB,mBAAmB,MAA2B;CAC5D,YAAY;CACZ,QAAQ,IAAI,eAAe,KAAK,QAAQ;CAKxC,MAAM,GAAG;EACP,UAAU
|
|
1
|
+
{"version":3,"file":"load-hook.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/load-hook.ts"],"sourcesContent":["import { transformSync } from \"esbuild\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { sourceSlug } from \"./source-slug.js\";\nimport { cacheKey, TranspileCache } from \"./transpile-cache.js\";\n\ntype LoadContext = {\n format?: string;\n importAttributes?: Record<string, string>;\n};\n\ntype LoadResult = {\n format: string;\n source: string | Buffer;\n shortCircuit?: boolean;\n};\n\ntype NextLoad = (url: string, context?: LoadContext) => Promise<LoadResult>;\n\n/**\n * Everything the transpile path needs, computed once on the main thread and\n * shipped into the hook worker via `initialize()`. Always present — esbuild\n * transpile is unconditional now (tsx is no longer in the TS path).\n */\nexport type TranspileInit = {\n /** Absolute `.warlock/transpile` directory. */\n cacheDir: string;\n /** Source-content key salt: esbuild version + epoch + tsconfig blob. */\n fingerprint: string;\n /** esbuild `target` (e.g. `\"node22\"` — must match the prod builder). */\n target: string;\n /** JSON string of `{ compilerOptions }` handed to esbuild as tsconfigRaw. */\n tsconfigRaw: string;\n /**\n * Debug-only: name cache files `<slug>.<hash>.js` and append a trailing\n * `// @source <path>` marker so entries are eyeball-identifiable. Off by\n * default (opaque `<hash>.js`). Cosmetic — never affects keys or lookup.\n */\n debugNames: boolean;\n};\n\nconst VERSION_QUERY = /\\?v=\\d+$/;\nconst TS_FILE = /\\.(ts|tsx|mts|cts)$/;\n\nlet transpile: TranspileInit;\nlet cache: TranspileCache;\n\n/**\n * Called once from the hook worker's `initialize()`. Wires the persisted\n * transpile cache and runs one opportunistic GC pass at boot — cheap, off\n * the hot path, single directory scan.\n */\nexport function configureTranspile(init: TranspileInit): void {\n transpile = init;\n cache = new TranspileCache(init.cacheDir);\n\n // Boot-time eviction so the cache can't grow unbounded across weeks of\n // dev. Bounds are generous; correctness never depends on GC (content\n // hashing already guarantees that) — this is purely disk hygiene.\n cache.gc({\n maxBytes: 256 * 1024 * 1024,\n maxAgeMs: 14 * 24 * 60 * 60 * 1000,\n });\n}\n\n/**\n * ESM loader `load()` hook.\n *\n * Owns the transpile for **every** TypeScript file — project `src/`,\n * `@warlock.js/*` framework source, and `warlock.config.ts` alike. There\n * is no tsx in the TypeScript path any more: we read the source, key it by\n * a content hash + options fingerprint, serve the cached JS on a hit, and\n * otherwise transform it with esbuild directly and persist. Non-TypeScript\n * URLs (npm `.js`/`.cjs`/`.mjs`, `node:` builtins, JSON) are not ours —\n * they fall through to the next loader (Node's default).\n *\n * The `?v=<N>` query drives Node's module identity (HMR) for `src/` files\n * and is **never** part of the cache key — the cache is keyed purely by\n * source content, so the two mechanisms are fully orthogonal. Framework\n * and config `.ts` carry no `?v` (no HMR) but are transpiled and cached\n * exactly the same way.\n *\n * The source map esbuild emits is inline base64 with `sourcefile` set to\n * the clean absolute `.ts` path, so V8 (run with source maps enabled)\n * reports stack frames at the original TypeScript location.\n *\n * @example\n * // load(\"file:///src/user.model.ts?v=3\") → esbuild transpile + cache\n * // load(\"file:///@warlock.js/core/src/x.ts\") → esbuild transpile + cache\n * // load(\"file:///node_modules/ms/index.js\") → nextLoad (Node default)\n */\nexport async function load(\n url: string,\n context: LoadContext,\n nextLoad: NextLoad,\n): Promise<LoadResult> {\n const cleanUrl = url.replace(VERSION_QUERY, \"\");\n\n // Not TypeScript → not ours. npm packages, node: builtins, JSON, etc.\n if (!TS_FILE.test(cleanUrl)) {\n return nextLoad(url, context);\n }\n\n const absolutePath = fileURLToPath(cleanUrl);\n const source = readFileSync(absolutePath, \"utf8\");\n const key = cacheKey(source, transpile.fingerprint);\n\n // Cosmetic filename label; undefined keeps opaque <hash>.js names.\n const label = transpile.debugNames ? sourceSlug(absolutePath) : undefined;\n\n const hit = cache.get(key, label);\n if (hit) {\n return { format: \"module\", source: hit.code, shortCircuit: true };\n }\n\n const loader = absolutePath.endsWith(\".tsx\") ? \"tsx\" : \"ts\";\n\n const result = transformSync(source, {\n loader,\n format: \"esm\",\n target: transpile.target,\n sourcefile: absolutePath,\n // Inline base64 map, self-contained (sourcesContent on by default), so\n // it survives the ?v=N URL with no extra resolution step.\n sourcemap: \"inline\",\n tsconfigRaw: transpile.tsconfigRaw,\n });\n\n // result.code already carries the inline //# sourceMappingURL. The\n // marker goes AFTER that line: a trailing comment can't shift earlier\n // generated lines, so the inline map (and therefore stack-frame line\n // numbers) stays exact. A leading marker would desync it by one line.\n const code = label ? `${result.code}\\n// @source ${absolutePath}\\n` : result.code;\n\n cache.put(key, { code, map: \"\" }, label);\n\n return { format: \"module\", source: code, shortCircuit: true };\n}\n"],"mappings":";;;;;;;AAyCA,MAAM,gBAAgB;AACtB,MAAM,UAAU;AAEhB,IAAI;AACJ,IAAI;;;;;;AAOJ,SAAgB,mBAAmB,MAA2B;CAC5D,YAAY;CACZ,QAAQ,IAAI,eAAe,KAAK,QAAQ;CAKxC,MAAM,GAAG;EACP,UAAU;EACV,UAAU;CACZ,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,KACpB,KACA,SACA,UACqB;CACrB,MAAM,WAAW,IAAI,QAAQ,eAAe,EAAE;CAG9C,IAAI,CAAC,QAAQ,KAAK,QAAQ,GACxB,OAAO,SAAS,KAAK,OAAO;CAG9B,MAAM,eAAe,cAAc,QAAQ;CAC3C,MAAM,SAAS,aAAa,cAAc,MAAM;CAChD,MAAM,MAAM,SAAS,QAAQ,UAAU,WAAW;CAGlD,MAAM,QAAQ,UAAU,aAAa,WAAW,YAAY,IAAI;CAEhE,MAAM,MAAM,MAAM,IAAI,KAAK,KAAK;CAChC,IAAI,KACF,OAAO;EAAE,QAAQ;EAAU,QAAQ,IAAI;EAAM,cAAc;CAAK;CAGlE,MAAM,SAAS,aAAa,SAAS,MAAM,IAAI,QAAQ;CAEvD,MAAM,SAAS,cAAc,QAAQ;EACnC;EACA,QAAQ;EACR,QAAQ,UAAU;EAClB,YAAY;EAGZ,WAAW;EACX,aAAa,UAAU;CACzB,CAAC;CAMD,MAAM,OAAO,QAAQ,GAAG,OAAO,KAAK,eAAe,aAAa,MAAM,OAAO;CAE7E,MAAM,IAAI,KAAK;EAAE;EAAM,KAAK;CAAG,GAAG,KAAK;CAEvC,OAAO;EAAE,QAAQ;EAAU,QAAQ;EAAM,cAAc;CAAK;AAC9D"}
|
|
@@ -77,8 +77,9 @@ const resolveExternalsFromCore = {
|
|
|
77
77
|
async function registerLoader(transpile) {
|
|
78
78
|
const { port1, port2 } = new MessageChannel();
|
|
79
79
|
const selfPath = fileURLToPath(import.meta.url);
|
|
80
|
+
const hookThreadPath = path.join(path.dirname(selfPath), `hook-thread${path.extname(selfPath)}`);
|
|
80
81
|
const bundledCode = (await build({
|
|
81
|
-
entryPoints: [
|
|
82
|
+
entryPoints: [hookThreadPath],
|
|
82
83
|
bundle: true,
|
|
83
84
|
format: "esm",
|
|
84
85
|
write: false,
|
|
@@ -102,5 +103,5 @@ async function registerLoader(transpile) {
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
//#endregion
|
|
105
|
-
export { registerLoader };
|
|
106
|
+
export { registerLoader, resolveExternalsFromCore };
|
|
106
107
|
//# sourceMappingURL=register-loader.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-loader.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/register-loader.ts"],"sourcesContent":["import { putFileAsync } from \"@warlock.js/fs\";\nimport { build, type Plugin } from \"esbuild\";\nimport { register } from \"node:module\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { type MessagePort, MessageChannel } from \"node:worker_threads\";\nimport type { TranspileInit } from \"./load-hook.js\";\n\n/**\n * Rewrite the hook bundle's remaining npm imports to absolute paths resolved\n * from **core's own** location.\n *\n * The bundle is written into the consuming app's `.warlock/` directory, so a\n * bare `import \"esbuild\"` in it resolves starting from the *app*, walking up\n * the app's `node_modules`. `esbuild` and `get-tsconfig` are core's\n * dependencies, not the app's — under npm/yarn's flat hoisting they happen to\n * be reachable anyway, but under pnpm's strict layout they are not, and the\n * dev server dies with `ERR_MODULE_NOT_FOUND` for a package the app never\n * imported. That is a phantom dependency baked into generated code.\n *\n * Bundling them in instead is not an option for `esbuild`: its JS API is a\n * thin wrapper that spawns a platform-specific native binary, so inlining the\n * JavaScript would not remove the need for the package on disk. Resolving to\n * an absolute `file://` URL at generation time does — the generated file then\n * points straight at the copy core itself is using, whatever the installer's\n * layout.\n */\nexport const resolveExternalsFromCore: Plugin = {\n name: \"warlock-resolve-externals-from-core\",\n setup(build) {\n // The filter is deliberately loose — anything not starting `.` or `/` —\n // so the guards below carry the real logic.\n build.onResolve({ filter: /^[^./]/ }, (args) => {\n // The entry point comes through here too, and on Windows its absolute\n // path (\"D:\\\\…\") is not `.` or `/`. Marking it external fails the build.\n if (args.kind === \"entry-point\" || path.isAbsolute(args.path)) {\n return null;\n }\n\n if (args.path.startsWith(\"node:\")) {\n return { external: true };\n }\n\n try {\n return { path: import.meta.resolve(args.path), external: true };\n } catch {\n // Unresolvable from here — leave it bare and let Node try, which is\n // exactly the previous behaviour rather than a hard failure.\n return { external: true };\n }\n });\n },\n};\n\n/**\n * Bundle, write, and register the ESM loader hook.\n *\n * **Why bundle?**\n * `module.register()` runs the hook file in a fresh Node.js worker thread that\n * has no tsx hook of its own. The hook source is TypeScript, so we must produce\n * a plain ESM bundle before registering. esbuild inline-bundles all three hook\n * modules (`hook-thread`, `resolve-hook`, `load-hook`, `version-registry`)\n * into a single `.mjs` file written to `.warlock/`. External npm packages\n * (`esbuild`, `node:*`) are kept external — the hook thread can resolve those\n * from `node_modules` normally.\n *\n * **Why a file and not a `data:` URL?**\n * Some Node versions have issues resolving `import.meta.url` inside `data:`\n * modules. A real file under `.warlock/` is simpler and debuggable.\n *\n * **Timing**\n * Called from `FilesOrchestrator.init()` before any user `src/` module is\n * dynamically imported. `module.register()` takes effect for all subsequent\n * `import()` calls, which is exactly the window we need.\n *\n * @param transpile - Transpile-cache config to ship into the hook worker,\n * or `null` to keep the hook in tsx-passthrough mode.\n *\n * @returns The main-thread side of the MessageChannel. Callers post\n * `{ type: \"bump\", absolutePath }` messages on it to invalidate modules.\n *\n * @example\n * const port = await registerLoader(transpileInit);\n * // Later, when a file changes:\n * port.postMessage({ type: \"bump\", absolutePath: \"/abs/path/to/user.model.ts\" });\n */\nexport async function registerLoader(transpile: TranspileInit): Promise<MessagePort> {\n const { port1, port2 } = new MessageChannel();\n\n // hook-thread is a sibling module, so it shares THIS file's extension:\n // `.ts` when core runs from source (tsx), `.mjs` when published.\n const selfPath = fileURLToPath(import.meta.url);\n const hookThreadPath = path.join(path.dirname(selfPath), `hook-thread${path.extname(selfPath)}`);\n\n const bundleResult = await build({\n entryPoints: [hookThreadPath],\n bundle: true,\n format: \"esm\",\n write: false,\n platform: \"node\",\n target: \"node20\",\n // npm packages and Node built-ins stay external, but the plugin rewrites\n // each remaining npm specifier to an absolute path resolved from core's\n // own install — see `resolveExternalsFromCore` for why bare imports break\n // under pnpm's strict layout.\n packages: \"external\",\n plugins: [resolveExternalsFromCore],\n });\n\n const bundledCode = bundleResult.outputFiles[0]!.text;\n // Caller (filesOrchestrator.init) guarantees .warlock/ exists before this runs.\n const hookBundlePath = path.join(process.cwd(), \".warlock\", \"loader-hook.mjs\");\n await putFileAsync(hookBundlePath, bundledCode);\n\n const srcRoot = path.join(process.cwd(), \"src\");\n\n // No tsx registration: our hook owns resolution (own-resolver) and the\n // transpile of every `.ts`/`.tsx` (esbuild, in the load hook). The chain\n // is simply [our hook] → [Node default] for non-TS (npm/.js, node:).\n // In this monorepo tsx is still the *launcher* (`tsx start.ts`) so its\n // loader is present anyway, but it is never consulted for TypeScript —\n // our hook short-circuits first. A released `node bin/warlock.js` has no\n // tsx at all and relies entirely on this hook.\n\n register(pathToFileURL(hookBundlePath).href, import.meta.url, {\n data: { port: port2, srcRoot, transpile },\n transferList: [port2],\n });\n\n return port1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAa,2BAAmC;CAC9C,MAAM;CACN,MAAM,OAAO;EAGX,MAAM,UAAU,EAAE,QAAQ,SAAS,IAAI,SAAS;GAG9C,IAAI,KAAK,SAAS,iBAAiB,KAAK,WAAW,KAAK,IAAI,GAC1D,OAAO;GAGT,IAAI,KAAK,KAAK,WAAW,OAAO,GAC9B,OAAO,EAAE,UAAU,KAAK;GAG1B,IAAI;IACF,OAAO;KAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"register-loader.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/register-loader.ts"],"sourcesContent":["import { putFileAsync } from \"@warlock.js/fs\";\nimport { build, type Plugin } from \"esbuild\";\nimport { register } from \"node:module\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { type MessagePort, MessageChannel } from \"node:worker_threads\";\nimport type { TranspileInit } from \"./load-hook.js\";\n\n/**\n * Rewrite the hook bundle's remaining npm imports to absolute paths resolved\n * from **core's own** location.\n *\n * The bundle is written into the consuming app's `.warlock/` directory, so a\n * bare `import \"esbuild\"` in it resolves starting from the *app*, walking up\n * the app's `node_modules`. `esbuild` and `get-tsconfig` are core's\n * dependencies, not the app's — under npm/yarn's flat hoisting they happen to\n * be reachable anyway, but under pnpm's strict layout they are not, and the\n * dev server dies with `ERR_MODULE_NOT_FOUND` for a package the app never\n * imported. That is a phantom dependency baked into generated code.\n *\n * Bundling them in instead is not an option for `esbuild`: its JS API is a\n * thin wrapper that spawns a platform-specific native binary, so inlining the\n * JavaScript would not remove the need for the package on disk. Resolving to\n * an absolute `file://` URL at generation time does — the generated file then\n * points straight at the copy core itself is using, whatever the installer's\n * layout.\n */\nexport const resolveExternalsFromCore: Plugin = {\n name: \"warlock-resolve-externals-from-core\",\n setup(build) {\n // The filter is deliberately loose — anything not starting `.` or `/` —\n // so the guards below carry the real logic.\n build.onResolve({ filter: /^[^./]/ }, (args) => {\n // The entry point comes through here too, and on Windows its absolute\n // path (\"D:\\\\…\") is not `.` or `/`. Marking it external fails the build.\n if (args.kind === \"entry-point\" || path.isAbsolute(args.path)) {\n return null;\n }\n\n if (args.path.startsWith(\"node:\")) {\n return { external: true };\n }\n\n try {\n return { path: import.meta.resolve(args.path), external: true };\n } catch {\n // Unresolvable from here — leave it bare and let Node try, which is\n // exactly the previous behaviour rather than a hard failure.\n return { external: true };\n }\n });\n },\n};\n\n/**\n * Bundle, write, and register the ESM loader hook.\n *\n * **Why bundle?**\n * `module.register()` runs the hook file in a fresh Node.js worker thread that\n * has no tsx hook of its own. The hook source is TypeScript, so we must produce\n * a plain ESM bundle before registering. esbuild inline-bundles all three hook\n * modules (`hook-thread`, `resolve-hook`, `load-hook`, `version-registry`)\n * into a single `.mjs` file written to `.warlock/`. External npm packages\n * (`esbuild`, `node:*`) are kept external — the hook thread can resolve those\n * from `node_modules` normally.\n *\n * **Why a file and not a `data:` URL?**\n * Some Node versions have issues resolving `import.meta.url` inside `data:`\n * modules. A real file under `.warlock/` is simpler and debuggable.\n *\n * **Timing**\n * Called from `FilesOrchestrator.init()` before any user `src/` module is\n * dynamically imported. `module.register()` takes effect for all subsequent\n * `import()` calls, which is exactly the window we need.\n *\n * @param transpile - Transpile-cache config to ship into the hook worker,\n * or `null` to keep the hook in tsx-passthrough mode.\n *\n * @returns The main-thread side of the MessageChannel. Callers post\n * `{ type: \"bump\", absolutePath }` messages on it to invalidate modules.\n *\n * @example\n * const port = await registerLoader(transpileInit);\n * // Later, when a file changes:\n * port.postMessage({ type: \"bump\", absolutePath: \"/abs/path/to/user.model.ts\" });\n */\nexport async function registerLoader(transpile: TranspileInit): Promise<MessagePort> {\n const { port1, port2 } = new MessageChannel();\n\n // hook-thread is a sibling module, so it shares THIS file's extension:\n // `.ts` when core runs from source (tsx), `.mjs` when published.\n const selfPath = fileURLToPath(import.meta.url);\n const hookThreadPath = path.join(path.dirname(selfPath), `hook-thread${path.extname(selfPath)}`);\n\n const bundleResult = await build({\n entryPoints: [hookThreadPath],\n bundle: true,\n format: \"esm\",\n write: false,\n platform: \"node\",\n target: \"node20\",\n // npm packages and Node built-ins stay external, but the plugin rewrites\n // each remaining npm specifier to an absolute path resolved from core's\n // own install — see `resolveExternalsFromCore` for why bare imports break\n // under pnpm's strict layout.\n packages: \"external\",\n plugins: [resolveExternalsFromCore],\n });\n\n const bundledCode = bundleResult.outputFiles[0]!.text;\n // Caller (filesOrchestrator.init) guarantees .warlock/ exists before this runs.\n const hookBundlePath = path.join(process.cwd(), \".warlock\", \"loader-hook.mjs\");\n await putFileAsync(hookBundlePath, bundledCode);\n\n const srcRoot = path.join(process.cwd(), \"src\");\n\n // No tsx registration: our hook owns resolution (own-resolver) and the\n // transpile of every `.ts`/`.tsx` (esbuild, in the load hook). The chain\n // is simply [our hook] → [Node default] for non-TS (npm/.js, node:).\n // In this monorepo tsx is still the *launcher* (`tsx start.ts`) so its\n // loader is present anyway, but it is never consulted for TypeScript —\n // our hook short-circuits first. A released `node bin/warlock.js` has no\n // tsx at all and relies entirely on this hook.\n\n register(pathToFileURL(hookBundlePath).href, import.meta.url, {\n data: { port: port2, srcRoot, transpile },\n transferList: [port2],\n });\n\n return port1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAa,2BAAmC;CAC9C,MAAM;CACN,MAAM,OAAO;EAGX,MAAM,UAAU,EAAE,QAAQ,SAAS,IAAI,SAAS;GAG9C,IAAI,KAAK,SAAS,iBAAiB,KAAK,WAAW,KAAK,IAAI,GAC1D,OAAO;GAGT,IAAI,KAAK,KAAK,WAAW,OAAO,GAC9B,OAAO,EAAE,UAAU,KAAK;GAG1B,IAAI;IACF,OAAO;KAAE,MAAM,YAAY,QAAQ,KAAK,IAAI;KAAG,UAAU;IAAK;GAChE,QAAQ;IAGN,OAAO,EAAE,UAAU,KAAK;GAC1B;EACF,CAAC;CACH;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,eAAsB,eAAe,WAAgD;CACnF,MAAM,EAAE,OAAO,UAAU,IAAI,eAAe;CAI5C,MAAM,WAAW,cAAc,YAAY,GAAG;CAC9C,MAAM,iBAAiB,KAAK,KAAK,KAAK,QAAQ,QAAQ,GAAG,cAAc,KAAK,QAAQ,QAAQ,GAAG;CAiB/F,MAAM,eAAc,MAfO,MAAM;EAC/B,aAAa,CAAC,cAAc;EAC5B,QAAQ;EACR,QAAQ;EACR,OAAO;EACP,UAAU;EACV,QAAQ;EAKR,UAAU;EACV,SAAS,CAAC,wBAAwB;CACpC,CAAC,EAE+B,CAAC,YAAY,EAAE,CAAE;CAEjD,MAAM,iBAAiB,KAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,iBAAiB;CAC7E,MAAM,aAAa,gBAAgB,WAAW;CAE9C,MAAM,UAAU,KAAK,KAAK,QAAQ,IAAI,GAAG,KAAK;CAU9C,SAAS,cAAc,cAAc,CAAC,CAAC,MAAM,YAAY,KAAK;EAC5D,MAAM;GAAE,MAAM;GAAO;GAAS;EAAU;EACxC,cAAc,CAAC,KAAK;CACtB,CAAC;CAED,OAAO;AACT"}
|
|
@@ -35,7 +35,7 @@ type NextResolve = (specifier: string, context?: ResolveContext) => Promise<Reso
|
|
|
35
35
|
* // First import of user.model.ts → ?v=0
|
|
36
36
|
* // File watcher bumps → next import → ?v=1 → fresh module
|
|
37
37
|
*/
|
|
38
|
-
declare function resolve(specifier: string, context: ResolveContext, nextResolve: NextResolve): Promise<ResolveResult>;
|
|
38
|
+
export declare function resolve(specifier: string, context: ResolveContext, nextResolve: NextResolve): Promise<ResolveResult>;
|
|
39
39
|
//#endregion
|
|
40
|
-
export {
|
|
40
|
+
export {};
|
|
41
41
|
//# sourceMappingURL=resolve-hook.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-hook.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/resolve-hook.ts"],"mappings":";KAqCK
|
|
1
|
+
{"version":3,"file":"resolve-hook.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/resolve-hook.ts"],"mappings":";KAqCK;EACH;EACA;EACA,mBAAmB;;KAGhB;EACH;EACA;EACA;;KAGG,eAAe,mBAAmB,UAAU,mBAAmB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;wBA2BtD,QACpB,mBACA,SAAS,gBACT,aAAa,cACZ,QAAQ"}
|
|
@@ -74,7 +74,8 @@ async function resolve(specifier, context, nextResolve) {
|
|
|
74
74
|
});
|
|
75
75
|
const cleanUrl = url.replace(/\?v=\d+$/, "");
|
|
76
76
|
if (!cleanUrl.startsWith(srcRootUrl) || !cleanUrl.endsWith(".ts") && !cleanUrl.endsWith(".tsx")) return result;
|
|
77
|
-
const
|
|
77
|
+
const absolutePath = fileURLToPath(cleanUrl);
|
|
78
|
+
const version = getVersion(absolutePath);
|
|
78
79
|
return {
|
|
79
80
|
...result,
|
|
80
81
|
url: `${cleanUrl}?v=${version}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-hook.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/resolve-hook.ts"],"sourcesContent":["import { getTsconfig, resolvePathAlias } from \"get-tsconfig\";\nimport { existsSync } from \"node:fs\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { ownResolve, type PathsMatcher } from \"./own-resolver.js\";\nimport { captureResolution } from \"./resolve-capture.js\";\nimport { getVersion } from \"./version-registry.js\";\n\n/**\n * The `file://` URL prefix for the project's `src/` root, set once during\n * `initialize()`. Used to identify which resolved URLs belong to user code.\n */\nlet srcRootUrl = \"\";\n\n/**\n * Configure the source root used by the resolve hook.\n * Must be called from `initialize()` before any imports are resolved.\n *\n * @param srcRoot - Absolute filesystem path to the project `src/` directory.\n */\nexport function setSrcRoot(srcRoot: string): void {\n srcRootUrl = pathToFileURL(srcRoot).href + \"/\";\n}\n\n/** Lazily-built tsconfig `paths` matcher (worker has no startup hook). */\nlet pathsMatcher: PathsMatcher | null = null;\nlet pathsMatcherBuilt = false;\n\nfunction getPathsMatcher(): PathsMatcher | null {\n if (pathsMatcherBuilt) return pathsMatcher;\n pathsMatcherBuilt = true;\n const tsconfig = getTsconfig(process.cwd());\n // get-tsconfig v5 renamed the curried `createPathsMatcher(t)(spec)` to a direct\n // `resolvePathAlias(t, spec)`. Wrap it to keep the PathsMatcher closure shape.\n pathsMatcher = tsconfig ? (specifier: string) => resolvePathAlias(tsconfig, specifier) : null;\n return pathsMatcher;\n}\n\ntype ResolveContext = {\n parentURL?: string;\n conditions?: string[];\n importAttributes?: Record<string, string>;\n};\n\ntype ResolveResult = {\n url: string;\n format?: string;\n shortCircuit?: boolean;\n};\n\ntype NextResolve = (specifier: string, context?: ResolveContext) => Promise<ResolveResult>;\n\n/**\n * ESM loader `resolve()` hook.\n *\n * The framework's own resolver (`ownResolve`) handles tsconfig `paths`,\n * aliases, and TS extension/`index` probing. Specifiers it doesn't own\n * (bare npm, `node:`, `file:`) fall through to `nextResolve` (Node\n * default). After resolution, stamps a `?v=<N>` version token onto any\n * `.ts` / `.tsx` file that lives under the configured `src/` root.\n *\n * The version token is the cache-bust mechanism: when a file changes the main\n * thread bumps its counter, the next `import()` produces a new URL, Node sees\n * a cache miss, and loads fresh content — native ESM cycles are preserved\n * because static imports remain static throughout.\n *\n * **parentURL cleaning**: the resolved URL carries `?v=N` as a suffix. If a\n * module loaded this way statically imports a relative sibling, Node uses that\n * `?v=N` URL as the `parentURL` for the next `resolve()` call. Passing it\n * unmodified to `nextResolve()` causes tsx to produce paths like\n * `some-sibling.ts?v=0` (the query leaks into URL joining). We strip `?v=N`\n * from `parentURL` before forwarding to prevent this.\n *\n * @example\n * // First import of user.model.ts → ?v=0\n * // File watcher bumps → next import → ?v=1 → fresh module\n */\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve,\n): Promise<ResolveResult> {\n const cleanContext = context.parentURL?.includes(\"?v=\")\n ? { ...context, parentURL: context.parentURL.replace(/\\?v=\\d+$/, \"\") }\n : context;\n\n // The framework's own resolver owns tsconfig `paths` + TS\n // extension/index probing. Anything it returns `null` for (bare npm,\n // `node:`, `file:`) falls through to Node default via `nextResolve`.\n const owned = ownResolve(specifier, cleanContext.parentURL, getPathsMatcher(), existsSync);\n // When we produced the URL ourselves we did NOT call nextResolve, so the\n // result must short-circuit the loader chain or Node throws\n // ERR_LOADER_CHAIN_INCOMPLETE (e.g. for @warlock.js/* .ts that resolve\n // outside the project src root and hit the early return below).\n const result: ResolveResult = owned\n ? { url: owned, shortCircuit: true }\n : await nextResolve(specifier, cleanContext);\n\n const { url } = result;\n\n // Ground-truth recorder (no-op unless WARLOCK_RESOLVE_CAPTURE is set):\n // logs the answer for this (specifier, parentURL) so the Phase B\n // resolver can be proven to reproduce tsx exactly.\n captureResolution({\n specifier,\n parentURL: cleanContext.parentURL,\n url,\n format: result.format,\n });\n\n const cleanUrl = url.replace(/\\?v=\\d+$/, \"\");\n\n if (\n !cleanUrl.startsWith(srcRootUrl) ||\n (!cleanUrl.endsWith(\".ts\") && !cleanUrl.endsWith(\".tsx\"))\n ) {\n return result;\n }\n\n const absolutePath = fileURLToPath(cleanUrl);\n const version = getVersion(absolutePath);\n\n // Spread the full result from nextResolve (preserves `format` and any other\n // fields tsx sets) and only override `url`. Dropping `format` would cause\n // tsx's load hook to see an undefined format and fall through to Node's\n // default loader, which rejects unknown extensions like .tsx.\n return { ...result, url: `${cleanUrl}?v=${version}`, shortCircuit: true };\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAI,aAAa;;;;;;;AAQjB,SAAgB,WAAW,SAAuB;CAChD,aAAa,cAAc,OAAO,CAAC,CAAC,OAAO;AAC7C;;AAGA,IAAI,eAAoC;AACxC,IAAI,oBAAoB;AAExB,SAAS,kBAAuC;CAC9C,IAAI,mBAAmB,OAAO;CAC9B,oBAAoB;CACpB,MAAM,WAAW,YAAY,QAAQ,IAAI,CAAC;CAG1C,eAAe,YAAY,cAAsB,iBAAiB,UAAU,SAAS,IAAI;CACzF,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,eAAsB,QACpB,WACA,SACA,aACwB;CACxB,MAAM,eAAe,QAAQ,WAAW,SAAS,KAAK,IAClD;EAAE,GAAG;EAAS,WAAW,QAAQ,UAAU,QAAQ,YAAY,EAAE;CAAE,IACnE;CAKJ,MAAM,QAAQ,WAAW,WAAW,aAAa,WAAW,gBAAgB,GAAG,UAAU;CAKzF,MAAM,SAAwB,QAC1B;EAAE,KAAK;EAAO,cAAc;CAAK,IACjC,MAAM,YAAY,WAAW,YAAY;CAE7C,MAAM,EAAE,QAAQ;CAKhB,kBAAkB;EAChB;EACA,WAAW,aAAa;EACxB;EACA,QAAQ,OAAO;CACjB,CAAC;CAED,MAAM,WAAW,IAAI,QAAQ,YAAY,EAAE;CAE3C,IACE,CAAC,SAAS,WAAW,UAAU,KAC9B,CAAC,SAAS,SAAS,KAAK,KAAK,CAAC,SAAS,SAAS,MAAM,GAEvD,OAAO;
|
|
1
|
+
{"version":3,"file":"resolve-hook.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/resolve-hook.ts"],"sourcesContent":["import { getTsconfig, resolvePathAlias } from \"get-tsconfig\";\nimport { existsSync } from \"node:fs\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { ownResolve, type PathsMatcher } from \"./own-resolver.js\";\nimport { captureResolution } from \"./resolve-capture.js\";\nimport { getVersion } from \"./version-registry.js\";\n\n/**\n * The `file://` URL prefix for the project's `src/` root, set once during\n * `initialize()`. Used to identify which resolved URLs belong to user code.\n */\nlet srcRootUrl = \"\";\n\n/**\n * Configure the source root used by the resolve hook.\n * Must be called from `initialize()` before any imports are resolved.\n *\n * @param srcRoot - Absolute filesystem path to the project `src/` directory.\n */\nexport function setSrcRoot(srcRoot: string): void {\n srcRootUrl = pathToFileURL(srcRoot).href + \"/\";\n}\n\n/** Lazily-built tsconfig `paths` matcher (worker has no startup hook). */\nlet pathsMatcher: PathsMatcher | null = null;\nlet pathsMatcherBuilt = false;\n\nfunction getPathsMatcher(): PathsMatcher | null {\n if (pathsMatcherBuilt) return pathsMatcher;\n pathsMatcherBuilt = true;\n const tsconfig = getTsconfig(process.cwd());\n // get-tsconfig v5 renamed the curried `createPathsMatcher(t)(spec)` to a direct\n // `resolvePathAlias(t, spec)`. Wrap it to keep the PathsMatcher closure shape.\n pathsMatcher = tsconfig ? (specifier: string) => resolvePathAlias(tsconfig, specifier) : null;\n return pathsMatcher;\n}\n\ntype ResolveContext = {\n parentURL?: string;\n conditions?: string[];\n importAttributes?: Record<string, string>;\n};\n\ntype ResolveResult = {\n url: string;\n format?: string;\n shortCircuit?: boolean;\n};\n\ntype NextResolve = (specifier: string, context?: ResolveContext) => Promise<ResolveResult>;\n\n/**\n * ESM loader `resolve()` hook.\n *\n * The framework's own resolver (`ownResolve`) handles tsconfig `paths`,\n * aliases, and TS extension/`index` probing. Specifiers it doesn't own\n * (bare npm, `node:`, `file:`) fall through to `nextResolve` (Node\n * default). After resolution, stamps a `?v=<N>` version token onto any\n * `.ts` / `.tsx` file that lives under the configured `src/` root.\n *\n * The version token is the cache-bust mechanism: when a file changes the main\n * thread bumps its counter, the next `import()` produces a new URL, Node sees\n * a cache miss, and loads fresh content — native ESM cycles are preserved\n * because static imports remain static throughout.\n *\n * **parentURL cleaning**: the resolved URL carries `?v=N` as a suffix. If a\n * module loaded this way statically imports a relative sibling, Node uses that\n * `?v=N` URL as the `parentURL` for the next `resolve()` call. Passing it\n * unmodified to `nextResolve()` causes tsx to produce paths like\n * `some-sibling.ts?v=0` (the query leaks into URL joining). We strip `?v=N`\n * from `parentURL` before forwarding to prevent this.\n *\n * @example\n * // First import of user.model.ts → ?v=0\n * // File watcher bumps → next import → ?v=1 → fresh module\n */\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve,\n): Promise<ResolveResult> {\n const cleanContext = context.parentURL?.includes(\"?v=\")\n ? { ...context, parentURL: context.parentURL.replace(/\\?v=\\d+$/, \"\") }\n : context;\n\n // The framework's own resolver owns tsconfig `paths` + TS\n // extension/index probing. Anything it returns `null` for (bare npm,\n // `node:`, `file:`) falls through to Node default via `nextResolve`.\n const owned = ownResolve(specifier, cleanContext.parentURL, getPathsMatcher(), existsSync);\n // When we produced the URL ourselves we did NOT call nextResolve, so the\n // result must short-circuit the loader chain or Node throws\n // ERR_LOADER_CHAIN_INCOMPLETE (e.g. for @warlock.js/* .ts that resolve\n // outside the project src root and hit the early return below).\n const result: ResolveResult = owned\n ? { url: owned, shortCircuit: true }\n : await nextResolve(specifier, cleanContext);\n\n const { url } = result;\n\n // Ground-truth recorder (no-op unless WARLOCK_RESOLVE_CAPTURE is set):\n // logs the answer for this (specifier, parentURL) so the Phase B\n // resolver can be proven to reproduce tsx exactly.\n captureResolution({\n specifier,\n parentURL: cleanContext.parentURL,\n url,\n format: result.format,\n });\n\n const cleanUrl = url.replace(/\\?v=\\d+$/, \"\");\n\n if (\n !cleanUrl.startsWith(srcRootUrl) ||\n (!cleanUrl.endsWith(\".ts\") && !cleanUrl.endsWith(\".tsx\"))\n ) {\n return result;\n }\n\n const absolutePath = fileURLToPath(cleanUrl);\n const version = getVersion(absolutePath);\n\n // Spread the full result from nextResolve (preserves `format` and any other\n // fields tsx sets) and only override `url`. Dropping `format` would cause\n // tsx's load hook to see an undefined format and fall through to Node's\n // default loader, which rejects unknown extensions like .tsx.\n return { ...result, url: `${cleanUrl}?v=${version}`, shortCircuit: true };\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAI,aAAa;;;;;;;AAQjB,SAAgB,WAAW,SAAuB;CAChD,aAAa,cAAc,OAAO,CAAC,CAAC,OAAO;AAC7C;;AAGA,IAAI,eAAoC;AACxC,IAAI,oBAAoB;AAExB,SAAS,kBAAuC;CAC9C,IAAI,mBAAmB,OAAO;CAC9B,oBAAoB;CACpB,MAAM,WAAW,YAAY,QAAQ,IAAI,CAAC;CAG1C,eAAe,YAAY,cAAsB,iBAAiB,UAAU,SAAS,IAAI;CACzF,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,eAAsB,QACpB,WACA,SACA,aACwB;CACxB,MAAM,eAAe,QAAQ,WAAW,SAAS,KAAK,IAClD;EAAE,GAAG;EAAS,WAAW,QAAQ,UAAU,QAAQ,YAAY,EAAE;CAAE,IACnE;CAKJ,MAAM,QAAQ,WAAW,WAAW,aAAa,WAAW,gBAAgB,GAAG,UAAU;CAKzF,MAAM,SAAwB,QAC1B;EAAE,KAAK;EAAO,cAAc;CAAK,IACjC,MAAM,YAAY,WAAW,YAAY;CAE7C,MAAM,EAAE,QAAQ;CAKhB,kBAAkB;EAChB;EACA,WAAW,aAAa;EACxB;EACA,QAAQ,OAAO;CACjB,CAAC;CAED,MAAM,WAAW,IAAI,QAAQ,YAAY,EAAE;CAE3C,IACE,CAAC,SAAS,WAAW,UAAU,KAC9B,CAAC,SAAS,SAAS,KAAK,KAAK,CAAC,SAAS,SAAS,MAAM,GAEvD,OAAO;CAGT,MAAM,eAAe,cAAc,QAAQ;CAC3C,MAAM,UAAU,WAAW,YAAY;CAMvC,OAAO;EAAE,GAAG;EAAQ,KAAK,GAAG,SAAS,KAAK;EAAW,cAAc;CAAK;AAC1E"}
|
|
@@ -113,7 +113,8 @@ var TranspileCache = class {
|
|
|
113
113
|
* concurrent {@link get} never observes a half-written module.
|
|
114
114
|
*/
|
|
115
115
|
put(key, entry, label) {
|
|
116
|
-
|
|
116
|
+
const shard = this.shardDir(key);
|
|
117
|
+
mkdirSync(shard, { recursive: true });
|
|
117
118
|
this.atomicWrite(this.codePath(key, label), entry.code);
|
|
118
119
|
if (entry.map) this.atomicWrite(this.mapPath(key, label), entry.map);
|
|
119
120
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transpile-cache.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/transpile-cache.ts"],"sourcesContent":["/**\n * Persisted transpile cache.\n *\n * Keyed by a hash of *source content* plus a transform-options fingerprint.\n * Same source + same options → same key → same output, always. Changed\n * content → different key → fresh transpile. There is no path-keyed entry\n * anywhere, so the old \"stack trace points at a mangled cache filename\" bug\n * class is structurally impossible — the on-disk filename is opaque and the\n * source identity lives only inside the source map.\n *\n * This module is pure and hook-agnostic on purpose: it knows how to read,\n * write and evict cache entries given a key, nothing about the ESM loader,\n * `?v=N` versioning, or esbuild. Phase 2 wires it into the load hook.\n *\n * @example\n * const fp = computeFingerprint({\n * esbuildVersion: esbuild.version,\n * cacheEpoch: CACHE_EPOCH,\n * compilerOptions,\n * });\n * const key = cacheKey(sourceText, fp);\n * const hit = cache.get(key);\n * if (!hit) cache.put(key, { code, map });\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport {\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * A cached transpile result: the emitted JS and its source map (raw JSON\n * string, exactly as esbuild produced it). Either may be empty for code\n * that produced no map.\n */\nexport type TranspileEntry = {\n code: string;\n map: string;\n};\n\n/**\n * Inputs that change transpiled output for identical source text. Bumping\n * any of these must invalidate every entry — that is achieved structurally\n * by folding them into the key, not by sweeping the cache.\n */\nexport type FingerprintParts = {\n /** `esbuild.version` — a transform-engine upgrade can change output. */\n esbuildVersion: string;\n /**\n * Monotonic cache-format epoch owned by the framework. Bump it whenever\n * the cache contract (entry shape, map handling, key derivation) changes\n * so old entries are guaranteed to miss after a framework upgrade.\n */\n cacheEpoch: number;\n /**\n * The resolved tsconfig `compilerOptions` blob, hashed wholesale rather\n * than cherry-picking fields — safer against tsconfig drift (a new option\n * that affects output can't silently serve stale code).\n */\n compilerOptions: unknown;\n};\n\n/**\n * Current cache-format epoch. Bump on any change to {@link TranspileEntry}\n * shape, the storage layout, or how the loader consumes entries.\n */\nexport const CACHE_EPOCH = 1;\n\n/**\n * Stable JSON stringify — object keys sorted recursively so semantically\n * equal option blobs always produce the same fingerprint regardless of key\n * insertion order.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value) ?? \"null\";\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n\n const entries = Object.keys(value as Record<string, unknown>)\n .sort()\n .map((key) => {\n const child = stableStringify((value as Record<string, unknown>)[key]);\n return `${JSON.stringify(key)}:${child}`;\n });\n\n return `{${entries.join(\",\")}}`;\n}\n\n/**\n * Fold every output-affecting input into one short hex fingerprint that\n * becomes part of every cache key.\n */\nexport function computeFingerprint(parts: FingerprintParts): string {\n const canonical = stableStringify({\n esbuildVersion: parts.esbuildVersion,\n cacheEpoch: parts.cacheEpoch,\n compilerOptions: parts.compilerOptions,\n });\n\n return createHash(\"sha256\").update(canonical).digest(\"hex\").slice(0, 16);\n}\n\n/**\n * Derive the cache key for a source file. The NUL separator makes\n * `sourceText` and `fingerprint` unambiguous (no concatenation collision).\n */\nexport function cacheKey(sourceText: string, fingerprint: string): string {\n return createHash(\"sha256\").update(sourceText).update(\"\\0\").update(fingerprint).digest(\"hex\");\n}\n\n/** Options for {@link TranspileCache.gc}. */\nexport type GcOptions = {\n /** Evict least-recently-modified entries once total size exceeds this. */\n maxBytes?: number;\n /** Evict entries whose mtime is older than this many milliseconds. */\n maxAgeMs?: number;\n};\n\ntype CacheFileInfo = {\n codePath: string;\n mapPath: string;\n size: number;\n mtimeMs: number;\n};\n\n/**\n * Content-hash-addressed transpile cache stored on disk.\n *\n * Layout: `<cacheDir>/<first2-of-key>/<key>.js` plus a sibling `.js.map`.\n * Sharding by the first two hex chars keeps any single directory small on\n * large projects. GC metadata is derived from filesystem mtime so there is\n * no second source of truth (no sidecar index to keep consistent).\n */\nexport class TranspileCache {\n public constructor(private readonly cacheDir: string) {}\n\n private shardDir(key: string): string {\n return path.join(this.cacheDir, key.slice(0, 2));\n }\n\n /**\n * `label` is an optional human-readable prefix (e.g. a path slug). It is\n * cosmetic only — the content `key` is still what makes the name unique,\n * so the same `(key, label)` pair must be passed to `get` and `put`.\n */\n private fileName(key: string, label: string | undefined, ext: string): string {\n return label ? `${label}.${key}${ext}` : `${key}${ext}`;\n }\n\n private codePath(key: string, label?: string): string {\n return path.join(this.shardDir(key), this.fileName(key, label, \".js\"));\n }\n\n private mapPath(key: string, label?: string): string {\n return path.join(this.shardDir(key), this.fileName(key, label, \".js.map\"));\n }\n\n /**\n * Return the cached entry for `key`, or `null` on a miss. Synchronous on\n * purpose: this sits on the module-load hot path and must not pay an\n * event-loop hop per import.\n */\n public get(key: string, label?: string): TranspileEntry | null {\n try {\n const code = readFileSync(this.codePath(key, label), \"utf8\");\n let map = \"\";\n try {\n map = readFileSync(this.mapPath(key, label), \"utf8\");\n } catch {\n // A code entry with no map is valid (e.g. map-less transform).\n }\n return { code, map };\n } catch {\n return null;\n }\n }\n\n /**\n * Store an entry for `key`. Written atomically (temp file + rename) so a\n * concurrent {@link get} never observes a half-written module.\n */\n public put(key: string, entry: TranspileEntry, label?: string): void {\n const shard = this.shardDir(key);\n mkdirSync(shard, { recursive: true });\n\n this.atomicWrite(this.codePath(key, label), entry.code);\n if (entry.map) {\n this.atomicWrite(this.mapPath(key, label), entry.map);\n }\n }\n\n private atomicWrite(filePath: string, content: string): void {\n const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeFileSync(tempPath, content);\n renameSync(tempPath, filePath);\n } catch (error) {\n // Windows can report EPERM/EACCES when another loader process wins the\n // rename to this content-addressed destination. The winner's file is a\n // valid commit only when it contains the exact bytes we meant to store;\n // otherwise preserve the original error instead of accepting corruption.\n const code = (error as NodeJS.ErrnoException).code;\n const mayBeConcurrentCommit = code === \"EEXIST\" || code === \"EPERM\" || code === \"EACCES\";\n\n if (!mayBeConcurrentCommit || !this.hasCommittedContent(filePath, content)) {\n throw error;\n }\n } finally {\n try {\n rmSync(tempPath, { force: true });\n } catch {\n // Best effort: a cleanup failure must not mask the rename result.\n }\n }\n }\n\n private hasCommittedContent(filePath: string, content: string): boolean {\n try {\n return readFileSync(filePath, \"utf8\") === content;\n } catch {\n return false;\n }\n }\n\n /**\n * Opportunistic eviction. Cheap, runs at boot (not on the hot path).\n * Removes age-expired entries first, then trims to the size budget by\n * evicting least-recently-modified entries. Both bounds are optional;\n * with neither set this is a no-op.\n */\n public gc(options: GcOptions = {}): void {\n const { maxBytes, maxAgeMs } = options;\n if (maxBytes === undefined && maxAgeMs === undefined) return;\n\n const files = this.scan();\n const now = Date.now();\n\n let live = files;\n\n if (maxAgeMs !== undefined) {\n live = [];\n for (const file of files) {\n if (now - file.mtimeMs > maxAgeMs) {\n this.evict(file);\n } else {\n live.push(file);\n }\n }\n }\n\n if (maxBytes !== undefined) {\n let total = live.reduce((sum, file) => sum + file.size, 0);\n if (total > maxBytes) {\n // Oldest first — least-recently-modified is the eviction order.\n live.sort((a, b) => a.mtimeMs - b.mtimeMs);\n for (const file of live) {\n if (total <= maxBytes) break;\n total -= file.size;\n this.evict(file);\n }\n }\n }\n }\n\n private scan(): CacheFileInfo[] {\n const result: CacheFileInfo[] = [];\n\n let shards: string[];\n try {\n shards = readdirSync(this.cacheDir);\n } catch {\n return result;\n }\n\n for (const shard of shards) {\n const shardPath = path.join(this.cacheDir, shard);\n let entries: string[];\n try {\n entries = readdirSync(shardPath);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!entry.endsWith(\".js\")) continue;\n const codePath = path.join(shardPath, entry);\n try {\n const stat = statSync(codePath);\n const mapPath = `${codePath}.map`;\n let mapSize = 0;\n try {\n mapSize = statSync(mapPath).size;\n } catch {\n // no map sidecar — fine\n }\n result.push({\n codePath,\n mapPath,\n size: stat.size + mapSize,\n mtimeMs: stat.mtimeMs,\n });\n } catch {\n // entry vanished mid-scan — skip\n }\n }\n }\n\n return result;\n }\n\n private evict(file: CacheFileInfo): void {\n try {\n rmSync(file.codePath, { force: true });\n } catch {\n // best effort\n }\n try {\n rmSync(file.mapPath, { force: true });\n } catch {\n // best effort\n }\n }\n\n /** Remove the entire cache directory (used by `--fresh`). */\n public clear(): void {\n try {\n rmSync(this.cacheDir, { recursive: true, force: true });\n } catch {\n // best effort\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transpile-cache.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/dev-server/loader/transpile-cache.ts"],"sourcesContent":["/**\n * Persisted transpile cache.\n *\n * Keyed by a hash of *source content* plus a transform-options fingerprint.\n * Same source + same options → same key → same output, always. Changed\n * content → different key → fresh transpile. There is no path-keyed entry\n * anywhere, so the old \"stack trace points at a mangled cache filename\" bug\n * class is structurally impossible — the on-disk filename is opaque and the\n * source identity lives only inside the source map.\n *\n * This module is pure and hook-agnostic on purpose: it knows how to read,\n * write and evict cache entries given a key, nothing about the ESM loader,\n * `?v=N` versioning, or esbuild. Phase 2 wires it into the load hook.\n *\n * @example\n * const fp = computeFingerprint({\n * esbuildVersion: esbuild.version,\n * cacheEpoch: CACHE_EPOCH,\n * compilerOptions,\n * });\n * const key = cacheKey(sourceText, fp);\n * const hit = cache.get(key);\n * if (!hit) cache.put(key, { code, map });\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport {\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * A cached transpile result: the emitted JS and its source map (raw JSON\n * string, exactly as esbuild produced it). Either may be empty for code\n * that produced no map.\n */\nexport type TranspileEntry = {\n code: string;\n map: string;\n};\n\n/**\n * Inputs that change transpiled output for identical source text. Bumping\n * any of these must invalidate every entry — that is achieved structurally\n * by folding them into the key, not by sweeping the cache.\n */\nexport type FingerprintParts = {\n /** `esbuild.version` — a transform-engine upgrade can change output. */\n esbuildVersion: string;\n /**\n * Monotonic cache-format epoch owned by the framework. Bump it whenever\n * the cache contract (entry shape, map handling, key derivation) changes\n * so old entries are guaranteed to miss after a framework upgrade.\n */\n cacheEpoch: number;\n /**\n * The resolved tsconfig `compilerOptions` blob, hashed wholesale rather\n * than cherry-picking fields — safer against tsconfig drift (a new option\n * that affects output can't silently serve stale code).\n */\n compilerOptions: unknown;\n};\n\n/**\n * Current cache-format epoch. Bump on any change to {@link TranspileEntry}\n * shape, the storage layout, or how the loader consumes entries.\n */\nexport const CACHE_EPOCH = 1;\n\n/**\n * Stable JSON stringify — object keys sorted recursively so semantically\n * equal option blobs always produce the same fingerprint regardless of key\n * insertion order.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value) ?? \"null\";\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n\n const entries = Object.keys(value as Record<string, unknown>)\n .sort()\n .map((key) => {\n const child = stableStringify((value as Record<string, unknown>)[key]);\n return `${JSON.stringify(key)}:${child}`;\n });\n\n return `{${entries.join(\",\")}}`;\n}\n\n/**\n * Fold every output-affecting input into one short hex fingerprint that\n * becomes part of every cache key.\n */\nexport function computeFingerprint(parts: FingerprintParts): string {\n const canonical = stableStringify({\n esbuildVersion: parts.esbuildVersion,\n cacheEpoch: parts.cacheEpoch,\n compilerOptions: parts.compilerOptions,\n });\n\n return createHash(\"sha256\").update(canonical).digest(\"hex\").slice(0, 16);\n}\n\n/**\n * Derive the cache key for a source file. The NUL separator makes\n * `sourceText` and `fingerprint` unambiguous (no concatenation collision).\n */\nexport function cacheKey(sourceText: string, fingerprint: string): string {\n return createHash(\"sha256\").update(sourceText).update(\"\\0\").update(fingerprint).digest(\"hex\");\n}\n\n/** Options for {@link TranspileCache.gc}. */\nexport type GcOptions = {\n /** Evict least-recently-modified entries once total size exceeds this. */\n maxBytes?: number;\n /** Evict entries whose mtime is older than this many milliseconds. */\n maxAgeMs?: number;\n};\n\ntype CacheFileInfo = {\n codePath: string;\n mapPath: string;\n size: number;\n mtimeMs: number;\n};\n\n/**\n * Content-hash-addressed transpile cache stored on disk.\n *\n * Layout: `<cacheDir>/<first2-of-key>/<key>.js` plus a sibling `.js.map`.\n * Sharding by the first two hex chars keeps any single directory small on\n * large projects. GC metadata is derived from filesystem mtime so there is\n * no second source of truth (no sidecar index to keep consistent).\n */\nexport class TranspileCache {\n public constructor(private readonly cacheDir: string) {}\n\n private shardDir(key: string): string {\n return path.join(this.cacheDir, key.slice(0, 2));\n }\n\n /**\n * `label` is an optional human-readable prefix (e.g. a path slug). It is\n * cosmetic only — the content `key` is still what makes the name unique,\n * so the same `(key, label)` pair must be passed to `get` and `put`.\n */\n private fileName(key: string, label: string | undefined, ext: string): string {\n return label ? `${label}.${key}${ext}` : `${key}${ext}`;\n }\n\n private codePath(key: string, label?: string): string {\n return path.join(this.shardDir(key), this.fileName(key, label, \".js\"));\n }\n\n private mapPath(key: string, label?: string): string {\n return path.join(this.shardDir(key), this.fileName(key, label, \".js.map\"));\n }\n\n /**\n * Return the cached entry for `key`, or `null` on a miss. Synchronous on\n * purpose: this sits on the module-load hot path and must not pay an\n * event-loop hop per import.\n */\n public get(key: string, label?: string): TranspileEntry | null {\n try {\n const code = readFileSync(this.codePath(key, label), \"utf8\");\n let map = \"\";\n try {\n map = readFileSync(this.mapPath(key, label), \"utf8\");\n } catch {\n // A code entry with no map is valid (e.g. map-less transform).\n }\n return { code, map };\n } catch {\n return null;\n }\n }\n\n /**\n * Store an entry for `key`. Written atomically (temp file + rename) so a\n * concurrent {@link get} never observes a half-written module.\n */\n public put(key: string, entry: TranspileEntry, label?: string): void {\n const shard = this.shardDir(key);\n mkdirSync(shard, { recursive: true });\n\n this.atomicWrite(this.codePath(key, label), entry.code);\n if (entry.map) {\n this.atomicWrite(this.mapPath(key, label), entry.map);\n }\n }\n\n private atomicWrite(filePath: string, content: string): void {\n const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeFileSync(tempPath, content);\n renameSync(tempPath, filePath);\n } catch (error) {\n // Windows can report EPERM/EACCES when another loader process wins the\n // rename to this content-addressed destination. The winner's file is a\n // valid commit only when it contains the exact bytes we meant to store;\n // otherwise preserve the original error instead of accepting corruption.\n const code = (error as NodeJS.ErrnoException).code;\n const mayBeConcurrentCommit = code === \"EEXIST\" || code === \"EPERM\" || code === \"EACCES\";\n\n if (!mayBeConcurrentCommit || !this.hasCommittedContent(filePath, content)) {\n throw error;\n }\n } finally {\n try {\n rmSync(tempPath, { force: true });\n } catch {\n // Best effort: a cleanup failure must not mask the rename result.\n }\n }\n }\n\n private hasCommittedContent(filePath: string, content: string): boolean {\n try {\n return readFileSync(filePath, \"utf8\") === content;\n } catch {\n return false;\n }\n }\n\n /**\n * Opportunistic eviction. Cheap, runs at boot (not on the hot path).\n * Removes age-expired entries first, then trims to the size budget by\n * evicting least-recently-modified entries. Both bounds are optional;\n * with neither set this is a no-op.\n */\n public gc(options: GcOptions = {}): void {\n const { maxBytes, maxAgeMs } = options;\n if (maxBytes === undefined && maxAgeMs === undefined) return;\n\n const files = this.scan();\n const now = Date.now();\n\n let live = files;\n\n if (maxAgeMs !== undefined) {\n live = [];\n for (const file of files) {\n if (now - file.mtimeMs > maxAgeMs) {\n this.evict(file);\n } else {\n live.push(file);\n }\n }\n }\n\n if (maxBytes !== undefined) {\n let total = live.reduce((sum, file) => sum + file.size, 0);\n if (total > maxBytes) {\n // Oldest first — least-recently-modified is the eviction order.\n live.sort((a, b) => a.mtimeMs - b.mtimeMs);\n for (const file of live) {\n if (total <= maxBytes) break;\n total -= file.size;\n this.evict(file);\n }\n }\n }\n }\n\n private scan(): CacheFileInfo[] {\n const result: CacheFileInfo[] = [];\n\n let shards: string[];\n try {\n shards = readdirSync(this.cacheDir);\n } catch {\n return result;\n }\n\n for (const shard of shards) {\n const shardPath = path.join(this.cacheDir, shard);\n let entries: string[];\n try {\n entries = readdirSync(shardPath);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!entry.endsWith(\".js\")) continue;\n const codePath = path.join(shardPath, entry);\n try {\n const stat = statSync(codePath);\n const mapPath = `${codePath}.map`;\n let mapSize = 0;\n try {\n mapSize = statSync(mapPath).size;\n } catch {\n // no map sidecar — fine\n }\n result.push({\n codePath,\n mapPath,\n size: stat.size + mapSize,\n mtimeMs: stat.mtimeMs,\n });\n } catch {\n // entry vanished mid-scan — skip\n }\n }\n }\n\n return result;\n }\n\n private evict(file: CacheFileInfo): void {\n try {\n rmSync(file.codePath, { force: true });\n } catch {\n // best effort\n }\n try {\n rmSync(file.mapPath, { force: true });\n } catch {\n // best effort\n }\n }\n\n /** Remove the entire cache directory (used by `--fresh`). */\n public clear(): void {\n try {\n rmSync(this.cacheDir, { recursive: true, force: true });\n } catch {\n // best effort\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { FileManifest } from "./types.mjs";
|
|
2
2
|
import { FileManager } from "./file-manager.mjs";
|
|
3
|
-
|
|
4
3
|
//#region ../../packages/core/src/dev-server/manifest-manager.d.ts
|
|
5
|
-
declare class ManifestManager {
|
|
4
|
+
export declare class ManifestManager {
|
|
6
5
|
private readonly files;
|
|
7
6
|
/**
|
|
8
7
|
* Manifest data with metadata
|
|
@@ -67,5 +66,4 @@ declare class ManifestManager {
|
|
|
67
66
|
clear(): void;
|
|
68
67
|
}
|
|
69
68
|
//#endregion
|
|
70
|
-
export { ManifestManager };
|
|
71
69
|
//# sourceMappingURL=manifest-manager.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-manager.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/dev-server/manifest-manager.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest-manager.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/dev-server/manifest-manager.ts"],"mappings":";;;qBAqBa;mBAiByB;;;;UAb5B;;;;EAaR,YAAoC,OAAO,YAAY;;;;;EAM1C,QAAQ;;;;EAuBR,QAAQ;;;;EAYd,QAAQ,mBAAmB;;;;EAO3B,QAAQ;;;;EAOR,QAAQ,kBAAkB,cAAc;;;;EAOxC,WAAW;;;;EAOX;;;;EAOA,eAAe,eAAe;;;;EAO9B;IAEH;IACA;IACA;IACA;MA/GU;MACO;;;;;;UAqHb;;;;EAUD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { container } from "../container/index.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import
|
|
3
|
+
import fsSync from "node:fs";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
|
|
6
6
|
//#region ../../packages/core/src/dev-server/model-module-registry.ts
|
|
@@ -11,7 +11,7 @@ function normalizeInputPath(absolutePath) {
|
|
|
11
11
|
function canonicalPath(absolutePath) {
|
|
12
12
|
let resolvedPath = path.resolve(absolutePath);
|
|
13
13
|
try {
|
|
14
|
-
resolvedPath =
|
|
14
|
+
resolvedPath = fsSync.realpathSync.native(resolvedPath);
|
|
15
15
|
} catch {}
|
|
16
16
|
return normalizeInputPath(resolvedPath);
|
|
17
17
|
}
|
|
@@ -86,5 +86,5 @@ function getDevelopmentModelModuleRegistry() {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
//#endregion
|
|
89
|
-
export { getDevelopmentModelModuleRegistry };
|
|
89
|
+
export { DevelopmentModelModuleRegistry, getDevelopmentModelModuleRegistry };
|
|
90
90
|
//# sourceMappingURL=model-module-registry.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-module-registry.mjs","names":[],"sources":["../../../../../../../../packages/core/src/dev-server/model-module-registry.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { container } from \"../container\";\nimport type {\n DevelopmentModelModuleEntry,\n DevelopmentModelModules,\n} from \"../container/development-model-modules\";\n\ntype StoredEntry = DevelopmentModelModuleEntry & { readonly namespace?: object };\n\nfunction normalizeInputPath(absolutePath: string): string {\n const slashNormalized = path.resolve(absolutePath).replaceAll(\"\\\\\", \"/\");\n return process.platform === \"win32\" ? slashNormalized.toLowerCase() : slashNormalized;\n}\n\nfunction canonicalPath(absolutePath: string): string {\n let resolvedPath = path.resolve(absolutePath);\n\n try {\n resolvedPath = fs.realpathSync.native(resolvedPath);\n } catch {\n // A deleted model must still resolve to the key it had before deletion.\n }\n\n return normalizeInputPath(resolvedPath);\n}\n\n/** Internal writer for the container's read-only development model carrier. */\nexport class DevelopmentModelModuleRegistry implements DevelopmentModelModules {\n private readonly entries = new Map<string, StoredEntry>();\n private readonly aliases = new Map<string, string>();\n private readonly listeners = new Set<(entry: DevelopmentModelModuleEntry) => void>();\n\n public get(absolutePath: string): DevelopmentModelModuleEntry | undefined {\n const inputPath = normalizeInputPath(absolutePath);\n const key = this.aliases.get(inputPath) ?? canonicalPath(absolutePath);\n const entry = this.entries.get(key);\n if (entry !== undefined) this.aliases.set(inputPath, key);\n return entry === undefined ? undefined : this.toPublicEntry(entry);\n }\n\n public subscribe(listener: (entry: DevelopmentModelModuleEntry) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n public publish(absolutePath: string, url: string, namespace: object): void {\n const inputPath = normalizeInputPath(absolutePath);\n const key = canonicalPath(absolutePath);\n this.aliases.set(inputPath, key);\n const current = this.entries.get(key);\n\n if (current?.state === \"ready\" && current.namespace === namespace) return;\n\n const entry: StoredEntry = {\n url,\n generation: (current?.generation ?? 0) + 1,\n hasDefault: Object.hasOwn(namespace, \"default\"),\n state: \"ready\",\n namespace,\n };\n this.entries.set(key, entry);\n this.notify(entry);\n }\n\n public remove(absolutePath: string): void {\n const inputPath = normalizeInputPath(absolutePath);\n const key = this.aliases.get(inputPath) ?? canonicalPath(absolutePath);\n this.aliases.set(inputPath, key);\n const current = this.entries.get(key);\n\n if (current?.state === \"removed\") return;\n\n const entry: DevelopmentModelModuleEntry = {\n url: current?.url ?? pathToFileURL(absolutePath).href,\n generation: (current?.generation ?? 0) + 1,\n hasDefault: false,\n state: \"removed\",\n };\n this.entries.set(key, entry);\n this.notify(entry);\n }\n\n private notify(entry: DevelopmentModelModuleEntry): void {\n const publicEntry = this.toPublicEntry(entry);\n for (const listener of this.listeners) listener(publicEntry);\n }\n\n private toPublicEntry(entry: DevelopmentModelModuleEntry): DevelopmentModelModuleEntry {\n return {\n url: entry.url,\n generation: entry.generation,\n hasDefault: entry.hasDefault,\n state: entry.state,\n };\n }\n}\n\nexport function getDevelopmentModelModuleRegistry(): DevelopmentModelModuleRegistry {\n const existing = container.tryGet(\"development.modelModules\");\n\n if (existing instanceof DevelopmentModelModuleRegistry) return existing;\n\n const registry = new DevelopmentModelModuleRegistry();\n container.set(\"development.modelModules\", registry);\n return registry;\n}\n"],"mappings":";;;;;;AAWA,SAAS,mBAAmB,cAA8B;CACxD,MAAM,kBAAkB,KAAK,QAAQ,YAAY,CAAC,CAAC,WAAW,MAAM,GAAG;CACvE,OAAO,QAAQ,aAAa,UAAU,gBAAgB,YAAY,IAAI;AACxE;AAEA,SAAS,cAAc,cAA8B;CACnD,IAAI,eAAe,KAAK,QAAQ,YAAY;CAE5C,IAAI;EACF,
|
|
1
|
+
{"version":3,"file":"model-module-registry.mjs","names":["fs"],"sources":["../../../../../../../../packages/core/src/dev-server/model-module-registry.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { container } from \"../container\";\nimport type {\n DevelopmentModelModuleEntry,\n DevelopmentModelModules,\n} from \"../container/development-model-modules\";\n\ntype StoredEntry = DevelopmentModelModuleEntry & { readonly namespace?: object };\n\nfunction normalizeInputPath(absolutePath: string): string {\n const slashNormalized = path.resolve(absolutePath).replaceAll(\"\\\\\", \"/\");\n return process.platform === \"win32\" ? slashNormalized.toLowerCase() : slashNormalized;\n}\n\nfunction canonicalPath(absolutePath: string): string {\n let resolvedPath = path.resolve(absolutePath);\n\n try {\n resolvedPath = fs.realpathSync.native(resolvedPath);\n } catch {\n // A deleted model must still resolve to the key it had before deletion.\n }\n\n return normalizeInputPath(resolvedPath);\n}\n\n/** Internal writer for the container's read-only development model carrier. */\nexport class DevelopmentModelModuleRegistry implements DevelopmentModelModules {\n private readonly entries = new Map<string, StoredEntry>();\n private readonly aliases = new Map<string, string>();\n private readonly listeners = new Set<(entry: DevelopmentModelModuleEntry) => void>();\n\n public get(absolutePath: string): DevelopmentModelModuleEntry | undefined {\n const inputPath = normalizeInputPath(absolutePath);\n const key = this.aliases.get(inputPath) ?? canonicalPath(absolutePath);\n const entry = this.entries.get(key);\n if (entry !== undefined) this.aliases.set(inputPath, key);\n return entry === undefined ? undefined : this.toPublicEntry(entry);\n }\n\n public subscribe(listener: (entry: DevelopmentModelModuleEntry) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n public publish(absolutePath: string, url: string, namespace: object): void {\n const inputPath = normalizeInputPath(absolutePath);\n const key = canonicalPath(absolutePath);\n this.aliases.set(inputPath, key);\n const current = this.entries.get(key);\n\n if (current?.state === \"ready\" && current.namespace === namespace) return;\n\n const entry: StoredEntry = {\n url,\n generation: (current?.generation ?? 0) + 1,\n hasDefault: Object.hasOwn(namespace, \"default\"),\n state: \"ready\",\n namespace,\n };\n this.entries.set(key, entry);\n this.notify(entry);\n }\n\n public remove(absolutePath: string): void {\n const inputPath = normalizeInputPath(absolutePath);\n const key = this.aliases.get(inputPath) ?? canonicalPath(absolutePath);\n this.aliases.set(inputPath, key);\n const current = this.entries.get(key);\n\n if (current?.state === \"removed\") return;\n\n const entry: DevelopmentModelModuleEntry = {\n url: current?.url ?? pathToFileURL(absolutePath).href,\n generation: (current?.generation ?? 0) + 1,\n hasDefault: false,\n state: \"removed\",\n };\n this.entries.set(key, entry);\n this.notify(entry);\n }\n\n private notify(entry: DevelopmentModelModuleEntry): void {\n const publicEntry = this.toPublicEntry(entry);\n for (const listener of this.listeners) listener(publicEntry);\n }\n\n private toPublicEntry(entry: DevelopmentModelModuleEntry): DevelopmentModelModuleEntry {\n return {\n url: entry.url,\n generation: entry.generation,\n hasDefault: entry.hasDefault,\n state: entry.state,\n };\n }\n}\n\nexport function getDevelopmentModelModuleRegistry(): DevelopmentModelModuleRegistry {\n const existing = container.tryGet(\"development.modelModules\");\n\n if (existing instanceof DevelopmentModelModuleRegistry) return existing;\n\n const registry = new DevelopmentModelModuleRegistry();\n container.set(\"development.modelModules\", registry);\n return registry;\n}\n"],"mappings":";;;;;;AAWA,SAAS,mBAAmB,cAA8B;CACxD,MAAM,kBAAkB,KAAK,QAAQ,YAAY,CAAC,CAAC,WAAW,MAAM,GAAG;CACvE,OAAO,QAAQ,aAAa,UAAU,gBAAgB,YAAY,IAAI;AACxE;AAEA,SAAS,cAAc,cAA8B;CACnD,IAAI,eAAe,KAAK,QAAQ,YAAY;CAE5C,IAAI;EACF,eAAeA,OAAG,aAAa,OAAO,YAAY;CACpD,QAAQ,CAER;CAEA,OAAO,mBAAmB,YAAY;AACxC;;AAGA,IAAa,iCAAb,MAA+E;;iCAClD,IAAI,IAAyB;iCAC7B,IAAI,IAAoB;mCACtB,IAAI,IAAkD;;CAEnF,AAAO,IAAI,cAA+D;EACxE,MAAM,YAAY,mBAAmB,YAAY;EACjD,MAAM,MAAM,KAAK,QAAQ,IAAI,SAAS,KAAK,cAAc,YAAY;EACrE,MAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG;EAClC,IAAI,UAAU,QAAW,KAAK,QAAQ,IAAI,WAAW,GAAG;EACxD,OAAO,UAAU,SAAY,SAAY,KAAK,cAAc,KAAK;CACnE;CAEA,AAAO,UAAU,UAAoE;EACnF,KAAK,UAAU,IAAI,QAAQ;EAC3B,aAAa,KAAK,UAAU,OAAO,QAAQ;CAC7C;CAEA,AAAO,QAAQ,cAAsB,KAAa,WAAyB;EACzE,MAAM,YAAY,mBAAmB,YAAY;EACjD,MAAM,MAAM,cAAc,YAAY;EACtC,KAAK,QAAQ,IAAI,WAAW,GAAG;EAC/B,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;EAEpC,IAAI,SAAS,UAAU,WAAW,QAAQ,cAAc,WAAW;EAEnE,MAAM,QAAqB;GACzB;GACA,aAAa,SAAS,cAAc,KAAK;GACzC,YAAY,OAAO,OAAO,WAAW,SAAS;GAC9C,OAAO;GACP;EACF;EACA,KAAK,QAAQ,IAAI,KAAK,KAAK;EAC3B,KAAK,OAAO,KAAK;CACnB;CAEA,AAAO,OAAO,cAA4B;EACxC,MAAM,YAAY,mBAAmB,YAAY;EACjD,MAAM,MAAM,KAAK,QAAQ,IAAI,SAAS,KAAK,cAAc,YAAY;EACrE,KAAK,QAAQ,IAAI,WAAW,GAAG;EAC/B,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;EAEpC,IAAI,SAAS,UAAU,WAAW;EAElC,MAAM,QAAqC;GACzC,KAAK,SAAS,OAAO,cAAc,YAAY,CAAC,CAAC;GACjD,aAAa,SAAS,cAAc,KAAK;GACzC,YAAY;GACZ,OAAO;EACT;EACA,KAAK,QAAQ,IAAI,KAAK,KAAK;EAC3B,KAAK,OAAO,KAAK;CACnB;CAEA,AAAQ,OAAO,OAA0C;EACvD,MAAM,cAAc,KAAK,cAAc,KAAK;EAC5C,KAAK,MAAM,YAAY,KAAK,WAAW,SAAS,WAAW;CAC7D;CAEA,AAAQ,cAAc,OAAiE;EACrF,OAAO;GACL,KAAK,MAAM;GACX,YAAY,MAAM;GAClB,YAAY,MAAM;GAClB,OAAO,MAAM;EACf;CACF;AACF;AAEA,SAAgB,oCAAoE;CAClF,MAAM,WAAW,UAAU,OAAO,0BAA0B;CAE5D,IAAI,oBAAoB,gCAAgC,OAAO;CAE/D,MAAM,WAAW,IAAI,+BAA+B;CACpD,UAAU,IAAI,4BAA4B,QAAQ;CAClD,OAAO;AACT"}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import { expressionOf, hasModifier as hasModifier$1, isClassDeclaration, isEnumDeclaration, isFunctionDeclaration, isIdentifier, isImportDeclaration, isParenthesizedExpression, isPropertyDeclaration, isStringLiteral, isVariableStatement, parseSourceFile, topLevelDeclarations, valueText } from "../tooling/syntax/ast.mjs";
|
|
1
2
|
import { dirname, isAbsolute, relative } from "node:path";
|
|
2
3
|
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import ts from "typescript";
|
|
4
4
|
|
|
5
5
|
//#region ../../packages/core/src/dev-server/model-resource-typings.ts
|
|
6
6
|
const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
7
|
-
|
|
8
|
-
return ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some((m) => m.kind === kind) ?? false);
|
|
9
|
-
}
|
|
7
|
+
const hasModifier = hasModifier$1;
|
|
10
8
|
function unwrapParentheses(expression) {
|
|
11
9
|
let current = expression;
|
|
12
|
-
while (
|
|
10
|
+
while (isParenthesizedExpression(current)) current = expressionOf(current);
|
|
13
11
|
return current;
|
|
14
12
|
}
|
|
15
13
|
/** Top-level names this file declares, and the names each is exported under. */
|
|
@@ -21,30 +19,28 @@ function readLocalDeclarations(sourceFile) {
|
|
|
21
19
|
names.push(exported);
|
|
22
20
|
exportNames.set(local, names);
|
|
23
21
|
};
|
|
24
|
-
for (const statement of sourceFile
|
|
25
|
-
const exported = hasModifier(statement,
|
|
26
|
-
const isDefault = hasModifier(statement,
|
|
27
|
-
if ((
|
|
28
|
-
declared.add(statement.
|
|
29
|
-
if (exported) addExport(statement.
|
|
22
|
+
for (const statement of topLevelDeclarations(sourceFile)) {
|
|
23
|
+
const exported = hasModifier(statement, "export");
|
|
24
|
+
const isDefault = hasModifier(statement, "default");
|
|
25
|
+
if ((isClassDeclaration(statement) || isFunctionDeclaration(statement) || isEnumDeclaration(statement)) && statement.id) {
|
|
26
|
+
declared.add(valueText(statement.id));
|
|
27
|
+
if (exported) addExport(valueText(statement.id), isDefault ? "default" : valueText(statement.id));
|
|
30
28
|
continue;
|
|
31
29
|
}
|
|
32
|
-
if (
|
|
33
|
-
for (const declaration of statement.
|
|
34
|
-
if (!
|
|
35
|
-
declared.add(declaration.
|
|
36
|
-
if (exported) addExport(declaration.
|
|
30
|
+
if (isVariableStatement(statement)) {
|
|
31
|
+
for (const declaration of statement.declarations) {
|
|
32
|
+
if (!isIdentifier(declaration.id)) continue;
|
|
33
|
+
declared.add(valueText(declaration.id));
|
|
34
|
+
if (exported) addExport(valueText(declaration.id), valueText(declaration.id));
|
|
37
35
|
}
|
|
38
36
|
continue;
|
|
39
37
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
continue;
|
|
38
|
+
}
|
|
39
|
+
for (const statement of sourceFile.body) {
|
|
40
|
+
if (statement.type === "ExportNamedDeclaration" && !statement.source && statement.exportKind !== "type") {
|
|
41
|
+
for (const element of statement.specifiers) if (element.exportKind !== "type") addExport(valueText(element.local), valueText(element.exported));
|
|
46
42
|
}
|
|
47
|
-
if (
|
|
43
|
+
if (statement.type === "ExportDefaultDeclaration" && statement.declaration.type === "Identifier") addExport(statement.declaration.name, "default");
|
|
48
44
|
}
|
|
49
45
|
return {
|
|
50
46
|
declared,
|
|
@@ -58,31 +54,28 @@ function pickExportName(names) {
|
|
|
58
54
|
}
|
|
59
55
|
function readImportBindings(sourceFile) {
|
|
60
56
|
const bindings = /* @__PURE__ */ new Map();
|
|
61
|
-
for (const statement of sourceFile
|
|
62
|
-
if (!
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
if (!clause) continue;
|
|
66
|
-
if (clause.name) bindings.set(clause.name.text, {
|
|
67
|
-
specifier,
|
|
57
|
+
for (const statement of topLevelDeclarations(sourceFile)) {
|
|
58
|
+
if (!isImportDeclaration(statement)) continue;
|
|
59
|
+
for (const specifier of statement.specifiers) if (specifier.type === "ImportDefaultSpecifier") bindings.set(specifier.local.name, {
|
|
60
|
+
specifier: statement.source.value,
|
|
68
61
|
exportName: "default"
|
|
69
62
|
});
|
|
70
|
-
if (
|
|
71
|
-
specifier,
|
|
72
|
-
exportName: (
|
|
63
|
+
else if (specifier.type === "ImportSpecifier") bindings.set(specifier.local.name, {
|
|
64
|
+
specifier: statement.source.value,
|
|
65
|
+
exportName: valueText(specifier.imported)
|
|
73
66
|
});
|
|
74
67
|
}
|
|
75
68
|
return bindings;
|
|
76
69
|
}
|
|
77
70
|
/** The identifier a class assigns to `static resource`, when it is a bare identifier. */
|
|
78
71
|
function readStaticResourceReference(member) {
|
|
79
|
-
if (!
|
|
80
|
-
if (!hasModifier(member,
|
|
81
|
-
if (hasModifier(member,
|
|
82
|
-
if (!((
|
|
83
|
-
if (!member.
|
|
84
|
-
const initializer = unwrapParentheses(member.
|
|
85
|
-
return
|
|
72
|
+
if (!isPropertyDeclaration(member)) return void 0;
|
|
73
|
+
if (!hasModifier(member, "static")) return void 0;
|
|
74
|
+
if (hasModifier(member, "declare")) return void 0;
|
|
75
|
+
if (!((isIdentifier(member.key) || isStringLiteral(member.key)) && valueText(member.key) === "resource")) return void 0;
|
|
76
|
+
if (!member.value) return void 0;
|
|
77
|
+
const initializer = unwrapParentheses(member.value);
|
|
78
|
+
return isIdentifier(initializer) ? { name: valueText(initializer) } : "computed";
|
|
86
79
|
}
|
|
87
80
|
/**
|
|
88
81
|
* Read every model class of one file that declares `static resource = <Identifier>`
|
|
@@ -95,14 +88,14 @@ function extractModelResourceEntries(input) {
|
|
|
95
88
|
skipped: []
|
|
96
89
|
};
|
|
97
90
|
if (!input.source.includes("resource")) return result;
|
|
98
|
-
const sourceFile =
|
|
91
|
+
const sourceFile = parseSourceFile(input.absolutePath, input.source);
|
|
99
92
|
const { declared, exportNames } = readLocalDeclarations(sourceFile);
|
|
100
93
|
const imports = readImportBindings(sourceFile);
|
|
101
|
-
for (const statement of sourceFile
|
|
102
|
-
if (!
|
|
103
|
-
const className = statement.
|
|
94
|
+
for (const statement of topLevelDeclarations(sourceFile)) {
|
|
95
|
+
if (!isClassDeclaration(statement) || !statement.id) continue;
|
|
96
|
+
const className = valueText(statement.id);
|
|
104
97
|
let reference;
|
|
105
|
-
for (const member of statement.
|
|
98
|
+
for (const member of statement.body.body) reference = readStaticResourceReference(member) ?? reference;
|
|
106
99
|
if (reference === void 0) continue;
|
|
107
100
|
const skip = (reason) => {
|
|
108
101
|
result.skipped.push({
|
|
@@ -115,7 +108,7 @@ function extractModelResourceEntries(input) {
|
|
|
115
108
|
skip("`static resource` is not a plain identifier");
|
|
116
109
|
continue;
|
|
117
110
|
}
|
|
118
|
-
if (statement.typeParameters?.some((parameter) => parameter.default
|
|
111
|
+
if (statement.typeParameters?.params.some((parameter) => parameter.default == null)) {
|
|
119
112
|
skip("the model class is generic");
|
|
120
113
|
continue;
|
|
121
114
|
}
|
|
@@ -242,5 +235,5 @@ async function writeFileIfChanged(filePath, content) {
|
|
|
242
235
|
}
|
|
243
236
|
|
|
244
237
|
//#endregion
|
|
245
|
-
export { extractModelResourceEntries, renderModelResourceRegistry, writeFileIfChanged };
|
|
238
|
+
export { assignRegistryKeys, extractModelResourceEntries, renderModelResourceRegistry, writeFileIfChanged };
|
|
246
239
|
//# sourceMappingURL=model-resource-typings.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-resource-typings.mjs","names":[],"sources":["../../../../../../../../packages/core/src/dev-server/model-resource-typings.ts"],"sourcesContent":["import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, relative } from \"node:path\";\nimport ts from \"typescript\";\n\n/**\n * Static `ModelResourceRegistry` generation.\n *\n * `Serialized<User>` can only resolve a model to its resource output through an\n * entry in the augmentable `ModelResourceRegistry` (see `http/serialized.ts`).\n * This module derives those entries from source: a model class that declares\n * `static resource = UserResource` produces\n *\n * ```ts\n * \"User\": { model: import(\"<model file>\").User; resource: typeof import(\"<resource file>\").UserResource };\n * ```\n *\n * Everything here is syntactic. It reads one `ts.createSourceFile` AST per model\n * file, follows the identifier through that file's own imports, and never\n * imports or executes application code (`read-config-ast.ts` explains why a\n * type checker is not an option). Anything it cannot prove from the AST alone\n * (a computed expression, `lazy(...)`, a namespace import, a class that is not\n * exported) is skipped, and nothing is recorded for it: a guessed entry would\n * make `Serialized` lie, which is worse than the raw-data type it falls back to.\n */\n\n/** One model class whose resource could be resolved statically. */\nexport type ModelResourceEntry = {\n /** The model class name (the registry key before de-duplication). */\n className: string;\n /** Absolute path of the model file. */\n modelFile: string;\n /** How the model file exports the class: its export name, or `\"default\"`. */\n modelExport: string;\n /** Absolute path of the module that exports the resource. */\n resourceFile: string;\n /** How that module exports the resource: its export name, or `\"default\"`. */\n resourceExport: string;\n};\n\n/** A model that declares `static resource` but could not be resolved. */\nexport type SkippedModelResource = {\n className: string;\n modelFile: string;\n reason: string;\n};\n\nexport type ModelResourceExtraction = {\n entries: ModelResourceEntry[];\n skipped: SkippedModelResource[];\n};\n\nexport type ExtractModelResourcesInput = {\n /** Source text of the model file. */\n source: string;\n /** Absolute path of the model file. */\n absolutePath: string;\n /**\n * Resolve an import specifier of the model file (relative or tsconfig alias) to\n * an absolute file path, or `undefined` when it does not point at app source.\n */\n resolveImport: (specifier: string) => string | undefined;\n};\n\ntype ImportBinding = { specifier: string; exportName: string };\n\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nfunction hasModifier(node: ts.Node, kind: ts.SyntaxKind): boolean {\n return (\n ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some((m) => m.kind === kind) ?? false)\n );\n}\n\nfunction unwrapParentheses(expression: ts.Expression): ts.Expression {\n let current = expression;\n\n while (ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n\n return current;\n}\n\n/** Top-level names this file declares, and the names each is exported under. */\nfunction readLocalDeclarations(sourceFile: ts.SourceFile): {\n declared: Set<string>;\n exportNames: Map<string, string[]>;\n} {\n const declared = new Set<string>();\n const exportNames = new Map<string, string[]>();\n\n const addExport = (local: string, exported: string): void => {\n const names = exportNames.get(local) ?? [];\n\n names.push(exported);\n exportNames.set(local, names);\n };\n\n for (const statement of sourceFile.statements) {\n const exported = hasModifier(statement, ts.SyntaxKind.ExportKeyword);\n const isDefault = hasModifier(statement, ts.SyntaxKind.DefaultKeyword);\n\n if (\n (ts.isClassDeclaration(statement) ||\n ts.isFunctionDeclaration(statement) ||\n ts.isEnumDeclaration(statement)) &&\n statement.name\n ) {\n declared.add(statement.name.text);\n\n if (exported) {\n addExport(statement.name.text, isDefault ? \"default\" : statement.name.text);\n }\n\n continue;\n }\n\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue;\n\n declared.add(declaration.name.text);\n\n if (exported) {\n addExport(declaration.name.text, declaration.name.text);\n }\n }\n\n continue;\n }\n\n // `export { A, B as C }` (local form only; a `from` clause re-exports a foreign name).\n if (\n ts.isExportDeclaration(statement) &&\n !statement.moduleSpecifier &&\n !statement.isTypeOnly &&\n statement.exportClause &&\n ts.isNamedExports(statement.exportClause)\n ) {\n for (const element of statement.exportClause.elements) {\n if (element.isTypeOnly) continue;\n\n addExport((element.propertyName ?? element.name).text, element.name.text);\n }\n\n continue;\n }\n\n // `export default UserResource;`\n if (\n ts.isExportAssignment(statement) &&\n !statement.isExportEquals &&\n ts.isIdentifier(statement.expression)\n ) {\n addExport(statement.expression.text, \"default\");\n }\n }\n\n return { declared, exportNames };\n}\n\n/** Prefer a named export over `default`; among named exports, the first sorted. */\nfunction pickExportName(names: readonly string[] | undefined): string | undefined {\n if (!names || names.length === 0) return undefined;\n\n const named = names.filter((name) => name !== \"default\").sort();\n\n return named[0] ?? \"default\";\n}\n\nfunction readImportBindings(sourceFile: ts.SourceFile): Map<string, ImportBinding> {\n const bindings = new Map<string, ImportBinding>();\n\n for (const statement of sourceFile.statements) {\n if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) {\n continue;\n }\n\n const clause = statement.importClause;\n const specifier = statement.moduleSpecifier.text;\n\n if (!clause) continue;\n\n if (clause.name) {\n bindings.set(clause.name.text, { specifier, exportName: \"default\" });\n }\n\n // A namespace import (`import * as ns`) cannot be the bare identifier a\n // `static resource = X` reads, so it never becomes a binding.\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const element of clause.namedBindings.elements) {\n bindings.set(element.name.text, {\n specifier,\n exportName: (element.propertyName ?? element.name).text,\n });\n }\n }\n }\n\n return bindings;\n}\n\n/** The identifier a class assigns to `static resource`, when it is a bare identifier. */\nfunction readStaticResourceReference(\n member: ts.ClassElement,\n): { name: string } | \"computed\" | undefined {\n if (!ts.isPropertyDeclaration(member)) return undefined;\n if (!hasModifier(member, ts.SyntaxKind.StaticKeyword)) return undefined;\n if (hasModifier(member, ts.SyntaxKind.DeclareKeyword)) return undefined;\n\n const isResourceName =\n (ts.isIdentifier(member.name) || ts.isStringLiteral(member.name)) &&\n member.name.text === \"resource\";\n\n if (!isResourceName) return undefined;\n if (!member.initializer) return undefined;\n\n const initializer = unwrapParentheses(member.initializer);\n\n return ts.isIdentifier(initializer) ? { name: initializer.text } : \"computed\";\n}\n\n/**\n * Read every model class of one file that declares `static resource = <Identifier>`\n * and resolve it to a model export plus a resource export. Pure: the only\n * outside knowledge is the injected {@link ExtractModelResourcesInput.resolveImport}.\n */\nexport function extractModelResourceEntries(\n input: ExtractModelResourcesInput,\n): ModelResourceExtraction {\n const result: ModelResourceExtraction = { entries: [], skipped: [] };\n\n // Cheap exit: most model files declare no resource.\n if (!input.source.includes(\"resource\")) return result;\n\n const sourceFile = ts.createSourceFile(\n input.absolutePath,\n input.source,\n ts.ScriptTarget.ESNext,\n /* setParentNodes */ false,\n input.absolutePath.endsWith(\"x\") ? ts.ScriptKind.TSX : ts.ScriptKind.TS,\n );\n\n const { declared, exportNames } = readLocalDeclarations(sourceFile);\n const imports = readImportBindings(sourceFile);\n\n for (const statement of sourceFile.statements) {\n if (!ts.isClassDeclaration(statement) || !statement.name) continue;\n\n const className = statement.name.text;\n\n let reference: { name: string } | \"computed\" | undefined;\n\n for (const member of statement.members) {\n reference = readStaticResourceReference(member) ?? reference;\n }\n\n if (reference === undefined) continue;\n\n const skip = (reason: string): void => {\n result.skipped.push({ className, modelFile: input.absolutePath, reason });\n };\n\n if (reference === \"computed\") {\n skip(\"`static resource` is not a plain identifier\");\n continue;\n }\n\n const requiresTypeArguments = statement.typeParameters?.some(\n (parameter) => parameter.default === undefined,\n );\n\n if (requiresTypeArguments) {\n skip(\"the model class is generic\");\n continue;\n }\n\n const modelExport = pickExportName(exportNames.get(className));\n\n if (modelExport === undefined) {\n skip(\"the model class is not exported\");\n continue;\n }\n\n if (modelExport !== \"default\" && !IDENTIFIER.test(modelExport)) {\n skip(\"the model export name is not an identifier\");\n continue;\n }\n\n const binding = imports.get(reference.name);\n\n let resourceFile: string | undefined;\n let resourceExport: string | undefined;\n\n if (binding) {\n resourceFile = input.resolveImport(binding.specifier);\n resourceExport = binding.exportName;\n } else if (declared.has(reference.name)) {\n resourceFile = input.absolutePath;\n resourceExport = pickExportName(exportNames.get(reference.name));\n }\n\n if (resourceFile === undefined || resourceExport === undefined) {\n skip(`\\`${reference.name}\\` cannot be resolved to an exported module member`);\n continue;\n }\n\n if (resourceExport !== \"default\" && !IDENTIFIER.test(resourceExport)) {\n skip(\"the resource export name is not an identifier\");\n continue;\n }\n\n result.entries.push({\n className,\n modelFile: input.absolutePath,\n modelExport,\n resourceFile,\n resourceExport,\n });\n }\n\n return result;\n}\n\n/** Module specifier, relative to the typings directory, without a TypeScript extension. */\nfunction toTypeImportSpecifier(typingsDirectory: string, absoluteFile: string): string | undefined {\n const path = relative(typingsDirectory, absoluteFile).replaceAll(\"\\\\\", \"/\");\n\n // A different drive (Windows) has no relative form; do not emit a guess.\n if (isAbsolute(path)) return undefined;\n\n const withoutExtension = path.replace(/\\.(?:d\\.)?(?:ts|tsx|mts|cts)$/, \"\");\n\n return withoutExtension.startsWith(\".\") ? withoutExtension : `./${withoutExtension}`;\n}\n\n/**\n * Registry keys: the class name, suffixed `_2`, `_3`, ... when several model\n * files declare the same class name. Order is by class name, then by file path,\n * so the same set of models always yields the same keys and the same text.\n */\nexport function assignRegistryKeys(\n entries: readonly ModelResourceEntry[],\n): Array<{ key: string; entry: ModelResourceEntry }> {\n const sorted = [...entries].sort(\n (a, b) =>\n a.className.localeCompare(b.className, \"en\") ||\n a.modelFile.localeCompare(b.modelFile, \"en\") ||\n a.modelExport.localeCompare(b.modelExport, \"en\"),\n );\n\n const taken = new Set<string>();\n const counts = new Map<string, number>();\n\n return sorted.map((entry) => {\n let count = (counts.get(entry.className) ?? 0) + 1;\n let key = count === 1 ? entry.className : `${entry.className}_${count}`;\n\n while (taken.has(key)) {\n count += 1;\n key = `${entry.className}_${count}`;\n }\n\n counts.set(entry.className, count);\n taken.add(key);\n\n return { key, entry };\n });\n}\n\n/**\n * Text of the generated declaration file.\n *\n * @param entries Every resolved model, in any order.\n * @param typingsDirectory Absolute directory the file is written to; import\n * specifiers are relative to it.\n */\nexport function renderModelResourceRegistry(\n entries: readonly ModelResourceEntry[],\n typingsDirectory: string,\n): string {\n const lines: string[] = [];\n\n for (const { key, entry } of assignRegistryKeys(entries)) {\n const modelPath = toTypeImportSpecifier(typingsDirectory, entry.modelFile);\n const resourcePath = toTypeImportSpecifier(typingsDirectory, entry.resourceFile);\n\n if (modelPath === undefined || resourcePath === undefined) continue;\n\n const model = `import(${JSON.stringify(modelPath)}).${entry.modelExport}`;\n const resource = `typeof import(${JSON.stringify(resourcePath)}).${entry.resourceExport}`;\n\n lines.push(` ${JSON.stringify(key)}: { model: ${model}; resource: ${resource} };`);\n }\n\n return `// Auto-generated by Warlock.js - DO NOT EDIT\n// One entry per model class that declares \\`static resource = <Resource>\\`, so\n// \\`Serialized<Model>\\` resolves to the resource output. Models whose resource\n// cannot be resolved statically are left out.\n\nimport \"@warlock.js/core\";\n\ndeclare module \"@warlock.js/core\" {\n interface ModelResourceRegistry {\n${lines.join(\"\\n\")}\n }\n}\n`;\n}\n\n/**\n * Write `content` to `filePath` through a temporary sibling and a rename, so a\n * reader (the editor's TypeScript server) never sees a half-written file, and\n * skip the write entirely when the file already holds exactly this text.\n *\n * @returns `true` when the file was written.\n */\nexport async function writeFileIfChanged(filePath: string, content: string): Promise<boolean> {\n try {\n if ((await readFile(filePath, \"utf-8\")) === content) return false;\n } catch {\n // Missing file: write it.\n }\n\n await mkdir(dirname(filePath), { recursive: true });\n\n const temporaryPath = `${filePath}.${process.pid}.tmp`;\n\n try {\n await writeFile(temporaryPath, content, \"utf-8\");\n await rename(temporaryPath, filePath);\n } catch (error) {\n await rm(temporaryPath, { force: true });\n\n throw error;\n }\n\n return true;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"model-resource-typings.mjs","names":["ast.hasModifier","ast.isParenthesizedExpression","ast.expressionOf","ast.topLevelDeclarations","ast.isClassDeclaration","ast.isFunctionDeclaration","ast.isEnumDeclaration","ast.valueText","ast.isVariableStatement","ast.isIdentifier","ast.isImportDeclaration","ast.isPropertyDeclaration","ast.isStringLiteral","ast.parseSourceFile"],"sources":["../../../../../../../../packages/core/src/dev-server/model-resource-typings.ts"],"sourcesContent":["import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, relative } from \"node:path\";\nimport * as ast from \"../tooling/syntax/ast\";\n\n/**\n * Static `ModelResourceRegistry` generation.\n *\n * `Serialized<User>` can only resolve a model to its resource output through an\n * entry in the augmentable `ModelResourceRegistry` (see `http/serialized.ts`).\n * This module derives those entries from source: a model class that declares\n * `static resource = UserResource` produces\n *\n * ```ts\n * \"User\": { model: import(\"<model file>\").User; resource: typeof import(\"<resource file>\").UserResource };\n * ```\n *\n * Everything here is syntactic. It reads one OXC syntax tree per model\n * file, follows the identifier through that file's own imports, and never\n * imports or executes application code (`read-config-ast.ts` explains why a\n * type checker is not an option). Anything it cannot prove from the AST alone\n * (a computed expression, `lazy(...)`, a namespace import, a class that is not\n * exported) is skipped, and nothing is recorded for it: a guessed entry would\n * make `Serialized` lie, which is worse than the raw-data type it falls back to.\n */\n\n/** One model class whose resource could be resolved statically. */\nexport type ModelResourceEntry = {\n /** The model class name (the registry key before de-duplication). */\n className: string;\n /** Absolute path of the model file. */\n modelFile: string;\n /** How the model file exports the class: its export name, or `\"default\"`. */\n modelExport: string;\n /** Absolute path of the module that exports the resource. */\n resourceFile: string;\n /** How that module exports the resource: its export name, or `\"default\"`. */\n resourceExport: string;\n};\n\n/** A model that declares `static resource` but could not be resolved. */\nexport type SkippedModelResource = {\n className: string;\n modelFile: string;\n reason: string;\n};\n\nexport type ModelResourceExtraction = {\n entries: ModelResourceEntry[];\n skipped: SkippedModelResource[];\n};\n\nexport type ExtractModelResourcesInput = {\n /** Source text of the model file. */\n source: string;\n /** Absolute path of the model file. */\n absolutePath: string;\n /**\n * Resolve an import specifier of the model file (relative or tsconfig alias) to\n * an absolute file path, or `undefined` when it does not point at app source.\n */\n resolveImport: (specifier: string) => string | undefined;\n};\n\ntype ImportBinding = { specifier: string; exportName: string };\n\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nconst hasModifier = ast.hasModifier;\n\nfunction unwrapParentheses(expression: ast.Node): ast.Node {\n let current = expression;\n\n while (ast.isParenthesizedExpression(current)) {\n current = ast.expressionOf(current);\n }\n\n return current;\n}\n\n/** Top-level names this file declares, and the names each is exported under. */\nfunction readLocalDeclarations(sourceFile: ast.SourceFile): {\n declared: Set<string>;\n exportNames: Map<string, string[]>;\n} {\n const declared = new Set<string>();\n const exportNames = new Map<string, string[]>();\n\n const addExport = (local: string, exported: string): void => {\n const names = exportNames.get(local) ?? [];\n\n names.push(exported);\n exportNames.set(local, names);\n };\n\n for (const statement of ast.topLevelDeclarations(sourceFile)) {\n const exported = hasModifier(statement, \"export\");\n const isDefault = hasModifier(statement, \"default\");\n\n if (\n (ast.isClassDeclaration(statement) ||\n ast.isFunctionDeclaration(statement) ||\n ast.isEnumDeclaration(statement)) &&\n statement.id\n ) {\n declared.add(ast.valueText(statement.id));\n\n if (exported) {\n addExport(ast.valueText(statement.id), isDefault ? \"default\" : ast.valueText(statement.id));\n }\n\n continue;\n }\n\n if (ast.isVariableStatement(statement)) {\n for (const declaration of statement.declarations) {\n if (!ast.isIdentifier(declaration.id)) continue;\n\n declared.add(ast.valueText(declaration.id));\n\n if (exported) {\n addExport(ast.valueText(declaration.id), ast.valueText(declaration.id));\n }\n }\n\n continue;\n }\n }\n for (const statement of sourceFile.body) {\n if (\n statement.type === \"ExportNamedDeclaration\" &&\n !statement.source &&\n statement.exportKind !== \"type\"\n ) {\n for (const element of statement.specifiers) {\n if (element.exportKind !== \"type\")\n addExport(ast.valueText(element.local), ast.valueText(element.exported));\n }\n }\n if (\n statement.type === \"ExportDefaultDeclaration\" &&\n statement.declaration.type === \"Identifier\"\n )\n addExport(statement.declaration.name, \"default\");\n }\n\n return { declared, exportNames };\n}\n\n/** Prefer a named export over `default`; among named exports, the first sorted. */\nfunction pickExportName(names: readonly string[] | undefined): string | undefined {\n if (!names || names.length === 0) return undefined;\n\n const named = names.filter((name) => name !== \"default\").sort();\n\n return named[0] ?? \"default\";\n}\n\nfunction readImportBindings(sourceFile: ast.SourceFile): Map<string, ImportBinding> {\n const bindings = new Map<string, ImportBinding>();\n\n for (const statement of ast.topLevelDeclarations(sourceFile)) {\n if (!ast.isImportDeclaration(statement)) continue;\n for (const specifier of statement.specifiers) {\n if (specifier.type === \"ImportDefaultSpecifier\")\n bindings.set(specifier.local.name, {\n specifier: statement.source.value,\n exportName: \"default\",\n });\n else if (specifier.type === \"ImportSpecifier\")\n bindings.set(specifier.local.name, {\n specifier: statement.source.value,\n exportName: ast.valueText(specifier.imported),\n });\n }\n }\n\n return bindings;\n}\n\n/** The identifier a class assigns to `static resource`, when it is a bare identifier. */\nfunction readStaticResourceReference(\n member: ast.ClassElement,\n): { name: string } | \"computed\" | undefined {\n if (!ast.isPropertyDeclaration(member)) return undefined;\n if (!hasModifier(member, \"static\")) return undefined;\n if (hasModifier(member, \"declare\")) return undefined;\n\n const isResourceName =\n (ast.isIdentifier(member.key) || ast.isStringLiteral(member.key)) &&\n ast.valueText(member.key) === \"resource\";\n\n if (!isResourceName) return undefined;\n if (!member.value) return undefined;\n\n const initializer = unwrapParentheses(member.value);\n\n return ast.isIdentifier(initializer) ? { name: ast.valueText(initializer) } : \"computed\";\n}\n\n/**\n * Read every model class of one file that declares `static resource = <Identifier>`\n * and resolve it to a model export plus a resource export. Pure: the only\n * outside knowledge is the injected {@link ExtractModelResourcesInput.resolveImport}.\n */\nexport function extractModelResourceEntries(\n input: ExtractModelResourcesInput,\n): ModelResourceExtraction {\n const result: ModelResourceExtraction = { entries: [], skipped: [] };\n\n // Cheap exit: most model files declare no resource.\n if (!input.source.includes(\"resource\")) return result;\n\n const sourceFile = ast.parseSourceFile(input.absolutePath, input.source);\n\n const { declared, exportNames } = readLocalDeclarations(sourceFile);\n const imports = readImportBindings(sourceFile);\n\n for (const statement of ast.topLevelDeclarations(sourceFile)) {\n if (!ast.isClassDeclaration(statement) || !statement.id) continue;\n\n const className = ast.valueText(statement.id);\n\n let reference: { name: string } | \"computed\" | undefined;\n\n for (const member of statement.body.body) {\n reference = readStaticResourceReference(member) ?? reference;\n }\n\n if (reference === undefined) continue;\n\n const skip = (reason: string): void => {\n result.skipped.push({ className, modelFile: input.absolutePath, reason });\n };\n\n if (reference === \"computed\") {\n skip(\"`static resource` is not a plain identifier\");\n continue;\n }\n\n const requiresTypeArguments = statement.typeParameters?.params.some(\n (parameter) => parameter.default == null,\n );\n\n if (requiresTypeArguments) {\n skip(\"the model class is generic\");\n continue;\n }\n\n const modelExport = pickExportName(exportNames.get(className));\n\n if (modelExport === undefined) {\n skip(\"the model class is not exported\");\n continue;\n }\n\n if (modelExport !== \"default\" && !IDENTIFIER.test(modelExport)) {\n skip(\"the model export name is not an identifier\");\n continue;\n }\n\n const binding = imports.get(reference.name);\n\n let resourceFile: string | undefined;\n let resourceExport: string | undefined;\n\n if (binding) {\n resourceFile = input.resolveImport(binding.specifier);\n resourceExport = binding.exportName;\n } else if (declared.has(reference.name)) {\n resourceFile = input.absolutePath;\n resourceExport = pickExportName(exportNames.get(reference.name));\n }\n\n if (resourceFile === undefined || resourceExport === undefined) {\n skip(`\\`${reference.name}\\` cannot be resolved to an exported module member`);\n continue;\n }\n\n if (resourceExport !== \"default\" && !IDENTIFIER.test(resourceExport)) {\n skip(\"the resource export name is not an identifier\");\n continue;\n }\n\n result.entries.push({\n className,\n modelFile: input.absolutePath,\n modelExport,\n resourceFile,\n resourceExport,\n });\n }\n\n return result;\n}\n\n/** Module specifier, relative to the typings directory, without a TypeScript extension. */\nfunction toTypeImportSpecifier(typingsDirectory: string, absoluteFile: string): string | undefined {\n const path = relative(typingsDirectory, absoluteFile).replaceAll(\"\\\\\", \"/\");\n\n // A different drive (Windows) has no relative form; do not emit a guess.\n if (isAbsolute(path)) return undefined;\n\n const withoutExtension = path.replace(/\\.(?:d\\.)?(?:ts|tsx|mts|cts)$/, \"\");\n\n return withoutExtension.startsWith(\".\") ? withoutExtension : `./${withoutExtension}`;\n}\n\n/**\n * Registry keys: the class name, suffixed `_2`, `_3`, ... when several model\n * files declare the same class name. Order is by class name, then by file path,\n * so the same set of models always yields the same keys and the same text.\n */\nexport function assignRegistryKeys(\n entries: readonly ModelResourceEntry[],\n): Array<{ key: string; entry: ModelResourceEntry }> {\n const sorted = [...entries].sort(\n (a, b) =>\n a.className.localeCompare(b.className, \"en\") ||\n a.modelFile.localeCompare(b.modelFile, \"en\") ||\n a.modelExport.localeCompare(b.modelExport, \"en\"),\n );\n\n const taken = new Set<string>();\n const counts = new Map<string, number>();\n\n return sorted.map((entry) => {\n let count = (counts.get(entry.className) ?? 0) + 1;\n let key = count === 1 ? entry.className : `${entry.className}_${count}`;\n\n while (taken.has(key)) {\n count += 1;\n key = `${entry.className}_${count}`;\n }\n\n counts.set(entry.className, count);\n taken.add(key);\n\n return { key, entry };\n });\n}\n\n/**\n * Text of the generated declaration file.\n *\n * @param entries Every resolved model, in any order.\n * @param typingsDirectory Absolute directory the file is written to; import\n * specifiers are relative to it.\n */\nexport function renderModelResourceRegistry(\n entries: readonly ModelResourceEntry[],\n typingsDirectory: string,\n): string {\n const lines: string[] = [];\n\n for (const { key, entry } of assignRegistryKeys(entries)) {\n const modelPath = toTypeImportSpecifier(typingsDirectory, entry.modelFile);\n const resourcePath = toTypeImportSpecifier(typingsDirectory, entry.resourceFile);\n\n if (modelPath === undefined || resourcePath === undefined) continue;\n\n const model = `import(${JSON.stringify(modelPath)}).${entry.modelExport}`;\n const resource = `typeof import(${JSON.stringify(resourcePath)}).${entry.resourceExport}`;\n\n lines.push(` ${JSON.stringify(key)}: { model: ${model}; resource: ${resource} };`);\n }\n\n return `// Auto-generated by Warlock.js - DO NOT EDIT\n// One entry per model class that declares \\`static resource = <Resource>\\`, so\n// \\`Serialized<Model>\\` resolves to the resource output. Models whose resource\n// cannot be resolved statically are left out.\n\nimport \"@warlock.js/core\";\n\ndeclare module \"@warlock.js/core\" {\n interface ModelResourceRegistry {\n${lines.join(\"\\n\")}\n }\n}\n`;\n}\n\n/**\n * Write `content` to `filePath` through a temporary sibling and a rename, so a\n * reader (the editor's TypeScript server) never sees a half-written file, and\n * skip the write entirely when the file already holds exactly this text.\n *\n * @returns `true` when the file was written.\n */\nexport async function writeFileIfChanged(filePath: string, content: string): Promise<boolean> {\n try {\n if ((await readFile(filePath, \"utf-8\")) === content) return false;\n } catch {\n // Missing file: write it.\n }\n\n await mkdir(dirname(filePath), { recursive: true });\n\n const temporaryPath = `${filePath}.${process.pid}.tmp`;\n\n try {\n await writeFile(temporaryPath, content, \"utf-8\");\n await rename(temporaryPath, filePath);\n } catch (error) {\n await rm(temporaryPath, { force: true });\n\n throw error;\n }\n\n return true;\n}\n"],"mappings":"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"}
|
|
@@ -2,12 +2,12 @@ import { router } from "../router/router.mjs";
|
|
|
2
2
|
import { registerGroupedTranslationKeys, registerLocaleDictionary } from "../localization/register-locale-dictionary.mjs";
|
|
3
3
|
import "../localization/index.mjs";
|
|
4
4
|
import { devLogError, formatModuleNotFoundError } from "./dev-logger.mjs";
|
|
5
|
+
import { parseSourceFile } from "../tooling/syntax/ast.mjs";
|
|
5
6
|
import { importAppModule } from "../loader/app-module-importer.mjs";
|
|
6
7
|
import { extractTranslationKeys } from "./extract-translation-keys.mjs";
|
|
7
8
|
import { warnForLegacyLocales } from "./legacy-locales-warning.mjs";
|
|
8
9
|
import { getDevelopmentModelModuleRegistry } from "./model-module-registry.mjs";
|
|
9
10
|
import { pathToFileURL } from "node:url";
|
|
10
|
-
import ts from "typescript";
|
|
11
11
|
|
|
12
12
|
//#region ../../packages/core/src/dev-server/module-loader.ts
|
|
13
13
|
/**
|
|
@@ -88,7 +88,7 @@ var ModuleLoader = class {
|
|
|
88
88
|
file.addCleanup(cleanup);
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
|
-
if (type === "locale") registerGroupedTranslationKeys(file.relativePath, extractTranslationKeys(
|
|
91
|
+
if (type === "locale") registerGroupedTranslationKeys(file.relativePath, extractTranslationKeys(parseSourceFile(file.relativePath, file.source)));
|
|
92
92
|
globalThis.__currentModuleFile = file;
|
|
93
93
|
try {
|
|
94
94
|
const fileUrl = pathToFileURL(file.absolutePath).href;
|