@warlock.js/core 4.1.15 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/LICENSE +21 -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/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 +6 -6
- 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 +3 -3
- 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 +39 -0
- package/esm/connectors/access-connector.d.mts.map +1 -0
- package/esm/connectors/access-connector.mjs +54 -0
- package/esm/connectors/access-connector.mjs.map +1 -0
- 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 +3 -3
- 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 +5 -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 +3 -3
- 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 +4 -4
- 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 +8 -6
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/index.d.mts +2 -0
- package/esm/connectors/index.mjs +2 -0
- 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 +3 -3
- 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 +3 -3
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.d.mts +38 -0
- package/esm/connectors/notifications-connector.d.mts.map +1 -0
- package/esm/connectors/notifications-connector.mjs +51 -0
- package/esm/connectors/notifications-connector.mjs.map +1 -0
- 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 +4 -4
- 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 +5 -3
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/connectors/types.mjs +3 -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/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/seeds/seeder.d.mts +1 -1
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.mjs +1 -1
- package/esm/database/seeds/seeder.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/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/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 +2 -13
- package/esm/dev-server/dev-logger.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/loader/build-transpile-init.mjs +1 -1
- package/esm/dev-server/loader/build-transpile-init.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/transpile-cache.mjs +2 -164
- package/esm/dev-server/loader/transpile-cache.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/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/tsconfig-manager.mjs +1 -1
- package/esm/dev-server/tsconfig-manager.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/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/http/config.d.mts +1 -1
- package/esm/http/config.d.mts.map +1 -1
- package/esm/http/config.mjs +3 -3
- 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 +3 -3
- 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/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 +6 -6
- 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 +3 -3
- 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 +5 -5
- 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 +10 -10
- 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 +4 -4
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +6 -6
- 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 +3 -3
- 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/index.d.mts +4 -1
- package/esm/index.mjs +5 -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/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/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/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 +4 -2
- 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/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 +2 -11
- 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/paths.d.mts +1 -1
- package/esm/utils/paths.d.mts.map +1 -1
- package/esm/utils/paths.mjs +3 -3
- 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/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 +3 -3
- 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/index.mjs +3 -0
- package/esm/vite/lower-stage3-decorators.d.mts +53 -0
- package/esm/vite/lower-stage3-decorators.d.mts.map +1 -0
- package/esm/vite/lower-stage3-decorators.mjs +63 -0
- package/esm/vite/lower-stage3-decorators.mjs.map +1 -0
- package/esm/warlock-config/default-configurations.mjs +1 -1
- package/esm/warlock-config/default-configurations.mjs.map +1 -1
- package/esm/warlock-config/define-config.d.mts +1 -1
- package/esm/warlock-config/define-config.d.mts.map +1 -1
- package/esm/warlock-config/define-config.mjs +1 -1
- package/esm/warlock-config/define-config.mjs.map +1 -1
- package/esm/warlock-config/types.d.mts +1 -1
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
- package/llms-full.txt +64 -4
- package/llms.txt +1 -0
- package/package.json +9 -33
- package/skills/lower-stage3-decorators/SKILL.md +54 -0
- package/skills/test-http/SKILL.md +3 -2
- package/skills/test-service/SKILL.md +3 -2
- package/esm/_virtual/_rolldown/runtime.mjs +0 -7
- package/esm/cli/cli-commands.manager.mjs +0 -290
- package/esm/cli/cli-commands.manager.mjs.map +0 -1
- package/esm/cli/cli-commands.utils.mjs +0 -217
- package/esm/cli/cli-commands.utils.mjs.map +0 -1
- package/esm/cli/commands/add.command.mjs +0 -27
- package/esm/cli/commands/add.command.mjs.map +0 -1
- package/esm/cli/commands/build.command.mjs +0 -14
- package/esm/cli/commands/build.command.mjs.map +0 -1
- package/esm/cli/commands/create-database.command.mjs +0 -24
- package/esm/cli/commands/create-database.command.mjs.map +0 -1
- package/esm/cli/commands/dev-server.command.mjs +0 -48
- package/esm/cli/commands/dev-server.command.mjs.map +0 -1
- package/esm/cli/commands/drop-tables.command.mjs +0 -23
- package/esm/cli/commands/drop-tables.command.mjs.map +0 -1
- package/esm/cli/commands/generate/generate.command.mjs +0 -201
- package/esm/cli/commands/generate/generate.command.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs +0 -49
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs +0 -48
- package/esm/cli/commands/generate/generators/controller.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs +0 -81
- package/esm/cli/commands/generate/generators/migration.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs +0 -60
- package/esm/cli/commands/generate/generators/model.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs +0 -113
- package/esm/cli/commands/generate/generators/module.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs +0 -42
- package/esm/cli/commands/generate/generators/repository.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs +0 -42
- package/esm/cli/commands/generate/generators/resource.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs +0 -42
- package/esm/cli/commands/generate/generators/service.generator.mjs.map +0 -1
- package/esm/cli/commands/generate/templates/stubs.mjs +0 -514
- package/esm/cli/commands/generate/templates/stubs.mjs.map +0 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs +0 -69
- package/esm/cli/commands/generate/utils/name-parser.mjs.map +0 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs +0 -56
- package/esm/cli/commands/generate/utils/path-resolver.mjs.map +0 -1
- package/esm/cli/commands/generate/utils/prompt.mjs +0 -28
- package/esm/cli/commands/generate/utils/prompt.mjs.map +0 -1
- package/esm/cli/commands/generate/utils/writer.mjs +0 -60
- package/esm/cli/commands/generate/utils/writer.mjs.map +0 -1
- package/esm/cli/commands/migrate.command.mjs +0 -60
- package/esm/cli/commands/migrate.command.mjs.map +0 -1
- package/esm/cli/commands/seed.command.mjs +0 -41
- package/esm/cli/commands/seed.command.mjs.map +0 -1
- package/esm/cli/commands/start-production.command.mjs +0 -50
- package/esm/cli/commands/start-production.command.mjs.map +0 -1
- package/esm/cli/commands/storage-put.action.mjs +0 -75
- package/esm/cli/commands/storage-put.action.mjs.map +0 -1
- package/esm/cli/commands/storage-put.command.mjs +0 -46
- package/esm/cli/commands/storage-put.command.mjs.map +0 -1
- package/esm/cli/commands/typings-generator.command.mjs +0 -38
- package/esm/cli/commands/typings-generator.command.mjs.map +0 -1
- package/esm/cli/commands-loader.mjs +0 -50
- package/esm/cli/commands-loader.mjs.map +0 -1
- package/esm/cli/framework-cli-commands.mjs +0 -37
- package/esm/cli/framework-cli-commands.mjs.map +0 -1
- package/esm/cli/parse-cli-args.mjs +0 -62
- package/esm/cli/parse-cli-args.mjs.map +0 -1
- package/esm/cli/start.d.mts +0 -1
- package/esm/cli/start.mjs +0 -8
- package/esm/cli/start.mjs.map +0 -1
- package/esm/cli/string-similarity.mjs +0 -56
- package/esm/cli/string-similarity.mjs.map +0 -1
- package/esm/database/create-database-action.mjs +0 -32
- package/esm/database/create-database-action.mjs.map +0 -1
- package/esm/database/drop-tables-action.mjs +0 -35
- package/esm/database/drop-tables-action.mjs.map +0 -1
- package/esm/database/migrate-action.mjs +0 -99
- package/esm/database/migrate-action.mjs.map +0 -1
- package/esm/database/seed-command-action.mjs +0 -74
- package/esm/database/seed-command-action.mjs.map +0 -1
- package/esm/database/seeds/seeders.manager.mjs +0 -129
- package/esm/database/seeds/seeders.manager.mjs.map +0 -1
- package/esm/database/seeds/seeds-table-migration.mjs +0 -31
- package/esm/database/seeds/seeds-table-migration.mjs.map +0 -1
- package/esm/database/seeds/utils.mjs +0 -6
- package/esm/database/seeds/utils.mjs.map +0 -1
- package/esm/dev-server/development-server.mjs +0 -115
- package/esm/dev-server/development-server.mjs.map +0 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +0 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.d.mts +0 -1
- package/esm/dev-server/layer-executor.mjs +0 -114
- package/esm/dev-server/layer-executor.mjs.map +0 -1
- package/esm/dev-server/loader/hook-thread.d.mts +0 -48
- package/esm/dev-server/loader/hook-thread.d.mts.map +0 -1
- package/esm/dev-server/loader/hook-thread.mjs +0 -47
- package/esm/dev-server/loader/hook-thread.mjs.map +0 -1
- package/esm/dev-server/loader/load-hook.d.mts +0 -58
- package/esm/dev-server/loader/load-hook.d.mts.map +0 -1
- package/esm/dev-server/loader/load-hook.mjs +0 -86
- package/esm/dev-server/loader/load-hook.mjs.map +0 -1
- package/esm/dev-server/loader/own-resolver.mjs +0 -69
- package/esm/dev-server/loader/own-resolver.mjs.map +0 -1
- package/esm/dev-server/loader/resolve-capture.mjs +0 -43
- package/esm/dev-server/loader/resolve-capture.mjs.map +0 -1
- package/esm/dev-server/loader/resolve-hook.d.mts +0 -41
- package/esm/dev-server/loader/resolve-hook.d.mts.map +0 -1
- package/esm/dev-server/loader/resolve-hook.mjs +0 -87
- package/esm/dev-server/loader/resolve-hook.mjs.map +0 -1
- package/esm/dev-server/loader/source-slug.mjs +0 -22
- package/esm/dev-server/loader/source-slug.mjs.map +0 -1
- package/esm/dev-server/loader/version-registry.mjs +0 -45
- package/esm/dev-server/loader/version-registry.mjs.map +0 -1
- package/esm/dev-server/start-development-server.mjs +0 -63
- package/esm/dev-server/start-development-server.mjs.map +0 -1
- package/esm/dev-server/type-generator.mjs +0 -453
- package/esm/dev-server/type-generator.mjs.map +0 -1
- package/esm/generations/add-command.action.mjs +0 -376
- package/esm/generations/add-command.action.mjs.map +0 -1
- package/esm/generations/stubs.mjs +0 -103
- package/esm/generations/stubs.mjs.map +0 -1
- package/esm/manifest/manifest-manager.mjs +0 -79
- package/esm/manifest/manifest-manager.mjs.map +0 -1
- package/esm/production/build-app-production.mjs +0 -14
- package/esm/production/build-app-production.mjs.map +0 -1
- package/esm/production/esbuild-plugins.mjs +0 -37
- package/esm/production/esbuild-plugins.mjs.map +0 -1
- package/esm/production/production-builder.mjs +0 -264
- package/esm/production/production-builder.mjs.map +0 -1
- package/esm/production/resolve-build-config.mjs +0 -28
- package/esm/production/resolve-build-config.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FileManager } from "../file-manager.mjs";
|
|
2
2
|
import { FileHealthCheckerContract } from "./file-health-checker.contract.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../@warlock.js/core/src/dev-server/health-checker/files-healthcare.manager.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Files Healthcare Manager
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-healthcare.manager.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"files-healthcare.manager.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/core/src/dev-server/health-checker/files-healthcare.manager.ts"],"mappings":";;;;;;AA0EA;;;;;;;;;;;;;;;;;;;;cAAa,sBAAA;EAAA,iBAoCyB,KAAA;EAtB5B;;;EAAA,QAVA,cAAA;EAgC+C;;;EAAA,QA3B/C,OAAA;EAiC8B;;;EAAA,QA5B9B,kBAAA;EAqCiB;;;EAAA,QAhCjB,YAAA;EAuEM;;;;cAtDsB,KAAA,EAAO,GAAA,SAAY,WAAA;EA4G/B;;;;EAtGjB,iBAAA,IAAqB,QAAA,EAAU,yBAAA,KAA8B,sBAAA;EAwQvD;;;;EA/PN,iBAAA,CAAkB,QAAA,EAAU,yBAAA,KAA8B,sBAAA;EAqRvC;;;;;;EA1Qb,UAAA,IAAc,OAAA;EA6YK;;;EAAA,QAjXlB,WAAA;;;;EAuCD,gBAAA,IAAoB,OAAA;;;;;;;;EAepB,UAAA,CAAW,KAAA,EAAO,WAAA,KAAgB,OAAA;;;;UAwBjC,WAAA;;;;UAkEA,SAAA;;;;UAmDN,WAAA;;;;EAqBK,aAAA,CAAc,KAAA,EAAO,WAAA,KAAgB,OAAA;;;;;EAsB3C,WAAA,CAAY,KAAA,EAAO,WAAA;;;;UAsBlB,kBAAA;;;;UAuCM,YAAA;;;;EAsED,QAAA,IAAY,OAAA;AAAA"}
|
|
@@ -2,7 +2,7 @@ import { devLogInfo } from "../dev-logger.mjs";
|
|
|
2
2
|
import { createWorker } from "../create-worker.mjs";
|
|
3
3
|
import { colors } from "@mongez/copper";
|
|
4
4
|
|
|
5
|
-
//#region
|
|
5
|
+
//#region ../@warlock.js/core/src/dev-server/health-checker/files-healthcare.manager.ts
|
|
6
6
|
/**
|
|
7
7
|
* Files Healthcare Manager
|
|
8
8
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-healthcare.manager.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/dev-server/health-checker/files-healthcare.manager.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { Worker } from \"worker_threads\";\nimport { createWorker } from \"../create-worker\";\nimport { devLogInfo } from \"../dev-logger\";\nimport type { FileManager } from \"../file-manager\";\nimport type {\n FileHealthCheckerContract,\n HealthCheckerFilesStats,\n} from \"./file-health-checker.contract\";\n\n/**\n * Serialized file data to send to workers\n */\ntype SerializedFile = {\n path: string;\n content: string;\n relativePath: string;\n};\n\n/**\n * Diagnostic message from worker\n */\ntype DiagnosticMessage = {\n type: \"error\" | \"warning\";\n message: string;\n lineNumber: number;\n columnNumber: number;\n length: number;\n filePath: string;\n relativePath: string;\n ruleId?: string;\n};\n\n/**\n * File check result from worker\n */\ntype FileCheckResult = {\n path: string;\n relativePath: string;\n healthy: boolean;\n errors: DiagnosticMessage[];\n warnings: DiagnosticMessage[];\n};\n\n/**\n * Worker response type\n */\ntype WorkerResponse =\n | { type: \"initialized\"; success: boolean; hasConfig?: boolean; error?: string }\n | { type: \"results\"; results: FileCheckResult[] }\n | { type: \"error\"; message: string };\n\n/**\n * Files Healthcare Manager\n *\n * Manages health checkers for file validation during development.\n * Supports both main-thread and worker-based checkers.\n *\n * Checkers with `workerPath` run in dedicated worker threads for performance.\n * Checkers without `workerPath` run in the main thread.\n *\n * @example\n * ```typescript\n * const manager = new FilesHealthcareManager(files);\n *\n * manager.setHealthCheckers([\n * new TypescriptHealthChecker(), // Has workerPath → runs in worker\n * new CustomChecker(), // No workerPath → runs in main thread\n * ]);\n *\n * await manager.initialize();\n * await manager.validateAllFiles();\n * ```\n */\nexport class FilesHealthcareManager {\n /**\n * Registered health checkers\n */\n private healthCheckers: FileHealthCheckerContract[] = [];\n\n /**\n * Active worker instances (checkerName → Worker)\n */\n private workers = new Map<string, Worker>();\n\n /**\n * Worker initialization promises (for ensuring workers are ready)\n */\n private workerInitPromises = new Map<string, Promise<boolean>>();\n\n /**\n * Aggregated stats for each checker\n */\n private checkerStats = new Map<\n string,\n {\n totalFiles: number;\n healthyFiles: number;\n defectiveFiles: number;\n totalErrors: number;\n totalWarnings: number;\n filesWithErrors: number;\n filesWithWarnings: number;\n }\n >();\n\n /**\n * Constructor\n * @param files - Map of tracked files\n */\n public constructor(private readonly files: Map<string, FileManager>) {}\n\n /**\n * Add health checkers to the manager\n * @param checkers - Checkers to add\n */\n public addHealthCheckers(...checkers: FileHealthCheckerContract[]): FilesHealthcareManager {\n this.healthCheckers.push(...checkers);\n return this;\n }\n\n /**\n * Set (replace) all health checkers\n * @param checkers - New set of checkers\n */\n public setHealthCheckers(checkers: FileHealthCheckerContract[]): FilesHealthcareManager {\n this.healthCheckers = checkers;\n return this;\n }\n\n /**\n * Initialize all health checkers\n *\n * For checkers with `workerPath`, spawns dedicated worker threads.\n * For other checkers, calls their `initialize()` method directly.\n */\n public async initialize(): Promise<void> {\n const initPromises = this.healthCheckers.map(async (checker) => {\n // Initialize stats for this checker\n this.checkerStats.set(checker.name, {\n totalFiles: 0,\n healthyFiles: 0,\n defectiveFiles: 0,\n totalErrors: 0,\n totalWarnings: 0,\n filesWithErrors: 0,\n filesWithWarnings: 0,\n });\n\n if (checker.workerPath) {\n // Spawn dedicated worker for this checker\n await this.spawnWorker(checker);\n } else {\n // Initialize checker on main thread\n checker.initialize();\n }\n });\n\n await Promise.all(initPromises);\n }\n\n /**\n * Spawn a worker for a checker\n */\n private async spawnWorker(checker: FileHealthCheckerContract): Promise<void> {\n if (!checker.workerPath) return;\n\n const worker = createWorker(checker.workerPath, import.meta.url, {\n workerData: { cwd: process.cwd() },\n });\n\n this.workers.set(checker.name, worker);\n\n // Create init promise\n const initPromise = new Promise<boolean>((resolve) => {\n const handler = (response: WorkerResponse) => {\n if (response.type === \"initialized\") {\n worker.off(\"message\", handler);\n resolve(response.success);\n }\n };\n\n worker.on(\"message\", handler);\n\n // Handle worker errors\n worker.on(\"error\", (error) => {\n console.error(`Health Checker Worker Error (${checker.name}):`, error);\n resolve(false);\n });\n\n // Send init message\n worker.postMessage({ type: \"init\", config: { cwd: process.cwd() } });\n });\n\n this.workerInitPromises.set(checker.name, initPromise);\n\n // Wait for initialization\n await initPromise;\n }\n\n /**\n * Validate all tracked files\n */\n public async validateAllFiles(): Promise<void> {\n const allFiles = Array.from(this.files.values());\n await this.checkFiles(allFiles);\n\n // Display stats\n await this.displayStats();\n }\n\n /**\n * Check the given files with all registered checkers\n *\n * All checkers run in parallel for performance.\n * Worker-based checkers communicate via postMessage.\n * Main-thread checkers are called directly.\n */\n public async checkFiles(files: FileManager[]): Promise<void> {\n const checkPromises = this.healthCheckers.map(async (checker) => {\n if (checker.workerPath) {\n return this.runInWorker(checker.name, files);\n } else {\n return this.runInline(checker, files);\n }\n });\n\n const results = await Promise.all(checkPromises);\n\n // Display any errors/warnings\n for (const checkerResults of results) {\n for (const result of checkerResults) {\n if (!result.healthy) {\n this.displayFileResults(result);\n }\n }\n }\n }\n\n /**\n * Run checker in worker thread\n */\n private async runInWorker(checkerName: string, files: FileManager[]): Promise<FileCheckResult[]> {\n const worker = this.workers.get(checkerName);\n\n if (!worker) {\n return files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n\n // Wait for worker to be initialized\n const initPromise = this.workerInitPromises.get(checkerName);\n if (initPromise) {\n const success = await initPromise;\n if (!success) {\n return files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n }\n\n // Serialize files for worker\n const serializedFiles: SerializedFile[] = files.map((f) => ({\n path: f.absolutePath,\n content: f.source,\n relativePath: f.relativePath,\n }));\n\n return new Promise((resolve) => {\n const handler = (response: WorkerResponse) => {\n if (response.type === \"results\") {\n worker.off(\"message\", handler);\n\n // Update stats\n this.updateStats(checkerName, response.results);\n\n resolve(response.results);\n } else if (response.type === \"error\") {\n worker.off(\"message\", handler);\n resolve(\n files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n })),\n );\n }\n };\n\n worker.on(\"message\", handler);\n worker.postMessage({ type: \"check\", files: serializedFiles });\n });\n }\n\n /**\n * Run checker inline (main thread)\n */\n private async runInline(\n checker: FileHealthCheckerContract,\n files: FileManager[],\n ): Promise<FileCheckResult[]> {\n const results: FileCheckResult[] = [];\n\n for (const file of files) {\n const healthResult = await checker.check(file);\n const stats = healthResult.getStats();\n\n results.push({\n path: file.absolutePath,\n relativePath: file.relativePath,\n healthy: stats.state === \"healthy\",\n errors: healthResult.messages\n .filter((m) => m.type === \"error\")\n .map((m) => ({\n type: \"error\" as const,\n message: m.message,\n lineNumber: m.lineNumber,\n columnNumber: m.columnNumber,\n length: m.length || 1,\n filePath: file.absolutePath,\n relativePath: file.relativePath,\n ruleId: m.ruleId,\n })),\n warnings: healthResult.messages\n .filter((m) => m.type === \"warning\")\n .map((m) => ({\n type: \"warning\" as const,\n message: m.message,\n lineNumber: m.lineNumber,\n columnNumber: m.columnNumber,\n length: m.length || 1,\n filePath: file.absolutePath,\n relativePath: file.relativePath,\n ruleId: m.ruleId,\n })),\n });\n }\n\n // Update stats\n const checkerResults = results;\n this.updateStats(checker.name, checkerResults);\n\n return results;\n }\n\n /**\n * Update aggregated stats for a checker\n */\n private updateStats(checkerName: string, results: FileCheckResult[]): void {\n const stats = this.checkerStats.get(checkerName);\n if (!stats) return;\n\n for (const result of results) {\n stats.totalFiles++;\n if (result.healthy) {\n stats.healthyFiles++;\n } else {\n stats.defectiveFiles++;\n }\n stats.totalErrors += result.errors.length;\n stats.totalWarnings += result.warnings.length;\n if (result.errors.length > 0) stats.filesWithErrors++;\n if (result.warnings.length > 0) stats.filesWithWarnings++;\n }\n }\n\n /**\n * Detect when files are changed\n */\n public async onFileChanges(files: FileManager[]): Promise<void> {\n // Notify workers of file changes\n const serializedFiles: SerializedFile[] = files.map((f) => ({\n path: f.absolutePath,\n content: f.source,\n relativePath: f.relativePath,\n }));\n\n for (const [, worker] of this.workers) {\n worker.postMessage({ type: \"fileChanges\", files: serializedFiles });\n }\n\n // Notify inline checkers\n await Promise.all(\n this.healthCheckers.filter((c) => !c.workerPath).map((c) => c.onFileChanges(files)),\n );\n }\n\n /**\n * Remove files from tracking\n * Notifies both inline checkers and worker-based checkers about removed files\n */\n public removeFiles(files: FileManager[]): void {\n // Notify inline checkers\n this.healthCheckers\n .filter((c) => !c.workerPath)\n .forEach((checker) => files.forEach((file) => checker.removeFile(file)));\n\n // Notify workers about deleted files\n if (files.length > 0) {\n const deletedPaths = files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n }));\n\n for (const [, worker] of this.workers) {\n worker.postMessage({ type: \"filesDeleted\", files: deletedPaths });\n }\n }\n }\n\n /**\n * Display file results (errors/warnings)\n */\n private displayFileResults(result: FileCheckResult): void {\n const fileName = result.relativePath.replace(/\\\\/g, \"/\");\n\n // Display errors\n for (const error of result.errors) {\n const icon = colors.redBright(\"✖\");\n const level = colors.redBright(colors.bold(\"ERROR\"));\n console.log(\n `\\n${icon} ${level} ${colors.dim(\"in\")} ${colors.cyanBright(fileName)}${colors.dim(`(${error.lineNumber},${error.columnNumber})`)}`,\n );\n if (error.ruleId) {\n console.log(\n ` ${colors.magentaBright(error.ruleId)} ${colors.dim(\"→\")} ${colors.red(error.message)}`,\n );\n } else {\n console.log(` ${colors.dim(\"→\")} ${colors.red(error.message)}`);\n }\n }\n\n // Display warnings\n for (const warning of result.warnings) {\n const icon = colors.yellowBright(\"⚠\");\n const level = colors.yellowBright(colors.bold(\"WARNING\"));\n console.log(\n `\\n${icon} ${level} ${colors.dim(\"in\")} ${colors.cyanBright(fileName)}${colors.dim(`(${warning.lineNumber},${warning.columnNumber})`)}`,\n );\n if (warning.ruleId) {\n console.log(\n ` ${colors.magentaBright(warning.ruleId)} ${colors.dim(\"→\")} ${colors.yellow(warning.message)}`,\n );\n } else {\n console.log(` ${colors.dim(\"→\")} ${colors.yellow(warning.message)}`);\n }\n }\n }\n\n /**\n * Display stats for all health checkers\n */\n private async displayStats(): Promise<void> {\n const allStats: HealthCheckerFilesStats[] = [];\n\n for (const checker of this.healthCheckers) {\n const stats = this.checkerStats.get(checker.name);\n if (stats) {\n allStats.push({\n name: checker.name,\n files: {\n healthy: stats.healthyFiles,\n defective: stats.defectiveFiles,\n },\n warnings: {\n total: stats.totalWarnings,\n totalFiles: stats.filesWithWarnings,\n },\n errors: {\n total: stats.totalErrors,\n totalFiles: stats.filesWithErrors,\n },\n });\n }\n }\n\n console.log(\"\\n\");\n console.log(colors.bold(colors.cyan(\"━\".repeat(80))));\n devLogInfo(colors.bold(\" 📊 Health Checker Statistics\"));\n console.log(colors.bold(colors.cyan(\"━\".repeat(80))));\n console.log(\"\");\n\n allStats.forEach((stats: HealthCheckerFilesStats, index: number) => {\n const totalFiles = stats.files.healthy + stats.files.defective;\n const hasIssues = stats.files.defective > 0;\n\n // Checker name with icon\n const statusIcon = hasIssues ? \"⚠️\" : \"✅\";\n console.log(colors.bold(` ${statusIcon} ${stats.name}`));\n console.log(colors.dim(\" \" + \"─\".repeat(76)));\n\n // Files summary\n const filesLine = ` Files: ${colors.white(totalFiles.toString())} total │ ${colors.green(\"✓ \" + stats.files.healthy)} healthy │ ${hasIssues ? colors.red(\"✗ \" + stats.files.defective) : colors.dim(\"✗ 0\")} defective`;\n console.log(filesLine);\n\n // Issues summary\n const warningsText =\n stats.warnings.total > 0\n ? colors.yellow(`⚠ ${stats.warnings.total} warnings`)\n : colors.dim(\"⚠ 0 warnings\");\n\n const errorsText =\n stats.errors.total > 0\n ? colors.red(`✗ ${stats.errors.total} errors`)\n : colors.dim(\"✗ 0 errors\");\n\n console.log(` Issues: ${warningsText} │ ${errorsText}`);\n\n // Add spacing between checkers\n if (index < allStats.length - 1) {\n console.log(\"\");\n }\n });\n\n console.log(\"\");\n console.log(colors.bold(colors.cyan(\"━\".repeat(80))));\n console.log(\"\");\n }\n\n /**\n * Shutdown all workers\n */\n public async shutdown(): Promise<void> {\n for (const [name, worker] of this.workers) {\n try {\n worker.postMessage({ type: \"shutdown\" });\n await worker.terminate();\n } catch {\n // Worker may already be terminated\n }\n }\n\n this.workers.clear();\n this.workerInitPromises.clear();\n this.checkerStats.clear();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"files-healthcare.manager.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/dev-server/health-checker/files-healthcare.manager.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { Worker } from \"worker_threads\";\nimport { createWorker } from \"../create-worker\";\nimport { devLogInfo } from \"../dev-logger\";\nimport type { FileManager } from \"../file-manager\";\nimport type {\n FileHealthCheckerContract,\n HealthCheckerFilesStats,\n} from \"./file-health-checker.contract\";\n\n/**\n * Serialized file data to send to workers\n */\ntype SerializedFile = {\n path: string;\n content: string;\n relativePath: string;\n};\n\n/**\n * Diagnostic message from worker\n */\ntype DiagnosticMessage = {\n type: \"error\" | \"warning\";\n message: string;\n lineNumber: number;\n columnNumber: number;\n length: number;\n filePath: string;\n relativePath: string;\n ruleId?: string;\n};\n\n/**\n * File check result from worker\n */\ntype FileCheckResult = {\n path: string;\n relativePath: string;\n healthy: boolean;\n errors: DiagnosticMessage[];\n warnings: DiagnosticMessage[];\n};\n\n/**\n * Worker response type\n */\ntype WorkerResponse =\n | { type: \"initialized\"; success: boolean; hasConfig?: boolean; error?: string }\n | { type: \"results\"; results: FileCheckResult[] }\n | { type: \"error\"; message: string };\n\n/**\n * Files Healthcare Manager\n *\n * Manages health checkers for file validation during development.\n * Supports both main-thread and worker-based checkers.\n *\n * Checkers with `workerPath` run in dedicated worker threads for performance.\n * Checkers without `workerPath` run in the main thread.\n *\n * @example\n * ```typescript\n * const manager = new FilesHealthcareManager(files);\n *\n * manager.setHealthCheckers([\n * new TypescriptHealthChecker(), // Has workerPath → runs in worker\n * new CustomChecker(), // No workerPath → runs in main thread\n * ]);\n *\n * await manager.initialize();\n * await manager.validateAllFiles();\n * ```\n */\nexport class FilesHealthcareManager {\n /**\n * Registered health checkers\n */\n private healthCheckers: FileHealthCheckerContract[] = [];\n\n /**\n * Active worker instances (checkerName → Worker)\n */\n private workers = new Map<string, Worker>();\n\n /**\n * Worker initialization promises (for ensuring workers are ready)\n */\n private workerInitPromises = new Map<string, Promise<boolean>>();\n\n /**\n * Aggregated stats for each checker\n */\n private checkerStats = new Map<\n string,\n {\n totalFiles: number;\n healthyFiles: number;\n defectiveFiles: number;\n totalErrors: number;\n totalWarnings: number;\n filesWithErrors: number;\n filesWithWarnings: number;\n }\n >();\n\n /**\n * Constructor\n * @param files - Map of tracked files\n */\n public constructor(private readonly files: Map<string, FileManager>) {}\n\n /**\n * Add health checkers to the manager\n * @param checkers - Checkers to add\n */\n public addHealthCheckers(...checkers: FileHealthCheckerContract[]): FilesHealthcareManager {\n this.healthCheckers.push(...checkers);\n return this;\n }\n\n /**\n * Set (replace) all health checkers\n * @param checkers - New set of checkers\n */\n public setHealthCheckers(checkers: FileHealthCheckerContract[]): FilesHealthcareManager {\n this.healthCheckers = checkers;\n return this;\n }\n\n /**\n * Initialize all health checkers\n *\n * For checkers with `workerPath`, spawns dedicated worker threads.\n * For other checkers, calls their `initialize()` method directly.\n */\n public async initialize(): Promise<void> {\n const initPromises = this.healthCheckers.map(async (checker) => {\n // Initialize stats for this checker\n this.checkerStats.set(checker.name, {\n totalFiles: 0,\n healthyFiles: 0,\n defectiveFiles: 0,\n totalErrors: 0,\n totalWarnings: 0,\n filesWithErrors: 0,\n filesWithWarnings: 0,\n });\n\n if (checker.workerPath) {\n // Spawn dedicated worker for this checker\n await this.spawnWorker(checker);\n } else {\n // Initialize checker on main thread\n checker.initialize();\n }\n });\n\n await Promise.all(initPromises);\n }\n\n /**\n * Spawn a worker for a checker\n */\n private async spawnWorker(checker: FileHealthCheckerContract): Promise<void> {\n if (!checker.workerPath) return;\n\n const worker = createWorker(checker.workerPath, import.meta.url, {\n workerData: { cwd: process.cwd() },\n });\n\n this.workers.set(checker.name, worker);\n\n // Create init promise\n const initPromise = new Promise<boolean>((resolve) => {\n const handler = (response: WorkerResponse) => {\n if (response.type === \"initialized\") {\n worker.off(\"message\", handler);\n resolve(response.success);\n }\n };\n\n worker.on(\"message\", handler);\n\n // Handle worker errors\n worker.on(\"error\", (error) => {\n console.error(`Health Checker Worker Error (${checker.name}):`, error);\n resolve(false);\n });\n\n // Send init message\n worker.postMessage({ type: \"init\", config: { cwd: process.cwd() } });\n });\n\n this.workerInitPromises.set(checker.name, initPromise);\n\n // Wait for initialization\n await initPromise;\n }\n\n /**\n * Validate all tracked files\n */\n public async validateAllFiles(): Promise<void> {\n const allFiles = Array.from(this.files.values());\n await this.checkFiles(allFiles);\n\n // Display stats\n await this.displayStats();\n }\n\n /**\n * Check the given files with all registered checkers\n *\n * All checkers run in parallel for performance.\n * Worker-based checkers communicate via postMessage.\n * Main-thread checkers are called directly.\n */\n public async checkFiles(files: FileManager[]): Promise<void> {\n const checkPromises = this.healthCheckers.map(async (checker) => {\n if (checker.workerPath) {\n return this.runInWorker(checker.name, files);\n } else {\n return this.runInline(checker, files);\n }\n });\n\n const results = await Promise.all(checkPromises);\n\n // Display any errors/warnings\n for (const checkerResults of results) {\n for (const result of checkerResults) {\n if (!result.healthy) {\n this.displayFileResults(result);\n }\n }\n }\n }\n\n /**\n * Run checker in worker thread\n */\n private async runInWorker(checkerName: string, files: FileManager[]): Promise<FileCheckResult[]> {\n const worker = this.workers.get(checkerName);\n\n if (!worker) {\n return files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n\n // Wait for worker to be initialized\n const initPromise = this.workerInitPromises.get(checkerName);\n if (initPromise) {\n const success = await initPromise;\n if (!success) {\n return files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n }\n\n // Serialize files for worker\n const serializedFiles: SerializedFile[] = files.map((f) => ({\n path: f.absolutePath,\n content: f.source,\n relativePath: f.relativePath,\n }));\n\n return new Promise((resolve) => {\n const handler = (response: WorkerResponse) => {\n if (response.type === \"results\") {\n worker.off(\"message\", handler);\n\n // Update stats\n this.updateStats(checkerName, response.results);\n\n resolve(response.results);\n } else if (response.type === \"error\") {\n worker.off(\"message\", handler);\n resolve(\n files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n })),\n );\n }\n };\n\n worker.on(\"message\", handler);\n worker.postMessage({ type: \"check\", files: serializedFiles });\n });\n }\n\n /**\n * Run checker inline (main thread)\n */\n private async runInline(\n checker: FileHealthCheckerContract,\n files: FileManager[],\n ): Promise<FileCheckResult[]> {\n const results: FileCheckResult[] = [];\n\n for (const file of files) {\n const healthResult = await checker.check(file);\n const stats = healthResult.getStats();\n\n results.push({\n path: file.absolutePath,\n relativePath: file.relativePath,\n healthy: stats.state === \"healthy\",\n errors: healthResult.messages\n .filter((m) => m.type === \"error\")\n .map((m) => ({\n type: \"error\" as const,\n message: m.message,\n lineNumber: m.lineNumber,\n columnNumber: m.columnNumber,\n length: m.length || 1,\n filePath: file.absolutePath,\n relativePath: file.relativePath,\n ruleId: m.ruleId,\n })),\n warnings: healthResult.messages\n .filter((m) => m.type === \"warning\")\n .map((m) => ({\n type: \"warning\" as const,\n message: m.message,\n lineNumber: m.lineNumber,\n columnNumber: m.columnNumber,\n length: m.length || 1,\n filePath: file.absolutePath,\n relativePath: file.relativePath,\n ruleId: m.ruleId,\n })),\n });\n }\n\n // Update stats\n const checkerResults = results;\n this.updateStats(checker.name, checkerResults);\n\n return results;\n }\n\n /**\n * Update aggregated stats for a checker\n */\n private updateStats(checkerName: string, results: FileCheckResult[]): void {\n const stats = this.checkerStats.get(checkerName);\n if (!stats) return;\n\n for (const result of results) {\n stats.totalFiles++;\n if (result.healthy) {\n stats.healthyFiles++;\n } else {\n stats.defectiveFiles++;\n }\n stats.totalErrors += result.errors.length;\n stats.totalWarnings += result.warnings.length;\n if (result.errors.length > 0) stats.filesWithErrors++;\n if (result.warnings.length > 0) stats.filesWithWarnings++;\n }\n }\n\n /**\n * Detect when files are changed\n */\n public async onFileChanges(files: FileManager[]): Promise<void> {\n // Notify workers of file changes\n const serializedFiles: SerializedFile[] = files.map((f) => ({\n path: f.absolutePath,\n content: f.source,\n relativePath: f.relativePath,\n }));\n\n for (const [, worker] of this.workers) {\n worker.postMessage({ type: \"fileChanges\", files: serializedFiles });\n }\n\n // Notify inline checkers\n await Promise.all(\n this.healthCheckers.filter((c) => !c.workerPath).map((c) => c.onFileChanges(files)),\n );\n }\n\n /**\n * Remove files from tracking\n * Notifies both inline checkers and worker-based checkers about removed files\n */\n public removeFiles(files: FileManager[]): void {\n // Notify inline checkers\n this.healthCheckers\n .filter((c) => !c.workerPath)\n .forEach((checker) => files.forEach((file) => checker.removeFile(file)));\n\n // Notify workers about deleted files\n if (files.length > 0) {\n const deletedPaths = files.map((f) => ({\n path: f.absolutePath,\n relativePath: f.relativePath,\n }));\n\n for (const [, worker] of this.workers) {\n worker.postMessage({ type: \"filesDeleted\", files: deletedPaths });\n }\n }\n }\n\n /**\n * Display file results (errors/warnings)\n */\n private displayFileResults(result: FileCheckResult): void {\n const fileName = result.relativePath.replace(/\\\\/g, \"/\");\n\n // Display errors\n for (const error of result.errors) {\n const icon = colors.redBright(\"✖\");\n const level = colors.redBright(colors.bold(\"ERROR\"));\n console.log(\n `\\n${icon} ${level} ${colors.dim(\"in\")} ${colors.cyanBright(fileName)}${colors.dim(`(${error.lineNumber},${error.columnNumber})`)}`,\n );\n if (error.ruleId) {\n console.log(\n ` ${colors.magentaBright(error.ruleId)} ${colors.dim(\"→\")} ${colors.red(error.message)}`,\n );\n } else {\n console.log(` ${colors.dim(\"→\")} ${colors.red(error.message)}`);\n }\n }\n\n // Display warnings\n for (const warning of result.warnings) {\n const icon = colors.yellowBright(\"⚠\");\n const level = colors.yellowBright(colors.bold(\"WARNING\"));\n console.log(\n `\\n${icon} ${level} ${colors.dim(\"in\")} ${colors.cyanBright(fileName)}${colors.dim(`(${warning.lineNumber},${warning.columnNumber})`)}`,\n );\n if (warning.ruleId) {\n console.log(\n ` ${colors.magentaBright(warning.ruleId)} ${colors.dim(\"→\")} ${colors.yellow(warning.message)}`,\n );\n } else {\n console.log(` ${colors.dim(\"→\")} ${colors.yellow(warning.message)}`);\n }\n }\n }\n\n /**\n * Display stats for all health checkers\n */\n private async displayStats(): Promise<void> {\n const allStats: HealthCheckerFilesStats[] = [];\n\n for (const checker of this.healthCheckers) {\n const stats = this.checkerStats.get(checker.name);\n if (stats) {\n allStats.push({\n name: checker.name,\n files: {\n healthy: stats.healthyFiles,\n defective: stats.defectiveFiles,\n },\n warnings: {\n total: stats.totalWarnings,\n totalFiles: stats.filesWithWarnings,\n },\n errors: {\n total: stats.totalErrors,\n totalFiles: stats.filesWithErrors,\n },\n });\n }\n }\n\n console.log(\"\\n\");\n console.log(colors.bold(colors.cyan(\"━\".repeat(80))));\n devLogInfo(colors.bold(\" 📊 Health Checker Statistics\"));\n console.log(colors.bold(colors.cyan(\"━\".repeat(80))));\n console.log(\"\");\n\n allStats.forEach((stats: HealthCheckerFilesStats, index: number) => {\n const totalFiles = stats.files.healthy + stats.files.defective;\n const hasIssues = stats.files.defective > 0;\n\n // Checker name with icon\n const statusIcon = hasIssues ? \"⚠️\" : \"✅\";\n console.log(colors.bold(` ${statusIcon} ${stats.name}`));\n console.log(colors.dim(\" \" + \"─\".repeat(76)));\n\n // Files summary\n const filesLine = ` Files: ${colors.white(totalFiles.toString())} total │ ${colors.green(\"✓ \" + stats.files.healthy)} healthy │ ${hasIssues ? colors.red(\"✗ \" + stats.files.defective) : colors.dim(\"✗ 0\")} defective`;\n console.log(filesLine);\n\n // Issues summary\n const warningsText =\n stats.warnings.total > 0\n ? colors.yellow(`⚠ ${stats.warnings.total} warnings`)\n : colors.dim(\"⚠ 0 warnings\");\n\n const errorsText =\n stats.errors.total > 0\n ? colors.red(`✗ ${stats.errors.total} errors`)\n : colors.dim(\"✗ 0 errors\");\n\n console.log(` Issues: ${warningsText} │ ${errorsText}`);\n\n // Add spacing between checkers\n if (index < allStats.length - 1) {\n console.log(\"\");\n }\n });\n\n console.log(\"\");\n console.log(colors.bold(colors.cyan(\"━\".repeat(80))));\n console.log(\"\");\n }\n\n /**\n * Shutdown all workers\n */\n public async shutdown(): Promise<void> {\n for (const [name, worker] of this.workers) {\n try {\n worker.postMessage({ type: \"shutdown\" });\n await worker.terminate();\n } catch {\n // Worker may already be terminated\n }\n }\n\n this.workers.clear();\n this.workerInitPromises.clear();\n this.checkerStats.clear();\n }\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import fs from "fs";
|
|
|
3
3
|
import { ESLint } from "eslint";
|
|
4
4
|
import { parentPort, workerData } from "worker_threads";
|
|
5
5
|
|
|
6
|
-
//#region
|
|
6
|
+
//#region ../@warlock.js/core/src/dev-server/health-checker/workers/eslint-health.worker.ts
|
|
7
7
|
/**
|
|
8
8
|
* ESLint Health Check Worker
|
|
9
9
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-health.worker.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/dev-server/health-checker/workers/eslint-health.worker.ts"],"sourcesContent":["/**\n * ESLint Health Check Worker\n *\n * This worker runs in a dedicated thread to perform ESLint linting\n * without blocking the main dev server thread. It maintains a persistent\n * ESLint instance for efficient linting.\n *\n * Communication:\n * - Receives: { type: 'init' | 'check' | 'shutdown', ... }\n * - Sends: { type: 'results' | 'initialized' | 'error', ... }\n */\nimport { ESLint } from \"eslint\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { parentPort, workerData } from \"worker_threads\";\n\n/**\n * Serialized file data received from main thread\n */\ntype SerializedFile = {\n /** Absolute file path */\n path: string;\n /** File content (source code) */\n content: string;\n /** Relative path for display */\n relativePath: string;\n};\n\n/**\n * Lint message sent back to main thread\n */\ntype LintMessage = {\n type: \"error\" | \"warning\";\n message: string;\n lineNumber: number;\n columnNumber: number;\n length: number;\n filePath: string;\n relativePath: string;\n ruleId?: string;\n};\n\n/**\n * Health check result for a single file\n */\ntype FileCheckResult = {\n path: string;\n relativePath: string;\n healthy: boolean;\n errors: LintMessage[];\n warnings: LintMessage[];\n};\n\n/**\n * Messages received from main thread\n */\n/**\n * Deleted file info\n */\ntype DeletedFile = {\n path: string;\n relativePath: string;\n};\n\n/**\n * Messages received from main thread\n */\ntype WorkerMessage =\n | { type: \"init\"; config: { cwd: string } }\n | { type: \"check\"; files: SerializedFile[] }\n | { type: \"filesDeleted\"; files: DeletedFile[] }\n | { type: \"shutdown\" };\n\n/**\n * Messages sent to main thread\n */\ntype WorkerResponse =\n | { type: \"initialized\"; success: boolean; hasConfig: boolean; error?: string }\n | { type: \"results\"; results: FileCheckResult[] }\n | { type: \"error\"; message: string };\n\n/**\n * ESLint Health Worker class\n * Maintains persistent ESLint instance for efficient linting\n */\nclass ESLintHealthWorker {\n /**\n * ESLint instance\n */\n private eslint: ESLint | null = null;\n\n /**\n * Whether the worker is initialized\n */\n private initialized = false;\n\n /**\n * Whether ESLint config was found\n */\n private hasConfig = false;\n\n /**\n * Current working directory\n */\n private cwd: string = process.cwd();\n\n /**\n * Initialize the worker with ESLint configuration\n */\n public initialize(config: { cwd: string }): { success: boolean; hasConfig: boolean } {\n try {\n this.cwd = config.cwd || process.cwd();\n\n // Check if ESLint flat config exists\n const flatConfigPath = path.join(this.cwd, \"eslint.config.js\");\n const flatConfigMjsPath = path.join(this.cwd, \"eslint.config.mjs\");\n const flatConfigCjsPath = path.join(this.cwd, \"eslint.config.cjs\");\n\n this.hasConfig =\n fs.existsSync(flatConfigPath) ||\n fs.existsSync(flatConfigMjsPath) ||\n fs.existsSync(flatConfigCjsPath);\n\n if (!this.hasConfig) {\n this.initialized = true;\n return { success: true, hasConfig: false };\n }\n\n // Create ESLint instance with flat config\n this.eslint = new ESLint({\n cwd: this.cwd,\n });\n\n this.initialized = true;\n return { success: true, hasConfig: true };\n } catch (error) {\n console.error(\"ESLint Worker: Failed to initialize:\", error);\n this.initialized = true;\n return { success: false, hasConfig: false };\n }\n }\n\n /**\n * Check files for ESLint errors\n */\n public async checkFiles(files: SerializedFile[]): Promise<FileCheckResult[]> {\n if (!this.eslint || !this.hasConfig) {\n // No ESLint config, return all files as healthy\n return files.map((file) => ({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n\n const results: FileCheckResult[] = [];\n\n for (const file of files) {\n // Only lint lintable files\n if (!this.isLintableFile(file.path)) {\n results.push({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n });\n continue;\n }\n\n try {\n const result = await this.checkSingleFile(file);\n results.push(result);\n } catch (error) {\n // On error, mark as healthy to avoid blocking\n results.push({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n });\n }\n }\n\n return results;\n }\n\n /**\n * Check a single file for lint issues\n */\n private async checkSingleFile(file: SerializedFile): Promise<FileCheckResult> {\n if (!this.eslint) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n // Use lintText to lint from memory (not disk)\n const lintResults = await this.eslint.lintText(file.content, {\n filePath: file.path,\n });\n\n if (lintResults.length === 0) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n const lintResult = lintResults[0];\n const errors: LintMessage[] = [];\n const warnings: LintMessage[] = [];\n\n for (const message of lintResult.messages) {\n const lintMessage: LintMessage = {\n type: message.severity === 2 ? \"error\" : \"warning\",\n message: message.message,\n lineNumber: message.line || 1,\n columnNumber: message.column || 1,\n length: message.endColumn && message.column ? message.endColumn - message.column : 1,\n filePath: file.path,\n relativePath: file.relativePath,\n ruleId: message.ruleId || undefined,\n };\n\n if (message.severity === 2) {\n errors.push(lintMessage);\n } else if (message.severity === 1) {\n warnings.push(lintMessage);\n }\n }\n\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: errors.length === 0 && warnings.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Check if file is a lintable file\n */\n private isLintableFile(filePath: string): boolean {\n const ext = filePath.toLowerCase();\n return (\n ext.endsWith(\".ts\") || ext.endsWith(\".tsx\") || ext.endsWith(\".js\") || ext.endsWith(\".jsx\")\n );\n }\n}\n\n// Create worker instance\nconst worker = new ESLintHealthWorker();\n\n// Handle messages from main thread\nparentPort?.on(\"message\", async (message: WorkerMessage) => {\n try {\n switch (message.type) {\n case \"init\": {\n const initResult = worker.initialize(message.config);\n const response: WorkerResponse = {\n type: \"initialized\",\n success: initResult.success,\n hasConfig: initResult.hasConfig,\n };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"check\": {\n const results = await worker.checkFiles(message.files);\n const response: WorkerResponse = { type: \"results\", results };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"filesDeleted\": {\n // ESLint doesn't maintain internal file cache (lints from memory)\n // No cleanup needed, just acknowledge\n break;\n }\n\n case \"shutdown\": {\n process.exit(0);\n }\n }\n } catch (error) {\n const response: WorkerResponse = {\n type: \"error\",\n message: error instanceof Error ? error.message : String(error),\n };\n parentPort?.postMessage(response);\n }\n});\n\n// Handle initialization from workerData if provided\nif (workerData?.autoInit) {\n worker.initialize({ cwd: workerData.cwd || process.cwd() });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eslint-health.worker.mjs","names":[],"sources":["../../../../../../../../../@warlock.js/core/src/dev-server/health-checker/workers/eslint-health.worker.ts"],"sourcesContent":["/**\n * ESLint Health Check Worker\n *\n * This worker runs in a dedicated thread to perform ESLint linting\n * without blocking the main dev server thread. It maintains a persistent\n * ESLint instance for efficient linting.\n *\n * Communication:\n * - Receives: { type: 'init' | 'check' | 'shutdown', ... }\n * - Sends: { type: 'results' | 'initialized' | 'error', ... }\n */\nimport { ESLint } from \"eslint\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { parentPort, workerData } from \"worker_threads\";\n\n/**\n * Serialized file data received from main thread\n */\ntype SerializedFile = {\n /** Absolute file path */\n path: string;\n /** File content (source code) */\n content: string;\n /** Relative path for display */\n relativePath: string;\n};\n\n/**\n * Lint message sent back to main thread\n */\ntype LintMessage = {\n type: \"error\" | \"warning\";\n message: string;\n lineNumber: number;\n columnNumber: number;\n length: number;\n filePath: string;\n relativePath: string;\n ruleId?: string;\n};\n\n/**\n * Health check result for a single file\n */\ntype FileCheckResult = {\n path: string;\n relativePath: string;\n healthy: boolean;\n errors: LintMessage[];\n warnings: LintMessage[];\n};\n\n/**\n * Messages received from main thread\n */\n/**\n * Deleted file info\n */\ntype DeletedFile = {\n path: string;\n relativePath: string;\n};\n\n/**\n * Messages received from main thread\n */\ntype WorkerMessage =\n | { type: \"init\"; config: { cwd: string } }\n | { type: \"check\"; files: SerializedFile[] }\n | { type: \"filesDeleted\"; files: DeletedFile[] }\n | { type: \"shutdown\" };\n\n/**\n * Messages sent to main thread\n */\ntype WorkerResponse =\n | { type: \"initialized\"; success: boolean; hasConfig: boolean; error?: string }\n | { type: \"results\"; results: FileCheckResult[] }\n | { type: \"error\"; message: string };\n\n/**\n * ESLint Health Worker class\n * Maintains persistent ESLint instance for efficient linting\n */\nclass ESLintHealthWorker {\n /**\n * ESLint instance\n */\n private eslint: ESLint | null = null;\n\n /**\n * Whether the worker is initialized\n */\n private initialized = false;\n\n /**\n * Whether ESLint config was found\n */\n private hasConfig = false;\n\n /**\n * Current working directory\n */\n private cwd: string = process.cwd();\n\n /**\n * Initialize the worker with ESLint configuration\n */\n public initialize(config: { cwd: string }): { success: boolean; hasConfig: boolean } {\n try {\n this.cwd = config.cwd || process.cwd();\n\n // Check if ESLint flat config exists\n const flatConfigPath = path.join(this.cwd, \"eslint.config.js\");\n const flatConfigMjsPath = path.join(this.cwd, \"eslint.config.mjs\");\n const flatConfigCjsPath = path.join(this.cwd, \"eslint.config.cjs\");\n\n this.hasConfig =\n fs.existsSync(flatConfigPath) ||\n fs.existsSync(flatConfigMjsPath) ||\n fs.existsSync(flatConfigCjsPath);\n\n if (!this.hasConfig) {\n this.initialized = true;\n return { success: true, hasConfig: false };\n }\n\n // Create ESLint instance with flat config\n this.eslint = new ESLint({\n cwd: this.cwd,\n });\n\n this.initialized = true;\n return { success: true, hasConfig: true };\n } catch (error) {\n console.error(\"ESLint Worker: Failed to initialize:\", error);\n this.initialized = true;\n return { success: false, hasConfig: false };\n }\n }\n\n /**\n * Check files for ESLint errors\n */\n public async checkFiles(files: SerializedFile[]): Promise<FileCheckResult[]> {\n if (!this.eslint || !this.hasConfig) {\n // No ESLint config, return all files as healthy\n return files.map((file) => ({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n\n const results: FileCheckResult[] = [];\n\n for (const file of files) {\n // Only lint lintable files\n if (!this.isLintableFile(file.path)) {\n results.push({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n });\n continue;\n }\n\n try {\n const result = await this.checkSingleFile(file);\n results.push(result);\n } catch (error) {\n // On error, mark as healthy to avoid blocking\n results.push({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n });\n }\n }\n\n return results;\n }\n\n /**\n * Check a single file for lint issues\n */\n private async checkSingleFile(file: SerializedFile): Promise<FileCheckResult> {\n if (!this.eslint) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n // Use lintText to lint from memory (not disk)\n const lintResults = await this.eslint.lintText(file.content, {\n filePath: file.path,\n });\n\n if (lintResults.length === 0) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n const lintResult = lintResults[0];\n const errors: LintMessage[] = [];\n const warnings: LintMessage[] = [];\n\n for (const message of lintResult.messages) {\n const lintMessage: LintMessage = {\n type: message.severity === 2 ? \"error\" : \"warning\",\n message: message.message,\n lineNumber: message.line || 1,\n columnNumber: message.column || 1,\n length: message.endColumn && message.column ? message.endColumn - message.column : 1,\n filePath: file.path,\n relativePath: file.relativePath,\n ruleId: message.ruleId || undefined,\n };\n\n if (message.severity === 2) {\n errors.push(lintMessage);\n } else if (message.severity === 1) {\n warnings.push(lintMessage);\n }\n }\n\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: errors.length === 0 && warnings.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Check if file is a lintable file\n */\n private isLintableFile(filePath: string): boolean {\n const ext = filePath.toLowerCase();\n return (\n ext.endsWith(\".ts\") || ext.endsWith(\".tsx\") || ext.endsWith(\".js\") || ext.endsWith(\".jsx\")\n );\n }\n}\n\n// Create worker instance\nconst worker = new ESLintHealthWorker();\n\n// Handle messages from main thread\nparentPort?.on(\"message\", async (message: WorkerMessage) => {\n try {\n switch (message.type) {\n case \"init\": {\n const initResult = worker.initialize(message.config);\n const response: WorkerResponse = {\n type: \"initialized\",\n success: initResult.success,\n hasConfig: initResult.hasConfig,\n };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"check\": {\n const results = await worker.checkFiles(message.files);\n const response: WorkerResponse = { type: \"results\", results };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"filesDeleted\": {\n // ESLint doesn't maintain internal file cache (lints from memory)\n // No cleanup needed, just acknowledge\n break;\n }\n\n case \"shutdown\": {\n process.exit(0);\n }\n }\n } catch (error) {\n const response: WorkerResponse = {\n type: \"error\",\n message: error instanceof Error ? error.message : String(error),\n };\n parentPort?.postMessage(response);\n }\n});\n\n// Handle initialization from workerData if provided\nif (workerData?.autoInit) {\n worker.initialize({ cwd: workerData.cwd || process.cwd() });\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { parentPort, workerData } from "worker_threads";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../@warlock.js/core/src/dev-server/health-checker/workers/ts-health.worker.ts
|
|
5
5
|
/**
|
|
6
6
|
* TypeScript Health Check Worker
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts-health.worker.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/dev-server/health-checker/workers/ts-health.worker.ts"],"sourcesContent":["/**\n * TypeScript Health Check Worker\n *\n * This worker runs in a dedicated thread to perform TypeScript type checking\n * without blocking the main dev server thread. It maintains a persistent\n * ts.Program instance for fast incremental type checking.\n *\n * Communication:\n * - Receives: { type: 'init' | 'check' | 'fileChanges' | 'shutdown', ... }\n * - Sends: { type: 'results' | 'initialized' | 'error', ... }\n */\nimport ts from \"typescript\";\nimport { parentPort, workerData } from \"worker_threads\";\n\n/**\n * Serialized file data received from main thread\n */\ntype SerializedFile = {\n /** Absolute file path */\n path: string;\n /** File content (source code) */\n content: string;\n /** Relative path for display */\n relativePath: string;\n};\n\n/**\n * Diagnostic message sent back to main thread\n */\ntype DiagnosticMessage = {\n type: \"error\" | \"warning\";\n message: string;\n lineNumber: number;\n columnNumber: number;\n length: number;\n filePath: string;\n relativePath: string;\n};\n\n/**\n * Health check result for a single file\n */\ntype FileCheckResult = {\n path: string;\n relativePath: string;\n healthy: boolean;\n errors: DiagnosticMessage[];\n warnings: DiagnosticMessage[];\n};\n\n/**\n * Messages received from main thread\n */\n/**\n * Deleted file info\n */\ntype DeletedFile = {\n path: string;\n relativePath: string;\n};\n\n/**\n * Messages received from main thread\n */\ntype WorkerMessage =\n | { type: \"init\"; config: { cwd: string; tsconfigPath?: string } }\n | { type: \"check\"; files: SerializedFile[] }\n | { type: \"fileChanges\"; files: SerializedFile[] }\n | { type: \"filesDeleted\"; files: DeletedFile[] }\n | { type: \"shutdown\" };\n\n/**\n * Messages sent to main thread\n */\ntype WorkerResponse =\n | { type: \"initialized\"; success: boolean; error?: string }\n | { type: \"results\"; results: FileCheckResult[] }\n | { type: \"error\"; message: string };\n\n/**\n * TypeScript Health Worker class\n * Maintains persistent ts.Program for incremental type checking\n */\nclass TypeScriptHealthWorker {\n /**\n * Cached TypeScript program instance\n */\n private program: ts.Program | null = null;\n\n /**\n * Parsed TypeScript configuration\n */\n private parsedConfig: ts.ParsedCommandLine | null = null;\n\n /**\n * In-memory file contents cache\n */\n private fileContents = new Map<string, string>();\n\n /**\n * Whether the worker is initialized\n */\n private initialized = false;\n\n /**\n * Current working directory\n */\n private cwd: string = process.cwd();\n\n /**\n * Initialize the worker with TypeScript configuration\n */\n public initialize(config: { cwd: string; tsconfigPath?: string }): boolean {\n try {\n this.cwd = config.cwd || process.cwd();\n\n // Try to load tsconfig.json\n const tsconfigPath = config.tsconfigPath || ts.findConfigFile(this.cwd, ts.sys.fileExists);\n\n if (!tsconfigPath) {\n this.initialized = true;\n return true; // No tsconfig, will skip type checking\n }\n\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configFile.error) {\n console.warn(\"TypeScript Worker: Error reading tsconfig:\", configFile.error);\n this.initialized = true;\n return true;\n }\n\n this.parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, this.cwd);\n\n if (this.parsedConfig.errors.length > 0) {\n console.warn(\"TypeScript Worker: tsconfig has errors:\", this.parsedConfig.errors);\n }\n\n this.initialized = true;\n return true;\n } catch (error) {\n console.error(\"TypeScript Worker: Failed to initialize:\", error);\n this.initialized = true;\n return false;\n }\n }\n\n /**\n * Check files for TypeScript errors\n */\n public checkFiles(files: SerializedFile[]): FileCheckResult[] {\n if (!this.parsedConfig) {\n // No config, return all files as healthy\n return files.map((file) => ({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n\n // Update in-memory file cache\n for (const file of files) {\n this.fileContents.set(file.path, file.content);\n }\n\n // Create or update the program (incremental)\n this.program = ts.createProgram(\n Array.from(this.fileContents.keys()),\n this.parsedConfig.options,\n this.createCompilerHost(),\n this.program || undefined, // Pass old program for incremental compilation\n );\n\n // Check each file\n const results: FileCheckResult[] = [];\n\n for (const file of files) {\n const result = this.checkSingleFile(file);\n results.push(result);\n }\n\n return results;\n }\n\n /**\n * Handle file changes (update program incrementally)\n */\n public handleFileChanges(files: SerializedFile[]): void {\n for (const file of files) {\n this.fileContents.set(file.path, file.content);\n }\n\n // Recreate program with new file contents\n if (this.parsedConfig && this.program) {\n this.program = ts.createProgram(\n Array.from(this.fileContents.keys()),\n this.parsedConfig.options,\n this.createCompilerHost(),\n this.program || undefined,\n );\n }\n }\n\n /**\n * Handle deleted files (remove from cache)\n */\n public handleFilesDeleted(files: DeletedFile[]): void {\n let hasChanges = false;\n\n for (const file of files) {\n if (this.fileContents.has(file.path)) {\n this.fileContents.delete(file.path);\n hasChanges = true;\n }\n }\n\n // Recreate program without deleted files\n if (hasChanges && this.parsedConfig) {\n this.program = ts.createProgram(\n Array.from(this.fileContents.keys()),\n this.parsedConfig.options,\n this.createCompilerHost(),\n this.program || undefined,\n );\n }\n }\n\n /**\n * Check a single file for diagnostics\n */\n private checkSingleFile(file: SerializedFile): FileCheckResult {\n if (!this.program) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n const sourceFile = this.program.getSourceFile(file.path);\n\n if (!sourceFile) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n const syntacticDiagnostics = this.program.getSyntacticDiagnostics(sourceFile);\n const semanticDiagnostics = this.program.getSemanticDiagnostics(sourceFile);\n const allDiagnostics = [...syntacticDiagnostics, ...semanticDiagnostics];\n\n const errors: DiagnosticMessage[] = [];\n const warnings: DiagnosticMessage[] = [];\n\n for (const diagnostic of allDiagnostics) {\n const message = this.formatDiagnostic(diagnostic, file);\n\n if (diagnostic.category === ts.DiagnosticCategory.Error) {\n errors.push(message);\n } else if (diagnostic.category === ts.DiagnosticCategory.Warning) {\n warnings.push(message);\n }\n }\n\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: errors.length === 0 && warnings.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Format a TypeScript diagnostic into our message format\n */\n private formatDiagnostic(diagnostic: ts.Diagnostic, file: SerializedFile): DiagnosticMessage {\n let lineNumber = 1;\n let columnNumber = 1;\n let length = 1;\n\n if (diagnostic.file && diagnostic.start !== undefined) {\n const pos = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);\n lineNumber = pos.line + 1;\n columnNumber = pos.character + 1;\n length = diagnostic.length || 1;\n }\n\n const messageText =\n typeof diagnostic.messageText === \"string\"\n ? diagnostic.messageText\n : diagnostic.messageText.messageText;\n\n return {\n type: diagnostic.category === ts.DiagnosticCategory.Error ? \"error\" : \"warning\",\n message: messageText,\n lineNumber,\n columnNumber,\n length,\n filePath: file.path,\n relativePath: file.relativePath,\n };\n }\n\n /**\n * Create a custom compiler host that reads from in-memory cache\n */\n private createCompilerHost(): ts.CompilerHost {\n const defaultHost = ts.createCompilerHost(this.parsedConfig?.options || {});\n\n return {\n ...defaultHost,\n readFile: (fileName: string) => {\n // Check in-memory cache first\n if (this.fileContents.has(fileName)) {\n return this.fileContents.get(fileName);\n }\n // Fall back to disk\n return defaultHost.readFile(fileName);\n },\n fileExists: (fileName: string) => {\n if (this.fileContents.has(fileName)) {\n return true;\n }\n return defaultHost.fileExists(fileName);\n },\n };\n }\n}\n\n// Create worker instance\nconst worker = new TypeScriptHealthWorker();\n\n// Handle messages from main thread\nparentPort?.on(\"message\", (message: WorkerMessage) => {\n try {\n switch (message.type) {\n case \"init\": {\n const success = worker.initialize(message.config);\n const response: WorkerResponse = { type: \"initialized\", success };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"check\": {\n const results = worker.checkFiles(message.files);\n const response: WorkerResponse = { type: \"results\", results };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"fileChanges\": {\n worker.handleFileChanges(message.files);\n break;\n }\n\n case \"filesDeleted\": {\n worker.handleFilesDeleted(message.files);\n break;\n }\n\n case \"shutdown\": {\n process.exit(0);\n }\n }\n } catch (error) {\n const response: WorkerResponse = {\n type: \"error\",\n message: error instanceof Error ? error.message : String(error),\n };\n parentPort?.postMessage(response);\n }\n});\n\n// Handle initialization from workerData if provided\nif (workerData?.autoInit) {\n worker.initialize({ cwd: workerData.cwd || process.cwd() });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ts-health.worker.mjs","names":[],"sources":["../../../../../../../../../@warlock.js/core/src/dev-server/health-checker/workers/ts-health.worker.ts"],"sourcesContent":["/**\n * TypeScript Health Check Worker\n *\n * This worker runs in a dedicated thread to perform TypeScript type checking\n * without blocking the main dev server thread. It maintains a persistent\n * ts.Program instance for fast incremental type checking.\n *\n * Communication:\n * - Receives: { type: 'init' | 'check' | 'fileChanges' | 'shutdown', ... }\n * - Sends: { type: 'results' | 'initialized' | 'error', ... }\n */\nimport ts from \"typescript\";\nimport { parentPort, workerData } from \"worker_threads\";\n\n/**\n * Serialized file data received from main thread\n */\ntype SerializedFile = {\n /** Absolute file path */\n path: string;\n /** File content (source code) */\n content: string;\n /** Relative path for display */\n relativePath: string;\n};\n\n/**\n * Diagnostic message sent back to main thread\n */\ntype DiagnosticMessage = {\n type: \"error\" | \"warning\";\n message: string;\n lineNumber: number;\n columnNumber: number;\n length: number;\n filePath: string;\n relativePath: string;\n};\n\n/**\n * Health check result for a single file\n */\ntype FileCheckResult = {\n path: string;\n relativePath: string;\n healthy: boolean;\n errors: DiagnosticMessage[];\n warnings: DiagnosticMessage[];\n};\n\n/**\n * Messages received from main thread\n */\n/**\n * Deleted file info\n */\ntype DeletedFile = {\n path: string;\n relativePath: string;\n};\n\n/**\n * Messages received from main thread\n */\ntype WorkerMessage =\n | { type: \"init\"; config: { cwd: string; tsconfigPath?: string } }\n | { type: \"check\"; files: SerializedFile[] }\n | { type: \"fileChanges\"; files: SerializedFile[] }\n | { type: \"filesDeleted\"; files: DeletedFile[] }\n | { type: \"shutdown\" };\n\n/**\n * Messages sent to main thread\n */\ntype WorkerResponse =\n | { type: \"initialized\"; success: boolean; error?: string }\n | { type: \"results\"; results: FileCheckResult[] }\n | { type: \"error\"; message: string };\n\n/**\n * TypeScript Health Worker class\n * Maintains persistent ts.Program for incremental type checking\n */\nclass TypeScriptHealthWorker {\n /**\n * Cached TypeScript program instance\n */\n private program: ts.Program | null = null;\n\n /**\n * Parsed TypeScript configuration\n */\n private parsedConfig: ts.ParsedCommandLine | null = null;\n\n /**\n * In-memory file contents cache\n */\n private fileContents = new Map<string, string>();\n\n /**\n * Whether the worker is initialized\n */\n private initialized = false;\n\n /**\n * Current working directory\n */\n private cwd: string = process.cwd();\n\n /**\n * Initialize the worker with TypeScript configuration\n */\n public initialize(config: { cwd: string; tsconfigPath?: string }): boolean {\n try {\n this.cwd = config.cwd || process.cwd();\n\n // Try to load tsconfig.json\n const tsconfigPath = config.tsconfigPath || ts.findConfigFile(this.cwd, ts.sys.fileExists);\n\n if (!tsconfigPath) {\n this.initialized = true;\n return true; // No tsconfig, will skip type checking\n }\n\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configFile.error) {\n console.warn(\"TypeScript Worker: Error reading tsconfig:\", configFile.error);\n this.initialized = true;\n return true;\n }\n\n this.parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, this.cwd);\n\n if (this.parsedConfig.errors.length > 0) {\n console.warn(\"TypeScript Worker: tsconfig has errors:\", this.parsedConfig.errors);\n }\n\n this.initialized = true;\n return true;\n } catch (error) {\n console.error(\"TypeScript Worker: Failed to initialize:\", error);\n this.initialized = true;\n return false;\n }\n }\n\n /**\n * Check files for TypeScript errors\n */\n public checkFiles(files: SerializedFile[]): FileCheckResult[] {\n if (!this.parsedConfig) {\n // No config, return all files as healthy\n return files.map((file) => ({\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n }));\n }\n\n // Update in-memory file cache\n for (const file of files) {\n this.fileContents.set(file.path, file.content);\n }\n\n // Create or update the program (incremental)\n this.program = ts.createProgram(\n Array.from(this.fileContents.keys()),\n this.parsedConfig.options,\n this.createCompilerHost(),\n this.program || undefined, // Pass old program for incremental compilation\n );\n\n // Check each file\n const results: FileCheckResult[] = [];\n\n for (const file of files) {\n const result = this.checkSingleFile(file);\n results.push(result);\n }\n\n return results;\n }\n\n /**\n * Handle file changes (update program incrementally)\n */\n public handleFileChanges(files: SerializedFile[]): void {\n for (const file of files) {\n this.fileContents.set(file.path, file.content);\n }\n\n // Recreate program with new file contents\n if (this.parsedConfig && this.program) {\n this.program = ts.createProgram(\n Array.from(this.fileContents.keys()),\n this.parsedConfig.options,\n this.createCompilerHost(),\n this.program || undefined,\n );\n }\n }\n\n /**\n * Handle deleted files (remove from cache)\n */\n public handleFilesDeleted(files: DeletedFile[]): void {\n let hasChanges = false;\n\n for (const file of files) {\n if (this.fileContents.has(file.path)) {\n this.fileContents.delete(file.path);\n hasChanges = true;\n }\n }\n\n // Recreate program without deleted files\n if (hasChanges && this.parsedConfig) {\n this.program = ts.createProgram(\n Array.from(this.fileContents.keys()),\n this.parsedConfig.options,\n this.createCompilerHost(),\n this.program || undefined,\n );\n }\n }\n\n /**\n * Check a single file for diagnostics\n */\n private checkSingleFile(file: SerializedFile): FileCheckResult {\n if (!this.program) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n const sourceFile = this.program.getSourceFile(file.path);\n\n if (!sourceFile) {\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: true,\n errors: [],\n warnings: [],\n };\n }\n\n const syntacticDiagnostics = this.program.getSyntacticDiagnostics(sourceFile);\n const semanticDiagnostics = this.program.getSemanticDiagnostics(sourceFile);\n const allDiagnostics = [...syntacticDiagnostics, ...semanticDiagnostics];\n\n const errors: DiagnosticMessage[] = [];\n const warnings: DiagnosticMessage[] = [];\n\n for (const diagnostic of allDiagnostics) {\n const message = this.formatDiagnostic(diagnostic, file);\n\n if (diagnostic.category === ts.DiagnosticCategory.Error) {\n errors.push(message);\n } else if (diagnostic.category === ts.DiagnosticCategory.Warning) {\n warnings.push(message);\n }\n }\n\n return {\n path: file.path,\n relativePath: file.relativePath,\n healthy: errors.length === 0 && warnings.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Format a TypeScript diagnostic into our message format\n */\n private formatDiagnostic(diagnostic: ts.Diagnostic, file: SerializedFile): DiagnosticMessage {\n let lineNumber = 1;\n let columnNumber = 1;\n let length = 1;\n\n if (diagnostic.file && diagnostic.start !== undefined) {\n const pos = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);\n lineNumber = pos.line + 1;\n columnNumber = pos.character + 1;\n length = diagnostic.length || 1;\n }\n\n const messageText =\n typeof diagnostic.messageText === \"string\"\n ? diagnostic.messageText\n : diagnostic.messageText.messageText;\n\n return {\n type: diagnostic.category === ts.DiagnosticCategory.Error ? \"error\" : \"warning\",\n message: messageText,\n lineNumber,\n columnNumber,\n length,\n filePath: file.path,\n relativePath: file.relativePath,\n };\n }\n\n /**\n * Create a custom compiler host that reads from in-memory cache\n */\n private createCompilerHost(): ts.CompilerHost {\n const defaultHost = ts.createCompilerHost(this.parsedConfig?.options || {});\n\n return {\n ...defaultHost,\n readFile: (fileName: string) => {\n // Check in-memory cache first\n if (this.fileContents.has(fileName)) {\n return this.fileContents.get(fileName);\n }\n // Fall back to disk\n return defaultHost.readFile(fileName);\n },\n fileExists: (fileName: string) => {\n if (this.fileContents.has(fileName)) {\n return true;\n }\n return defaultHost.fileExists(fileName);\n },\n };\n }\n}\n\n// Create worker instance\nconst worker = new TypeScriptHealthWorker();\n\n// Handle messages from main thread\nparentPort?.on(\"message\", (message: WorkerMessage) => {\n try {\n switch (message.type) {\n case \"init\": {\n const success = worker.initialize(message.config);\n const response: WorkerResponse = { type: \"initialized\", success };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"check\": {\n const results = worker.checkFiles(message.files);\n const response: WorkerResponse = { type: \"results\", results };\n parentPort?.postMessage(response);\n break;\n }\n\n case \"fileChanges\": {\n worker.handleFileChanges(message.files);\n break;\n }\n\n case \"filesDeleted\": {\n worker.handleFilesDeleted(message.files);\n break;\n }\n\n case \"shutdown\": {\n process.exit(0);\n }\n }\n } catch (error) {\n const response: WorkerResponse = {\n type: \"error\",\n message: error instanceof Error ? error.message : String(error),\n };\n parentPort?.postMessage(response);\n }\n});\n\n// Handle initialization from workerData if provided\nif (workerData?.autoInit) {\n worker.initialize({ cwd: workerData.cwd || process.cwd() });\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import "../../utils/index.mjs";
|
|
|
3
3
|
import { computeFingerprint } from "./transpile-cache.mjs";
|
|
4
4
|
import { version } from "esbuild";
|
|
5
5
|
|
|
6
|
-
//#region
|
|
6
|
+
//#region ../@warlock.js/core/src/dev-server/loader/build-transpile-init.ts
|
|
7
7
|
/**
|
|
8
8
|
* esbuild `target` for the dev transform. Pinned to the same value the
|
|
9
9
|
* production builder uses so dev and prod lower TC39 decorators (Cascade
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-transpile-init.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"build-transpile-init.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/dev-server/loader/build-transpile-init.ts"],"sourcesContent":["import { version as esbuildVersion } from \"esbuild\";\nimport { warlockPath } from \"../../utils\";\nimport type { TranspileInit } from \"./load-hook.js\";\nimport { CACHE_EPOCH, computeFingerprint } from \"./transpile-cache.js\";\n\n/**\n * esbuild `target` for the dev transform. Pinned to the same value the\n * production builder uses so dev and prod lower TC39 decorators (Cascade\n * leans on them) to identical helper output — a file transpiled in dev and\n * the same file built for prod must behave the same.\n */\nconst TRANSPILE_TARGET = \"node22\";\n\n/**\n * Build the transpile payload shipped into the hook worker. Always\n * returned — esbuild transpile is unconditional (tsx is no longer in the\n * TypeScript path); persistence to `.warlock/transpile` is intrinsic.\n *\n * The fingerprint folds esbuild's version, the cache-format epoch and the\n * whole tsconfig `compilerOptions` blob (plus the target) so any change to\n * the transform contract invalidates every entry structurally — no sweep,\n * no stale output.\n *\n * @param compilerOptions - Raw tsconfig `compilerOptions` (handed to esbuild\n * as `tsconfigRaw` and hashed wholesale into the fingerprint).\n * @param debugNames - `devServer.transpileCacheDebug` — cosmetic readable\n * cache filenames. Default off.\n */\nexport function buildTranspileInit(\n compilerOptions: unknown,\n debugNames: boolean,\n): TranspileInit {\n const fingerprint = computeFingerprint({\n esbuildVersion,\n cacheEpoch: CACHE_EPOCH,\n compilerOptions: { compilerOptions, target: TRANSPILE_TARGET },\n });\n\n return {\n cacheDir: warlockPath(\"transpile\"),\n fingerprint,\n target: TRANSPILE_TARGET,\n tsconfigRaw: JSON.stringify({ compilerOptions: compilerOptions ?? {} }),\n debugNames,\n };\n}\n"],"mappings":";;;;;;;;;;;;AAWA,MAAM,mBAAmB;;;;;;;;;;;;;;;;AAiBzB,SAAgB,mBACd,iBACA,YACe;CACf,MAAM,cAAc,mBAAmB;EACrC;EACA;EACA,iBAAiB;GAAE;GAAiB,QAAQ;EAAiB;CAC/D,CAAC;CAED,OAAO;EACL,UAAU,YAAY,WAAW;EACjC;EACA,QAAQ;EACR,aAAa,KAAK,UAAU,EAAE,iBAAiB,mBAAmB,CAAC,EAAE,CAAC;EACtE;CACF;AACF"}
|
|
@@ -5,7 +5,7 @@ import { build } from "esbuild";
|
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
6
|
import { MessageChannel } from "node:worker_threads";
|
|
7
7
|
|
|
8
|
-
//#region
|
|
8
|
+
//#region ../@warlock.js/core/src/dev-server/loader/register-loader.ts
|
|
9
9
|
/**
|
|
10
10
|
* Bundle, write, and register the ESM loader hook.
|
|
11
11
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-loader.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"register-loader.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/dev-server/loader/register-loader.ts"],"sourcesContent":["import { putFileAsync } from \"@warlock.js/fs\";\nimport { build } from \"esbuild\";\nimport { register } from \"node:module\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { type MessagePort, MessageChannel } from \"node:worker_threads\";\nimport type { TranspileInit } from \"./load-hook.js\";\n\n/**\n * Bundle, write, and register the ESM loader hook.\n *\n * **Why bundle?**\n * `module.register()` runs the hook file in a fresh Node.js worker thread that\n * has no tsx hook of its own. The hook source is TypeScript, so we must produce\n * a plain ESM bundle before registering. esbuild inline-bundles all three hook\n * modules (`hook-thread`, `resolve-hook`, `load-hook`, `version-registry`)\n * into a single `.mjs` file written to `.warlock/`. External npm packages\n * (`esbuild`, `node:*`) are kept external — the hook thread can resolve those\n * from `node_modules` normally.\n *\n * **Why a file and not a `data:` URL?**\n * Some Node versions have issues resolving `import.meta.url` inside `data:`\n * modules. A real file under `.warlock/` is simpler and debuggable.\n *\n * **Timing**\n * Called from `FilesOrchestrator.init()` before any user `src/` module is\n * dynamically imported. `module.register()` takes effect for all subsequent\n * `import()` calls, which is exactly the window we need.\n *\n * @param transpile - Transpile-cache config to ship into the hook worker,\n * or `null` to keep the hook in tsx-passthrough mode.\n *\n * @returns The main-thread side of the MessageChannel. Callers post\n * `{ type: \"bump\", absolutePath }` messages on it to invalidate modules.\n *\n * @example\n * const port = await registerLoader(transpileInit);\n * // Later, when a file changes:\n * port.postMessage({ type: \"bump\", absolutePath: \"/abs/path/to/user.model.ts\" });\n */\nexport async function registerLoader(\n transpile: TranspileInit,\n): Promise<MessagePort> {\n const { port1, port2 } = new MessageChannel();\n\n // hook-thread is a sibling module, so it shares THIS file's extension:\n // `.ts` when core runs from source (tsx), `.mjs` when published.\n const selfPath = fileURLToPath(import.meta.url);\n const hookThreadPath = path.join(\n path.dirname(selfPath),\n `hook-thread${path.extname(selfPath)}`,\n );\n\n const bundleResult = await build({\n entryPoints: [hookThreadPath],\n bundle: true,\n format: \"esm\",\n write: false,\n platform: \"node\",\n target: \"node20\",\n // Keep npm packages and Node built-ins external — the hook thread resolves\n // them normally from node_modules at runtime.\n packages: \"external\",\n });\n\n const bundledCode = bundleResult.outputFiles[0].text;\n // Caller (filesOrchestrator.init) guarantees .warlock/ exists before this runs.\n const hookBundlePath = path.join(process.cwd(), \".warlock\", \"loader-hook.mjs\");\n await putFileAsync(hookBundlePath, bundledCode);\n\n const srcRoot = path.join(process.cwd(), \"src\");\n\n // No tsx registration: our hook owns resolution (own-resolver) and the\n // transpile of every `.ts`/`.tsx` (esbuild, in the load hook). The chain\n // is simply [our hook] → [Node default] for non-TS (npm/.js, node:).\n // In this monorepo tsx is still the *launcher* (`tsx start.ts`) so its\n // loader is present anyway, but it is never consulted for TypeScript —\n // our hook short-circuits first. A released `node bin/warlock.js` has no\n // tsx at all and relies entirely on this hook.\n\n register(pathToFileURL(hookBundlePath).href, import.meta.url, {\n data: { port: port2, srcRoot, transpile },\n transferList: [port2],\n });\n\n return port1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,eAAsB,eACpB,WACsB;CACtB,MAAM,EAAE,OAAO,UAAU,IAAI,eAAe;CAI5C,MAAM,WAAW,cAAc,OAAO,KAAK,GAAG;CAkB9C,MAAM,eAAc,MAZO,MAAM;EAC/B,aAAa,CANQ,KAAK,KAC1B,KAAK,QAAQ,QAAQ,GACrB,cAAc,KAAK,QAAQ,QAAQ,GAIR,CAAC;EAC5B,QAAQ;EACR,QAAQ;EACR,OAAO;EACP,UAAU;EACV,QAAQ;EAGR,UAAU;CACZ,CAAC,EAE+B,CAAC,YAAY,EAAE,CAAC;CAEhD,MAAM,iBAAiB,KAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,iBAAiB;CAC7E,MAAM,aAAa,gBAAgB,WAAW;CAE9C,MAAM,UAAU,KAAK,KAAK,QAAQ,IAAI,GAAG,KAAK;CAU9C,SAAS,cAAc,cAAc,CAAC,CAAC,MAAM,OAAO,KAAK,KAAK;EAC5D,MAAM;GAAE,MAAM;GAAO;GAAS;EAAU;EACxC,cAAc,CAAC,KAAK;CACtB,CAAC;CAED,OAAO;AACT"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
3
|
|
|
5
|
-
//#region
|
|
4
|
+
//#region ../@warlock.js/core/src/dev-server/loader/transpile-cache.ts
|
|
6
5
|
/**
|
|
7
6
|
* Persisted transpile cache.
|
|
8
7
|
*
|
|
@@ -52,168 +51,7 @@ function computeFingerprint(parts) {
|
|
|
52
51
|
});
|
|
53
52
|
return createHash("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
54
53
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Derive the cache key for a source file. The NUL separator makes
|
|
57
|
-
* `sourceText` and `fingerprint` unambiguous (no concatenation collision).
|
|
58
|
-
*/
|
|
59
|
-
function cacheKey(sourceText, fingerprint) {
|
|
60
|
-
return createHash("sha256").update(sourceText).update("\0").update(fingerprint).digest("hex");
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Content-hash-addressed transpile cache stored on disk.
|
|
64
|
-
*
|
|
65
|
-
* Layout: `<cacheDir>/<first2-of-key>/<key>.js` plus a sibling `.js.map`.
|
|
66
|
-
* Sharding by the first two hex chars keeps any single directory small on
|
|
67
|
-
* large projects. GC metadata is derived from filesystem mtime so there is
|
|
68
|
-
* no second source of truth (no sidecar index to keep consistent).
|
|
69
|
-
*/
|
|
70
|
-
var TranspileCache = class {
|
|
71
|
-
constructor(cacheDir) {
|
|
72
|
-
this.cacheDir = cacheDir;
|
|
73
|
-
}
|
|
74
|
-
shardDir(key) {
|
|
75
|
-
return path.join(this.cacheDir, key.slice(0, 2));
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* `label` is an optional human-readable prefix (e.g. a path slug). It is
|
|
79
|
-
* cosmetic only — the content `key` is still what makes the name unique,
|
|
80
|
-
* so the same `(key, label)` pair must be passed to `get` and `put`.
|
|
81
|
-
*/
|
|
82
|
-
fileName(key, label, ext) {
|
|
83
|
-
return label ? `${label}.${key}${ext}` : `${key}${ext}`;
|
|
84
|
-
}
|
|
85
|
-
codePath(key, label) {
|
|
86
|
-
return path.join(this.shardDir(key), this.fileName(key, label, ".js"));
|
|
87
|
-
}
|
|
88
|
-
mapPath(key, label) {
|
|
89
|
-
return path.join(this.shardDir(key), this.fileName(key, label, ".js.map"));
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Return the cached entry for `key`, or `null` on a miss. Synchronous on
|
|
93
|
-
* purpose: this sits on the module-load hot path and must not pay an
|
|
94
|
-
* event-loop hop per import.
|
|
95
|
-
*/
|
|
96
|
-
get(key, label) {
|
|
97
|
-
try {
|
|
98
|
-
const code = readFileSync(this.codePath(key, label), "utf8");
|
|
99
|
-
let map = "";
|
|
100
|
-
try {
|
|
101
|
-
map = readFileSync(this.mapPath(key, label), "utf8");
|
|
102
|
-
} catch {}
|
|
103
|
-
return {
|
|
104
|
-
code,
|
|
105
|
-
map
|
|
106
|
-
};
|
|
107
|
-
} catch {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Store an entry for `key`. Written atomically (temp file + rename) so a
|
|
113
|
-
* concurrent {@link get} never observes a half-written module.
|
|
114
|
-
*/
|
|
115
|
-
put(key, entry, label) {
|
|
116
|
-
mkdirSync(this.shardDir(key), { recursive: true });
|
|
117
|
-
this.atomicWrite(this.codePath(key, label), entry.code);
|
|
118
|
-
if (entry.map) this.atomicWrite(this.mapPath(key, label), entry.map);
|
|
119
|
-
}
|
|
120
|
-
atomicWrite(filePath, content) {
|
|
121
|
-
const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
122
|
-
try {
|
|
123
|
-
writeFileSync(tempPath, content);
|
|
124
|
-
renameSync(tempPath, filePath);
|
|
125
|
-
} catch (error) {
|
|
126
|
-
try {
|
|
127
|
-
rmSync(tempPath, { force: true });
|
|
128
|
-
} catch {}
|
|
129
|
-
throw error;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Opportunistic eviction. Cheap, runs at boot (not on the hot path).
|
|
134
|
-
* Removes age-expired entries first, then trims to the size budget by
|
|
135
|
-
* evicting least-recently-modified entries. Both bounds are optional;
|
|
136
|
-
* with neither set this is a no-op.
|
|
137
|
-
*/
|
|
138
|
-
gc(options = {}) {
|
|
139
|
-
const { maxBytes, maxAgeMs } = options;
|
|
140
|
-
if (maxBytes === void 0 && maxAgeMs === void 0) return;
|
|
141
|
-
const files = this.scan();
|
|
142
|
-
const now = Date.now();
|
|
143
|
-
let live = files;
|
|
144
|
-
if (maxAgeMs !== void 0) {
|
|
145
|
-
live = [];
|
|
146
|
-
for (const file of files) if (now - file.mtimeMs > maxAgeMs) this.evict(file);
|
|
147
|
-
else live.push(file);
|
|
148
|
-
}
|
|
149
|
-
if (maxBytes !== void 0) {
|
|
150
|
-
let total = live.reduce((sum, file) => sum + file.size, 0);
|
|
151
|
-
if (total > maxBytes) {
|
|
152
|
-
live.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
153
|
-
for (const file of live) {
|
|
154
|
-
if (total <= maxBytes) break;
|
|
155
|
-
total -= file.size;
|
|
156
|
-
this.evict(file);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
scan() {
|
|
162
|
-
const result = [];
|
|
163
|
-
let shards;
|
|
164
|
-
try {
|
|
165
|
-
shards = readdirSync(this.cacheDir);
|
|
166
|
-
} catch {
|
|
167
|
-
return result;
|
|
168
|
-
}
|
|
169
|
-
for (const shard of shards) {
|
|
170
|
-
const shardPath = path.join(this.cacheDir, shard);
|
|
171
|
-
let entries;
|
|
172
|
-
try {
|
|
173
|
-
entries = readdirSync(shardPath);
|
|
174
|
-
} catch {
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
for (const entry of entries) {
|
|
178
|
-
if (!entry.endsWith(".js")) continue;
|
|
179
|
-
const codePath = path.join(shardPath, entry);
|
|
180
|
-
try {
|
|
181
|
-
const stat = statSync(codePath);
|
|
182
|
-
const mapPath = `${codePath}.map`;
|
|
183
|
-
let mapSize = 0;
|
|
184
|
-
try {
|
|
185
|
-
mapSize = statSync(mapPath).size;
|
|
186
|
-
} catch {}
|
|
187
|
-
result.push({
|
|
188
|
-
codePath,
|
|
189
|
-
mapPath,
|
|
190
|
-
size: stat.size + mapSize,
|
|
191
|
-
mtimeMs: stat.mtimeMs
|
|
192
|
-
});
|
|
193
|
-
} catch {}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return result;
|
|
197
|
-
}
|
|
198
|
-
evict(file) {
|
|
199
|
-
try {
|
|
200
|
-
rmSync(file.codePath, { force: true });
|
|
201
|
-
} catch {}
|
|
202
|
-
try {
|
|
203
|
-
rmSync(file.mapPath, { force: true });
|
|
204
|
-
} catch {}
|
|
205
|
-
}
|
|
206
|
-
/** Remove the entire cache directory (used by `--fresh`). */
|
|
207
|
-
clear() {
|
|
208
|
-
try {
|
|
209
|
-
rmSync(this.cacheDir, {
|
|
210
|
-
recursive: true,
|
|
211
|
-
force: true
|
|
212
|
-
});
|
|
213
|
-
} catch {}
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
54
|
|
|
217
55
|
//#endregion
|
|
218
|
-
export {
|
|
56
|
+
export { computeFingerprint };
|
|
219
57
|
//# sourceMappingURL=transpile-cache.mjs.map
|
|
@@ -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":["../../../../../../../../@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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAS,gBAAgB,OAAwB;CAC/C,IAAI,UAAU,QAAQ,OAAO,UAAU,UACrC,OAAO,KAAK,UAAU,KAAK,KAAK;CAGlC,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,IAAI,MAAM,IAAI,eAAe,CAAC,CAAC,KAAK,GAAG,EAAE;CAUlD,OAAO,IAPS,OAAO,KAAK,KAAgC,CAAC,CAC1D,KAAK,CAAC,CACN,KAAI,QAAO;EACV,MAAM,QAAQ,gBAAiB,MAAkC,IAAI;EACrE,OAAO,GAAG,KAAK,UAAU,GAAG,EAAE,GAAG;CACnC,CAEe,CAAC,CAAC,KAAK,GAAG,EAAE;AAC/B;;;;;AAMA,SAAgB,mBAAmB,OAAiC;CAClE,MAAM,YAAY,gBAAgB;EAChC,gBAAgB,MAAM;EACtB,YAAY,MAAM;EAClB,iBAAiB,MAAM;CACzB,CAAC;CAED,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;AACzE"}
|
|
@@ -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 ../@warlock.js/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":["../../../../../../../@warlock.js/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"}
|