@warlock.js/core 4.5.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/esm/ai/src/agent/agent.mjs +126 -7
- package/esm/ai/src/agent/agent.mjs.map +1 -1
- package/esm/ai/src/agent/signature.mjs +57 -0
- package/esm/ai/src/agent/signature.mjs.map +1 -0
- package/esm/ai/src/agent/snapshot.mjs +101 -0
- package/esm/ai/src/agent/snapshot.mjs.map +1 -0
- package/esm/ai/src/ai.mjs +37 -1
- package/esm/ai/src/ai.mjs.map +1 -1
- package/esm/ai/src/errors/agent-drift-error.mjs +31 -0
- package/esm/ai/src/errors/agent-drift-error.mjs.map +1 -0
- package/esm/ai/src/errors/index.mjs +2 -0
- package/esm/ai/src/errors/planner-drift-error.mjs +33 -0
- package/esm/ai/src/errors/planner-drift-error.mjs.map +1 -0
- package/esm/ai/src/image/image-cost.mjs +55 -0
- package/esm/ai/src/image/image-cost.mjs.map +1 -0
- package/esm/ai/src/image/image.mjs +112 -0
- package/esm/ai/src/image/image.mjs.map +1 -0
- package/esm/ai/src/image/index.mjs +4 -0
- package/esm/ai/src/index.mjs +20 -0
- package/esm/ai/src/planner/planner-run.mjs +161 -6
- package/esm/ai/src/planner/planner-run.mjs.map +1 -1
- package/esm/ai/src/planner/planner.mjs +25 -1
- package/esm/ai/src/planner/planner.mjs.map +1 -1
- package/esm/ai/src/planner/snapshot.mjs +95 -0
- package/esm/ai/src/planner/snapshot.mjs.map +1 -0
- package/esm/ai/src/rag/hybrid/bm25.mjs +51 -0
- package/esm/ai/src/rag/hybrid/bm25.mjs.map +1 -0
- package/esm/ai/src/rag/hybrid/hybrid-rank.mjs +29 -0
- package/esm/ai/src/rag/hybrid/hybrid-rank.mjs.map +1 -0
- package/esm/ai/src/rag/hybrid/rrf.mjs +30 -0
- package/esm/ai/src/rag/hybrid/rrf.mjs.map +1 -0
- package/esm/ai/src/rag/index.mjs +11 -0
- package/esm/ai/src/rag/loaders/errors.mjs +25 -0
- package/esm/ai/src/rag/loaders/errors.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/index.mjs +7 -0
- package/esm/ai/src/rag/loaders/load-html.mjs +138 -0
- package/esm/ai/src/rag/loaders/load-html.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/load-pdf.mjs +150 -0
- package/esm/ai/src/rag/loaders/load-pdf.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/load-text.mjs +60 -0
- package/esm/ai/src/rag/loaders/load-text.mjs.map +1 -0
- package/esm/ai/src/rag/loaders/load-web.mjs +89 -0
- package/esm/ai/src/rag/loaders/load-web.mjs.map +1 -0
- package/esm/ai/src/rag/store/pg-vector-store.mjs +328 -0
- package/esm/ai/src/rag/store/pg-vector-store.mjs.map +1 -0
- package/esm/ai/src/rag/transforms/multi-query.mjs +41 -0
- package/esm/ai/src/rag/transforms/multi-query.mjs.map +1 -0
- package/esm/ai/src/speech/index.mjs +3 -0
- package/esm/ai/src/speech/speech.mjs +122 -0
- package/esm/ai/src/speech/speech.mjs.map +1 -0
- package/esm/ai/src/supervisor/entries.mjs +2 -2
- package/esm/ai/src/supervisor/entries.mjs.map +1 -1
- package/esm/ai/src/transcribe/audio-input.mjs +84 -0
- package/esm/ai/src/transcribe/audio-input.mjs.map +1 -0
- package/esm/ai/src/transcribe/index.mjs +4 -0
- package/esm/ai/src/transcribe/transcribe.mjs +127 -0
- package/esm/ai/src/transcribe/transcribe.mjs.map +1 -0
- package/esm/ai-openai/src/image.mjs +5 -0
- package/esm/ai-openai/src/index.mjs +3 -0
- package/esm/ai-openai/src/sdk.mjs +3 -0
- package/esm/ai-openai/src/speech.mjs +5 -0
- package/esm/ai-openai/src/transcription.mjs +6 -0
- package/esm/ai-openai/src/utils/index.mjs +1 -0
- package/esm/ai-openai/src/utils/to-openai-messages.mjs +3 -0
- package/esm/cli/commands/doctor/checks/config.check.mjs +42 -0
- package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/connectors.check.mjs +28 -0
- package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/health.check.mjs +35 -0
- package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/index.mjs +25 -0
- package/esm/cli/commands/doctor/checks/index.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +90 -0
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +69 -0
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/checks/routes.check.mjs +30 -0
- package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -0
- package/esm/cli/commands/doctor/doctor-command.action.mjs +28 -0
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -0
- package/esm/cli/commands/doctor/format-report.mjs +44 -0
- package/esm/cli/commands/doctor/format-report.mjs.map +1 -0
- package/esm/cli/commands/doctor/run-checks.mjs +50 -0
- package/esm/cli/commands/doctor/run-checks.mjs.map +1 -0
- package/esm/cli/commands/doctor.command.mjs +29 -0
- package/esm/cli/commands/doctor.command.mjs.map +1 -0
- package/esm/cli/commands/generate/templates/stubs.mjs +6 -8
- package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +129 -0
- package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -0
- package/esm/cli/commands/routes/route-row.mjs +92 -0
- package/esm/cli/commands/routes/route-row.mjs.map +1 -0
- package/esm/cli/commands/routes/routes-command.action.mjs +43 -0
- package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -0
- package/esm/cli/commands/routes.command.mjs +51 -0
- package/esm/cli/commands/routes.command.mjs.map +1 -0
- package/esm/cli/commands/seed.command.mjs +5 -0
- package/esm/cli/commands/seed.command.mjs.map +1 -1
- package/esm/cli/framework-cli-commands.mjs +4 -0
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/config/config-getter.mjs +5 -5
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-loader.mjs +2 -2
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/connectors/access-connector.mjs +2 -2
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.mjs +2 -2
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/cache-connector.mjs +2 -2
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/database-connector.mjs +2 -2
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/herald-connector.mjs +2 -2
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +9 -7
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/logger-connector.mjs +2 -2
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.mjs +2 -2
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.mjs +2 -2
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/socket-connector.mjs +3 -3
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/database/index.d.mts +2 -1
- package/esm/database/index.mjs +1 -0
- package/esm/database/seed-command-action.mjs +44 -4
- package/esm/database/seed-command-action.mjs.map +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs +36 -0
- package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -0
- package/esm/database/seeds/seeder.d.mts +22 -5
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +22 -0
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -0
- package/esm/database/seeds/seeder.errors.mjs +29 -0
- package/esm/database/seeds/seeder.errors.mjs.map +1 -0
- package/esm/database/seeds/seeder.mjs.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +90 -11
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +117 -1
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/seeds/utils.mjs +6 -1
- package/esm/database/seeds/utils.mjs.map +1 -1
- package/esm/dev-server/module-loader.d.mts +12 -0
- package/esm/dev-server/module-loader.d.mts.map +1 -1
- package/esm/dev-server/module-loader.mjs +30 -2
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/http/config.mjs +2 -2
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/createHttpApplication.mjs +2 -2
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/health.d.mts +14 -0
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/health.mjs +16 -0
- package/esm/http/health.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +5 -5
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +2 -2
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +4 -4
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/plugins.mjs +9 -9
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/response.mjs +5 -5
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.mjs +4 -4
- package/esm/http/server.mjs.map +1 -1
- package/esm/index.d.mts +4 -3
- package/esm/index.mjs +2 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +28 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +39 -0
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
- package/esm/repositories/contracts/index.d.mts +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +87 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/index.d.mts +1 -1
- package/esm/repositories/repository.manager.d.mts +99 -1
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +128 -0
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/router/router.d.mts +9 -0
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +21 -1
- package/esm/router/router.mjs.map +1 -1
- package/esm/utils/paths.mjs +2 -2
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/validation/validateAll.mjs +2 -2
- package/esm/validation/validateAll.mjs.map +1 -1
- package/llms-full.txt +427 -45
- package/llms.txt +4 -2
- package/package.json +9 -9
- package/skills/README.md +65 -0
- package/skills/health-checks/SKILL.md +13 -0
- package/skills/use-repository/SKILL.md +38 -1
- package/skills/warlock-doctor/SKILL.md +135 -0
- package/skills/warlock-routes/SKILL.md +91 -0
- package/skills/write-seeder/SKILL.md +143 -45
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-connector.mjs","names":[
|
|
1
|
+
{"version":3,"file":"database-connector.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/database-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { connectToDatabase, dataSourceRegistry } from \"@warlock.js/cascade\";\r\nimport { container } from \"../container\";\r\nimport { BaseConnector } from \"./base-connector\";\r\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\r\n\r\n/**\r\n * Database Connector\r\n * Manages database connection lifecycle using @warlock.js/cascade\r\n */\r\nexport class DatabaseConnector extends BaseConnector {\r\n public readonly name = \"database\";\r\n public readonly priority = ConnectorPriority.DATABASE;\r\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\r\n\r\n /**\r\n * Files that trigger database restart\r\n */\r\n protected readonly watchedFiles = [\"src/config/database.ts\", \"src/config/database.tsx\"];\r\n\r\n /**\r\n * Initialize database connection\r\n */\r\n public async start(): Promise<void> {\r\n const databaseConfig = config.get(\"database\");\r\n\r\n if (!databaseConfig) {\r\n return;\r\n }\r\n\r\n try {\r\n const source = await connectToDatabase(databaseConfig);\r\n container.set(\"database.source\", source);\r\n this.active = true;\r\n } catch (error) {\r\n console.error(\"Failed to connect to database:\", error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown database connection\r\n */\r\n public async shutdown(): Promise<void> {\r\n if (!this.active) {\r\n return;\r\n }\r\n\r\n try {\r\n // Disconnect all registered data sources\r\n const dataSources = dataSourceRegistry.getAllDataSources();\r\n\r\n for (const dataSource of dataSources) {\r\n if (dataSource.driver.isConnected) {\r\n await dataSource.driver.disconnect();\r\n }\r\n }\r\n\r\n this.active = false;\r\n } catch (error) {\r\n console.error(\"Failed to disconnect from database:\", error);\r\n throw error;\r\n }\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;AAUA,IAAa,oBAAb,cAAuC,cAAc;;;cAC5B;;;sBAOW,CAAC,0BAA0B,yBAAyB;;;;;CAKtF,MAAa,QAAuB;EAClC,MAAM,iBAAiB,OAAO,IAAI,UAAU;EAE5C,IAAI,CAAC,gBACH;EAGF,IAAI;GACF,MAAM,SAAS,MAAM,kBAAkB,cAAc;GACrD,UAAU,IAAI,mBAAmB,MAAM;GACvC,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,QAAQ,MAAM,kCAAkC,KAAK;GACrD,MAAM;EACR;CACF;;;;CAKA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,IAAI;GAEF,MAAM,cAAc,mBAAmB,kBAAkB;GAEzD,KAAK,MAAM,cAAc,aACvB,IAAI,WAAW,OAAO,aACpB,MAAM,WAAW,OAAO,WAAW;GAIvC,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,QAAQ,MAAM,uCAAuC,KAAK;GAC1D,MAAM;EACR;CACF;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
|
|
2
2
|
import { BaseConnector } from "./base-connector.mjs";
|
|
3
|
-
import
|
|
3
|
+
import config from "@mongez/config";
|
|
4
4
|
import { log } from "@warlock.js/logger";
|
|
5
5
|
|
|
6
6
|
//#region ../@warlock.js/core/src/connectors/herald-connector.ts
|
|
@@ -20,7 +20,7 @@ var HeraldConnector = class extends BaseConnector {
|
|
|
20
20
|
* Initialize broker connection
|
|
21
21
|
*/
|
|
22
22
|
async start() {
|
|
23
|
-
const heraldConfig =
|
|
23
|
+
const heraldConfig = config.get("herald");
|
|
24
24
|
if (!heraldConfig) return;
|
|
25
25
|
try {
|
|
26
26
|
const { connectToBroker } = await import("@warlock.js/herald");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"herald-connector.mjs","names":[
|
|
1
|
+
{"version":3,"file":"herald-connector.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/herald-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { log } from \"@warlock.js/logger\";\r\nimport { BaseConnector } from \"./base-connector\";\r\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\r\n\r\n/**\r\n * Herald Connector\r\n * Manages message broker connection lifecycle using @warlock.js/herald\r\n */\r\nexport class HeraldConnector extends BaseConnector {\r\n public readonly name = \"herald\";\r\n public readonly priority = ConnectorPriority.COMMUNICATOR;\r\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\r\n\r\n /**\r\n * Files that trigger herald restart\r\n */\r\n protected readonly watchedFiles = [\"src/config/herald.ts\"];\r\n\r\n /**\r\n * Initialize broker connection\r\n */\r\n public async start(): Promise<void> {\r\n const heraldConfig = config.get(\"herald\");\r\n\r\n if (!heraldConfig) {\r\n return;\r\n }\r\n\r\n try {\r\n const { connectToBroker } = await import(\"@warlock.js/herald\");\r\n\r\n log.info(`herald.${heraldConfig.driver}`, \"connection\", \"Connecting to message broker\");\r\n await connectToBroker(heraldConfig);\r\n log.success(`herald.${heraldConfig.driver}`, \"connection\", \"Connected to message broker\");\r\n this.active = true;\r\n } catch (error) {\r\n // Boot-time broker connection failure is unrecoverable — `fatal` makes\r\n // \"page on fatal only\" alerting clean, aligned with the cascade and\r\n // cache drivers. Disconnect failures (shutdown path) stay at error.\r\n log.fatal(\r\n `herald.${heraldConfig.driver}`,\r\n \"connection\",\r\n \"Failed to connect to message broker\",\r\n );\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown broker connection\r\n */\r\n public async shutdown(): Promise<void> {\r\n if (!this.active) {\r\n return;\r\n }\r\n\r\n try {\r\n const { brokerRegistry } = await import(\"@warlock.js/herald\");\r\n\r\n // Disconnect all registered brokers\r\n const brokers = brokerRegistry.getAll();\r\n\r\n for (const broker of brokers) {\r\n if (broker.driver.isConnected) {\r\n await broker.driver.disconnect();\r\n }\r\n }\r\n\r\n // Clear the registry for clean restart\r\n brokerRegistry.clear();\r\n\r\n this.active = false;\r\n } catch (error) {\r\n log.error(\"herald\", \"shutdown\", \"Failed to disconnect from message broker\");\r\n throw error;\r\n }\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;AASA,IAAa,kBAAb,cAAqC,cAAc;;;cAC1B;;;sBAOW,CAAC,sBAAsB;;;;;CAKzD,MAAa,QAAuB;EAClC,MAAM,eAAe,OAAO,IAAI,QAAQ;EAExC,IAAI,CAAC,cACH;EAGF,IAAI;GACF,MAAM,EAAE,oBAAoB,MAAM,OAAO;GAEzC,IAAI,KAAK,UAAU,aAAa,UAAU,cAAc,8BAA8B;GACtF,MAAM,gBAAgB,YAAY;GAClC,IAAI,QAAQ,UAAU,aAAa,UAAU,cAAc,6BAA6B;GACxF,KAAK,SAAS;EAChB,SAAS,OAAO;GAId,IAAI,MACF,UAAU,aAAa,UACvB,cACA,qCACF;GACA,MAAM;EACR;CACF;;;;CAKA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,IAAI;GACF,MAAM,EAAE,mBAAmB,MAAM,OAAO;GAGxC,MAAM,UAAU,eAAe,OAAO;GAEtC,KAAK,MAAM,UAAU,SACnB,IAAI,OAAO,OAAO,aAChB,MAAM,OAAO,OAAO,WAAW;GAKnC,eAAe,MAAM;GAErB,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,IAAI,MAAM,UAAU,YAAY,0CAA0C;GAC1E,MAAM;EACR;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-connector.d.mts","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/http-connector.ts"],"mappings":";;;;;;;AAsCA;;cAAa,aAAA,SAAsB,aAAA;EAAA,SACjB,IAAA;EAAA,SACA,QAAA,GAAQ,iBAAA,CAAA,IAAA;EAAA,SACR,cAAA,GAAc,uBAAA,CAAA,IAAA;EAmBb;;;;;EAAA,mBAZE,YAAA;EAV2B;;;EAAA,UAepC,IAAA,GAAO,eAAA;EAbO;;;;;EAoBX,IAAA,IAAI,OAAA;EAPP;;;;;;;EAAA,QA0CF,oBAAA;
|
|
1
|
+
{"version":3,"file":"http-connector.d.mts","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/http-connector.ts"],"mappings":";;;;;;;AAsCA;;cAAa,aAAA,SAAsB,aAAA;EAAA,SACjB,IAAA;EAAA,SACA,QAAA,GAAQ,iBAAA,CAAA,IAAA;EAAA,SACR,cAAA,GAAc,uBAAA,CAAA,IAAA;EAmBb;;;;;EAAA,mBAZE,YAAA;EAV2B;;;EAAA,UAepC,IAAA,GAAO,eAAA;EAbO;;;;;EAoBX,IAAA,IAAI,OAAA;EAPP;;;;;;;EAAA,QA0CF,oBAAA;EAiFgB;;;;;EAjDX,KAAA,IAAS,OAAA;EAsFqB;;;;;EArC9B,OAAA,IAAW,OAAA;;;;EASX,QAAA,IAAY,OAAA;;;;;;EA4BlB,aAAA,CAAc,YAAA;AAAA"}
|
|
@@ -9,7 +9,7 @@ import { health } from "../http/health.mjs";
|
|
|
9
9
|
import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
|
|
10
10
|
import { BaseConnector } from "./base-connector.mjs";
|
|
11
11
|
import { devLogError } from "../dev-server/dev-logger.mjs";
|
|
12
|
-
import
|
|
12
|
+
import config from "@mongez/config";
|
|
13
13
|
import { log } from "@warlock.js/logger";
|
|
14
14
|
import { colors } from "@mongez/copper";
|
|
15
15
|
|
|
@@ -45,14 +45,14 @@ var HttpConnector = class extends BaseConnector {
|
|
|
45
45
|
* `start()` so it reads the router after app code has registered.
|
|
46
46
|
*/
|
|
47
47
|
async boot() {
|
|
48
|
-
const httpConfig =
|
|
48
|
+
const httpConfig = config.get("http");
|
|
49
49
|
if (!httpConfig) return;
|
|
50
50
|
const port = httpConfig.port;
|
|
51
51
|
log.info(`http`, "connection", `Starting http server on port ${port} in ${environmentColor(Application.environment)} mode`);
|
|
52
52
|
this.http = startHttpServer(httpConfig.serverOptions);
|
|
53
53
|
container.set("http.server", this.http);
|
|
54
54
|
await registerHttpPlugins(this.http);
|
|
55
|
-
setBaseUrl(
|
|
55
|
+
setBaseUrl(config.get("app.baseUrl"));
|
|
56
56
|
this.registerHealthRoutes();
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
@@ -64,7 +64,7 @@ var HttpConnector = class extends BaseConnector {
|
|
|
64
64
|
*/
|
|
65
65
|
registerHealthRoutes() {
|
|
66
66
|
if (!this.http) return;
|
|
67
|
-
const healthConfig =
|
|
67
|
+
const healthConfig = config.get("http.health");
|
|
68
68
|
if (healthConfig?.enabled === false) return;
|
|
69
69
|
const livenessPath = healthConfig?.path ?? "/health";
|
|
70
70
|
const readinessPath = healthConfig?.readinessPath ?? "/ready";
|
|
@@ -83,16 +83,18 @@ var HttpConnector = class extends BaseConnector {
|
|
|
83
83
|
* app code without losing routes.
|
|
84
84
|
*/
|
|
85
85
|
async start() {
|
|
86
|
-
const httpConfig =
|
|
86
|
+
const httpConfig = config.get("http");
|
|
87
87
|
if (!httpConfig || !this.http) return;
|
|
88
88
|
if (Application.runtimeStrategy === "development") router.scanDevServer(this.http);
|
|
89
89
|
else router.scan(this.http);
|
|
90
|
+
health.addRoutesRegisteredCheck(() => router.routeCount());
|
|
91
|
+
log.info("http", "routes", `${router.routeCount()} route(s) registered`);
|
|
90
92
|
try {
|
|
91
93
|
await this.http.listen({
|
|
92
94
|
port: httpConfig.port,
|
|
93
95
|
host: httpConfig.host || "localhost"
|
|
94
96
|
});
|
|
95
|
-
const baseUrl =
|
|
97
|
+
const baseUrl = config.get("app.baseUrl");
|
|
96
98
|
log.success(`http`, "connection", `Server ready at ${baseUrl}`);
|
|
97
99
|
} catch (error) {
|
|
98
100
|
devLogError("Error while starting http server", error);
|
|
@@ -119,7 +121,7 @@ var HttpConnector = class extends BaseConnector {
|
|
|
119
121
|
if (!this.active) return;
|
|
120
122
|
const server = getHttpServer();
|
|
121
123
|
if (server) {
|
|
122
|
-
const timeout =
|
|
124
|
+
const timeout = config.get("http.gracefulShutdown.timeout", DEFAULT_SHUTDOWN_TIMEOUT);
|
|
123
125
|
if (!await closeServerWithTimeout(server, timeout)) log.warn("http", "shutdown", `In-flight requests did not drain within ${timeout}ms; closing anyway`);
|
|
124
126
|
}
|
|
125
127
|
this.active = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-connector.mjs","names":["config"],"sources":["../../../../../../../@warlock.js/core/src/connectors/http-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { colors } from \"@mongez/copper\";\r\nimport { log } from \"@warlock.js/logger\";\r\nimport { Application } from \"../application\";\r\nimport { devLogError } from \"../dev-server/dev-logger\";\r\nimport { health } from \"../http/health\";\r\nimport { registerHttpPlugins } from \"../http/plugins\";\r\nimport { closeServerWithTimeout, FastifyInstance, getHttpServer, startHttpServer } from \"../http/server\";\r\nimport { router } from \"../router/router\";\r\nimport { Environment } from \"../utils\";\r\nimport { setBaseUrl } from \"../utils/urls\";\r\nimport { container } from \"./../container\";\r\nimport { BaseConnector } from \"./base-connector\";\r\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\r\n\r\nfunction environmentColor(environment: Environment) {\r\n switch (environment) {\r\n case \"development\":\r\n return colors.magentaBright(environment);\r\n case \"test\":\r\n return colors.yellowBright(environment);\r\n case \"production\":\r\n return colors.greenBright(environment);\r\n default:\r\n return colors.white(environment);\r\n }\r\n}\r\n\r\n/**\r\n * Default time to wait for in-flight requests to drain on shutdown before the\r\n * HTTP server is force-closed. Override via `http.gracefulShutdown.timeout`.\r\n */\r\nconst DEFAULT_SHUTDOWN_TIMEOUT = 10_000;\r\n\r\n/**\r\n * HTTP Connector\r\n * Manages HTTP server (Fastify) lifecycle\r\n */\r\nexport class HttpConnector extends BaseConnector {\r\n public readonly name = \"http\";\r\n public readonly priority = ConnectorPriority.HTTP;\r\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Late;\r\n\r\n /**\r\n * Files that trigger HTTP server restart\r\n * Note: routes.ts changes will be handled by HMR with wildcard routing\r\n * Connectors receive config file paths directly (not .env) thanks to layer-executor\r\n */\r\n protected readonly watchedFiles = [\"src/config/http.ts\", \"src/config/http.tsx\"];\r\n\r\n /**\r\n * Fastify Server instance\r\n */\r\n protected http?: FastifyInstance;\r\n\r\n /**\r\n * Boot the connector — construction only (create Fastify, register\r\n * plugins, populate container). Route scanning is deferred to\r\n * `start()` so it reads the router after app code has registered.\r\n */\r\n public async boot() {\r\n const httpConfig = config.get(\"http\");\r\n\r\n if (!httpConfig) return;\r\n\r\n const port = httpConfig.port;\r\n log.info(\r\n `http`,\r\n \"connection\",\r\n `Starting http server on port ${port} in ${environmentColor(Application.environment)} mode`,\r\n );\r\n\r\n this.http = startHttpServer(httpConfig.serverOptions);\r\n\r\n container.set(\"http.server\", this.http);\r\n\r\n await registerHttpPlugins(this.http);\r\n\r\n const baseUrl = config.get(\"app.baseUrl\");\r\n\r\n // update base url\r\n setBaseUrl(baseUrl);\r\n\r\n // Liveness/readiness endpoints — registered on Fastify before start() scans\r\n // the app router, so they exist by the time the server listens.\r\n this.registerHealthRoutes();\r\n }\r\n\r\n /**\r\n * Register the built-in liveness (`/health`) and readiness (`/ready`)\r\n * endpoints directly on the Fastify instance — infra routes, kept off the app\r\n * router so they're immune to HMR and never collide with route scanning. Opt\r\n * out via `http.health.enabled = false`; rename via `http.health.path` /\r\n * `http.health.readinessPath`.\r\n */\r\n private registerHealthRoutes(): void {\r\n if (!this.http) {\r\n return;\r\n }\r\n\r\n const healthConfig = config.get(\"http.health\");\r\n\r\n if (healthConfig?.enabled === false) {\r\n return;\r\n }\r\n\r\n const livenessPath = healthConfig?.path ?? \"/health\";\r\n const readinessPath = healthConfig?.readinessPath ?? \"/ready\";\r\n\r\n this.http.get(livenessPath, async (_request: any, reply: any) => {\r\n const result = health.liveness();\r\n\r\n return reply.code(result.status === \"ok\" ? 200 : 503).send(result);\r\n });\r\n\r\n this.http.get(readinessPath, async (_request: any, reply: any) => {\r\n const result = await health.readiness();\r\n\r\n return reply.code(result.status === \"ok\" ? 200 : 503).send(result);\r\n });\r\n }\r\n\r\n /**\r\n * Initialize HTTP server — bind app-registered routes to Fastify\r\n * then listen. Scanning here (not in `boot`) lets HTTP boot before\r\n * app code without losing routes.\r\n */\r\n public async start(): Promise<void> {\r\n const httpConfig = config.get(\"http\");\r\n\r\n if (!httpConfig || !this.http) return;\r\n\r\n if (Application.runtimeStrategy === \"development\") {\r\n router.scanDevServer(this.http);\r\n } else {\r\n router.scan(this.http);\r\n }\r\n\r\n try {\r\n // We can use the url of the server\r\n await this.http.listen({\r\n port: httpConfig.port,\r\n host: httpConfig.host || \"localhost\",\r\n });\r\n\r\n const baseUrl = config.get(\"app.baseUrl\");\r\n\r\n log.success(`http`, \"connection\", `Server ready at ${baseUrl}`);\r\n } catch (error) {\r\n devLogError(\"Error while starting http server\", error);\r\n\r\n // A failed listen()/port-bind at boot means the app can't serve — fatal.\r\n // devLogError above is the dev-server console UI and bypasses the logger\r\n // pipeline, so also route it through `log.fatal` to reach Sentry/file,\r\n // then `await log.flush()` to drain buffered/async channels before exit.\r\n await log.fatal(\"http\", \"connection\", error);\r\n await log.flush();\r\n\r\n process.exit(1); // stop the process, exit with error\r\n }\r\n\r\n this.active = true;\r\n }\r\n\r\n /**\r\n * Restart — needs a fresh Fastify instance since `start()` now\r\n * re-runs `router.scan()`, and re-scanning the same Fastify would\r\n * register duplicate route handlers.\r\n */\r\n public async restart(): Promise<void> {\r\n await this.shutdown();\r\n await this.boot();\r\n await this.start();\r\n }\r\n\r\n /**\r\n * Shutdown HTTP server\r\n */\r\n public async shutdown(): Promise<void> {\r\n if (!this.active) {\r\n return;\r\n }\r\n\r\n const server = getHttpServer();\r\n\r\n if (server) {\r\n const timeout = config.get(\"http.gracefulShutdown.timeout\", DEFAULT_SHUTDOWN_TIMEOUT);\r\n const drained = await closeServerWithTimeout(server, timeout);\r\n\r\n if (!drained) {\r\n log.warn(\r\n \"http\",\r\n \"shutdown\",\r\n `In-flight requests did not drain within ${timeout}ms; closing anyway`,\r\n );\r\n }\r\n }\r\n\r\n this.active = false;\r\n }\r\n\r\n /**\r\n * Override shouldRestart to handle routes.ts specially\r\n * routes.ts changes should NOT restart the server (use HMR instead)\r\n * Now receives config file paths directly from layer-executor\r\n */\r\n public shouldRestart(changedFiles: string[]): boolean {\r\n // Only restart for config changes, not routes\r\n return changedFiles.some((file) => {\r\n const relativePath = file.replace(/\\\\/g, \"/\");\r\n return this.watchedFiles.includes(relativePath);\r\n });\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,SAAS,iBAAiB,aAA0B;CAClD,QAAQ,aAAR;EACE,KAAK,eACH,OAAO,OAAO,cAAc,WAAW;EACzC,KAAK,QACH,OAAO,OAAO,aAAa,WAAW;EACxC,KAAK,cACH,OAAO,OAAO,YAAY,WAAW;EACvC,SACE,OAAO,OAAO,MAAM,WAAW;CACnC;AACF;;;;;AAMA,MAAM,2BAA2B;;;;;AAMjC,IAAa,gBAAb,cAAmC,cAAc;;;cACxB;;;sBASW,CAAC,sBAAsB,qBAAqB;;;;;;;CAY9E,MAAa,OAAO;EAClB,MAAM,aAAaA,WAAO,IAAI,MAAM;EAEpC,IAAI,CAAC,YAAY;EAEjB,MAAM,OAAO,WAAW;EACxB,IAAI,KACF,QACA,cACA,gCAAgC,KAAK,MAAM,iBAAiB,YAAY,WAAW,EAAE,MACvF;EAEA,KAAK,OAAO,gBAAgB,WAAW,aAAa;EAEpD,UAAU,IAAI,eAAe,KAAK,IAAI;EAEtC,MAAM,oBAAoB,KAAK,IAAI;EAKnC,WAHgBA,WAAO,IAAI,aAGV,CAAC;EAIlB,KAAK,qBAAqB;CAC5B;;;;;;;;CASA,AAAQ,uBAA6B;EACnC,IAAI,CAAC,KAAK,MACR;EAGF,MAAM,eAAeA,WAAO,IAAI,aAAa;EAE7C,IAAI,cAAc,YAAY,OAC5B;EAGF,MAAM,eAAe,cAAc,QAAQ;EAC3C,MAAM,gBAAgB,cAAc,iBAAiB;EAErD,KAAK,KAAK,IAAI,cAAc,OAAO,UAAe,UAAe;GAC/D,MAAM,SAAS,OAAO,SAAS;GAE/B,OAAO,MAAM,KAAK,OAAO,WAAW,OAAO,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM;EACnE,CAAC;EAED,KAAK,KAAK,IAAI,eAAe,OAAO,UAAe,UAAe;GAChE,MAAM,SAAS,MAAM,OAAO,UAAU;GAEtC,OAAO,MAAM,KAAK,OAAO,WAAW,OAAO,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM;EACnE,CAAC;CACH;;;;;;CAOA,MAAa,QAAuB;EAClC,MAAM,aAAaA,WAAO,IAAI,MAAM;EAEpC,IAAI,CAAC,cAAc,CAAC,KAAK,MAAM;EAE/B,IAAI,YAAY,oBAAoB,eAClC,OAAO,cAAc,KAAK,IAAI;OAE9B,OAAO,KAAK,KAAK,IAAI;EAGvB,IAAI;GAEF,MAAM,KAAK,KAAK,OAAO;IACrB,MAAM,WAAW;IACjB,MAAM,WAAW,QAAQ;GAC3B,CAAC;GAED,MAAM,UAAUA,WAAO,IAAI,aAAa;GAExC,IAAI,QAAQ,QAAQ,cAAc,mBAAmB,SAAS;EAChE,SAAS,OAAO;GACd,YAAY,oCAAoC,KAAK;GAMrD,MAAM,IAAI,MAAM,QAAQ,cAAc,KAAK;GAC3C,MAAM,IAAI,MAAM;GAEhB,QAAQ,KAAK,CAAC;EAChB;EAEA,KAAK,SAAS;CAChB;;;;;;CAOA,MAAa,UAAyB;EACpC,MAAM,KAAK,SAAS;EACpB,MAAM,KAAK,KAAK;EAChB,MAAM,KAAK,MAAM;CACnB;;;;CAKA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,MAAM,SAAS,cAAc;EAE7B,IAAI,QAAQ;GACV,MAAM,UAAUA,WAAO,IAAI,iCAAiC,wBAAwB;GAGpF,IAAI,CAAC,MAFiB,uBAAuB,QAAQ,OAAO,GAG1D,IAAI,KACF,QACA,YACA,2CAA2C,QAAQ,mBACrD;EAEJ;EAEA,KAAK,SAAS;CAChB;;;;;;CAOA,AAAO,cAAc,cAAiC;EAEpD,OAAO,aAAa,MAAM,SAAS;GACjC,MAAM,eAAe,KAAK,QAAQ,OAAO,GAAG;GAC5C,OAAO,KAAK,aAAa,SAAS,YAAY;EAChD,CAAC;CACH;AACF"}
|
|
1
|
+
{"version":3,"file":"http-connector.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/http-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { colors } from \"@mongez/copper\";\r\nimport { log } from \"@warlock.js/logger\";\r\nimport { Application } from \"../application\";\r\nimport { devLogError } from \"../dev-server/dev-logger\";\r\nimport { health } from \"../http/health\";\r\nimport { registerHttpPlugins } from \"../http/plugins\";\r\nimport { closeServerWithTimeout, FastifyInstance, getHttpServer, startHttpServer } from \"../http/server\";\r\nimport { router } from \"../router/router\";\r\nimport { Environment } from \"../utils\";\r\nimport { setBaseUrl } from \"../utils/urls\";\r\nimport { container } from \"./../container\";\r\nimport { BaseConnector } from \"./base-connector\";\r\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\r\n\r\nfunction environmentColor(environment: Environment) {\r\n switch (environment) {\r\n case \"development\":\r\n return colors.magentaBright(environment);\r\n case \"test\":\r\n return colors.yellowBright(environment);\r\n case \"production\":\r\n return colors.greenBright(environment);\r\n default:\r\n return colors.white(environment);\r\n }\r\n}\r\n\r\n/**\r\n * Default time to wait for in-flight requests to drain on shutdown before the\r\n * HTTP server is force-closed. Override via `http.gracefulShutdown.timeout`.\r\n */\r\nconst DEFAULT_SHUTDOWN_TIMEOUT = 10_000;\r\n\r\n/**\r\n * HTTP Connector\r\n * Manages HTTP server (Fastify) lifecycle\r\n */\r\nexport class HttpConnector extends BaseConnector {\r\n public readonly name = \"http\";\r\n public readonly priority = ConnectorPriority.HTTP;\r\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Late;\r\n\r\n /**\r\n * Files that trigger HTTP server restart\r\n * Note: routes.ts changes will be handled by HMR with wildcard routing\r\n * Connectors receive config file paths directly (not .env) thanks to layer-executor\r\n */\r\n protected readonly watchedFiles = [\"src/config/http.ts\", \"src/config/http.tsx\"];\r\n\r\n /**\r\n * Fastify Server instance\r\n */\r\n protected http?: FastifyInstance;\r\n\r\n /**\r\n * Boot the connector — construction only (create Fastify, register\r\n * plugins, populate container). Route scanning is deferred to\r\n * `start()` so it reads the router after app code has registered.\r\n */\r\n public async boot() {\r\n const httpConfig = config.get(\"http\");\r\n\r\n if (!httpConfig) return;\r\n\r\n const port = httpConfig.port;\r\n log.info(\r\n `http`,\r\n \"connection\",\r\n `Starting http server on port ${port} in ${environmentColor(Application.environment)} mode`,\r\n );\r\n\r\n this.http = startHttpServer(httpConfig.serverOptions);\r\n\r\n container.set(\"http.server\", this.http);\r\n\r\n await registerHttpPlugins(this.http);\r\n\r\n const baseUrl = config.get(\"app.baseUrl\");\r\n\r\n // update base url\r\n setBaseUrl(baseUrl);\r\n\r\n // Liveness/readiness endpoints — registered on Fastify before start() scans\r\n // the app router, so they exist by the time the server listens.\r\n this.registerHealthRoutes();\r\n }\r\n\r\n /**\r\n * Register the built-in liveness (`/health`) and readiness (`/ready`)\r\n * endpoints directly on the Fastify instance — infra routes, kept off the app\r\n * router so they're immune to HMR and never collide with route scanning. Opt\r\n * out via `http.health.enabled = false`; rename via `http.health.path` /\r\n * `http.health.readinessPath`.\r\n */\r\n private registerHealthRoutes(): void {\r\n if (!this.http) {\r\n return;\r\n }\r\n\r\n const healthConfig = config.get(\"http.health\");\r\n\r\n if (healthConfig?.enabled === false) {\r\n return;\r\n }\r\n\r\n const livenessPath = healthConfig?.path ?? \"/health\";\r\n const readinessPath = healthConfig?.readinessPath ?? \"/ready\";\r\n\r\n this.http.get(livenessPath, async (_request: any, reply: any) => {\r\n const result = health.liveness();\r\n\r\n return reply.code(result.status === \"ok\" ? 200 : 503).send(result);\r\n });\r\n\r\n this.http.get(readinessPath, async (_request: any, reply: any) => {\r\n const result = await health.readiness();\r\n\r\n return reply.code(result.status === \"ok\" ? 200 : 503).send(result);\r\n });\r\n }\r\n\r\n /**\r\n * Initialize HTTP server — bind app-registered routes to Fastify\r\n * then listen. Scanning here (not in `boot`) lets HTTP boot before\r\n * app code without losing routes.\r\n */\r\n public async start(): Promise<void> {\r\n const httpConfig = config.get(\"http\");\r\n\r\n if (!httpConfig || !this.http) return;\r\n\r\n if (Application.runtimeStrategy === \"development\") {\r\n router.scanDevServer(this.http);\r\n } else {\r\n router.scan(this.http);\r\n }\r\n\r\n // Surface the route table as a readiness signal + a boot log, so an empty\r\n // or partial route surface (e.g. a route module that failed to register) is\r\n // detectable instead of silently 404ing. `addRoutesRegisteredCheck` is\r\n // keyed by name, so re-running on restart is idempotent.\r\n health.addRoutesRegisteredCheck(() => router.routeCount());\r\n log.info(\"http\", \"routes\", `${router.routeCount()} route(s) registered`);\r\n\r\n try {\r\n // We can use the url of the server\r\n await this.http.listen({\r\n port: httpConfig.port,\r\n host: httpConfig.host || \"localhost\",\r\n });\r\n\r\n const baseUrl = config.get(\"app.baseUrl\");\r\n\r\n log.success(`http`, \"connection\", `Server ready at ${baseUrl}`);\r\n } catch (error) {\r\n devLogError(\"Error while starting http server\", error);\r\n\r\n // A failed listen()/port-bind at boot means the app can't serve — fatal.\r\n // devLogError above is the dev-server console UI and bypasses the logger\r\n // pipeline, so also route it through `log.fatal` to reach Sentry/file,\r\n // then `await log.flush()` to drain buffered/async channels before exit.\r\n await log.fatal(\"http\", \"connection\", error);\r\n await log.flush();\r\n\r\n process.exit(1); // stop the process, exit with error\r\n }\r\n\r\n this.active = true;\r\n }\r\n\r\n /**\r\n * Restart — needs a fresh Fastify instance since `start()` now\r\n * re-runs `router.scan()`, and re-scanning the same Fastify would\r\n * register duplicate route handlers.\r\n */\r\n public async restart(): Promise<void> {\r\n await this.shutdown();\r\n await this.boot();\r\n await this.start();\r\n }\r\n\r\n /**\r\n * Shutdown HTTP server\r\n */\r\n public async shutdown(): Promise<void> {\r\n if (!this.active) {\r\n return;\r\n }\r\n\r\n const server = getHttpServer();\r\n\r\n if (server) {\r\n const timeout = config.get(\"http.gracefulShutdown.timeout\", DEFAULT_SHUTDOWN_TIMEOUT);\r\n const drained = await closeServerWithTimeout(server, timeout);\r\n\r\n if (!drained) {\r\n log.warn(\r\n \"http\",\r\n \"shutdown\",\r\n `In-flight requests did not drain within ${timeout}ms; closing anyway`,\r\n );\r\n }\r\n }\r\n\r\n this.active = false;\r\n }\r\n\r\n /**\r\n * Override shouldRestart to handle routes.ts specially\r\n * routes.ts changes should NOT restart the server (use HMR instead)\r\n * Now receives config file paths directly from layer-executor\r\n */\r\n public shouldRestart(changedFiles: string[]): boolean {\r\n // Only restart for config changes, not routes\r\n return changedFiles.some((file) => {\r\n const relativePath = file.replace(/\\\\/g, \"/\");\r\n return this.watchedFiles.includes(relativePath);\r\n });\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
|
|
|
2
2
|
import { BaseConnector } from "./base-connector.mjs";
|
|
3
3
|
import { setLogConfigurations } from "../logger/logger.mjs";
|
|
4
4
|
import "../logger/index.mjs";
|
|
5
|
-
import
|
|
5
|
+
import config from "@mongez/config";
|
|
6
6
|
import { log } from "@warlock.js/logger";
|
|
7
7
|
|
|
8
8
|
//#region ../@warlock.js/core/src/connectors/logger-connector.ts
|
|
@@ -22,7 +22,7 @@ var LoggerConnector = class extends BaseConnector {
|
|
|
22
22
|
* Initialize logger configurations
|
|
23
23
|
*/
|
|
24
24
|
async start() {
|
|
25
|
-
const logConfig =
|
|
25
|
+
const logConfig = config.get("log");
|
|
26
26
|
if (!logConfig) return;
|
|
27
27
|
try {
|
|
28
28
|
setLogConfigurations(logConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger-connector.mjs","names":[
|
|
1
|
+
{"version":3,"file":"logger-connector.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/logger-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { log } from \"@warlock.js/logger\";\r\nimport { setLogConfigurations } from \"../logger\";\r\nimport { BaseConnector } from \"./base-connector\";\r\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\r\n\r\n/**\r\n * Logger Connector\r\n * Manages logger lifecycle and ensures synchronous flushing on termination\r\n */\r\nexport class LoggerConnector extends BaseConnector {\r\n public readonly name = \"logger\";\r\n public readonly priority = ConnectorPriority.LOGGER;\r\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\r\n\r\n /**\r\n * Files that trigger logger restart\r\n */\r\n protected readonly watchedFiles = [\"src/config/log.ts\", \"src/config/log.tsx\"];\r\n\r\n /**\r\n * Initialize logger configurations\r\n */\r\n public async start(): Promise<void> {\r\n const logConfig = config.get(\"log\");\r\n\r\n if (!logConfig) {\r\n return;\r\n }\r\n\r\n try {\r\n setLogConfigurations(logConfig);\r\n this.active = true;\r\n } catch (error) {\r\n console.error(\"Failed to initialize logger:\", error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown logger and flush messages synchronously\r\n */\r\n public async shutdown(): Promise<void> {\r\n if (!this.active) {\r\n return;\r\n }\r\n\r\n try {\r\n log.flushSync();\r\n this.active = false;\r\n } catch (error) {\r\n console.error(\"Failed to flush logger:\", error);\r\n throw error;\r\n }\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;AAUA,IAAa,kBAAb,cAAqC,cAAc;;;cAC1B;;;sBAOW,CAAC,qBAAqB,oBAAoB;;;;;CAK5E,MAAa,QAAuB;EAClC,MAAM,YAAY,OAAO,IAAI,KAAK;EAElC,IAAI,CAAC,WACH;EAGF,IAAI;GACF,qBAAqB,SAAS;GAC9B,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,QAAQ,MAAM,gCAAgC,KAAK;GACnD,MAAM;EACR;CACF;;;;CAKA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,IAAI;GACF,IAAI,UAAU;GACd,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,QAAQ,MAAM,2BAA2B,KAAK;GAC9C,MAAM;EACR;CACF;AACF"}
|
|
@@ -3,7 +3,7 @@ import { BaseConnector } from "./base-connector.mjs";
|
|
|
3
3
|
import { setMailConfigurations } from "../mail/config.mjs";
|
|
4
4
|
import { closeAllMailers } from "../mail/mailer-pool.mjs";
|
|
5
5
|
import "../mail/index.mjs";
|
|
6
|
-
import
|
|
6
|
+
import config from "@mongez/config";
|
|
7
7
|
|
|
8
8
|
//#region ../@warlock.js/core/src/connectors/mail-connector.ts
|
|
9
9
|
/**
|
|
@@ -26,7 +26,7 @@ var MailerConnector = class extends BaseConnector {
|
|
|
26
26
|
* Initialize mailer configurations
|
|
27
27
|
*/
|
|
28
28
|
async start() {
|
|
29
|
-
const mailConfig =
|
|
29
|
+
const mailConfig = config.get("mail");
|
|
30
30
|
if (!mailConfig) return;
|
|
31
31
|
try {
|
|
32
32
|
setMailConfigurations(mailConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mail-connector.mjs","names":[
|
|
1
|
+
{"version":3,"file":"mail-connector.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/mail-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { closeAllMailers, setMailConfigurations } from \"../mail\";\r\nimport { BaseConnector } from \"./base-connector\";\r\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\r\n\r\n/**\r\n * Mailer Connector\r\n * Manages mailer lifecycle and ensures graceful pool shutdown\r\n */\r\nexport class MailerConnector extends BaseConnector {\r\n public readonly name = \"mailer\";\r\n public readonly priority = ConnectorPriority.MAILER;\r\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\r\n\r\n /**\r\n * Files that trigger mailer restart\r\n */\r\n protected readonly watchedFiles = [\".env\", \"src/config/mail.ts\", \"src/config/mail.tsx\"];\r\n\r\n /**\r\n * Initialize mailer configurations\r\n */\r\n public async start(): Promise<void> {\r\n const mailConfig = config.get(\"mail\");\r\n\r\n if (!mailConfig) {\r\n return;\r\n }\r\n\r\n try {\r\n setMailConfigurations(mailConfig);\r\n this.active = true;\r\n } catch (error) {\r\n console.error(\"Failed to initialize mailer:\", error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown mailer pool\r\n */\r\n public async shutdown(): Promise<void> {\r\n if (!this.active) {\r\n return;\r\n }\r\n\r\n try {\r\n closeAllMailers();\r\n this.active = false;\r\n } catch (error) {\r\n console.error(\"Failed to close all mailers:\", error);\r\n throw error;\r\n }\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;AASA,IAAa,kBAAb,cAAqC,cAAc;;;cAC1B;;;sBAOW;GAAC;GAAQ;GAAsB;EAAqB;;;;;CAKtF,MAAa,QAAuB;EAClC,MAAM,aAAa,OAAO,IAAI,MAAM;EAEpC,IAAI,CAAC,YACH;EAGF,IAAI;GACF,sBAAsB,UAAU;GAChC,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,QAAQ,MAAM,gCAAgC,KAAK;GACnD,MAAM;EACR;CACF;;;;CAKA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,IAAI;GACF,gBAAgB;GAChB,KAAK,SAAS;EAChB,SAAS,OAAO;GACd,QAAQ,MAAM,gCAAgC,KAAK;GACnD,MAAM;EACR;CACF;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
|
|
2
2
|
import { BaseConnector } from "./base-connector.mjs";
|
|
3
|
-
import
|
|
3
|
+
import config from "@mongez/config";
|
|
4
4
|
import { log } from "@warlock.js/logger";
|
|
5
5
|
|
|
6
6
|
//#region ../@warlock.js/core/src/connectors/notifications-connector.ts
|
|
@@ -28,7 +28,7 @@ var NotificationsConnector = class extends BaseConnector {
|
|
|
28
28
|
* Register the notifications configuration with the package.
|
|
29
29
|
*/
|
|
30
30
|
async start() {
|
|
31
|
-
const notificationsConfig =
|
|
31
|
+
const notificationsConfig = config.get("notifications");
|
|
32
32
|
if (!notificationsConfig) return;
|
|
33
33
|
const { setNotificationConfig } = await import("@warlock.js/notifications");
|
|
34
34
|
setNotificationConfig(notificationsConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications-connector.mjs","names":[
|
|
1
|
+
{"version":3,"file":"notifications-connector.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/connectors/notifications-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { log } from \"@warlock.js/logger\";\nimport { BaseConnector } from \"./base-connector\";\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\n\n/**\n * Notifications Connector\n *\n * Wires `@warlock.js/notifications` from `src/config/notifications.ts` at boot:\n * reads the exported config object and hands it to the package's\n * `setNotificationConfig`. Config files stay declarative — they export the\n * config, the connector performs the side-effect.\n *\n * The package is lazy-imported (only when a notifications config is present),\n * so core carries no hard dependency on it — the same pattern as the herald\n * connector with `@warlock.js/herald`.\n */\nexport class NotificationsConnector extends BaseConnector {\n public readonly name = \"notifications\";\n public readonly priority = ConnectorPriority.NOTIFICATIONS;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger a notifications restart\n */\n protected readonly watchedFiles = [\"src/config/notifications.ts\"];\n\n /**\n * Register the notifications configuration with the package.\n */\n public async start(): Promise<void> {\n const notificationsConfig = config.get(\"notifications\");\n\n if (!notificationsConfig) {\n return;\n }\n\n const { setNotificationConfig } = await import(\"@warlock.js/notifications\");\n\n setNotificationConfig(notificationsConfig);\n this.active = true;\n\n log.info(\"notifications\", \"configured\", \"Notifications wired from config/notifications.ts\");\n }\n\n /**\n * Nothing to tear down — the package holds no external connection of its own\n * (the optional queue worker + its broker own their lifecycle). Clear the\n * active flag so a dev restart re-registers from the (possibly changed) config.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) {\n return;\n }\n\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,IAAa,yBAAb,cAA4C,cAAc;;;cACjC;;;sBAOW,CAAC,6BAA6B;;;;;CAKhE,MAAa,QAAuB;EAClC,MAAM,sBAAsB,OAAO,IAAI,eAAe;EAEtD,IAAI,CAAC,qBACH;EAGF,MAAM,EAAE,0BAA0B,MAAM,OAAO;EAE/C,sBAAsB,mBAAmB;EACzC,KAAK,SAAS;EAEd,IAAI,KAAK,iBAAiB,cAAc,kDAAkD;CAC5F;;;;;;CAOA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,KAAK,SAAS;CAChB;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { container } from "../container/index.mjs";
|
|
2
2
|
import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
|
|
3
3
|
import { BaseConnector } from "./base-connector.mjs";
|
|
4
|
-
import
|
|
4
|
+
import config from "@mongez/config";
|
|
5
5
|
import { log } from "@warlock.js/logger";
|
|
6
6
|
import { createServer } from "http";
|
|
7
7
|
import { createServer as createServer$1 } from "https";
|
|
@@ -40,7 +40,7 @@ var SocketConnector = class extends BaseConnector {
|
|
|
40
40
|
* Boot the connector
|
|
41
41
|
*/
|
|
42
42
|
async boot() {
|
|
43
|
-
const socketConfig =
|
|
43
|
+
const socketConfig = config.get("socket");
|
|
44
44
|
if (!socketConfig) return;
|
|
45
45
|
let SocketServer;
|
|
46
46
|
try {
|
|
@@ -66,7 +66,7 @@ var SocketConnector = class extends BaseConnector {
|
|
|
66
66
|
* Initialize Socket server
|
|
67
67
|
*/
|
|
68
68
|
async start() {
|
|
69
|
-
if (!
|
|
69
|
+
if (!config.get("socket") || !this.socket) return;
|
|
70
70
|
log.success("socket", "connection", "Established Socket.IO server");
|
|
71
71
|
this.active = true;
|
|
72
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-connector.mjs","names":["
|
|
1
|
+
{"version":3,"file":"socket-connector.mjs","names":["createHttpsServer","createHttpServer"],"sources":["../../../../../../../@warlock.js/core/src/connectors/socket-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { log } from \"@warlock.js/logger\";\nimport { createServer as createHttpServer } from \"http\";\nimport { createServer as createHttpsServer } from \"https\";\nimport type { Server } from \"socket.io\";\nimport { container } from \"../container\";\nimport { BaseConnector } from \"./base-connector\";\nimport { ConnectorLifecyclePhase, ConnectorName, ConnectorPriority } from \"./types\";\n\n/**\n * Shown when a project enables sockets (a `socket` config is present) but the\n * optional `socket.io` peer is not installed.\n */\nconst SOCKET_INSTALL_INSTRUCTIONS = `\nRealtime socket server requires the socket.io package.\nInstall it with:\n\n warlock add socket\n\nOr manually:\n\n npm install socket.io\n pnpm add socket.io\n yarn add socket.io\n`.trim();\n\n/**\n * Socket Connector\n * Manages Socket server (Socket.IO) lifecycle\n */\nexport class SocketConnector extends BaseConnector {\n public readonly name: ConnectorName = \"socket\";\n public readonly priority = ConnectorPriority.SOCKET;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Late;\n\n /**\n * Files that trigger Socket server restart\n * Note: routes.ts changes will be handled by HMR with wildcard routing\n * Connectors receive config file paths directly (not .env) thanks to layer-executor\n */\n protected readonly watchedFiles = [\"src/config/socket.ts\"];\n\n protected socket?: Server;\n\n /**\n * Whether this connector created the underlying node HTTP(S) server.\n *\n * When `http` is present, socket binds onto the HTTP connector's shared\n * `fastify.server` and must NOT close it on shutdown — the HTTP connector\n * owns the graceful drain. Socket only closes the node server when it\n * created one itself (http absent). See {@link shutdown}.\n */\n protected ownsRawServer = false;\n\n /**\n * Boot the connector\n */\n public async boot() {\n const socketConfig = config.get(\"socket\");\n\n if (!socketConfig) return;\n\n // socket.io is an optional peer — load it lazily so projects that don't use\n // realtime sockets never need it installed (mirrors the mail/storage drivers).\n let SocketServer: typeof import(\"socket.io\").Server;\n try {\n ({ Server: SocketServer } = await import(\"socket.io\"));\n } catch {\n throw new Error(SOCKET_INSTALL_INSTRUCTIONS);\n }\n\n log.info(\"socket\", \"connection\", \"Starting Socket.IO server\");\n\n // now we have two cases\n // 1. http is used, then use it (shared — the HTTP connector owns it)\n // 2. http is not used, then create a new server (we own it)\n let server;\n if (container.has(\"http.server\")) {\n const fastify = container.get(\"http.server\");\n server = fastify.server;\n this.ownsRawServer = false;\n } else {\n server = socketConfig.ssl ? createHttpsServer() : createHttpServer();\n server.listen(socketConfig.port);\n this.ownsRawServer = true;\n }\n\n container.set(\"socket.rawServer\", server);\n\n this.socket = new SocketServer(server, socketConfig.options);\n\n container.set(\"socket\", this.socket);\n }\n\n /**\n * Initialize Socket server\n */\n public async start(): Promise<void> {\n const socketConfig = config.get(\"socket\");\n\n // `this.socket` is only set by boot() once a socket config is present —\n // use it (not a never-assigned field) to detect a successful boot.\n if (!socketConfig || !this.socket) return;\n\n log.success(\"socket\", \"connection\", \"Established Socket.IO server\");\n\n this.active = true;\n }\n\n /**\n * Shutdown Socket server\n *\n * Always closes the Socket.IO layer (and awaits the drain). The underlying\n * node HTTP(S) server is only closed here when this connector created it\n * ({@link ownsRawServer}); when `http` owns the shared server, we leave it\n * for the HTTP connector to drain and close, so the two connectors don't\n * race to `close()` the same socket.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) {\n return;\n }\n\n if (container.has(\"socket\")) {\n const socket = container.get(\"socket\");\n // socket.io's close() takes a callback — await it so shutdown doesn't\n // report done while sockets are still draining.\n await new Promise<void>((resolve) => {\n socket.close(() => resolve());\n });\n }\n\n if (this.ownsRawServer && container.has(\"socket.rawServer\")) {\n const server = container.get(\"socket.rawServer\");\n await new Promise<void>((resolve, reject) => {\n server.close((error?: Error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n }\n\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAM,8BAA8B;;;;;;;;;;;EAWlC,KAAK;;;;;AAMP,IAAa,kBAAb,cAAqC,cAAc;;;cACX;;;sBASJ,CAAC,sBAAsB;uBAY/B;;;;;CAK1B,MAAa,OAAO;EAClB,MAAM,eAAe,OAAO,IAAI,QAAQ;EAExC,IAAI,CAAC,cAAc;EAInB,IAAI;EACJ,IAAI;GACF,CAAC,CAAE,QAAQ,gBAAiB,MAAM,OAAO;EAC3C,QAAQ;GACN,MAAM,IAAI,MAAM,2BAA2B;EAC7C;EAEA,IAAI,KAAK,UAAU,cAAc,2BAA2B;EAK5D,IAAI;EACJ,IAAI,UAAU,IAAI,aAAa,GAAG;GAEhC,SADgB,UAAU,IAAI,aACf,CAAC,CAAC;GACjB,KAAK,gBAAgB;EACvB,OAAO;GACL,SAAS,aAAa,MAAMA,eAAkB,IAAIC,aAAiB;GACnE,OAAO,OAAO,aAAa,IAAI;GAC/B,KAAK,gBAAgB;EACvB;EAEA,UAAU,IAAI,oBAAoB,MAAM;EAExC,KAAK,SAAS,IAAI,aAAa,QAAQ,aAAa,OAAO;EAE3D,UAAU,IAAI,UAAU,KAAK,MAAM;CACrC;;;;CAKA,MAAa,QAAuB;EAKlC,IAAI,CAJiB,OAAO,IAAI,QAIhB,KAAK,CAAC,KAAK,QAAQ;EAEnC,IAAI,QAAQ,UAAU,cAAc,8BAA8B;EAElE,KAAK,SAAS;CAChB;;;;;;;;;;CAWA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,IAAI,UAAU,IAAI,QAAQ,GAAG;GAC3B,MAAM,SAAS,UAAU,IAAI,QAAQ;GAGrC,MAAM,IAAI,SAAe,YAAY;IACnC,OAAO,YAAY,QAAQ,CAAC;GAC9B,CAAC;EACH;EAEA,IAAI,KAAK,iBAAiB,UAAU,IAAI,kBAAkB,GAAG;GAC3D,MAAM,SAAS,UAAU,IAAI,kBAAkB;GAC/C,MAAM,IAAI,SAAe,SAAS,WAAW;IAC3C,OAAO,OAAO,UAAkB;KAC9B,IAAI,OACF,OAAO,KAAK;UAEZ,QAAQ;IAEZ,CAAC;GACH,CAAC;EACH;EAEA,KAAK,SAAS;CAChB;AACF"}
|
package/esm/database/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DatabaseLogModel } from "./models/database-log/database-log.mjs";
|
|
2
|
-
import { SeedResult, SeederMetadata } from "./seeds/types.mjs";
|
|
2
|
+
import { SeedClock, SeedContext, SeedRecordRef, SeedResult, SeederMetadata, Track, TrackableModel } from "./seeds/types.mjs";
|
|
3
3
|
import { Seeder, seeder } from "./seeds/seeder.mjs";
|
|
4
|
+
import { SeederDependencyCycleError, UnknownSeederDependencyError } from "./seeds/seeder.errors.mjs";
|
|
4
5
|
import { useComputedModel, useComputedSlug, useHashedPassword } from "./utils.mjs";
|
package/esm/database/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DatabaseLogModel } from "./models/database-log/database-log.mjs";
|
|
2
2
|
import "./models/database-log/index.mjs";
|
|
3
3
|
import { seeder } from "./seeds/seeder.mjs";
|
|
4
|
+
import { SeederDependencyCycleError, UnknownSeederDependencyError } from "./seeds/seeder.errors.mjs";
|
|
4
5
|
import { useComputedModel, useComputedSlug, useHashedPassword } from "./utils.mjs";
|
|
5
6
|
|
|
6
7
|
export { };
|
|
@@ -3,8 +3,9 @@ import "../utils/index.mjs";
|
|
|
3
3
|
import { Path } from "../dev-server/path.mjs";
|
|
4
4
|
import { getFilesFromDirectory } from "../dev-server/utils.mjs";
|
|
5
5
|
import { filesOrchestrator } from "../dev-server/files-orchestrator.mjs";
|
|
6
|
+
import { seedRecordsTableName, seedsTableName } from "./seeds/utils.mjs";
|
|
6
7
|
import { SeedersManager } from "./seeds/seeders.manager.mjs";
|
|
7
|
-
import { dataSourceRegistry } from "@warlock.js/cascade";
|
|
8
|
+
import { dataSourceRegistry, transaction } from "@warlock.js/cascade";
|
|
8
9
|
import { colors } from "@mongez/copper";
|
|
9
10
|
|
|
10
11
|
//#region ../@warlock.js/core/src/database/seed-command-action.ts
|
|
@@ -13,6 +14,35 @@ async function clearAllTables(datasource) {
|
|
|
13
14
|
for (const table of tables) await datasource.driver.truncateTable(table, { cascade: true });
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
17
|
+
* Undo seeded data by deleting the records a seeder tracked via `track`.
|
|
18
|
+
*
|
|
19
|
+
* Reads `seed_records` (all seeders, or a single `seederName`), then deletes
|
|
20
|
+
* the referenced records in REVERSE seed-order and, within each seed, in
|
|
21
|
+
* reverse insertion-order. Insertion id is strictly increasing across the
|
|
22
|
+
* whole run, so deleting by descending `id` satisfies both at once. The whole
|
|
23
|
+
* operation runs in a single transaction, and the matching seeds-log rows are
|
|
24
|
+
* reset afterwards so `once: true` seeds re-run on the next `warlock seed`.
|
|
25
|
+
*
|
|
26
|
+
* @returns the number of tracked records deleted.
|
|
27
|
+
*/
|
|
28
|
+
async function dropSeedRecords(datasource, seederName) {
|
|
29
|
+
const driver = datasource.driver;
|
|
30
|
+
if (!await driver.blueprint.tableExists("_seed_records")) return 0;
|
|
31
|
+
const query = driver.queryBuilder(seedRecordsTableName);
|
|
32
|
+
if (seederName) query.where("seeder", seederName);
|
|
33
|
+
const rows = await query.get();
|
|
34
|
+
if (rows.length === 0) return 0;
|
|
35
|
+
const ordered = [...rows].sort((a, b) => b.id - a.id);
|
|
36
|
+
await transaction(async () => {
|
|
37
|
+
for (const row of ordered) await driver.deleteMany(row.table, { id: row.recordId });
|
|
38
|
+
if (seederName) await driver.deleteMany(seedRecordsTableName, { seeder: seederName });
|
|
39
|
+
else await driver.deleteMany(seedRecordsTableName, {});
|
|
40
|
+
const seederNames = seederName ? [seederName] : [...new Set(ordered.map((row) => row.seeder))];
|
|
41
|
+
for (const name of seederNames) await driver.deleteMany(seedsTableName, { name });
|
|
42
|
+
});
|
|
43
|
+
return ordered.length;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
16
46
|
* Run database seeds.
|
|
17
47
|
*
|
|
18
48
|
* @example
|
|
@@ -24,10 +54,20 @@ async function clearAllTables(datasource) {
|
|
|
24
54
|
* options: { fresh: true, list: false }
|
|
25
55
|
* });
|
|
26
56
|
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param overrides Programmatic-only overrides (e.g. an injected `clock`); the
|
|
59
|
+
* CLI never passes this, so the command-line signature stays unchanged.
|
|
27
60
|
*/
|
|
28
|
-
async function seedCommandAction(options) {
|
|
29
|
-
const { path, fresh, transaction, list } = options.options;
|
|
61
|
+
async function seedCommandAction(options, overrides) {
|
|
62
|
+
const { path, fresh, transaction, list, drop } = options.options;
|
|
30
63
|
const datasource = dataSourceRegistry.get();
|
|
64
|
+
if (drop) {
|
|
65
|
+
const seederName = typeof drop === "string" ? drop : void 0;
|
|
66
|
+
const deleted = await dropSeedRecords(datasource, seederName);
|
|
67
|
+
const scope = seederName ? colors.cyan(seederName) : "all seeders";
|
|
68
|
+
console.log(`🗑️ Dropped ${colors.redBright(deleted)} tracked record(s) for ${scope}; matching seeds-log entries reset.`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
31
71
|
if (fresh) await clearAllTables(datasource);
|
|
32
72
|
if (list) {
|
|
33
73
|
const seedFiles = await listSeedsFiles();
|
|
@@ -49,7 +89,7 @@ async function seedCommandAction(options) {
|
|
|
49
89
|
return;
|
|
50
90
|
}
|
|
51
91
|
const seeds = path ? [await loadSeedFile(Path.toAbsolute(path))] : await listSeedsFiles();
|
|
52
|
-
const seedersManager = new SeedersManager();
|
|
92
|
+
const seedersManager = new SeedersManager({ clock: overrides?.clock });
|
|
53
93
|
seedersManager.register(...seeds);
|
|
54
94
|
await seedersManager.run(transaction);
|
|
55
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed-command-action.mjs","names":[],"sources":["../../../../../../../@warlock.js/core/src/database/seed-command-action.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\
|
|
1
|
+
{"version":3,"file":"seed-command-action.mjs","names":["runInTransaction"],"sources":["../../../../../../../@warlock.js/core/src/database/seed-command-action.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n DataSource,\n dataSourceRegistry,\n transaction as runInTransaction,\n} from \"@warlock.js/cascade\";\nimport { CommandActionData } from \"../cli/types\";\nimport { filesOrchestrator } from \"../dev-server/files-orchestrator\";\nimport { Path } from \"../dev-server/path\";\nimport { getFilesFromDirectory } from \"../dev-server/utils\";\nimport { srcPath } from \"../utils\";\nimport { Seeder } from \"./seeds/seeder\";\nimport { SeedersManager } from \"./seeds/seeders.manager\";\nimport { SeedClock, SeedRecordRef } from \"./seeds/types\";\nimport { seedRecordsTableName, seedsTableName } from \"./seeds/utils\";\n\n/**\n * Programmatic-only overrides for {@link seedCommandAction}.\n *\n * Not derived from CLI flags (the CLI passes only {@link CommandActionData}),\n * so a back-fill script or a test can inject behaviour the command line can't\n * express.\n */\nexport type SeedCommandOverrides = {\n /**\n * Clock the run reads for the `now` handed to each seeder and for the\n * seeds-log metadata timestamps. Defaults to `() => new Date()`. Forwarded to\n * {@link SeedersManager}'s `clock` option.\n */\n clock?: SeedClock;\n};\n\nasync function clearAllTables(datasource: DataSource) {\n const tables = await datasource.driver.blueprint.listTables();\n\n for (const table of tables) {\n await datasource.driver.truncateTable(table, { cascade: true });\n }\n}\n\ntype SeedRecordRow = SeedRecordRef & { id: number };\n\n/**\n * Undo seeded data by deleting the records a seeder tracked via `track`.\n *\n * Reads `seed_records` (all seeders, or a single `seederName`), then deletes\n * the referenced records in REVERSE seed-order and, within each seed, in\n * reverse insertion-order. Insertion id is strictly increasing across the\n * whole run, so deleting by descending `id` satisfies both at once. The whole\n * operation runs in a single transaction, and the matching seeds-log rows are\n * reset afterwards so `once: true` seeds re-run on the next `warlock seed`.\n *\n * @returns the number of tracked records deleted.\n */\nexport async function dropSeedRecords(\n datasource: DataSource,\n seederName?: string,\n): Promise<number> {\n const driver = datasource.driver;\n\n if (!(await driver.blueprint.tableExists(seedRecordsTableName))) {\n return 0;\n }\n\n const query = driver.queryBuilder<SeedRecordRow>(seedRecordsTableName);\n\n if (seederName) {\n query.where(\"seeder\", seederName);\n }\n\n const rows = await query.get();\n\n if (rows.length === 0) {\n return 0;\n }\n\n // Descending insertion id == reverse seed-order + reverse within-seed order.\n const ordered = [...rows].sort((a, b) => b.id - a.id);\n\n await runInTransaction(async () => {\n for (const row of ordered) {\n await driver.deleteMany(row.table, { id: row.recordId });\n }\n\n // Clear the tracked refs we just acted on.\n if (seederName) {\n await driver.deleteMany(seedRecordsTableName, { seeder: seederName });\n } else {\n await driver.deleteMany(seedRecordsTableName, {});\n }\n\n // Reset the seeds-log rows so `once: true` seeds re-run.\n const seederNames = seederName\n ? [seederName]\n : [...new Set(ordered.map((row) => row.seeder))];\n\n for (const name of seederNames) {\n await driver.deleteMany(seedsTableName, { name });\n }\n });\n\n return ordered.length;\n}\n\n/**\n * Run database seeds.\n *\n * @example\n * ```ts\n * import { seedCommandAction } from \"@warlock.js/core\";\n *\n * await seedCommandAction({\n * command: \"seed\",\n * options: { fresh: true, list: false }\n * });\n * ```\n *\n * @param overrides Programmatic-only overrides (e.g. an injected `clock`); the\n * CLI never passes this, so the command-line signature stays unchanged.\n */\nexport async function seedCommandAction(\n options: CommandActionData,\n overrides?: SeedCommandOverrides,\n) {\n const { path, fresh, transaction, list, drop } = options.options;\n\n const datasource = dataSourceRegistry.get();\n\n if (drop) {\n // `--drop` (boolean) undoes every tracked record; `--drop=<name>` scopes to\n // a single seeder.\n const seederName = typeof drop === \"string\" ? drop : undefined;\n\n const deleted = await dropSeedRecords(datasource, seederName);\n\n const scope = seederName ? colors.cyan(seederName) : \"all seeders\";\n console.log(\n `🗑️ Dropped ${colors.redBright(deleted)} tracked record(s) for ${scope}; matching seeds-log entries reset.`,\n );\n return;\n }\n\n if (fresh) {\n await clearAllTables(datasource);\n }\n\n if (list) {\n const seedFiles = await listSeedsFiles();\n\n if (seedFiles.length === 0) {\n console.log(\"No seeds found.\");\n return;\n }\n\n const seedersManager = new SeedersManager();\n\n seedersManager.register(...seedFiles);\n\n const seeds = seedersManager.sort().seeders.map((seed) => {\n return {\n name: seed.name,\n order: seed.order,\n enabled: seed.enabled,\n };\n });\n\n console.table(seeds);\n\n console.log(\n `Total Seeds: ${colors.blueBright(seeds.length)}, enabled: ${colors.greenBright(seeds.filter((seed) => seed.enabled !== false).length)}, disabled: ${colors.redBright(seeds.filter((seed) => seed.enabled === false).length)}`,\n );\n return;\n }\n\n const seeds = path\n ? [await loadSeedFile(Path.toAbsolute(path as string))]\n : await listSeedsFiles();\n\n const seedersManager = new SeedersManager({ clock: overrides?.clock });\n\n seedersManager.register(...seeds);\n\n await seedersManager.run(transaction as boolean);\n}\n\nasync function listSeedsFiles() {\n const seedsFiles = await getFilesFromDirectory(srcPath(\"app\"), \"*/seeds/*.ts\");\n\n const seeds = [];\n\n for (const seedFile of seedsFiles) {\n const seed = await loadSeedFile(seedFile);\n seeds.push(seed);\n }\n\n return seeds;\n}\n\nasync function loadSeedFile(absPath: string): Promise<Seeder> {\n const relativePath = Path.toRelative(absPath);\n const seedImport = await filesOrchestrator.load<{ default: Seeder }>(relativePath);\n\n if (!seedImport || !seedImport.default) {\n throw new Error(`Seeder file ${relativePath} does not export a default seeder.`);\n }\n\n return seedImport.default;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { seedRecordsTableName } from "./utils.mjs";
|
|
2
|
+
import { Migration } from "@warlock.js/cascade";
|
|
3
|
+
|
|
4
|
+
//#region ../@warlock.js/core/src/database/seeds/seed-records-table-migration.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates the `seed_records` table that backs `warlock seed --drop`.
|
|
7
|
+
*
|
|
8
|
+
* Each row is a reference to a single record a seeder created, captured via the
|
|
9
|
+
* `track` helper inside the same transaction the seed ran in. `--drop` reads
|
|
10
|
+
* these refs to delete exactly (and only) the records a seed produced, then
|
|
11
|
+
* resets the matching seeds-log row so a `once: true` seed can re-run.
|
|
12
|
+
*/
|
|
13
|
+
var SeedRecordsTableMigration = class extends Migration {
|
|
14
|
+
constructor(..._args) {
|
|
15
|
+
super(..._args);
|
|
16
|
+
this.table = seedRecordsTableName;
|
|
17
|
+
}
|
|
18
|
+
static {
|
|
19
|
+
this.migrationName = "seed-records-table-migration";
|
|
20
|
+
}
|
|
21
|
+
up() {
|
|
22
|
+
this.createTableIfNotExists();
|
|
23
|
+
this.id();
|
|
24
|
+
this.text("seeder");
|
|
25
|
+
this.text("table");
|
|
26
|
+
this.text("recordId");
|
|
27
|
+
this.dateTime("runAt").useCurrent();
|
|
28
|
+
}
|
|
29
|
+
down() {
|
|
30
|
+
this.dropTableIfExists(seedRecordsTableName);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { SeedRecordsTableMigration };
|
|
36
|
+
//# sourceMappingURL=seed-records-table-migration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-records-table-migration.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/database/seeds/seed-records-table-migration.ts"],"sourcesContent":["import { Migration } from \"@warlock.js/cascade\";\nimport { seedRecordsTableName } from \"./utils\";\n\n/**\n * Creates the `seed_records` table that backs `warlock seed --drop`.\n *\n * Each row is a reference to a single record a seeder created, captured via the\n * `track` helper inside the same transaction the seed ran in. `--drop` reads\n * these refs to delete exactly (and only) the records a seed produced, then\n * resets the matching seeds-log row so a `once: true` seed can re-run.\n */\nexport class SeedRecordsTableMigration extends Migration {\n public static migrationName = \"seed-records-table-migration\";\n public table = seedRecordsTableName;\n\n public up() {\n this.createTableIfNotExists();\n\n this.id();\n this.text(\"seeder\");\n this.text(\"table\");\n this.text(\"recordId\");\n this.dateTime(\"runAt\").useCurrent();\n }\n\n public down() {\n this.dropTableIfExists(seedRecordsTableName);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAa,4BAAb,cAA+C,UAAU;;;eAExC;;;uBADe;;CAG9B,AAAO,KAAK;EACV,KAAK,uBAAuB;EAE5B,KAAK,GAAG;EACR,KAAK,KAAK,QAAQ;EAClB,KAAK,KAAK,OAAO;EACjB,KAAK,KAAK,UAAU;EACpB,KAAK,SAAS,OAAO,CAAC,CAAC,WAAW;CACpC;CAEA,AAAO,OAAO;EACZ,KAAK,kBAAkB,oBAAoB;CAC7C;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SeedResult } from "./types.mjs";
|
|
1
|
+
import { SeedContext, SeedResult } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
//#region ../@warlock.js/core/src/database/seeds/seeder.d.ts
|
|
4
4
|
type Seeder = {
|
|
@@ -27,13 +27,30 @@ type Seeder = {
|
|
|
27
27
|
*/
|
|
28
28
|
order?: number;
|
|
29
29
|
/**
|
|
30
|
-
* Batch size
|
|
30
|
+
* Batch size.
|
|
31
|
+
*
|
|
32
|
+
* Surfaced to `run()` as {@link SeedContext.batchSize} (defaulting to this
|
|
33
|
+
* value, or `0` when unset) so a seed can forward it to
|
|
34
|
+
* `Model.createMany(rows, { batchSize })`.
|
|
31
35
|
*/
|
|
32
36
|
batchSize?: number;
|
|
33
37
|
/**
|
|
34
|
-
* Run seed
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
* Run seed.
|
|
39
|
+
*
|
|
40
|
+
* Receives a {@link SeedContext} exposing:
|
|
41
|
+
* - `track` — registers the records this seed creates so they can be undone
|
|
42
|
+
* by `warlock seed --drop`. Auto-derives `recordsCreated` from the track
|
|
43
|
+
* count; an explicitly returned {@link SeedResult} is an optional fallback.
|
|
44
|
+
* - `now` — the injectable clock to read instead of an ambient `new Date()` /
|
|
45
|
+
* `dayjs()`, so historical seeds and the seeds-log share one overridable
|
|
46
|
+
* clock.
|
|
47
|
+
* - `batchSize` — the suggested bulk-insert batch size (from this seeder's
|
|
48
|
+
* `batchSize`, default `0`).
|
|
49
|
+
*
|
|
50
|
+
* The `ctx` parameter is optional at the call site — an existing zero-arg
|
|
51
|
+
* `run()` keeps working unchanged.
|
|
52
|
+
*/
|
|
53
|
+
run(ctx: SeedContext): Promise<SeedResult | void>;
|
|
37
54
|
};
|
|
38
55
|
/**
|
|
39
56
|
* Create a new seeder
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seeder.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/core/src/database/seeds/seeder.ts"],"mappings":";;;KAEY,MAAA;;AAAZ;;EAIE,IAAA;
|
|
1
|
+
{"version":3,"file":"seeder.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/core/src/database/seeds/seeder.ts"],"mappings":";;;KAEY,MAAA;;AAAZ;;EAIE,IAAA;EA6CS;;;EAzCT,OAAA;EAyC8B;;;EArC9B,WAAA;EAIA;;;EAAA,SAAA;EAiCA;;;EA7BA,IAAA;EA6B+B;;AAAU;EAzBzC,KAAA;EA+BoB;;;;;;;EAvBpB,SAAA;;;;;;;;;;;;;;;;;EAiBA,GAAA,CAAI,GAAA,EAAK,WAAA,GAAc,OAAA,CAAQ,UAAA;AAAA;;;;iBAMjB,MAAA,CAAO,MAAA,EAAQ,MAAA,GAAM,MAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region ../@warlock.js/core/src/database/seeds/seeder.errors.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when a seeder's `dependsOn` references a seeder name that is not
|
|
4
|
+
* registered with the manager. Surfaces the offending dependent + the missing
|
|
5
|
+
* dependency so the misconfiguration is obvious without spelunking.
|
|
6
|
+
*/
|
|
7
|
+
declare class UnknownSeederDependencyError extends Error {
|
|
8
|
+
readonly seeder: string;
|
|
9
|
+
readonly dependency: string;
|
|
10
|
+
constructor(seeder: string, dependency: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Thrown when the `dependsOn` graph contains a cycle, which would make a
|
|
14
|
+
* deterministic run order impossible. Carries the cycle path for diagnosis.
|
|
15
|
+
*/
|
|
16
|
+
declare class SeederDependencyCycleError extends Error {
|
|
17
|
+
readonly cycle: string[];
|
|
18
|
+
constructor(cycle: string[]);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { SeederDependencyCycleError, UnknownSeederDependencyError };
|
|
22
|
+
//# sourceMappingURL=seeder.errors.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seeder.errors.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/core/src/database/seeds/seeder.errors.ts"],"mappings":";;AAKA;;;;cAAa,4BAAA,SAAqC,KAAK;EAAA,SAEnC,MAAA;EAAA,SACA,UAAA;cADA,MAAA,UACA,UAAA;AAAA;;;AAAkB;AAatC;cAAa,0BAAA,SAAmC,KAAK;EAAA,SAChB,KAAA;cAAA,KAAA;AAAA"}
|