@warlock.js/core 4.8.1 → 4.9.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 +25 -0
- package/esm/application/app.d.mts +1 -1
- package/esm/application/app.d.mts.map +1 -1
- package/esm/application/app.mjs +1 -1
- package/esm/application/app.mjs.map +1 -1
- package/esm/application/application-config-types.d.mts +1 -1
- package/esm/application/application-config-types.d.mts.map +1 -1
- package/esm/application/application.d.mts +1 -1
- package/esm/application/application.d.mts.map +1 -1
- package/esm/application/application.mjs +1 -1
- package/esm/application/application.mjs.map +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
- package/esm/benchmark/benchmark-snapshots.mjs +1 -1
- package/esm/benchmark/benchmark-snapshots.mjs.map +1 -1
- package/esm/benchmark/benchmark.d.mts +1 -1
- package/esm/benchmark/benchmark.d.mts.map +1 -1
- package/esm/benchmark/benchmark.mjs +1 -1
- package/esm/benchmark/benchmark.mjs.map +1 -1
- package/esm/benchmark/channels/console.channel.d.mts +1 -1
- package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/console.channel.mjs +1 -1
- package/esm/benchmark/channels/console.channel.mjs.map +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/noop.channel.mjs +1 -1
- package/esm/benchmark/channels/noop.channel.mjs.map +1 -1
- package/esm/benchmark/profiler.d.mts +1 -1
- package/esm/benchmark/profiler.d.mts.map +1 -1
- package/esm/benchmark/profiler.mjs +1 -1
- package/esm/benchmark/profiler.mjs.map +1 -1
- package/esm/benchmark/types.d.mts +1 -1
- package/esm/benchmark/types.d.mts.map +1 -1
- package/esm/bootstrap/setup.d.mts +1 -1
- package/esm/bootstrap/setup.d.mts.map +1 -1
- package/esm/bootstrap/setup.mjs +1 -1
- package/esm/bootstrap/setup.mjs.map +1 -1
- package/esm/bootstrap.d.mts +1 -1
- package/esm/bootstrap.d.mts.map +1 -1
- package/esm/bootstrap.mjs +1 -1
- package/esm/bootstrap.mjs.map +1 -1
- package/esm/cache/database-cache-driver.d.mts +1 -1
- package/esm/cache/database-cache-driver.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.mjs +1 -1
- package/esm/cache/database-cache-driver.mjs.map +1 -1
- package/esm/cache/index.mjs +1 -1
- package/esm/cache/index.mjs.map +1 -1
- package/esm/cli/cli-command.d.mts +1 -1
- package/esm/cli/cli-command.d.mts.map +1 -1
- package/esm/cli/cli-command.mjs +1 -1
- package/esm/cli/cli-command.mjs.map +1 -1
- package/esm/cli/cli-commands.manager.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/cli-commands.utils.mjs +1 -1
- package/esm/cli/cli-commands.utils.mjs.map +1 -1
- package/esm/cli/commands/add.command.mjs +1 -1
- package/esm/cli/commands/add.command.mjs.map +1 -1
- package/esm/cli/commands/build.command.mjs +1 -1
- package/esm/cli/commands/build.command.mjs.map +1 -1
- package/esm/cli/commands/create-database.command.mjs +1 -1
- package/esm/cli/commands/create-database.command.mjs.map +1 -1
- package/esm/cli/commands/dev-server.command.mjs +5 -4
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/config.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/connectors.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/health.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/index.mjs +1 -1
- package/esm/cli/commands/doctor/checks/index.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/routes.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
- package/esm/cli/commands/doctor/format-report.mjs +1 -1
- package/esm/cli/commands/doctor/format-report.mjs.map +1 -1
- package/esm/cli/commands/doctor/run-checks.mjs +1 -1
- package/esm/cli/commands/doctor/run-checks.mjs.map +1 -1
- package/esm/cli/commands/doctor.command.mjs +1 -1
- package/esm/cli/commands/doctor.command.mjs.map +1 -1
- package/esm/cli/commands/drop-tables.command.mjs +1 -1
- package/esm/cli/commands/drop-tables.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generate.command.mjs +1 -1
- package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/templates/stubs.mjs +1 -1
- package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/prompt.mjs +1 -1
- package/esm/cli/commands/generate/utils/prompt.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/writer.mjs +1 -1
- package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
- package/esm/cli/commands/migrate.command.mjs +1 -1
- package/esm/cli/commands/migrate.command.mjs.map +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -1
- package/esm/cli/commands/routes/route-row.mjs +1 -1
- package/esm/cli/commands/routes/route-row.mjs.map +1 -1
- package/esm/cli/commands/routes/routes-command.action.mjs +1 -1
- package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -1
- package/esm/cli/commands/routes.command.mjs +1 -1
- package/esm/cli/commands/routes.command.mjs.map +1 -1
- package/esm/cli/commands/seed.command.mjs +1 -1
- package/esm/cli/commands/seed.command.mjs.map +1 -1
- package/esm/cli/commands/start-production.command.mjs +2 -2
- package/esm/cli/commands/start-production.command.mjs.map +1 -1
- package/esm/cli/commands/storage-put.action.mjs +1 -1
- package/esm/cli/commands/storage-put.action.mjs.map +1 -1
- package/esm/cli/commands/storage-put.command.mjs +1 -1
- package/esm/cli/commands/storage-put.command.mjs.map +1 -1
- package/esm/cli/commands/typings-generator.command.mjs +1 -1
- package/esm/cli/commands/typings-generator.command.mjs.map +1 -1
- package/esm/cli/commands/update.command.mjs +30 -7
- package/esm/cli/commands/update.command.mjs.map +1 -1
- package/esm/cli/commands-loader.mjs +1 -1
- package/esm/cli/commands-loader.mjs.map +1 -1
- package/esm/cli/framework-cli-commands.mjs +1 -1
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/cli/parse-cli-args.mjs +1 -1
- package/esm/cli/parse-cli-args.mjs.map +1 -1
- package/esm/cli/start.mjs +1 -1
- package/esm/cli/start.mjs.map +1 -1
- package/esm/cli/string-similarity.mjs +1 -1
- package/esm/cli/string-similarity.mjs.map +1 -1
- package/esm/cli/types.d.mts +1 -1
- package/esm/cli/types.d.mts.map +1 -1
- package/esm/config/config-getter.d.mts +1 -1
- package/esm/config/config-getter.d.mts.map +1 -1
- package/esm/config/config-getter.mjs +1 -1
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-handlers.d.mts +1 -1
- package/esm/config/config-handlers.d.mts.map +1 -1
- package/esm/config/config-handlers.mjs +1 -1
- package/esm/config/config-handlers.mjs.map +1 -1
- package/esm/config/config-loader.d.mts +1 -1
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +1 -1
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/config-manager.mjs +1 -1
- package/esm/config/config-manager.mjs.map +1 -1
- package/esm/config/config-special-handlers.d.mts +1 -1
- package/esm/config/config-special-handlers.d.mts.map +1 -1
- package/esm/config/config-special-handlers.mjs +1 -1
- package/esm/config/config-special-handlers.mjs.map +1 -1
- package/esm/config/load-config-files.mjs +1 -1
- package/esm/config/load-config-files.mjs.map +1 -1
- package/esm/config/types.d.mts +1 -1
- package/esm/config/types.d.mts.map +1 -1
- package/esm/connectors/access-connector.d.mts +1 -1
- package/esm/connectors/access-connector.d.mts.map +1 -1
- package/esm/connectors/access-connector.mjs +1 -1
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.d.mts +1 -1
- package/esm/connectors/ai-connector.d.mts.map +1 -1
- package/esm/connectors/ai-connector.mjs +1 -1
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/base-connector.d.mts +1 -1
- package/esm/connectors/base-connector.d.mts.map +1 -1
- package/esm/connectors/base-connector.mjs +1 -1
- package/esm/connectors/base-connector.mjs.map +1 -1
- package/esm/connectors/cache-connector.d.mts +1 -1
- package/esm/connectors/cache-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.mjs +1 -1
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/connectors-manager.d.mts +1 -1
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +1 -1
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/database-connector.d.mts +1 -1
- package/esm/connectors/database-connector.d.mts.map +1 -1
- package/esm/connectors/database-connector.mjs +1 -1
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/herald-connector.d.mts +1 -1
- package/esm/connectors/herald-connector.d.mts.map +1 -1
- package/esm/connectors/herald-connector.mjs +1 -1
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts +1 -1
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +1 -1
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/logger-connector.d.mts +1 -1
- package/esm/connectors/logger-connector.d.mts.map +1 -1
- package/esm/connectors/logger-connector.mjs +1 -1
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.d.mts +1 -1
- package/esm/connectors/mail-connector.d.mts.map +1 -1
- package/esm/connectors/mail-connector.mjs +1 -1
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.d.mts +1 -1
- package/esm/connectors/notifications-connector.d.mts.map +1 -1
- package/esm/connectors/notifications-connector.mjs +1 -1
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/socket-connector.d.mts +1 -1
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +1 -1
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/connectors/storage.connector.d.mts +1 -1
- package/esm/connectors/storage.connector.d.mts.map +1 -1
- package/esm/connectors/storage.connector.mjs +1 -1
- package/esm/connectors/storage.connector.mjs.map +1 -1
- package/esm/connectors/types.d.mts +1 -1
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/connectors/types.mjs +1 -1
- package/esm/connectors/types.mjs.map +1 -1
- package/esm/container/index.d.mts +1 -1
- package/esm/container/index.d.mts.map +1 -1
- package/esm/container/index.mjs +1 -1
- package/esm/container/index.mjs.map +1 -1
- package/esm/database/create-database-action.mjs +1 -1
- package/esm/database/create-database-action.mjs.map +1 -1
- package/esm/database/drop-tables-action.mjs +1 -1
- package/esm/database/drop-tables-action.mjs.map +1 -1
- package/esm/database/migrate-action.mjs +1 -1
- package/esm/database/migrate-action.mjs.map +1 -1
- package/esm/database/models/database-log/database-log.d.mts +1 -1
- package/esm/database/models/database-log/database-log.d.mts.map +1 -1
- package/esm/database/models/database-log/database-log.mjs +1 -1
- package/esm/database/models/database-log/database-log.mjs.map +1 -1
- package/esm/database/seed-command-action.mjs +1 -1
- package/esm/database/seed-command-action.mjs.map +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -1
- package/esm/database/seeds/seeder.d.mts +1 -1
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +1 -1
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.mjs +1 -1
- package/esm/database/seeds/seeder.errors.mjs.map +1 -1
- package/esm/database/seeds/seeder.mjs +1 -1
- package/esm/database/seeds/seeder.mjs.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +1 -1
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/seeds-table-migration.mjs +1 -1
- package/esm/database/seeds/seeds-table-migration.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +1 -1
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/seeds/utils.mjs +1 -1
- package/esm/database/seeds/utils.mjs.map +1 -1
- package/esm/database/utils.d.mts +1 -1
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/database/utils.mjs +1 -1
- package/esm/database/utils.mjs.map +1 -1
- package/esm/dev-server/check-for-updates.mjs +91 -8
- package/esm/dev-server/check-for-updates.mjs.map +1 -1
- package/esm/dev-server/create-worker.mjs +1 -1
- package/esm/dev-server/create-worker.mjs.map +1 -1
- package/esm/dev-server/dependency-graph.d.mts +1 -1
- package/esm/dev-server/dependency-graph.d.mts.map +1 -1
- package/esm/dev-server/dependency-graph.mjs +1 -1
- package/esm/dev-server/dependency-graph.mjs.map +1 -1
- package/esm/dev-server/dev-logger.mjs +1 -1
- package/esm/dev-server/dev-logger.mjs.map +1 -1
- package/esm/dev-server/development-server.mjs +32 -3
- package/esm/dev-server/development-server.mjs.map +1 -1
- package/esm/dev-server/events.mjs +1 -1
- package/esm/dev-server/events.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs +1 -1
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +1 -1
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-manager.mjs +1 -1
- package/esm/dev-server/file-manager.mjs.map +1 -1
- package/esm/dev-server/file-operations.d.mts +1 -1
- package/esm/dev-server/file-operations.d.mts.map +1 -1
- package/esm/dev-server/file-operations.mjs +1 -1
- package/esm/dev-server/file-operations.mjs.map +1 -1
- package/esm/dev-server/files-orchestrator.d.mts +1 -1
- package/esm/dev-server/files-orchestrator.d.mts.map +1 -1
- package/esm/dev-server/files-orchestrator.mjs +1 -1
- package/esm/dev-server/files-orchestrator.mjs.map +1 -1
- package/esm/dev-server/files-watcher.d.mts +1 -1
- package/esm/dev-server/files-watcher.d.mts.map +1 -1
- package/esm/dev-server/files-watcher.mjs +1 -1
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/flags.mjs +1 -1
- package/esm/dev-server/flags.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.d.mts +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.d.mts.map +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.d.mts +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.d.mts.map +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.d.mts +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.d.mts.map +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +1 -1
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs.map +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.d.mts +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.d.mts.map +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
- package/esm/dev-server/layer-executor.mjs +1 -1
- package/esm/dev-server/layer-executor.mjs.map +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs.map +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
- package/esm/dev-server/loader/hook-thread.mjs +1 -1
- package/esm/dev-server/loader/hook-thread.mjs.map +1 -1
- package/esm/dev-server/loader/load-hook.d.mts +1 -1
- package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.mjs +1 -1
- package/esm/dev-server/loader/load-hook.mjs.map +1 -1
- package/esm/dev-server/loader/own-resolver.mjs +1 -1
- package/esm/dev-server/loader/own-resolver.mjs.map +1 -1
- package/esm/dev-server/loader/register-loader.mjs +1 -1
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-capture.mjs +1 -1
- package/esm/dev-server/loader/resolve-capture.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
- package/esm/dev-server/loader/source-slug.mjs +1 -1
- package/esm/dev-server/loader/source-slug.mjs.map +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
- package/esm/dev-server/loader/version-registry.mjs +1 -1
- package/esm/dev-server/loader/version-registry.mjs.map +1 -1
- package/esm/dev-server/manifest-manager.d.mts +1 -1
- package/esm/dev-server/manifest-manager.d.mts.map +1 -1
- package/esm/dev-server/manifest-manager.mjs +1 -1
- package/esm/dev-server/manifest-manager.mjs.map +1 -1
- package/esm/dev-server/module-loader.d.mts +1 -1
- package/esm/dev-server/module-loader.d.mts.map +1 -1
- package/esm/dev-server/module-loader.mjs +1 -1
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/package-json-manager.mjs +1 -1
- package/esm/dev-server/package-json-manager.mjs.map +1 -1
- package/esm/dev-server/parse-imports.mjs +1 -1
- package/esm/dev-server/parse-imports.mjs.map +1 -1
- package/esm/dev-server/path.mjs +1 -1
- package/esm/dev-server/path.mjs.map +1 -1
- package/esm/dev-server/register-dev-shortcuts.mjs +70 -0
- package/esm/dev-server/register-dev-shortcuts.mjs.map +1 -0
- package/esm/dev-server/restart-dev-server.mjs +36 -0
- package/esm/dev-server/restart-dev-server.mjs.map +1 -0
- package/esm/dev-server/shortcuts.mjs +121 -0
- package/esm/dev-server/shortcuts.mjs.map +1 -0
- package/esm/dev-server/special-files-collector.d.mts +1 -1
- package/esm/dev-server/special-files-collector.d.mts.map +1 -1
- package/esm/dev-server/special-files-collector.mjs +1 -1
- package/esm/dev-server/special-files-collector.mjs.map +1 -1
- package/esm/dev-server/start-development-server.mjs +3 -1
- package/esm/dev-server/start-development-server.mjs.map +1 -1
- package/esm/dev-server/supervisor.mjs +141 -0
- package/esm/dev-server/supervisor.mjs.map +1 -0
- package/esm/dev-server/tsconfig-manager.mjs +1 -1
- package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs +1 -1
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/dev-server/types.d.mts +1 -1
- package/esm/dev-server/types.d.mts.map +1 -1
- package/esm/dev-server/update-check-cache.mjs +53 -0
- package/esm/dev-server/update-check-cache.mjs.map +1 -0
- package/esm/dev-server/utils.mjs +1 -1
- package/esm/dev-server/utils.mjs.map +1 -1
- package/esm/encryption/encrypt.d.mts +1 -1
- package/esm/encryption/encrypt.d.mts.map +1 -1
- package/esm/encryption/encrypt.mjs +1 -1
- package/esm/encryption/encrypt.mjs.map +1 -1
- package/esm/encryption/hash.d.mts +1 -1
- package/esm/encryption/hash.d.mts.map +1 -1
- package/esm/encryption/hash.mjs +1 -1
- package/esm/encryption/hash.mjs.map +1 -1
- package/esm/encryption/password.d.mts +1 -1
- package/esm/encryption/password.d.mts.map +1 -1
- package/esm/encryption/password.mjs +1 -1
- package/esm/encryption/password.mjs.map +1 -1
- package/esm/encryption/types.d.mts +1 -1
- package/esm/encryption/types.d.mts.map +1 -1
- package/esm/generations/add-command.action.mjs +3 -13
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/stubs.mjs +1 -1
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/config.d.mts +1 -1
- package/esm/http/config.d.mts.map +1 -1
- package/esm/http/config.mjs +1 -1
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/context/request-context.d.mts +1 -1
- package/esm/http/context/request-context.d.mts.map +1 -1
- package/esm/http/context/request-context.mjs +1 -1
- package/esm/http/context/request-context.mjs.map +1 -1
- package/esm/http/createHttpApplication.d.mts +1 -1
- package/esm/http/createHttpApplication.d.mts.map +1 -1
- package/esm/http/createHttpApplication.mjs +1 -1
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/database/RequestLog.d.mts +1 -1
- package/esm/http/database/RequestLog.d.mts.map +1 -1
- package/esm/http/database/RequestLog.mjs +1 -1
- package/esm/http/database/RequestLog.mjs.map +1 -1
- package/esm/http/error-codes.d.mts +1 -1
- package/esm/http/error-codes.d.mts.map +1 -1
- package/esm/http/error-codes.mjs +1 -1
- package/esm/http/error-codes.mjs.map +1 -1
- package/esm/http/errors/errors.d.mts +1 -1
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/errors/errors.mjs +1 -1
- package/esm/http/errors/errors.mjs.map +1 -1
- package/esm/http/events.d.mts +1 -1
- package/esm/http/events.d.mts.map +1 -1
- package/esm/http/events.mjs +1 -1
- package/esm/http/events.mjs.map +1 -1
- package/esm/http/health.d.mts +1 -1
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/health.mjs +1 -1
- package/esm/http/health.mjs.map +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/inject-request-context.d.mts +1 -1
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +1 -1
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
- package/esm/http/middleware/middleware-list.d.mts +1 -1
- package/esm/http/middleware/middleware-list.d.mts.map +1 -1
- package/esm/http/middleware/middleware-list.mjs +1 -1
- package/esm/http/middleware/middleware-list.mjs.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
- package/esm/http/middleware/utils/cidr-match.mjs +1 -1
- package/esm/http/middleware/utils/cidr-match.mjs.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs.map +1 -1
- package/esm/http/middleware/utils/parse-size.d.mts +1 -1
- package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
- package/esm/http/middleware/utils/parse-size.mjs +1 -1
- package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
- package/esm/http/plugins.d.mts +1 -1
- package/esm/http/plugins.d.mts.map +1 -1
- package/esm/http/plugins.mjs +1 -1
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/request-controller.d.mts +1 -1
- package/esm/http/request-controller.d.mts.map +1 -1
- package/esm/http/request-controller.mjs +1 -1
- package/esm/http/request-controller.mjs.map +1 -1
- package/esm/http/request.d.mts +1 -1
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +1 -1
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/response.d.mts +1 -1
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +1 -1
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.d.mts +1 -1
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +1 -1
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/types.d.mts +1 -1
- package/esm/http/types.d.mts.map +1 -1
- package/esm/http/uploaded-file.d.mts +1 -1
- package/esm/http/uploaded-file.d.mts.map +1 -1
- package/esm/http/uploaded-file.mjs +1 -1
- package/esm/http/uploaded-file.mjs.map +1 -1
- package/esm/http/uploads-config.d.mts +1 -1
- package/esm/http/uploads-config.d.mts.map +1 -1
- package/esm/http/uploads-config.mjs +1 -1
- package/esm/http/uploads-config.mjs.map +1 -1
- package/esm/http/uploads-types.d.mts +1 -1
- package/esm/http/uploads-types.d.mts.map +1 -1
- package/esm/image/image.d.mts +1 -1
- package/esm/image/image.d.mts.map +1 -1
- package/esm/image/image.mjs +1 -1
- package/esm/image/image.mjs.map +1 -1
- package/esm/logger/logger.d.mts +1 -1
- package/esm/logger/logger.d.mts.map +1 -1
- package/esm/logger/logger.mjs +1 -1
- package/esm/logger/logger.mjs.map +1 -1
- package/esm/logger/types.d.mts +1 -1
- package/esm/logger/types.d.mts.map +1 -1
- package/esm/mail/config.d.mts +1 -1
- package/esm/mail/config.d.mts.map +1 -1
- package/esm/mail/config.mjs +1 -1
- package/esm/mail/config.mjs.map +1 -1
- package/esm/mail/events.d.mts +1 -1
- package/esm/mail/events.d.mts.map +1 -1
- package/esm/mail/events.mjs +1 -1
- package/esm/mail/events.mjs.map +1 -1
- package/esm/mail/mail.d.mts +1 -1
- package/esm/mail/mail.d.mts.map +1 -1
- package/esm/mail/mail.mjs +1 -1
- package/esm/mail/mail.mjs.map +1 -1
- package/esm/mail/mailer-pool.d.mts +1 -1
- package/esm/mail/mailer-pool.d.mts.map +1 -1
- package/esm/mail/mailer-pool.mjs +1 -1
- package/esm/mail/mailer-pool.mjs.map +1 -1
- package/esm/mail/react-mail.d.mts +1 -1
- package/esm/mail/react-mail.d.mts.map +1 -1
- package/esm/mail/react-mail.mjs +1 -1
- package/esm/mail/react-mail.mjs.map +1 -1
- package/esm/mail/send-mail.d.mts +1 -1
- package/esm/mail/send-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.mjs +1 -1
- package/esm/mail/send-mail.mjs.map +1 -1
- package/esm/mail/test-mailbox.d.mts +1 -1
- package/esm/mail/test-mailbox.d.mts.map +1 -1
- package/esm/mail/test-mailbox.mjs +1 -1
- package/esm/mail/test-mailbox.mjs.map +1 -1
- package/esm/mail/types.d.mts +1 -1
- package/esm/mail/types.d.mts.map +1 -1
- package/esm/mail/types.mjs +1 -1
- package/esm/mail/types.mjs.map +1 -1
- package/esm/manifest/manifest-manager.mjs +1 -1
- package/esm/manifest/manifest-manager.mjs.map +1 -1
- package/esm/production/build-app-production.mjs +1 -1
- package/esm/production/build-app-production.mjs.map +1 -1
- package/esm/production/esbuild-plugins.mjs +1 -1
- package/esm/production/esbuild-plugins.mjs.map +1 -1
- package/esm/production/production-builder.mjs +1 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/resolve-build-config.mjs +3 -2
- package/esm/production/resolve-build-config.mjs.map +1 -1
- package/esm/react/index.d.mts +1 -1
- package/esm/react/index.d.mts.map +1 -1
- package/esm/react/index.mjs +1 -1
- package/esm/react/index.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.mjs +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/types.d.mts +1 -1
- package/esm/repositories/contracts/types.d.mts.map +1 -1
- package/esm/repositories/repository.manager.d.mts +1 -1
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +1 -1
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/resource/define-resource.d.mts +1 -1
- package/esm/resource/define-resource.d.mts.map +1 -1
- package/esm/resource/define-resource.mjs +1 -1
- package/esm/resource/define-resource.mjs.map +1 -1
- package/esm/resource/register-resource.d.mts +1 -1
- package/esm/resource/register-resource.d.mts.map +1 -1
- package/esm/resource/register-resource.mjs +1 -1
- package/esm/resource/register-resource.mjs.map +1 -1
- package/esm/resource/resource-field-builder.d.mts +1 -1
- package/esm/resource/resource-field-builder.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.mjs +1 -1
- package/esm/resource/resource-field-builder.mjs.map +1 -1
- package/esm/resource/resource.d.mts +1 -1
- package/esm/resource/resource.d.mts.map +1 -1
- package/esm/resource/resource.mjs +1 -1
- package/esm/resource/resource.mjs.map +1 -1
- package/esm/resource/types.d.mts +1 -1
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/restful/restful.d.mts +1 -1
- package/esm/restful/restful.d.mts.map +1 -1
- package/esm/restful/restful.mjs +1 -1
- package/esm/restful/restful.mjs.map +1 -1
- package/esm/router/route-builder.d.mts +1 -1
- package/esm/router/route-builder.d.mts.map +1 -1
- package/esm/router/route-builder.mjs +1 -1
- package/esm/router/route-builder.mjs.map +1 -1
- package/esm/router/route-registry.mjs +1 -1
- package/esm/router/route-registry.mjs.map +1 -1
- package/esm/router/router.d.mts +1 -1
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +1 -1
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts +1 -1
- package/esm/router/types.d.mts.map +1 -1
- package/esm/socket/types.d.mts +1 -1
- package/esm/socket/types.d.mts.map +1 -1
- package/esm/socket/utils.d.mts +1 -1
- package/esm/socket/utils.d.mts.map +1 -1
- package/esm/socket/utils.mjs +1 -1
- package/esm/socket/utils.mjs.map +1 -1
- package/esm/storage/config.d.mts +1 -1
- package/esm/storage/config.d.mts.map +1 -1
- package/esm/storage/config.mjs +1 -1
- package/esm/storage/config.mjs.map +1 -1
- package/esm/storage/context/storage-driver-context.d.mts +1 -1
- package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
- package/esm/storage/context/storage-driver-context.mjs +1 -1
- package/esm/storage/context/storage-driver-context.mjs.map +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.mjs +1 -1
- package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.mjs +1 -1
- package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
- package/esm/storage/drivers/local-driver.d.mts +1 -1
- package/esm/storage/drivers/local-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.mjs +1 -1
- package/esm/storage/drivers/local-driver.mjs.map +1 -1
- package/esm/storage/drivers/r2-driver.d.mts +1 -1
- package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
- package/esm/storage/drivers/r2-driver.mjs +1 -1
- package/esm/storage/drivers/r2-driver.mjs.map +1 -1
- package/esm/storage/drivers/s3-driver.d.mts +1 -1
- package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
- package/esm/storage/drivers/s3-driver.mjs +1 -1
- package/esm/storage/drivers/s3-driver.mjs.map +1 -1
- package/esm/storage/scoped-storage.d.mts +1 -1
- package/esm/storage/scoped-storage.d.mts.map +1 -1
- package/esm/storage/scoped-storage.mjs +1 -1
- package/esm/storage/scoped-storage.mjs.map +1 -1
- package/esm/storage/storage-file.d.mts +1 -1
- package/esm/storage/storage-file.d.mts.map +1 -1
- package/esm/storage/storage-file.mjs +1 -1
- package/esm/storage/storage-file.mjs.map +1 -1
- package/esm/storage/storage.d.mts +1 -1
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/storage.mjs +1 -1
- package/esm/storage/storage.mjs.map +1 -1
- package/esm/storage/types.d.mts +1 -1
- package/esm/storage/types.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.d.mts +1 -1
- package/esm/storage/utils/contain-path.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.mjs +1 -1
- package/esm/storage/utils/contain-path.mjs.map +1 -1
- package/esm/storage/utils/mime.d.mts +1 -1
- package/esm/storage/utils/mime.d.mts.map +1 -1
- package/esm/storage/utils/mime.mjs +1 -1
- package/esm/storage/utils/mime.mjs.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts +1 -1
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs +1 -1
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/storage/utils/storage-error.d.mts +1 -1
- package/esm/storage/utils/storage-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-error.mjs +1 -1
- package/esm/storage/utils/storage-error.mjs.map +1 -1
- package/esm/tests/start-http-development-server.d.mts +1 -1
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +1 -1
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-helpers.d.mts +1 -1
- package/esm/tests/test-helpers.d.mts.map +1 -1
- package/esm/tests/test-helpers.mjs +1 -1
- package/esm/tests/test-helpers.mjs.map +1 -1
- package/esm/tests/vitest-setup.d.mts +1 -1
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs +1 -1
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/updater/package-manager.mjs +47 -7
- package/esm/updater/package-manager.mjs.map +1 -1
- package/esm/updater/update-warlock-packages.mjs +63 -10
- package/esm/updater/update-warlock-packages.mjs.map +1 -1
- package/esm/use-cases/types.d.mts +1 -1
- package/esm/use-cases/types.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.mjs +1 -1
- package/esm/use-cases/use-case-broadcast.mjs.map +1 -1
- package/esm/use-cases/use-case-events.d.mts +1 -1
- package/esm/use-cases/use-case-events.d.mts.map +1 -1
- package/esm/use-cases/use-case-events.mjs +1 -1
- package/esm/use-cases/use-case-events.mjs.map +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
- package/esm/use-cases/use-case-pipeline.mjs +1 -1
- package/esm/use-cases/use-case-pipeline.mjs.map +1 -1
- package/esm/use-cases/use-case.d.mts +1 -1
- package/esm/use-cases/use-case.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.d.mts +1 -1
- package/esm/use-cases/use-case.errors.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.mjs +1 -1
- package/esm/use-cases/use-case.errors.mjs.map +1 -1
- package/esm/use-cases/use-case.mjs +1 -1
- package/esm/use-cases/use-case.mjs.map +1 -1
- package/esm/use-cases/use-cases-registry.d.mts +1 -1
- package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
- package/esm/use-cases/use-cases-registry.mjs +1 -1
- package/esm/use-cases/use-cases-registry.mjs.map +1 -1
- package/esm/utils/app-log.d.mts +1 -1
- package/esm/utils/app-log.d.mts.map +1 -1
- package/esm/utils/app-log.mjs +1 -1
- package/esm/utils/app-log.mjs.map +1 -1
- package/esm/utils/database-log.d.mts +1 -1
- package/esm/utils/database-log.d.mts.map +1 -1
- package/esm/utils/database-log.mjs +1 -1
- package/esm/utils/database-log.mjs.map +1 -1
- package/esm/utils/environment.d.mts +1 -1
- package/esm/utils/environment.d.mts.map +1 -1
- package/esm/utils/environment.mjs +1 -1
- package/esm/utils/environment.mjs.map +1 -1
- package/esm/utils/framework-vesion.mjs +1 -1
- package/esm/utils/framework-vesion.mjs.map +1 -1
- package/esm/utils/get-localized.d.mts +1 -1
- package/esm/utils/get-localized.d.mts.map +1 -1
- package/esm/utils/get-localized.mjs +1 -1
- package/esm/utils/get-localized.mjs.map +1 -1
- package/esm/utils/npm-registry.d.mts +1 -1
- package/esm/utils/npm-registry.d.mts.map +1 -1
- package/esm/utils/npm-registry.mjs +1 -1
- package/esm/utils/npm-registry.mjs.map +1 -1
- package/esm/utils/paths.d.mts +1 -1
- package/esm/utils/paths.d.mts.map +1 -1
- package/esm/utils/paths.mjs +1 -1
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/utils/promise-all-object.d.mts +1 -1
- package/esm/utils/promise-all-object.d.mts.map +1 -1
- package/esm/utils/promise-all-object.mjs +1 -1
- package/esm/utils/promise-all-object.mjs.map +1 -1
- package/esm/utils/queue.d.mts +1 -1
- package/esm/utils/queue.d.mts.map +1 -1
- package/esm/utils/queue.mjs +1 -1
- package/esm/utils/queue.mjs.map +1 -1
- package/esm/utils/sleep.d.mts +1 -1
- package/esm/utils/sleep.d.mts.map +1 -1
- package/esm/utils/sleep.mjs +1 -1
- package/esm/utils/sleep.mjs.map +1 -1
- package/esm/utils/sluggable.d.mts +1 -1
- package/esm/utils/sluggable.d.mts.map +1 -1
- package/esm/utils/sluggable.mjs +1 -1
- package/esm/utils/sluggable.mjs.map +1 -1
- package/esm/utils/to-json.d.mts +1 -1
- package/esm/utils/to-json.d.mts.map +1 -1
- package/esm/utils/to-json.mjs +1 -1
- package/esm/utils/to-json.mjs.map +1 -1
- package/esm/utils/types.d.mts +1 -1
- package/esm/utils/types.d.mts.map +1 -1
- package/esm/utils/urls.d.mts +1 -1
- package/esm/utils/urls.d.mts.map +1 -1
- package/esm/utils/urls.mjs +1 -1
- package/esm/utils/urls.mjs.map +1 -1
- package/esm/utils/version-compare.d.mts +1 -1
- package/esm/utils/version-compare.d.mts.map +1 -1
- package/esm/utils/version-compare.mjs +1 -1
- package/esm/utils/version-compare.mjs.map +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-id.mjs +1 -1
- package/esm/validation/database/exists-except-current-id.mjs.map +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-user.mjs +1 -1
- package/esm/validation/database/exists-except-current-user.mjs.map +1 -1
- package/esm/validation/database/types.d.mts +1 -1
- package/esm/validation/database/types.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.mjs +1 -1
- package/esm/validation/database/unique-except-current-id.mjs.map +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-user.mjs +1 -1
- package/esm/validation/database/unique-except-current-user.mjs.map +1 -1
- package/esm/validation/file/file.d.mts +1 -1
- package/esm/validation/file/file.d.mts.map +1 -1
- package/esm/validation/file/file.mjs +1 -1
- package/esm/validation/file/file.mjs.map +1 -1
- package/esm/validation/init.mjs +1 -1
- package/esm/validation/init.mjs.map +1 -1
- package/esm/validation/plugins/database-plugin.mjs +1 -1
- package/esm/validation/plugins/database-plugin.mjs.map +1 -1
- package/esm/validation/plugins/file-plugin.mjs +1 -1
- package/esm/validation/plugins/file-plugin.mjs.map +1 -1
- package/esm/validation/plugins/localized-plugin.mjs +1 -1
- package/esm/validation/plugins/localized-plugin.mjs.map +1 -1
- package/esm/validation/types.d.mts +1 -1
- package/esm/validation/types.d.mts.map +1 -1
- package/esm/validation/validateAll.mjs +1 -1
- package/esm/validation/validateAll.mjs.map +1 -1
- package/esm/validation/validators/file-validator.d.mts +1 -1
- package/esm/validation/validators/file-validator.d.mts.map +1 -1
- package/esm/validation/validators/file-validator.mjs +1 -1
- package/esm/validation/validators/file-validator.mjs.map +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
- package/esm/vite/lower-stage3-decorators.mjs +1 -1
- package/esm/vite/lower-stage3-decorators.mjs.map +1 -1
- package/esm/warlock-config/default-configurations.mjs +1 -1
- package/esm/warlock-config/default-configurations.mjs.map +1 -1
- package/esm/warlock-config/define-config.d.mts +1 -1
- package/esm/warlock-config/define-config.d.mts.map +1 -1
- package/esm/warlock-config/define-config.mjs +6 -2
- package/esm/warlock-config/define-config.mjs.map +1 -1
- package/esm/warlock-config/normalize-build-config.mjs +24 -0
- package/esm/warlock-config/normalize-build-config.mjs.map +1 -0
- package/esm/warlock-config/types.d.mts +21 -1
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
- package/llms-full.txt +131 -13
- package/llms.txt +2 -2
- package/package.json +12 -12
- package/skills/run-app/SKILL.md +70 -7
- package/skills/update-packages/SKILL.md +61 -6
|
@@ -5,7 +5,7 @@ import { existsSync } from "node:fs";
|
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
6
|
import { getTsconfig, resolvePathAlias } from "get-tsconfig";
|
|
7
7
|
|
|
8
|
-
//#region
|
|
8
|
+
//#region ../core/src/dev-server/loader/resolve-hook.ts
|
|
9
9
|
/**
|
|
10
10
|
* The `file://` URL prefix for the project's `src/` root, set once during
|
|
11
11
|
* `initialize()`. Used to identify which resolved URLs belong to user code.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-hook.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"resolve-hook.mjs","names":[],"sources":["../../../../../../../../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 =\n 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(\n specifier,\n cleanContext.parentURL,\n getPathsMatcher(),\n existsSync,\n );\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,eACJ,QAAQ,WAAW,SAAS,KAAK,IAC7B;EAAE,GAAG;EAAS,WAAW,QAAQ,UAAU,QAAQ,YAAY,EAAE;CAAE,IACnE;CAKN,MAAM,QAAQ,WACZ,WACA,aAAa,WACb,gBAAgB,GAChB,UACF;CAKA,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;CAIT,MAAM,UAAU,WADK,cAAc,QACG,CAAC;CAMvC,OAAO;EAAE,GAAG;EAAQ,KAAK,GAAG,SAAS,KAAK;EAAW,cAAc;CAAK;AAC1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-slug.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"source-slug.mjs","names":[],"sources":["../../../../../../../../core/src/dev-server/loader/source-slug.ts"],"sourcesContent":["/**\n * Human-readable label for a cached transpile file, derived from the last\n * three path segments of the source file.\n *\n * Purely cosmetic: it rides in front of the content hash in the cache\n * filename so `ls .warlock/transpile/<shard>/` is browsable when debugging.\n * It is **never** used as a cache key, module URL, or source-map\n * `sourcefile` — correctness still rests entirely on the content hash, so\n * the slug is allowed to be lossy (sanitised, capped).\n *\n * @example\n * sourceSlug(\"D:/proj/src/app/vectors/utils/locales.ts\")\n * // → \"vectors-utils-locales\"\n */\nexport function sourceSlug(absolutePath: string): string {\n const noExt = absolutePath.replace(/\\\\/g, \"/\").replace(/\\.[cm]?[jt]sx?$/, \"\");\n\n const slug = noExt\n .split(\"/\")\n .filter(Boolean)\n .slice(-3)\n .join(\"-\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n // The hash guarantees uniqueness; the slug is just a label, so capping it\n // is safe and keeps total path length sane on deep trees / Windows.\n return slug.slice(0, 60) || \"src\";\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAgB,WAAW,cAA8B;CAcvD,OAbc,aAAa,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,mBAAmB,EAEzD,CAAC,CACf,MAAM,GAAG,CAAC,CACV,OAAO,OAAO,CAAC,CACf,MAAM,EAAE,CAAC,CACT,KAAK,GAAG,CAAC,CACT,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EAIb,CAAC,CAAC,MAAM,GAAG,EAAE,KAAK;AAC9B"}
|
|
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
|
|
5
|
-
//#region
|
|
5
|
+
//#region ../core/src/dev-server/loader/transpile-cache.ts
|
|
6
6
|
/**
|
|
7
7
|
* Persisted transpile cache.
|
|
8
8
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transpile-cache.mjs","names":[],"sources":["../../../../../../../../@warlock.js/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 } 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\")\n .update(sourceText)\n .update(\"\\0\")\n .update(fingerprint)\n .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}.${Date.now()}.tmp`;\n try {\n writeFileSync(tempPath, content);\n renameSync(tempPath, filePath);\n } catch (error) {\n try {\n rmSync(tempPath, { force: true });\n } catch {\n // best effort — original error is the one that matters\n }\n throw error;\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":["../../../../../../../../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 } 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\")\n .update(sourceText)\n .update(\"\\0\")\n .update(fingerprint)\n .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}.${Date.now()}.tmp`;\n try {\n writeFileSync(tempPath, content);\n renameSync(tempPath, filePath);\n } catch (error) {\n try {\n rmSync(tempPath, { force: true });\n } catch {\n // best effort — original error is the one that matters\n }\n throw error;\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-registry.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"version-registry.mjs","names":[],"sources":["../../../../../../../../core/src/dev-server/loader/version-registry.ts"],"sourcesContent":["/**\n * Version registry for the ESM loader hook.\n *\n * Lives in the hook worker thread. The main thread sends bump messages via\n * MessageChannel; each bump increments the monotonic counter for that path,\n * which causes `resolve()` to produce a new URL — Node sees a fresh module.\n *\n * Monotonic integers are used instead of timestamps so there is no clock-drift\n * risk and the version is trivial to reason about during debugging.\n *\n * @example\n * // Hook worker receives a bump from the file watcher:\n * bumpVersion(\"/abs/path/to/user.model.ts\");\n * // → getVersion returns 1, resolve() appends ?v=1 to the URL\n */\n\nconst versionMap = new Map<string, number>();\n\n/**\n * Normalize a filesystem path to a single canonical form so the main thread\n * (which often holds forward-slash paths from posix-style joins) and the\n * hook worker (which gets backslash paths from `fileURLToPath` on Windows)\n * agree on map keys.\n */\nfunction normalizeKey(absolutePath: string): string {\n return absolutePath.replace(/\\\\/g, \"/\").toLowerCase();\n}\n\n/**\n * Increment the version counter for the given absolute path.\n * Called when the file watcher detects a change.\n */\nexport function bumpVersion(absolutePath: string): void {\n const key = normalizeKey(absolutePath);\n versionMap.set(key, (versionMap.get(key) ?? 0) + 1);\n}\n\n/**\n * Return the current version counter for the given absolute path.\n * Returns 0 for paths not yet seen (first import).\n */\nexport function getVersion(absolutePath: string): number {\n return versionMap.get(normalizeKey(absolutePath)) ?? 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,6BAAa,IAAI,IAAoB;;;;;;;AAQ3C,SAAS,aAAa,cAA8B;CAClD,OAAO,aAAa,QAAQ,OAAO,GAAG,CAAC,CAAC,YAAY;AACtD;;;;;AAMA,SAAgB,YAAY,cAA4B;CACtD,MAAM,MAAM,aAAa,YAAY;CACrC,WAAW,IAAI,MAAM,WAAW,IAAI,GAAG,KAAK,KAAK,CAAC;AACpD;;;;;AAMA,SAAgB,WAAW,cAA8B;CACvD,OAAO,WAAW,IAAI,aAAa,YAAY,CAAC,KAAK;AACvD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FileManifest } from "./types.mjs";
|
|
2
2
|
import { FileManager } from "./file-manager.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../core/src/dev-server/manifest-manager.d.ts
|
|
5
5
|
declare class ManifestManager {
|
|
6
6
|
private readonly files;
|
|
7
7
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-manager.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"manifest-manager.d.mts","names":[],"sources":["../../../../../../../core/src/dev-server/manifest-manager.ts"],"mappings":";;;;cAmBa,eAAA;EAAA,iBAiByB,KAAA;EAAA;;;EAAA,QAb5B,QAAA;EAa+C;;;cAAnB,KAAA,EAAO,GAAA,SAAY,WAAA;EAkB1C;;;;EAZA,IAAA,IAAQ,OAAA;EA+Bd;;;EAnBM,IAAA,IAAQ,OAAA;EA0B0B;;;EAdxC,OAAA,CAAQ,QAAA,WAAmB,YAAA;EA4B3B;;;EArBA,OAAA,CAAQ,QAAA;EAmCR;;;EA5BA,OAAA,CAAQ,QAAA,UAAkB,YAAA,EAAc,YAAA;;;;EAOxC,UAAA,CAAW,QAAA;EA2CX;;AAAK;EApCL,eAAA;;;;EAOA,WAAA,IAAe,MAAA,SAAe,YAAA;;;;EAO9B,WAAA;;;;;;;;;;;;UAYC,0BAAA;;;;EAUD,KAAA;AAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MANIFEST_PATH } from "./flags.mjs";
|
|
2
2
|
import { fileExistsAsync, getJsonFileAsync, putFileAsync } from "@warlock.js/fs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../core/src/dev-server/manifest-manager.ts
|
|
5
5
|
var ManifestManager = class {
|
|
6
6
|
/**
|
|
7
7
|
* Constructor
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-manager.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"manifest-manager.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/manifest-manager.ts"],"sourcesContent":["import { fileExistsAsync, getJsonFileAsync, putFileAsync } from \"@warlock.js/fs\";\r\nimport { FileManager } from \"./file-manager\";\r\nimport type { FileManifest } from \"./types\";\r\nimport { MANIFEST_PATH } from \"./flags\";\r\n\r\n/**\r\n * Manifest structure with metadata and files\r\n */\r\nexport type Manifest = {\r\n version: string;\r\n lastBuildTime: number;\r\n projectHash?: string;\r\n stats: {\r\n totalFiles: number;\r\n totalDependencies: number;\r\n };\r\n files: Record<string, FileManifest>;\r\n};\r\n\r\nexport class ManifestManager {\r\n /**\r\n * Manifest data with metadata\r\n */\r\n private manifest: Manifest = {\r\n version: \"1.0.0\",\r\n lastBuildTime: Date.now(),\r\n stats: {\r\n totalFiles: 0,\r\n totalDependencies: 0,\r\n },\r\n files: {},\r\n };\r\n\r\n /**\r\n * Constructor\r\n */\r\n public constructor(private readonly files: Map<string, FileManager>) {}\r\n\r\n /**\r\n * Initialize manifest manager\r\n * @returns true if manifest exists, false otherwise\r\n */\r\n public async init(): Promise<boolean> {\r\n if (await fileExistsAsync(MANIFEST_PATH)) {\r\n this.manifest = await getJsonFileAsync(MANIFEST_PATH);\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Save manifest to disk\r\n */\r\n public async save(): Promise<void> {\r\n // Update stats before saving\r\n this.manifest.stats.totalFiles = Object.keys(this.manifest.files).length;\r\n this.manifest.stats.totalDependencies = this.calculateTotalDependencies();\r\n this.manifest.lastBuildTime = Date.now();\r\n\r\n await putFileAsync(MANIFEST_PATH, JSON.stringify(this.manifest, null, 2));\r\n }\r\n\r\n /**\r\n * Get file manifest data\r\n */\r\n public getFile(filePath: string): FileManifest | undefined {\r\n return this.manifest.files[filePath];\r\n }\r\n\r\n /**\r\n * Check if file exists in manifest\r\n */\r\n public hasFile(filePath: string): boolean {\r\n return filePath in this.manifest.files;\r\n }\r\n\r\n /**\r\n * Set file manifest data\r\n */\r\n public setFile(filePath: string, fileManifest: FileManifest): void {\r\n this.manifest.files[filePath] = fileManifest;\r\n }\r\n\r\n /**\r\n * Remove file from manifest\r\n */\r\n public removeFile(filePath: string): void {\r\n delete this.manifest.files[filePath];\r\n }\r\n\r\n /**\r\n * Get all file paths in manifest\r\n */\r\n public getAllFilePaths(): string[] {\r\n return Object.keys(this.manifest.files);\r\n }\r\n\r\n /**\r\n * Get all file manifests\r\n */\r\n public getAllFiles(): Record<string, FileManifest> {\r\n return this.manifest.files;\r\n }\r\n\r\n /**\r\n * Get manifest metadata\r\n */\r\n public getMetadata() {\r\n return {\r\n version: this.manifest.version,\r\n lastBuildTime: this.manifest.lastBuildTime,\r\n projectHash: this.manifest.projectHash,\r\n stats: this.manifest.stats,\r\n };\r\n }\r\n\r\n /**\r\n * Calculate total dependencies across all files\r\n */\r\n private calculateTotalDependencies(): number {\r\n return Object.values(this.manifest.files).reduce(\r\n (total, file) => total + (file.dependencies?.length || 0),\r\n 0,\r\n );\r\n }\r\n\r\n /**\r\n * Clear all files from manifest\r\n */\r\n public clear(): void {\r\n this.manifest.files = {};\r\n this.manifest.stats = {\r\n totalFiles: 0,\r\n totalDependencies: 0,\r\n };\r\n }\r\n}\r\n"],"mappings":";;;;AAmBA,IAAa,kBAAb,MAA6B;;;;CAiB3B,AAAO,YAAY,AAAiB,OAAiC;EAAjC;kBAbP;GAC3B,SAAS;GACT,eAAe,KAAK,IAAI;GACxB,OAAO;IACL,YAAY;IACZ,mBAAmB;GACrB;GACA,OAAO,CAAC;EACV;CAKsE;;;;;CAMtE,MAAa,OAAyB;EACpC,IAAI,MAAM,gBAAgB,aAAa,GAAG;GACxC,KAAK,WAAW,MAAM,iBAAiB,aAAa;GACpD,OAAO;EACT,OACE,OAAO;CAEX;;;;CAKA,MAAa,OAAsB;EAEjC,KAAK,SAAS,MAAM,aAAa,OAAO,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC;EAClE,KAAK,SAAS,MAAM,oBAAoB,KAAK,2BAA2B;EACxE,KAAK,SAAS,gBAAgB,KAAK,IAAI;EAEvC,MAAM,aAAa,eAAe,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,CAAC;CAC1E;;;;CAKA,AAAO,QAAQ,UAA4C;EACzD,OAAO,KAAK,SAAS,MAAM;CAC7B;;;;CAKA,AAAO,QAAQ,UAA2B;EACxC,OAAO,YAAY,KAAK,SAAS;CACnC;;;;CAKA,AAAO,QAAQ,UAAkB,cAAkC;EACjE,KAAK,SAAS,MAAM,YAAY;CAClC;;;;CAKA,AAAO,WAAW,UAAwB;EACxC,OAAO,KAAK,SAAS,MAAM;CAC7B;;;;CAKA,AAAO,kBAA4B;EACjC,OAAO,OAAO,KAAK,KAAK,SAAS,KAAK;CACxC;;;;CAKA,AAAO,cAA4C;EACjD,OAAO,KAAK,SAAS;CACvB;;;;CAKA,AAAO,cAAc;EACnB,OAAO;GACL,SAAS,KAAK,SAAS;GACvB,eAAe,KAAK,SAAS;GAC7B,aAAa,KAAK,SAAS;GAC3B,OAAO,KAAK,SAAS;EACvB;CACF;;;;CAKA,AAAQ,6BAAqC;EAC3C,OAAO,OAAO,OAAO,KAAK,SAAS,KAAK,CAAC,CAAC,QACvC,OAAO,SAAS,SAAS,KAAK,cAAc,UAAU,IACvD,CACF;CACF;;;;CAKA,AAAO,QAAc;EACnB,KAAK,SAAS,QAAQ,CAAC;EACvB,KAAK,SAAS,QAAQ;GACpB,YAAY;GACZ,mBAAmB;EACrB;CACF;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SpecialFilesCollector } from "./special-files-collector.mjs";
|
|
2
2
|
import { FileManager } from "./file-manager.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../core/src/dev-server/module-loader.d.ts
|
|
5
5
|
declare global {
|
|
6
6
|
var __currentModuleFile: FileManager | undefined;
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-loader.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"module-loader.d.mts","names":[],"sources":["../../../../../../../core/src/dev-server/module-loader.ts"],"mappings":";;;;QAMQ,MAAA;EAAA,IACF,mBAAA,EAAqB,WAAW;AAAA;;;;;;;;;;;cAgCzB,YAAA;EAAA,iBAGkB,qBAAA;EAAA,iBAFZ,aAAA;cAEY,qBAAA,EAAuB,qBAAA;EAgIlB;;;;;;;;;;;EAnHrB,OAAA,IAAW,OAAA;EA6BhB;;;;EADK,UAAA,cACX,IAAA,EAAM,WAAA,EACN,IAAA,WACC,OAAA,CAAQ,CAAA;EAgDE;;;;;EAAA,YAAA,CAAa,IAAA,EAAM,WAAA,GAAc,OAAA;EAkB5B;;;;EAAX,UAAA,CAAW,IAAA,EAAM,WAAA;EAiCD;AAAA;;EAfhB,oBAAA,CAAqB,IAAA,EAAM,WAAA;;;;;;UAe1B,eAAA;AAAA"}
|
|
@@ -2,7 +2,7 @@ import { router } from "../router/router.mjs";
|
|
|
2
2
|
import { devLogError, formatModuleNotFoundError } from "./dev-logger.mjs";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
|
|
5
|
-
//#region
|
|
5
|
+
//#region ../core/src/dev-server/module-loader.ts
|
|
6
6
|
/**
|
|
7
7
|
* Thrown when a special file (route/event/main/locale) fails to import or
|
|
8
8
|
* register. Carries the file that failed and the original cause so a broken
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-loader.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"module-loader.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/module-loader.ts"],"sourcesContent":["import { pathToFileURL } from \"node:url\";\nimport { router } from \"../router/router\";\nimport { devLogError, formatModuleNotFoundError } from \"./dev-logger\";\nimport type { CleanupFunction, FileManager } from \"./file-manager\";\nimport type { SpecialFileType, SpecialFilesCollector } from \"./special-files-collector\";\n\ndeclare global {\n var __currentModuleFile: FileManager | undefined;\n}\n\n/**\n * Thrown when a special file (route/event/main/locale) fails to import or\n * register. Carries the file that failed and the original cause so a broken\n * module surfaces with its origin instead of vanishing into a 404.\n */\nexport class ModuleLoadError extends Error {\n public constructor(\n public readonly type: string,\n public readonly file: FileManager,\n public readonly cause: unknown,\n ) {\n const reason = cause instanceof Error ? cause.message : String(cause);\n super(`Failed to load ${type}: ${file.relativePath} - ${reason}`);\n this.name = \"ModuleLoadError\";\n }\n}\n\n/**\n * The four \"special\" file kinds that the dev server eagerly imports at boot.\n * Order matters: locales first (used by everything), events before main so\n * listeners are registered when main runs, routes last so handlers are bound.\n */\nconst SPECIAL_TYPES: readonly SpecialFileType[] = [\"locale\", \"event\", \"main\", \"route\"] as const;\n\n/**\n * Loads application modules through the ESM loader hook. The hook stamps\n * `?v=N` on every import, so each reload is a fresh module without any\n * userland cache-busting plumbing.\n */\nexport class ModuleLoader {\n private readonly loadedModules = new Map<string, unknown>();\n\n constructor(private readonly specialFilesCollector: SpecialFilesCollector) {}\n\n /**\n * Eagerly load every special file at boot, in the canonical order so\n * later phases (e.g. routes) see state earlier phases registered.\n *\n * A failing module no longer vanishes silently: each failure is collected\n * (so one broken file doesn't hide the others) and, once every file has been\n * attempted, an aggregate error is thrown. The boot callers\n * (`DevelopmentServer.start`, the HTTP test bootstrap) already wrap this in a\n * try/catch that logs and aborts the boot — so a broken route module aborts\n * boot loudly rather than booting into a surface that 404s.\n */\n public async loadAll(): Promise<void> {\n const failures: ModuleLoadError[] = [];\n\n for (const type of SPECIAL_TYPES) {\n for (const file of this.specialFilesCollector.getFilesByType(type)) {\n try {\n await this.loadModule(file, type);\n } catch (error) {\n failures.push(\n error instanceof ModuleLoadError ? error : new ModuleLoadError(type, file, error),\n );\n }\n }\n }\n\n if (failures.length > 0) {\n throw new AggregateError(\n failures,\n `${failures.length} module(s) failed to load during boot:\\n` +\n failures.map((failure) => ` - ${failure.message}`).join(\"\\n\"),\n );\n }\n }\n\n /**\n * Import a file through the loader hook. For routes, scopes the import in\n * `router.withSourceFile()` so the added routes carry their origin.\n */\n public async loadModule<T = unknown>(\n file: FileManager,\n type: string,\n ): Promise<T | undefined> {\n if (file.relativePath.endsWith(\".env\")) return undefined;\n\n globalThis.__currentModuleFile = file;\n\n try {\n const fileUrl = pathToFileURL(file.absolutePath).href;\n\n const load = async () => {\n const module = (await import(fileUrl)) as Record<string, unknown>;\n this.loadedModules.set(file.absolutePath, module);\n this.registerCleanup(file, module);\n return module as T;\n };\n\n return type === \"route\"\n ? await router.withSourceFile(file.relativePath, load)\n : await load();\n } catch (error: any) {\n if (error.code === \"ERR_MODULE_NOT_FOUND\") {\n devLogError(formatModuleNotFoundError(error));\n } else {\n // Pass the error through so devLogError prints the stack. With dev\n // source maps enabled, frames remap to the original `.ts` line/col\n // (e.g. the actual call site of an undefined symbol) instead of\n // vanishing — a one-line \"x is not defined\" is undebuggable.\n devLogError(\n `Failed to load ${type}: ${file.relativePath} - ${error?.message || error}`,\n error,\n );\n }\n\n // RETHROW after logging. Previously this returned undefined, so a route\n // file that threw on import or registration disappeared with no boot\n // error — the whole surface 404'd silently. Boot callers abort on the\n // throw; the HMR batch-reload handler catches it, keeps the server\n // alive, and shows it loudly.\n throw error instanceof ModuleLoadError ? error : new ModuleLoadError(type, file, error);\n } finally {\n globalThis.__currentModuleFile = undefined;\n }\n }\n\n /**\n * Reload a previously-loaded special file. The version-bump that makes the\n * import fresh is done by the caller (layer-executor) before invoking this.\n * Routes are removed from the registry first so re-registration is clean.\n */\n public async reloadModule(file: FileManager): Promise<void> {\n const moduleType = this.specialFilesCollector.getFileType(file.relativePath);\n if (!moduleType) return;\n\n this.runCleanup(file);\n\n if (moduleType === \"route\") {\n router.removeRoutesBySourceFile(file.relativePath);\n }\n\n this.loadedModules.delete(file.absolutePath);\n await this.loadModule(file, moduleType);\n }\n\n /**\n * Run every cleanup hook the file registered (or `$cleanup` on its exports)\n * and reset the list. Called once per HMR reload.\n */\n public runCleanup(file: FileManager): void {\n for (const hook of file.cleanup) {\n try {\n if (typeof hook === \"function\") {\n hook();\n } else if (hook && typeof (hook as { unsubscribe?: () => void }).unsubscribe === \"function\") {\n (hook as { unsubscribe: () => void }).unsubscribe();\n }\n } catch {\n // Cleanup errors shouldn't break HMR.\n }\n }\n file.resetCleanup();\n }\n\n /**\n * Clean up after a file whose source was deleted from disk.\n */\n public cleanupDeletedModule(file: FileManager): void {\n this.loadedModules.delete(file.absolutePath);\n\n if (file.type === \"route\") {\n router.removeRoutesBySourceFile(file.relativePath);\n }\n\n this.runCleanup(file);\n }\n\n /**\n * Scan a freshly-loaded module for cleanup handlers and register them on\n * the FileManager so they run before the next reload. Priority: explicit\n * `export function cleanup()` → `.$cleanup` on any exported value.\n */\n private registerCleanup(file: FileManager, module: Record<string, unknown>): void {\n if (typeof module.cleanup === \"function\") {\n file.addCleanup(module.cleanup as CleanupFunction);\n return;\n }\n\n const cleanups: CleanupFunction[] = [];\n\n for (const exportedValue of Object.values(module)) {\n const cleanup = (exportedValue as { $cleanup?: unknown })?.$cleanup;\n if (typeof cleanup === \"function\") {\n cleanups.push(cleanup.bind(exportedValue) as CleanupFunction);\n }\n }\n\n if (cleanups.length > 0) {\n file.addCleanup(cleanups);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Path } from "./path.mjs";
|
|
2
2
|
import { getJsonFileAsync } from "@warlock.js/fs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../core/src/dev-server/package-json-manager.ts
|
|
5
5
|
var PackageJsonManager = class {
|
|
6
6
|
constructor() {
|
|
7
7
|
this.packageJson = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-json-manager.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"package-json-manager.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/package-json-manager.ts"],"sourcesContent":["import { getJsonFileAsync } from \"@warlock.js/fs\";\r\nimport { Path } from \"./path\";\r\n\r\nexport class PackageJsonManager {\r\n /**\r\n * Package.json data\r\n */\r\n public packageJson: any = {};\r\n\r\n /**\r\n * Initialize the package.json manager\r\n */\r\n public async init() {\r\n this.packageJson = await getJsonFileAsync(Path.toAbsolute(\"package.json\"));\r\n }\r\n\r\n /**\r\n * Check if the given path is a package path\r\n */\r\n public isPathPackage(path: string) {\r\n const allPackages = Object.keys(this.packageJson.dependencies || {}).concat(\r\n Object.keys(this.packageJson.devDependencies || {}),\r\n );\r\n\r\n return allPackages.some((packageName) => path.startsWith(packageName));\r\n }\r\n}\r\n\r\nexport const packageJsonManager = new PackageJsonManager();\r\n"],"mappings":";;;;AAGA,IAAa,qBAAb,MAAgC;;qBAIJ,CAAC;;;;;CAK3B,MAAa,OAAO;EAClB,KAAK,cAAc,MAAM,iBAAiB,KAAK,WAAW,cAAc,CAAC;CAC3E;;;;CAKA,AAAO,cAAc,MAAc;EAKjC,OAJoB,OAAO,KAAK,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC,CAAC,OACnE,OAAO,KAAK,KAAK,YAAY,mBAAmB,CAAC,CAAC,CAGnC,CAAC,CAAC,MAAM,gBAAgB,KAAK,WAAW,WAAW,CAAC;CACvE;AACF;AAEA,MAAa,qBAAqB,IAAI,mBAAmB"}
|
|
@@ -4,7 +4,7 @@ import { directoryExistsAsync, fileExistsAsync } from "@warlock.js/fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { parse } from "es-module-lexer";
|
|
6
6
|
|
|
7
|
-
//#region
|
|
7
|
+
//#region ../core/src/dev-server/parse-imports.ts
|
|
8
8
|
/**
|
|
9
9
|
* Detect if a file contains only type definitions (no runtime code)
|
|
10
10
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-imports.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/dev-server/parse-imports.ts"],"sourcesContent":["import { fileExistsAsync, directoryExistsAsync } from \"@warlock.js/fs\";\r\nimport { ImportSpecifier, parse } from \"es-module-lexer\";\r\nimport path from \"node:path\";\r\nimport { Path } from \"./path\";\r\nimport { tsconfigManager } from \"./tsconfig-manager\";\r\n\r\n/**\r\n * Detect if a file contains only type definitions (no runtime code)\r\n *\r\n * A file is considered type-only if ALL its exports are:\r\n * - interface declarations\r\n * - type alias declarations\r\n * - export type { ... } statements\r\n * - export type { ... } from \"...\" statements\r\n *\r\n * Files with any of these are NOT type-only:\r\n * - export const/let/var\r\n * - export function\r\n * - export class\r\n * - export default (non-type)\r\n * - export { ... } (without type keyword)\r\n * - export * from (without type keyword)\r\n *\r\n * @param source - The source code to analyze\r\n * @returns true if the file exports only types\r\n */\r\nexport function isTypeOnlyFile(source: string): boolean {\r\n // Remove comments to avoid false positives\r\n const withoutComments = source\r\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\") // block comments\r\n .replace(/\\/\\/.*$/gm, \"\"); // line comments\r\n\r\n // Remove string literals to avoid false positives\r\n const withoutStrings = withoutComments\r\n .replace(/'(?:[^'\\\\]|\\\\.)*'/g, \"''\")\r\n .replace(/\"(?:[^\"\\\\]|\\\\.)*\"/g, '\"\"')\r\n .replace(/`(?:[^`\\\\]|\\\\.)*`/g, \"``\");\r\n\r\n // Patterns for type-only exports (these are safe)\r\n const typeOnlyPatterns = [\r\n /export\\s+type\\s+\\{[^}]*\\}/g, // export type { Foo, Bar }\r\n /export\\s+type\\s+\\{[^}]*\\}\\s+from\\s+['\"]/g, // export type { Foo } from \"...\"\r\n /export\\s+interface\\s+\\w+/g, // export interface Foo\r\n /export\\s+type\\s+\\w+\\s*=/g, // export type Foo =\r\n ];\r\n\r\n // Remove all type-only exports from consideration\r\n let remaining = withoutStrings;\r\n for (const pattern of typeOnlyPatterns) {\r\n remaining = remaining.replace(pattern, \"\");\r\n }\r\n\r\n // Patterns for runtime exports (these make the file NOT type-only)\r\n const runtimeExportPatterns = [\r\n /export\\s+(?:const|let|var)\\s+\\w+/g, // export const/let/var foo\r\n /export\\s+function\\s+\\w+/g, // export function foo\r\n /export\\s+async\\s+function\\s+\\w+/g, // export async function foo\r\n /export\\s+class\\s+\\w+/g, // export class Foo\r\n /export\\s+enum\\s+\\w+/g, // export enum Foo (enums have runtime value)\r\n /export\\s+default\\s+(?!type\\s)/g, // export default (not type)\r\n /export\\s+\\{[^}]*\\}(?!\\s+from)/g, // export { foo } (local re-export without type)\r\n /export\\s+\\{[^}]*\\}\\s+from\\s+['\"][^'\"]+['\"]/g, // export { foo } from (without type)\r\n /export\\s+\\*\\s+from\\s+['\"][^'\"]+['\"]/g, // export * from (re-exports everything)\r\n /export\\s+\\*\\s+as\\s+\\w+/g, // export * as namespace\r\n ];\r\n\r\n for (const pattern of runtimeExportPatterns) {\r\n if (pattern.test(remaining)) {\r\n // Reset regex lastIndex for subsequent tests\r\n pattern.lastIndex = 0;\r\n\r\n // Special case: check if export { } contains only type exports\r\n if (pattern.source.includes(\"export\\\\s+\\\\{\")) {\r\n const matches = remaining.match(/export\\s+\\{([^}]*)\\}(?:\\s+from\\s+['\"][^'\"]+['\"])?/g);\r\n if (matches) {\r\n for (const match of matches) {\r\n // Skip if it's already a type export\r\n if (/^export\\s+type\\s+/.test(match)) continue;\r\n\r\n // Extract the specifiers\r\n const specifiersMatch = match.match(/export\\s+\\{([^}]*)\\}/);\r\n if (specifiersMatch) {\r\n const specifiers = specifiersMatch[1];\r\n const items = specifiers\r\n .split(\",\")\r\n .map((s) => s.trim())\r\n .filter(Boolean);\r\n\r\n // If any specifier is NOT prefixed with \"type \", this is a runtime export\r\n const hasRuntimeSpecifier = items.some((item) => !item.startsWith(\"type \"));\r\n if (hasRuntimeSpecifier) {\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n return false;\r\n }\r\n }\r\n\r\n // If we get here, no runtime exports were found\r\n // But we should also verify the file has at least some type exports\r\n // (an empty file or file with only imports is not really \"type-only\")\r\n const hasTypeExports = typeOnlyPatterns.some((pattern) => {\r\n pattern.lastIndex = 0;\r\n return pattern.test(withoutStrings);\r\n });\r\n\r\n return hasTypeExports;\r\n}\r\n\r\n/**\r\n * Check if an import statement is a pure `import type` (the keyword sits\r\n * immediately after `import`, covering `import type { X }`, `import type Foo`,\r\n * and `import type * as Ns`).\r\n */\r\nfunction isTypeOnlyImport(line: string): boolean {\r\n const trimmed = line.trim();\r\n\r\n return trimmed.startsWith(\"import type \") || !!trimmed.match(/^import\\s+type\\s+[\\{\\*]/);\r\n}\r\n\r\n/**\r\n * Decide whether an `import ... from \"m\"` statement contributes any runtime\r\n * binding. Returns false for pure `import type` and for destructured imports\r\n * where every specifier is prefixed with the `type` keyword.\r\n */\r\nfunction hasRuntimeImports(line: string): boolean {\r\n const trimmed = line.trim();\r\n\r\n if (isTypeOnlyImport(trimmed)) {\r\n return false;\r\n }\r\n\r\n const specifiersMatch = trimmed.match(/import\\s+(?:type\\s+)?\\{([^}]+)\\}/);\r\n\r\n if (!specifiersMatch) {\r\n return true;\r\n }\r\n\r\n const items = specifiersMatch[1].split(\",\").map((s) => s.trim()).filter(Boolean);\r\n\r\n return !items.every((item) => /^type\\s+\\w+/.test(item));\r\n}\r\n\r\n/**\r\n * Decide whether an `export ... from \"m\"` statement re-exports only types.\r\n * Covers `export type { X } from`, `export type * from`, and\r\n * `export { type X, type Y } from`.\r\n */\r\nfunction isExportTypeOnlyStatement(line: string): boolean {\r\n const trimmed = line.trim();\r\n\r\n if (/^export\\s+type\\s+/.test(trimmed)) {\r\n return true;\r\n }\r\n\r\n const specifiersMatch = trimmed.match(/export\\s+\\{([^}]+)\\}/);\r\n\r\n if (!specifiersMatch) {\r\n return false;\r\n }\r\n\r\n const items = specifiersMatch[1].split(\",\").map((s) => s.trim()).filter(Boolean);\r\n\r\n return items.every((item) => /^type\\s+\\w+/.test(item));\r\n}\r\n\r\n/**\r\n * Extract import paths using regex (more reliable for TypeScript).\r\n * Each entry carries an `isTypeOnly` flag: true when every occurrence of the\r\n * path in the source is a type-only statement (no runtime binding).\r\n * A single runtime occurrence makes the path runtime.\r\n */\r\nfunction extractImportPathsWithRegex(\r\n source: string,\r\n): Array<{ path: string; originalLine: string; isTypeOnly: boolean }> {\r\n const imports: Array<{ path: string; originalLine: string; isTypeOnly: boolean }> = [];\r\n const seenPaths = new Map<string, number>();\r\n\r\n /**\r\n * Record an import path with its type-only flag.\r\n * If the same path appears in multiple statements, the edge is type-only\r\n * iff every occurrence is type-only — a single runtime statement makes it runtime.\r\n */\r\n const record = (importPath: string, originalLine: string, isTypeOnly: boolean): void => {\r\n if (!importPath) {\r\n return;\r\n }\r\n\r\n const existingIndex = seenPaths.get(importPath);\r\n\r\n if (existingIndex === undefined) {\r\n seenPaths.set(importPath, imports.length);\r\n imports.push({ path: importPath, originalLine, isTypeOnly });\r\n\r\n return;\r\n }\r\n\r\n if (!isTypeOnly) {\r\n imports[existingIndex].isTypeOnly = false;\r\n }\r\n };\r\n\r\n // Pattern 1: Standard ES module imports (handles multiline)\r\n // Matches: import { ... } from \"path\", import Foo from \"path\", import Foo, { ... } from \"path\"\r\n const importRegex =\r\n /import\\s+(?:type\\s+)?(\\{[\\s\\S]*?\\}|\\*\\s+as\\s+\\w+|\\w+(?:\\s*,\\s*\\{[\\s\\S]*?\\})?)\\s+from\\s+['\"]([^'\"]+)['\"]/g;\r\n\r\n let match;\r\n\r\n while ((match = importRegex.exec(source)) !== null) {\r\n const fullMatch = match[0];\r\n const importPath = match[2];\r\n const isTypeOnly = !hasRuntimeImports(fullMatch);\r\n\r\n record(importPath, fullMatch, isTypeOnly);\r\n }\r\n\r\n // Pattern 1b: Side-effect imports - import \"path\" — always runtime\r\n const sideEffectRegex = /import\\s+['\"]([^'\"]+)['\"]/g;\r\n\r\n while ((match = sideEffectRegex.exec(source)) !== null) {\r\n record(match[1], match[0], false);\r\n }\r\n\r\n // Pattern 2: Dynamic imports - import(\"path\") — always runtime\r\n const dynamicImportPattern = /import\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\r\n\r\n while ((match = dynamicImportPattern.exec(source)) !== null) {\r\n record(match[1], match[0], false);\r\n }\r\n\r\n // Pattern 3: Export from - export ... from \"path\"\r\n const exportFromPattern = /export\\s+(?:\\{[^}]*\\}|\\*|\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]/g;\r\n\r\n while ((match = exportFromPattern.exec(source)) !== null) {\r\n const fullMatch = match[0];\r\n\r\n record(match[1], fullMatch, isExportTypeOnlyStatement(fullMatch));\r\n }\r\n\r\n return imports;\r\n}\r\n\r\n/**\r\n * Metadata for a single resolved import edge.\r\n * `isTypeOnly` is true iff every import/export statement that references this\r\n * path is type-only (pure `import type`, `export type`, or destructured lists\r\n * where every specifier carries the `type` keyword). A single runtime\r\n * occurrence flips the flag to false — that's what matters for cycle detection.\r\n */\r\nexport type ResolvedImport = {\r\n absolutePath: string;\r\n isTypeOnly: boolean;\r\n};\r\n\r\n/**\r\n * Parse import/export statements in a TS/JS source file and return the\r\n * resolved dependency edges keyed by the original import path. Includes\r\n * type-only edges (flagged) so downstream consumers can distinguish runtime\r\n * cycles from type-only ones.\r\n *\r\n * @example\r\n * const importMap = await parseImports(source, \"/abs/path/to/file.ts\");\r\n * for (const [importPath, { absolutePath, isTypeOnly }] of importMap) {\r\n * // ...\r\n * }\r\n */\r\nexport async function parseImports(\r\n source: string,\r\n filePath: string,\r\n): Promise<Map<string, ResolvedImport>> {\r\n try {\r\n // Skip .d.ts files - they're type declarations, not runtime code\r\n if (filePath.endsWith(\".d.ts\")) {\r\n return new Map();\r\n }\r\n\r\n // Try es-module-lexer first (faster and more accurate for simple cases)\r\n try {\r\n const [imports] = await parse(source);\r\n\r\n if (imports && imports.length > 0) {\r\n return await resolveImports(imports as ImportSpecifier[], source, filePath);\r\n }\r\n } catch (lexerError) {\r\n // es-module-lexer failed, fall back to regex-based extraction\r\n // This is common with TypeScript files that have complex syntax\r\n }\r\n\r\n // Fallback: Use regex-based extraction (more forgiving with TypeScript)\r\n const regexImports = extractImportPathsWithRegex(source);\r\n const resolvedImports = new Map<string, ResolvedImport>();\r\n\r\n for (const { path: importPath, isTypeOnly } of regexImports) {\r\n if (isNodeBuiltin(importPath)) {\r\n continue;\r\n }\r\n\r\n if (!importPath.startsWith(\".\") && !tsconfigManager.isAlias(importPath)) {\r\n continue;\r\n }\r\n\r\n let resolvedPath: string | null = null;\r\n\r\n if (tsconfigManager.isAlias(importPath)) {\r\n resolvedPath = await resolveAliasImport(importPath);\r\n } else if (importPath.startsWith(\".\")) {\r\n resolvedPath = await resolveRelativeImport(importPath, filePath);\r\n }\r\n\r\n if (resolvedPath) {\r\n mergeResolvedImport(resolvedImports, importPath, resolvedPath, isTypeOnly);\r\n }\r\n }\r\n\r\n return resolvedImports;\r\n } catch (error) {\r\n console.error(`Error parsing imports for ${filePath}:`, error);\r\n\r\n return new Map();\r\n }\r\n}\r\n\r\n/**\r\n * Merge a resolved import into the output map, preserving the type-only rule:\r\n * a path is type-only iff every statement that references it is type-only.\r\n */\r\nfunction mergeResolvedImport(\r\n target: Map<string, ResolvedImport>,\r\n importPath: string,\r\n absolutePath: string,\r\n isTypeOnly: boolean,\r\n): void {\r\n const existing = target.get(importPath);\r\n\r\n if (!existing) {\r\n target.set(importPath, { absolutePath, isTypeOnly });\r\n\r\n return;\r\n }\r\n\r\n if (!isTypeOnly) {\r\n existing.isTypeOnly = false;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve imports from `es-module-lexer` output. For each specifier, slice the\r\n * raw statement (`ss..se`) and re-run the type-only heuristic so we can flag\r\n * the edge correctly — the lexer itself does not distinguish `import type`.\r\n */\r\nasync function resolveImports(\r\n imports: ImportSpecifier[],\r\n source: string,\r\n filePath: string,\r\n): Promise<Map<string, ResolvedImport>> {\r\n const resolvedImports = new Map<string, ResolvedImport>();\r\n\r\n for (const imp of imports) {\r\n const importPath = imp.n;\r\n\r\n if (!importPath) {\r\n continue;\r\n }\r\n\r\n if (isNodeBuiltin(importPath)) {\r\n continue;\r\n }\r\n\r\n if (!importPath.startsWith(\".\") && !tsconfigManager.isAlias(importPath)) {\r\n continue;\r\n }\r\n\r\n let resolvedPath: string | null = null;\r\n\r\n if (tsconfigManager.isAlias(importPath)) {\r\n resolvedPath = await resolveAliasImport(importPath);\r\n } else if (importPath.startsWith(\".\")) {\r\n resolvedPath = await resolveRelativeImport(importPath, filePath);\r\n }\r\n\r\n if (!resolvedPath) {\r\n continue;\r\n }\r\n\r\n const isTypeOnly = isLexerStatementTypeOnly(imp, source);\r\n\r\n mergeResolvedImport(resolvedImports, importPath, resolvedPath, isTypeOnly);\r\n }\r\n\r\n return resolvedImports;\r\n}\r\n\r\n/**\r\n * Classify a single lexer-reported statement as type-only or runtime.\r\n * Dynamic imports (`import(...)`) are always runtime. For static\r\n * imports/export-from we slice the raw source and apply the same heuristic\r\n * the regex fallback uses.\r\n */\r\nfunction isLexerStatementTypeOnly(imp: ImportSpecifier, source: string): boolean {\r\n // Dynamic imports always execute — they cannot be type-only.\r\n // es-module-lexer reports dynamic with a.n === undefined typically, but\r\n // we guard by checking the statement prefix too.\r\n const statementStart = imp.ss;\r\n const statementEnd = imp.se;\r\n\r\n if (\r\n typeof statementStart !== \"number\" ||\r\n typeof statementEnd !== \"number\" ||\r\n statementEnd <= statementStart\r\n ) {\r\n return false;\r\n }\r\n\r\n const statement = source.slice(statementStart, statementEnd);\r\n const trimmed = statement.trim();\r\n\r\n if (trimmed.startsWith(\"import(\") || /^\\bimport\\s*\\(/.test(trimmed)) {\r\n return false;\r\n }\r\n\r\n if (trimmed.startsWith(\"export\")) {\r\n return isExportTypeOnlyStatement(statement);\r\n }\r\n\r\n return !hasRuntimeImports(statement);\r\n}\r\n\r\n/**\r\n * Resolve alias imports to actual file paths with extensions\r\n * Example: app/users/services/get-users.service -> /absolute/path/to/src/app/users/services/get-users.service.ts\r\n */\r\nasync function resolveAliasImport(importPath: string): Promise<string | null> {\r\n // Use tsconfig manager to resolve the alias to an absolute path\r\n const resolvedBase = tsconfigManager.resolveAliasToAbsolute(importPath);\r\n\r\n if (!resolvedBase) return null;\r\n\r\n // Try to resolve with extensions\r\n const resolvedPath = await tryResolveWithExtensions(resolvedBase);\r\n\r\n return resolvedPath;\r\n}\r\n\r\n/**\r\n * Resolve relative imports to actual file paths\r\n * Example: ./../services/get-user.service -> /absolute/path/to/services/get-user.service.ts\r\n */\r\nasync function resolveRelativeImport(\r\n importPath: string,\r\n currentFilePath: string,\r\n): Promise<string | null> {\r\n const dir = path.dirname(currentFilePath);\r\n // Use path.resolve to handle .. and . properly, then normalize to forward slashes\r\n const resolvedBase = Path.normalize(path.resolve(dir, importPath));\r\n\r\n // Try to resolve with extensions\r\n const resolvedPath = await tryResolveWithExtensions(resolvedBase);\r\n\r\n return resolvedPath;\r\n}\r\n\r\n/**\r\n * Try to resolve a file path by checking different extensions\r\n * TypeScript/JavaScript files can be imported without extensions\r\n *\r\n * @TODO: For better performance, we need to check the files in files orchestrator\r\n * instead of using the file system as we will be fetching all project files anyway.\r\n */\r\n// Cache for file existence checks to avoid redundant filesystem calls\r\nconst fileExistsCache = new Map<string, boolean>();\r\n\r\n/**\r\n * Clear the file exists cache\r\n * Should be called when new files are created to ensure fresh lookups\r\n */\r\nexport function clearFileExistsCache(): void {\r\n fileExistsCache.clear();\r\n}\r\n\r\nasync function cachedFileExists(filePath: string): Promise<boolean> {\r\n if (fileExistsCache.has(filePath)) {\r\n return fileExistsCache.get(filePath)!;\r\n }\r\n const exists = (await fileExistsAsync(filePath)) as boolean;\r\n fileExistsCache.set(filePath, exists);\r\n return exists;\r\n}\r\n\r\nasync function tryResolveWithExtensions(basePath: string): Promise<string | null> {\r\n // Normalize the base path first (handle Windows paths)\r\n const normalizedBase = Path.normalize(basePath);\r\n\r\n // List of extensions to try, in order of preference\r\n const extensions = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\"];\r\n const validExtensions = new Set(extensions);\r\n\r\n // If the path already has a VALID code file extension, check if it exists\r\n const ext = path.extname(normalizedBase);\r\n if (ext && validExtensions.has(ext)) {\r\n if (await cachedFileExists(normalizedBase)) {\r\n return normalizedBase;\r\n }\r\n // If explicit extension doesn't exist, return null\r\n return null;\r\n }\r\n\r\n // Try all extensions in parallel for better performance\r\n const pathsToCheck = extensions.map((extension) => normalizedBase + extension);\r\n const results = await Promise.all(\r\n pathsToCheck.map(async (p) => ({ path: p, exists: await cachedFileExists(p) })),\r\n );\r\n\r\n // Return the first one that exists (in order of preference)\r\n for (const result of results) {\r\n if (result.exists) {\r\n return result.path;\r\n }\r\n }\r\n\r\n // Try index files in directory\r\n if (await directoryExistsAsync(normalizedBase)) {\r\n const indexPaths = extensions.map((extension) =>\r\n Path.join(normalizedBase, `index${extension}`),\r\n );\r\n const indexResults = await Promise.all(\r\n indexPaths.map(async (p) => ({ path: p, exists: await cachedFileExists(p) })),\r\n );\r\n\r\n for (const result of indexResults) {\r\n if (result.exists) {\r\n return result.path;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Check if import is a Node.js built-in module\r\n */\r\nfunction isNodeBuiltin(importPath: string): boolean {\r\n const builtins = [\r\n \"fs\",\r\n \"path\",\r\n \"http\",\r\n \"https\",\r\n \"crypto\",\r\n \"stream\",\r\n \"util\",\r\n \"events\",\r\n \"buffer\",\r\n \"child_process\",\r\n \"os\",\r\n \"url\",\r\n \"querystring\",\r\n \"zlib\",\r\n \"net\",\r\n \"tls\",\r\n \"dns\",\r\n \"dgram\",\r\n \"cluster\",\r\n \"worker_threads\",\r\n \"perf_hooks\",\r\n \"async_hooks\",\r\n \"timers\",\r\n \"readline\",\r\n \"repl\",\r\n \"vm\",\r\n \"assert\",\r\n \"console\",\r\n \"process\",\r\n \"v8\",\r\n ];\r\n\r\n // Check for node: prefix or direct builtin name\r\n if (importPath.startsWith(\"node:\")) return true;\r\n\r\n const moduleName = importPath.split(\"/\")[0];\r\n return builtins.includes(moduleName);\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parse-imports.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/parse-imports.ts"],"sourcesContent":["import { fileExistsAsync, directoryExistsAsync } from \"@warlock.js/fs\";\r\nimport { ImportSpecifier, parse } from \"es-module-lexer\";\r\nimport path from \"node:path\";\r\nimport { Path } from \"./path\";\r\nimport { tsconfigManager } from \"./tsconfig-manager\";\r\n\r\n/**\r\n * Detect if a file contains only type definitions (no runtime code)\r\n *\r\n * A file is considered type-only if ALL its exports are:\r\n * - interface declarations\r\n * - type alias declarations\r\n * - export type { ... } statements\r\n * - export type { ... } from \"...\" statements\r\n *\r\n * Files with any of these are NOT type-only:\r\n * - export const/let/var\r\n * - export function\r\n * - export class\r\n * - export default (non-type)\r\n * - export { ... } (without type keyword)\r\n * - export * from (without type keyword)\r\n *\r\n * @param source - The source code to analyze\r\n * @returns true if the file exports only types\r\n */\r\nexport function isTypeOnlyFile(source: string): boolean {\r\n // Remove comments to avoid false positives\r\n const withoutComments = source\r\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\") // block comments\r\n .replace(/\\/\\/.*$/gm, \"\"); // line comments\r\n\r\n // Remove string literals to avoid false positives\r\n const withoutStrings = withoutComments\r\n .replace(/'(?:[^'\\\\]|\\\\.)*'/g, \"''\")\r\n .replace(/\"(?:[^\"\\\\]|\\\\.)*\"/g, '\"\"')\r\n .replace(/`(?:[^`\\\\]|\\\\.)*`/g, \"``\");\r\n\r\n // Patterns for type-only exports (these are safe)\r\n const typeOnlyPatterns = [\r\n /export\\s+type\\s+\\{[^}]*\\}/g, // export type { Foo, Bar }\r\n /export\\s+type\\s+\\{[^}]*\\}\\s+from\\s+['\"]/g, // export type { Foo } from \"...\"\r\n /export\\s+interface\\s+\\w+/g, // export interface Foo\r\n /export\\s+type\\s+\\w+\\s*=/g, // export type Foo =\r\n ];\r\n\r\n // Remove all type-only exports from consideration\r\n let remaining = withoutStrings;\r\n for (const pattern of typeOnlyPatterns) {\r\n remaining = remaining.replace(pattern, \"\");\r\n }\r\n\r\n // Patterns for runtime exports (these make the file NOT type-only)\r\n const runtimeExportPatterns = [\r\n /export\\s+(?:const|let|var)\\s+\\w+/g, // export const/let/var foo\r\n /export\\s+function\\s+\\w+/g, // export function foo\r\n /export\\s+async\\s+function\\s+\\w+/g, // export async function foo\r\n /export\\s+class\\s+\\w+/g, // export class Foo\r\n /export\\s+enum\\s+\\w+/g, // export enum Foo (enums have runtime value)\r\n /export\\s+default\\s+(?!type\\s)/g, // export default (not type)\r\n /export\\s+\\{[^}]*\\}(?!\\s+from)/g, // export { foo } (local re-export without type)\r\n /export\\s+\\{[^}]*\\}\\s+from\\s+['\"][^'\"]+['\"]/g, // export { foo } from (without type)\r\n /export\\s+\\*\\s+from\\s+['\"][^'\"]+['\"]/g, // export * from (re-exports everything)\r\n /export\\s+\\*\\s+as\\s+\\w+/g, // export * as namespace\r\n ];\r\n\r\n for (const pattern of runtimeExportPatterns) {\r\n if (pattern.test(remaining)) {\r\n // Reset regex lastIndex for subsequent tests\r\n pattern.lastIndex = 0;\r\n\r\n // Special case: check if export { } contains only type exports\r\n if (pattern.source.includes(\"export\\\\s+\\\\{\")) {\r\n const matches = remaining.match(/export\\s+\\{([^}]*)\\}(?:\\s+from\\s+['\"][^'\"]+['\"])?/g);\r\n if (matches) {\r\n for (const match of matches) {\r\n // Skip if it's already a type export\r\n if (/^export\\s+type\\s+/.test(match)) continue;\r\n\r\n // Extract the specifiers\r\n const specifiersMatch = match.match(/export\\s+\\{([^}]*)\\}/);\r\n if (specifiersMatch) {\r\n const specifiers = specifiersMatch[1];\r\n const items = specifiers\r\n .split(\",\")\r\n .map((s) => s.trim())\r\n .filter(Boolean);\r\n\r\n // If any specifier is NOT prefixed with \"type \", this is a runtime export\r\n const hasRuntimeSpecifier = items.some((item) => !item.startsWith(\"type \"));\r\n if (hasRuntimeSpecifier) {\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n return false;\r\n }\r\n }\r\n\r\n // If we get here, no runtime exports were found\r\n // But we should also verify the file has at least some type exports\r\n // (an empty file or file with only imports is not really \"type-only\")\r\n const hasTypeExports = typeOnlyPatterns.some((pattern) => {\r\n pattern.lastIndex = 0;\r\n return pattern.test(withoutStrings);\r\n });\r\n\r\n return hasTypeExports;\r\n}\r\n\r\n/**\r\n * Check if an import statement is a pure `import type` (the keyword sits\r\n * immediately after `import`, covering `import type { X }`, `import type Foo`,\r\n * and `import type * as Ns`).\r\n */\r\nfunction isTypeOnlyImport(line: string): boolean {\r\n const trimmed = line.trim();\r\n\r\n return trimmed.startsWith(\"import type \") || !!trimmed.match(/^import\\s+type\\s+[\\{\\*]/);\r\n}\r\n\r\n/**\r\n * Decide whether an `import ... from \"m\"` statement contributes any runtime\r\n * binding. Returns false for pure `import type` and for destructured imports\r\n * where every specifier is prefixed with the `type` keyword.\r\n */\r\nfunction hasRuntimeImports(line: string): boolean {\r\n const trimmed = line.trim();\r\n\r\n if (isTypeOnlyImport(trimmed)) {\r\n return false;\r\n }\r\n\r\n const specifiersMatch = trimmed.match(/import\\s+(?:type\\s+)?\\{([^}]+)\\}/);\r\n\r\n if (!specifiersMatch) {\r\n return true;\r\n }\r\n\r\n const items = specifiersMatch[1].split(\",\").map((s) => s.trim()).filter(Boolean);\r\n\r\n return !items.every((item) => /^type\\s+\\w+/.test(item));\r\n}\r\n\r\n/**\r\n * Decide whether an `export ... from \"m\"` statement re-exports only types.\r\n * Covers `export type { X } from`, `export type * from`, and\r\n * `export { type X, type Y } from`.\r\n */\r\nfunction isExportTypeOnlyStatement(line: string): boolean {\r\n const trimmed = line.trim();\r\n\r\n if (/^export\\s+type\\s+/.test(trimmed)) {\r\n return true;\r\n }\r\n\r\n const specifiersMatch = trimmed.match(/export\\s+\\{([^}]+)\\}/);\r\n\r\n if (!specifiersMatch) {\r\n return false;\r\n }\r\n\r\n const items = specifiersMatch[1].split(\",\").map((s) => s.trim()).filter(Boolean);\r\n\r\n return items.every((item) => /^type\\s+\\w+/.test(item));\r\n}\r\n\r\n/**\r\n * Extract import paths using regex (more reliable for TypeScript).\r\n * Each entry carries an `isTypeOnly` flag: true when every occurrence of the\r\n * path in the source is a type-only statement (no runtime binding).\r\n * A single runtime occurrence makes the path runtime.\r\n */\r\nfunction extractImportPathsWithRegex(\r\n source: string,\r\n): Array<{ path: string; originalLine: string; isTypeOnly: boolean }> {\r\n const imports: Array<{ path: string; originalLine: string; isTypeOnly: boolean }> = [];\r\n const seenPaths = new Map<string, number>();\r\n\r\n /**\r\n * Record an import path with its type-only flag.\r\n * If the same path appears in multiple statements, the edge is type-only\r\n * iff every occurrence is type-only — a single runtime statement makes it runtime.\r\n */\r\n const record = (importPath: string, originalLine: string, isTypeOnly: boolean): void => {\r\n if (!importPath) {\r\n return;\r\n }\r\n\r\n const existingIndex = seenPaths.get(importPath);\r\n\r\n if (existingIndex === undefined) {\r\n seenPaths.set(importPath, imports.length);\r\n imports.push({ path: importPath, originalLine, isTypeOnly });\r\n\r\n return;\r\n }\r\n\r\n if (!isTypeOnly) {\r\n imports[existingIndex].isTypeOnly = false;\r\n }\r\n };\r\n\r\n // Pattern 1: Standard ES module imports (handles multiline)\r\n // Matches: import { ... } from \"path\", import Foo from \"path\", import Foo, { ... } from \"path\"\r\n const importRegex =\r\n /import\\s+(?:type\\s+)?(\\{[\\s\\S]*?\\}|\\*\\s+as\\s+\\w+|\\w+(?:\\s*,\\s*\\{[\\s\\S]*?\\})?)\\s+from\\s+['\"]([^'\"]+)['\"]/g;\r\n\r\n let match;\r\n\r\n while ((match = importRegex.exec(source)) !== null) {\r\n const fullMatch = match[0];\r\n const importPath = match[2];\r\n const isTypeOnly = !hasRuntimeImports(fullMatch);\r\n\r\n record(importPath, fullMatch, isTypeOnly);\r\n }\r\n\r\n // Pattern 1b: Side-effect imports - import \"path\" — always runtime\r\n const sideEffectRegex = /import\\s+['\"]([^'\"]+)['\"]/g;\r\n\r\n while ((match = sideEffectRegex.exec(source)) !== null) {\r\n record(match[1], match[0], false);\r\n }\r\n\r\n // Pattern 2: Dynamic imports - import(\"path\") — always runtime\r\n const dynamicImportPattern = /import\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\r\n\r\n while ((match = dynamicImportPattern.exec(source)) !== null) {\r\n record(match[1], match[0], false);\r\n }\r\n\r\n // Pattern 3: Export from - export ... from \"path\"\r\n const exportFromPattern = /export\\s+(?:\\{[^}]*\\}|\\*|\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]/g;\r\n\r\n while ((match = exportFromPattern.exec(source)) !== null) {\r\n const fullMatch = match[0];\r\n\r\n record(match[1], fullMatch, isExportTypeOnlyStatement(fullMatch));\r\n }\r\n\r\n return imports;\r\n}\r\n\r\n/**\r\n * Metadata for a single resolved import edge.\r\n * `isTypeOnly` is true iff every import/export statement that references this\r\n * path is type-only (pure `import type`, `export type`, or destructured lists\r\n * where every specifier carries the `type` keyword). A single runtime\r\n * occurrence flips the flag to false — that's what matters for cycle detection.\r\n */\r\nexport type ResolvedImport = {\r\n absolutePath: string;\r\n isTypeOnly: boolean;\r\n};\r\n\r\n/**\r\n * Parse import/export statements in a TS/JS source file and return the\r\n * resolved dependency edges keyed by the original import path. Includes\r\n * type-only edges (flagged) so downstream consumers can distinguish runtime\r\n * cycles from type-only ones.\r\n *\r\n * @example\r\n * const importMap = await parseImports(source, \"/abs/path/to/file.ts\");\r\n * for (const [importPath, { absolutePath, isTypeOnly }] of importMap) {\r\n * // ...\r\n * }\r\n */\r\nexport async function parseImports(\r\n source: string,\r\n filePath: string,\r\n): Promise<Map<string, ResolvedImport>> {\r\n try {\r\n // Skip .d.ts files - they're type declarations, not runtime code\r\n if (filePath.endsWith(\".d.ts\")) {\r\n return new Map();\r\n }\r\n\r\n // Try es-module-lexer first (faster and more accurate for simple cases)\r\n try {\r\n const [imports] = await parse(source);\r\n\r\n if (imports && imports.length > 0) {\r\n return await resolveImports(imports as ImportSpecifier[], source, filePath);\r\n }\r\n } catch (lexerError) {\r\n // es-module-lexer failed, fall back to regex-based extraction\r\n // This is common with TypeScript files that have complex syntax\r\n }\r\n\r\n // Fallback: Use regex-based extraction (more forgiving with TypeScript)\r\n const regexImports = extractImportPathsWithRegex(source);\r\n const resolvedImports = new Map<string, ResolvedImport>();\r\n\r\n for (const { path: importPath, isTypeOnly } of regexImports) {\r\n if (isNodeBuiltin(importPath)) {\r\n continue;\r\n }\r\n\r\n if (!importPath.startsWith(\".\") && !tsconfigManager.isAlias(importPath)) {\r\n continue;\r\n }\r\n\r\n let resolvedPath: string | null = null;\r\n\r\n if (tsconfigManager.isAlias(importPath)) {\r\n resolvedPath = await resolveAliasImport(importPath);\r\n } else if (importPath.startsWith(\".\")) {\r\n resolvedPath = await resolveRelativeImport(importPath, filePath);\r\n }\r\n\r\n if (resolvedPath) {\r\n mergeResolvedImport(resolvedImports, importPath, resolvedPath, isTypeOnly);\r\n }\r\n }\r\n\r\n return resolvedImports;\r\n } catch (error) {\r\n console.error(`Error parsing imports for ${filePath}:`, error);\r\n\r\n return new Map();\r\n }\r\n}\r\n\r\n/**\r\n * Merge a resolved import into the output map, preserving the type-only rule:\r\n * a path is type-only iff every statement that references it is type-only.\r\n */\r\nfunction mergeResolvedImport(\r\n target: Map<string, ResolvedImport>,\r\n importPath: string,\r\n absolutePath: string,\r\n isTypeOnly: boolean,\r\n): void {\r\n const existing = target.get(importPath);\r\n\r\n if (!existing) {\r\n target.set(importPath, { absolutePath, isTypeOnly });\r\n\r\n return;\r\n }\r\n\r\n if (!isTypeOnly) {\r\n existing.isTypeOnly = false;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve imports from `es-module-lexer` output. For each specifier, slice the\r\n * raw statement (`ss..se`) and re-run the type-only heuristic so we can flag\r\n * the edge correctly — the lexer itself does not distinguish `import type`.\r\n */\r\nasync function resolveImports(\r\n imports: ImportSpecifier[],\r\n source: string,\r\n filePath: string,\r\n): Promise<Map<string, ResolvedImport>> {\r\n const resolvedImports = new Map<string, ResolvedImport>();\r\n\r\n for (const imp of imports) {\r\n const importPath = imp.n;\r\n\r\n if (!importPath) {\r\n continue;\r\n }\r\n\r\n if (isNodeBuiltin(importPath)) {\r\n continue;\r\n }\r\n\r\n if (!importPath.startsWith(\".\") && !tsconfigManager.isAlias(importPath)) {\r\n continue;\r\n }\r\n\r\n let resolvedPath: string | null = null;\r\n\r\n if (tsconfigManager.isAlias(importPath)) {\r\n resolvedPath = await resolveAliasImport(importPath);\r\n } else if (importPath.startsWith(\".\")) {\r\n resolvedPath = await resolveRelativeImport(importPath, filePath);\r\n }\r\n\r\n if (!resolvedPath) {\r\n continue;\r\n }\r\n\r\n const isTypeOnly = isLexerStatementTypeOnly(imp, source);\r\n\r\n mergeResolvedImport(resolvedImports, importPath, resolvedPath, isTypeOnly);\r\n }\r\n\r\n return resolvedImports;\r\n}\r\n\r\n/**\r\n * Classify a single lexer-reported statement as type-only or runtime.\r\n * Dynamic imports (`import(...)`) are always runtime. For static\r\n * imports/export-from we slice the raw source and apply the same heuristic\r\n * the regex fallback uses.\r\n */\r\nfunction isLexerStatementTypeOnly(imp: ImportSpecifier, source: string): boolean {\r\n // Dynamic imports always execute — they cannot be type-only.\r\n // es-module-lexer reports dynamic with a.n === undefined typically, but\r\n // we guard by checking the statement prefix too.\r\n const statementStart = imp.ss;\r\n const statementEnd = imp.se;\r\n\r\n if (\r\n typeof statementStart !== \"number\" ||\r\n typeof statementEnd !== \"number\" ||\r\n statementEnd <= statementStart\r\n ) {\r\n return false;\r\n }\r\n\r\n const statement = source.slice(statementStart, statementEnd);\r\n const trimmed = statement.trim();\r\n\r\n if (trimmed.startsWith(\"import(\") || /^\\bimport\\s*\\(/.test(trimmed)) {\r\n return false;\r\n }\r\n\r\n if (trimmed.startsWith(\"export\")) {\r\n return isExportTypeOnlyStatement(statement);\r\n }\r\n\r\n return !hasRuntimeImports(statement);\r\n}\r\n\r\n/**\r\n * Resolve alias imports to actual file paths with extensions\r\n * Example: app/users/services/get-users.service -> /absolute/path/to/src/app/users/services/get-users.service.ts\r\n */\r\nasync function resolveAliasImport(importPath: string): Promise<string | null> {\r\n // Use tsconfig manager to resolve the alias to an absolute path\r\n const resolvedBase = tsconfigManager.resolveAliasToAbsolute(importPath);\r\n\r\n if (!resolvedBase) return null;\r\n\r\n // Try to resolve with extensions\r\n const resolvedPath = await tryResolveWithExtensions(resolvedBase);\r\n\r\n return resolvedPath;\r\n}\r\n\r\n/**\r\n * Resolve relative imports to actual file paths\r\n * Example: ./../services/get-user.service -> /absolute/path/to/services/get-user.service.ts\r\n */\r\nasync function resolveRelativeImport(\r\n importPath: string,\r\n currentFilePath: string,\r\n): Promise<string | null> {\r\n const dir = path.dirname(currentFilePath);\r\n // Use path.resolve to handle .. and . properly, then normalize to forward slashes\r\n const resolvedBase = Path.normalize(path.resolve(dir, importPath));\r\n\r\n // Try to resolve with extensions\r\n const resolvedPath = await tryResolveWithExtensions(resolvedBase);\r\n\r\n return resolvedPath;\r\n}\r\n\r\n/**\r\n * Try to resolve a file path by checking different extensions\r\n * TypeScript/JavaScript files can be imported without extensions\r\n *\r\n * @TODO: For better performance, we need to check the files in files orchestrator\r\n * instead of using the file system as we will be fetching all project files anyway.\r\n */\r\n// Cache for file existence checks to avoid redundant filesystem calls\r\nconst fileExistsCache = new Map<string, boolean>();\r\n\r\n/**\r\n * Clear the file exists cache\r\n * Should be called when new files are created to ensure fresh lookups\r\n */\r\nexport function clearFileExistsCache(): void {\r\n fileExistsCache.clear();\r\n}\r\n\r\nasync function cachedFileExists(filePath: string): Promise<boolean> {\r\n if (fileExistsCache.has(filePath)) {\r\n return fileExistsCache.get(filePath)!;\r\n }\r\n const exists = (await fileExistsAsync(filePath)) as boolean;\r\n fileExistsCache.set(filePath, exists);\r\n return exists;\r\n}\r\n\r\nasync function tryResolveWithExtensions(basePath: string): Promise<string | null> {\r\n // Normalize the base path first (handle Windows paths)\r\n const normalizedBase = Path.normalize(basePath);\r\n\r\n // List of extensions to try, in order of preference\r\n const extensions = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\"];\r\n const validExtensions = new Set(extensions);\r\n\r\n // If the path already has a VALID code file extension, check if it exists\r\n const ext = path.extname(normalizedBase);\r\n if (ext && validExtensions.has(ext)) {\r\n if (await cachedFileExists(normalizedBase)) {\r\n return normalizedBase;\r\n }\r\n // If explicit extension doesn't exist, return null\r\n return null;\r\n }\r\n\r\n // Try all extensions in parallel for better performance\r\n const pathsToCheck = extensions.map((extension) => normalizedBase + extension);\r\n const results = await Promise.all(\r\n pathsToCheck.map(async (p) => ({ path: p, exists: await cachedFileExists(p) })),\r\n );\r\n\r\n // Return the first one that exists (in order of preference)\r\n for (const result of results) {\r\n if (result.exists) {\r\n return result.path;\r\n }\r\n }\r\n\r\n // Try index files in directory\r\n if (await directoryExistsAsync(normalizedBase)) {\r\n const indexPaths = extensions.map((extension) =>\r\n Path.join(normalizedBase, `index${extension}`),\r\n );\r\n const indexResults = await Promise.all(\r\n indexPaths.map(async (p) => ({ path: p, exists: await cachedFileExists(p) })),\r\n );\r\n\r\n for (const result of indexResults) {\r\n if (result.exists) {\r\n return result.path;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Check if import is a Node.js built-in module\r\n */\r\nfunction isNodeBuiltin(importPath: string): boolean {\r\n const builtins = [\r\n \"fs\",\r\n \"path\",\r\n \"http\",\r\n \"https\",\r\n \"crypto\",\r\n \"stream\",\r\n \"util\",\r\n \"events\",\r\n \"buffer\",\r\n \"child_process\",\r\n \"os\",\r\n \"url\",\r\n \"querystring\",\r\n \"zlib\",\r\n \"net\",\r\n \"tls\",\r\n \"dns\",\r\n \"dgram\",\r\n \"cluster\",\r\n \"worker_threads\",\r\n \"perf_hooks\",\r\n \"async_hooks\",\r\n \"timers\",\r\n \"readline\",\r\n \"repl\",\r\n \"vm\",\r\n \"assert\",\r\n \"console\",\r\n \"process\",\r\n \"v8\",\r\n ];\r\n\r\n // Check for node: prefix or direct builtin name\r\n if (importPath.startsWith(\"node:\")) return true;\r\n\r\n const moduleName = importPath.split(\"/\")[0];\r\n return builtins.includes(moduleName);\r\n}\r\n"],"mappings":"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"}
|
package/esm/dev-server/path.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"path.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/path.ts"],"sourcesContent":["import path from \"node:path\";\n\nexport class Path {\n /**\n * Convert the given absolute path to a relative path\n */\n public static toRelative(absolutePath: string) {\n return this.normalize(path.relative(process.cwd(), absolutePath));\n }\n\n /**\n * Get relative path of the given path\n */\n public static relative(relativePath: string) {\n return this.normalize(path.relative(process.cwd(), relativePath));\n }\n\n /**\n * Get normalized absolute path of the given path\n */\n public static toNormalizedAbsolute(relativePath: string) {\n return this.normalize(path.resolve(process.cwd(), relativePath));\n }\n\n /**\n * Get absolute path of the given path\n */\n public static toAbsolute(relativePath: string) {\n return this.normalize(path.resolve(process.cwd(), relativePath));\n }\n\n /**\n * Normalize the given path (convert backslashes to forward slashes)\n */\n public static normalize(filePath: string) {\n return filePath.replace(/\\\\/g, \"/\");\n }\n\n /**\n * Join paths and normalize\n */\n public static join(...paths: string[]) {\n return this.normalize(path.join(...paths));\n }\n\n /**\n * Get directory name of a path\n */\n public static dirname(filePath: string) {\n return this.normalize(path.dirname(filePath));\n }\n\n /**\n * Get base name of a path\n */\n public static basename(filePath: string, ext?: string) {\n return path.basename(filePath, ext);\n }\n\n /**\n * Get extension of a path\n */\n public static extname(filePath: string) {\n return path.extname(filePath);\n }\n}\n"],"mappings":";;;AAEA,IAAa,OAAb,MAAkB;;;;CAIhB,OAAc,WAAW,cAAsB;EAC7C,OAAO,KAAK,UAAU,KAAK,SAAS,QAAQ,IAAI,GAAG,YAAY,CAAC;CAClE;;;;CAKA,OAAc,SAAS,cAAsB;EAC3C,OAAO,KAAK,UAAU,KAAK,SAAS,QAAQ,IAAI,GAAG,YAAY,CAAC;CAClE;;;;CAKA,OAAc,qBAAqB,cAAsB;EACvD,OAAO,KAAK,UAAU,KAAK,QAAQ,QAAQ,IAAI,GAAG,YAAY,CAAC;CACjE;;;;CAKA,OAAc,WAAW,cAAsB;EAC7C,OAAO,KAAK,UAAU,KAAK,QAAQ,QAAQ,IAAI,GAAG,YAAY,CAAC;CACjE;;;;CAKA,OAAc,UAAU,UAAkB;EACxC,OAAO,SAAS,QAAQ,OAAO,GAAG;CACpC;;;;CAKA,OAAc,KAAK,GAAG,OAAiB;EACrC,OAAO,KAAK,UAAU,KAAK,KAAK,GAAG,KAAK,CAAC;CAC3C;;;;CAKA,OAAc,QAAQ,UAAkB;EACtC,OAAO,KAAK,UAAU,KAAK,QAAQ,QAAQ,CAAC;CAC9C;;;;CAKA,OAAc,SAAS,UAAkB,KAAc;EACrD,OAAO,KAAK,SAAS,UAAU,GAAG;CACpC;;;;CAKA,OAAc,QAAQ,UAAkB;EACtC,OAAO,KAAK,QAAQ,QAAQ;CAC9B;AACF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { devLogError } from "./dev-logger.mjs";
|
|
2
|
+
import { restartDevServer } from "./restart-dev-server.mjs";
|
|
3
|
+
import { devServerShortcuts } from "./shortcuts.mjs";
|
|
4
|
+
import { colors } from "@mongez/copper";
|
|
5
|
+
|
|
6
|
+
//#region ../core/src/dev-server/register-dev-shortcuts.ts
|
|
7
|
+
/**
|
|
8
|
+
* Arm the dev server's standing keyboard shortcuts and print the one-line
|
|
9
|
+
* hint that tells the developer they exist.
|
|
10
|
+
*
|
|
11
|
+
* These stay available for the whole session. The update shortcut (`u`) is
|
|
12
|
+
* deliberately not here — it is armed by the update notice only when there is
|
|
13
|
+
* something to update, and dropped again once it has been used.
|
|
14
|
+
*
|
|
15
|
+
* Entirely TTY-gated: with piped stdin (CI, a supervisor, `warlock dev | tee`)
|
|
16
|
+
* nothing is registered, no hint is printed, and stdin is never touched.
|
|
17
|
+
*/
|
|
18
|
+
function registerDevShortcuts(devServer) {
|
|
19
|
+
if (!devServerShortcuts.isSupported()) return;
|
|
20
|
+
devServerShortcuts.register({
|
|
21
|
+
key: "r",
|
|
22
|
+
description: "restart the server",
|
|
23
|
+
handler: () => restart(devServer)
|
|
24
|
+
});
|
|
25
|
+
devServerShortcuts.register({
|
|
26
|
+
key: "c",
|
|
27
|
+
description: "clear the console",
|
|
28
|
+
handler: () => console.clear()
|
|
29
|
+
});
|
|
30
|
+
devServerShortcuts.register({
|
|
31
|
+
key: "q",
|
|
32
|
+
description: "quit",
|
|
33
|
+
handler: () => quit(devServer)
|
|
34
|
+
});
|
|
35
|
+
devServerShortcuts.register({
|
|
36
|
+
key: "h",
|
|
37
|
+
description: "show this help",
|
|
38
|
+
handler: printShortcuts
|
|
39
|
+
});
|
|
40
|
+
console.log(` ${colors.dim("press")} ${colors.bold(colors.cyan("h"))} ${colors.dim("for shortcuts")}`);
|
|
41
|
+
}
|
|
42
|
+
/** `r` — bring the server back up on a clean process. */
|
|
43
|
+
async function restart(devServer) {
|
|
44
|
+
if (!await restartDevServer(devServer)) {
|
|
45
|
+
devServerShortcuts.resume();
|
|
46
|
+
devLogError("Restart failed — start the dev server again manually.");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** `q` — the same graceful shutdown Ctrl+C performs. */
|
|
50
|
+
async function quit(devServer) {
|
|
51
|
+
try {
|
|
52
|
+
await devServer.shutdown();
|
|
53
|
+
process.exit(0);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
devLogError(`Shutdown failed: ${error.message}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** `h` — list whatever is armed right now, `u` included when it is. */
|
|
60
|
+
function printShortcuts() {
|
|
61
|
+
console.log();
|
|
62
|
+
console.log(` ${colors.bold("Shortcuts")}`);
|
|
63
|
+
for (const shortcut of devServerShortcuts.list()) console.log(` ${colors.bold(colors.cyan(shortcut.key))} ${colors.dim(shortcut.description)}`);
|
|
64
|
+
console.log(` ${colors.bold(colors.cyan("Ctrl+C"))} ${colors.dim("quit")}`);
|
|
65
|
+
console.log();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { registerDevShortcuts };
|
|
70
|
+
//# sourceMappingURL=register-dev-shortcuts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-dev-shortcuts.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/register-dev-shortcuts.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { devLogError } from \"./dev-logger\";\nimport type { DevelopmentServer } from \"./development-server\";\nimport { restartDevServer } from \"./restart-dev-server\";\nimport { devServerShortcuts } from \"./shortcuts\";\n\n/**\n * Arm the dev server's standing keyboard shortcuts and print the one-line\n * hint that tells the developer they exist.\n *\n * These stay available for the whole session. The update shortcut (`u`) is\n * deliberately not here — it is armed by the update notice only when there is\n * something to update, and dropped again once it has been used.\n *\n * Entirely TTY-gated: with piped stdin (CI, a supervisor, `warlock dev | tee`)\n * nothing is registered, no hint is printed, and stdin is never touched.\n */\nexport function registerDevShortcuts(devServer: DevelopmentServer): void {\n if (!devServerShortcuts.isSupported()) {\n return;\n }\n\n devServerShortcuts.register({\n key: \"r\",\n description: \"restart the server\",\n handler: () => restart(devServer),\n });\n\n devServerShortcuts.register({\n key: \"c\",\n description: \"clear the console\",\n handler: () => console.clear(),\n });\n\n devServerShortcuts.register({\n key: \"q\",\n description: \"quit\",\n handler: () => quit(devServer),\n });\n\n devServerShortcuts.register({\n key: \"h\",\n description: \"show this help\",\n handler: printShortcuts,\n });\n\n console.log(\n ` ${colors.dim(\"press\")} ${colors.bold(colors.cyan(\"h\"))} ` +\n `${colors.dim(\"for shortcuts\")}`,\n );\n}\n\n/** `r` — bring the server back up on a clean process. */\nasync function restart(devServer: DevelopmentServer): Promise<void> {\n const restarted = await restartDevServer(devServer);\n\n if (!restarted) {\n devServerShortcuts.resume();\n devLogError(\"Restart failed — start the dev server again manually.\");\n }\n}\n\n/** `q` — the same graceful shutdown Ctrl+C performs. */\nasync function quit(devServer: DevelopmentServer): Promise<void> {\n try {\n await devServer.shutdown();\n process.exit(0);\n } catch (error) {\n devLogError(`Shutdown failed: ${(error as Error).message}`);\n process.exit(1);\n }\n}\n\n/** `h` — list whatever is armed right now, `u` included when it is. */\nfunction printShortcuts(): void {\n console.log();\n console.log(` ${colors.bold(\"Shortcuts\")}`);\n\n for (const shortcut of devServerShortcuts.list()) {\n console.log(\n ` ${colors.bold(colors.cyan(shortcut.key))} ${colors.dim(shortcut.description)}`,\n );\n }\n\n console.log(` ${colors.bold(colors.cyan(\"Ctrl+C\"))} ${colors.dim(\"quit\")}`);\n console.log();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,qBAAqB,WAAoC;CACvE,IAAI,CAAC,mBAAmB,YAAY,GAClC;CAGF,mBAAmB,SAAS;EAC1B,KAAK;EACL,aAAa;EACb,eAAe,QAAQ,SAAS;CAClC,CAAC;CAED,mBAAmB,SAAS;EAC1B,KAAK;EACL,aAAa;EACb,eAAe,QAAQ,MAAM;CAC/B,CAAC;CAED,mBAAmB,SAAS;EAC1B,KAAK;EACL,aAAa;EACb,eAAe,KAAK,SAAS;CAC/B,CAAC;CAED,mBAAmB,SAAS;EAC1B,KAAK;EACL,aAAa;EACb,SAAS;CACX,CAAC;CAED,QAAQ,IACN,MAAM,OAAO,IAAI,OAAO,EAAE,GAAG,OAAO,KAAK,OAAO,KAAK,GAAG,CAAC,EAAE,GACtD,OAAO,IAAI,eAAe,GACjC;AACF;;AAGA,eAAe,QAAQ,WAA6C;CAGlE,IAAI,CAAC,MAFmB,iBAAiB,SAAS,GAElC;EACd,mBAAmB,OAAO;EAC1B,YAAY,uDAAuD;CACrE;AACF;;AAGA,eAAe,KAAK,WAA6C;CAC/D,IAAI;EACF,MAAM,UAAU,SAAS;EACzB,QAAQ,KAAK,CAAC;CAChB,SAAS,OAAO;EACd,YAAY,oBAAqB,MAAgB,SAAS;EAC1D,QAAQ,KAAK,CAAC;CAChB;AACF;;AAGA,SAAS,iBAAuB;CAC9B,QAAQ,IAAI;CACZ,QAAQ,IAAI,KAAK,OAAO,KAAK,WAAW,GAAG;CAE3C,KAAK,MAAM,YAAY,mBAAmB,KAAK,GAC7C,QAAQ,IACN,QAAQ,OAAO,KAAK,OAAO,KAAK,SAAS,GAAG,CAAC,EAAE,IAAI,OAAO,IAAI,SAAS,WAAW,GACpF;CAGF,QAAQ,IAAI,QAAQ,OAAO,KAAK,OAAO,KAAK,QAAQ,CAAC,EAAE,IAAI,OAAO,IAAI,MAAM,GAAG;CAC/E,QAAQ,IAAI;AACd"}
|