@warlock.js/core 4.10.0 → 4.12.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.
Files changed (144) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/esm/application/application.d.mts +19 -0
  3. package/esm/application/application.d.mts.map +1 -1
  4. package/esm/application/application.mjs +25 -0
  5. package/esm/application/application.mjs.map +1 -1
  6. package/esm/application/boot-signal.d.mts +77 -0
  7. package/esm/application/boot-signal.d.mts.map +1 -0
  8. package/esm/application/boot-signal.mjs +64 -0
  9. package/esm/application/boot-signal.mjs.map +1 -0
  10. package/esm/application/index.d.mts +1 -0
  11. package/esm/application/index.mjs +1 -0
  12. package/esm/bootstrap.mjs +2 -2
  13. package/esm/bootstrap.mjs.map +1 -1
  14. package/esm/cli/cli-commands.manager.mjs +31 -8
  15. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  16. package/esm/cli/cli-commands.utils.mjs +57 -1
  17. package/esm/cli/cli-commands.utils.mjs.map +1 -1
  18. package/esm/cli/commands/add.command.mjs +4 -2
  19. package/esm/cli/commands/add.command.mjs.map +1 -1
  20. package/esm/cli/commands/generate/generate.command.mjs +42 -21
  21. package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
  22. package/esm/cli/commands/generate/generators/module.generator.mjs +1 -1
  23. package/esm/cli/commands/generate/generators/module.generator.mjs.map +1 -1
  24. package/esm/cli/commands/migrate.command.mjs +6 -2
  25. package/esm/cli/commands/migrate.command.mjs.map +1 -1
  26. package/esm/cli/commands/start-production.command.mjs +4 -25
  27. package/esm/cli/commands/start-production.command.mjs.map +1 -1
  28. package/esm/cli/parse-cli-args.mjs +86 -9
  29. package/esm/cli/parse-cli-args.mjs.map +1 -1
  30. package/esm/cli/types.d.mts +6 -1
  31. package/esm/cli/types.d.mts.map +1 -1
  32. package/esm/config/config-getter.mjs +5 -5
  33. package/esm/config/config-getter.mjs.map +1 -1
  34. package/esm/config/config-loader.mjs +2 -2
  35. package/esm/config/config-loader.mjs.map +1 -1
  36. package/esm/config/config-setter.d.mts +27 -0
  37. package/esm/config/config-setter.d.mts.map +1 -0
  38. package/esm/config/config-setter.mjs +10 -0
  39. package/esm/config/config-setter.mjs.map +1 -0
  40. package/esm/config/index.mjs +1 -0
  41. package/esm/connectors/access-connector.mjs +2 -2
  42. package/esm/connectors/access-connector.mjs.map +1 -1
  43. package/esm/connectors/ai-connector.mjs +2 -2
  44. package/esm/connectors/ai-connector.mjs.map +1 -1
  45. package/esm/connectors/cache-connector.mjs +2 -2
  46. package/esm/connectors/cache-connector.mjs.map +1 -1
  47. package/esm/connectors/database-connector.mjs +2 -2
  48. package/esm/connectors/database-connector.mjs.map +1 -1
  49. package/esm/connectors/herald-connector.mjs +2 -2
  50. package/esm/connectors/herald-connector.mjs.map +1 -1
  51. package/esm/connectors/http-connector.d.mts.map +1 -1
  52. package/esm/connectors/http-connector.mjs +8 -7
  53. package/esm/connectors/http-connector.mjs.map +1 -1
  54. package/esm/connectors/logger-connector.mjs +2 -2
  55. package/esm/connectors/logger-connector.mjs.map +1 -1
  56. package/esm/connectors/mail-connector.mjs +2 -2
  57. package/esm/connectors/mail-connector.mjs.map +1 -1
  58. package/esm/connectors/notifications-connector.mjs +2 -2
  59. package/esm/connectors/notifications-connector.mjs.map +1 -1
  60. package/esm/connectors/socket-connector.mjs +3 -3
  61. package/esm/connectors/socket-connector.mjs.map +1 -1
  62. package/esm/connectors/storage.connector.d.mts +11 -5
  63. package/esm/connectors/storage.connector.d.mts.map +1 -1
  64. package/esm/connectors/storage.connector.mjs +11 -5
  65. package/esm/connectors/storage.connector.mjs.map +1 -1
  66. package/esm/database/migrate-action.mjs +53 -1
  67. package/esm/database/migrate-action.mjs.map +1 -1
  68. package/esm/database/pending-exit-code.mjs +39 -0
  69. package/esm/database/pending-exit-code.mjs.map +1 -0
  70. package/esm/database/resolve-pending-migrations.mjs +49 -0
  71. package/esm/database/resolve-pending-migrations.mjs.map +1 -0
  72. package/esm/dev-server/loader/load-hook.mjs +1 -1
  73. package/esm/generations/stubs.mjs +1 -1
  74. package/esm/generations/stubs.mjs.map +1 -1
  75. package/esm/http/config.mjs +2 -2
  76. package/esm/http/config.mjs.map +1 -1
  77. package/esm/http/createHttpApplication.mjs +2 -2
  78. package/esm/http/createHttpApplication.mjs.map +1 -1
  79. package/esm/http/index.d.mts +1 -0
  80. package/esm/http/index.mjs +1 -0
  81. package/esm/http/middleware/idempotency.middleware.mjs +5 -5
  82. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  83. package/esm/http/middleware/inject-request-context.mjs +2 -2
  84. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  85. package/esm/http/middleware/maintenance.middleware.mjs +4 -4
  86. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  87. package/esm/http/plugins.mjs +9 -9
  88. package/esm/http/plugins.mjs.map +1 -1
  89. package/esm/http/port-preflight.d.mts +34 -0
  90. package/esm/http/port-preflight.d.mts.map +1 -0
  91. package/esm/http/port-preflight.mjs +66 -0
  92. package/esm/http/port-preflight.mjs.map +1 -0
  93. package/esm/http/response.mjs +5 -5
  94. package/esm/http/response.mjs.map +1 -1
  95. package/esm/http/server.mjs +4 -4
  96. package/esm/http/server.mjs.map +1 -1
  97. package/esm/image/image.d.mts +3 -2
  98. package/esm/image/image.d.mts.map +1 -1
  99. package/esm/image/image.mjs +63 -17
  100. package/esm/image/image.mjs.map +1 -1
  101. package/esm/index.d.mts +6 -2
  102. package/esm/index.mjs +5 -1
  103. package/esm/mail/mailer-pool.d.mts.map +1 -1
  104. package/esm/mail/mailer-pool.mjs.map +1 -1
  105. package/esm/production/assert-generated-imports.mjs +94 -0
  106. package/esm/production/assert-generated-imports.mjs.map +1 -0
  107. package/esm/production/production-builder.mjs +29 -4
  108. package/esm/production/production-builder.mjs.map +1 -1
  109. package/esm/production/production-supervisor.mjs +108 -0
  110. package/esm/production/production-supervisor.mjs.map +1 -0
  111. package/esm/react/index.d.mts +4 -0
  112. package/esm/react/index.d.mts.map +1 -1
  113. package/esm/react/index.mjs +88 -14
  114. package/esm/react/index.mjs.map +1 -1
  115. package/esm/storage/storage.d.mts +16 -0
  116. package/esm/storage/storage.d.mts.map +1 -1
  117. package/esm/storage/storage.mjs +24 -1
  118. package/esm/storage/storage.mjs.map +1 -1
  119. package/esm/tests/index.d.mts +2 -1
  120. package/esm/tests/index.mjs +1 -0
  121. package/esm/tests/start-http-development-server.d.mts +15 -2
  122. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  123. package/esm/tests/start-http-development-server.mjs +43 -16
  124. package/esm/tests/start-http-development-server.mjs.map +1 -1
  125. package/esm/tests/test-helpers.d.mts.map +1 -1
  126. package/esm/tests/test-helpers.mjs +2 -1
  127. package/esm/tests/test-helpers.mjs.map +1 -1
  128. package/esm/tests/test-server-port-channel.d.mts +27 -0
  129. package/esm/tests/test-server-port-channel.d.mts.map +1 -0
  130. package/esm/tests/test-server-port-channel.mjs +32 -0
  131. package/esm/tests/test-server-port-channel.mjs.map +1 -0
  132. package/esm/utils/load-environment.mjs +59 -0
  133. package/esm/utils/load-environment.mjs.map +1 -0
  134. package/esm/utils/paths.mjs +2 -2
  135. package/esm/utils/paths.mjs.map +1 -1
  136. package/esm/validation/validateAll.mjs +2 -2
  137. package/esm/validation/validateAll.mjs.map +1 -1
  138. package/llms-full.txt +90 -3
  139. package/llms.txt +1 -1
  140. package/package.json +13 -13
  141. package/skills/process-image/SKILL.md +3 -1
  142. package/skills/run-app/SKILL.md +63 -0
  143. package/skills/test-http/SKILL.md +27 -3
  144. package/skills/write-cli-command/SKILL.md +19 -1
@@ -1,7 +1,6 @@
1
1
  import { command } from "../cli-command.mjs";
2
- import { displayStartupBanner } from "../cli-commands.utils.mjs";
3
2
  import { resolveBuildConfig } from "../../production/resolve-build-config.mjs";
4
- import { spawn } from "child_process";
3
+ import { superviseProductionProcess } from "../../production/production-supervisor.mjs";
5
4
 
6
5
  //#region ../core/src/cli/commands/start-production.command.ts
7
6
  const startProductionCommand = command({
@@ -9,9 +8,6 @@ const startProductionCommand = command({
9
8
  description: "Start production server",
10
9
  persistent: true,
11
10
  preload: { warlockConfig: true },
12
- preAction: async () => {
13
- displayStartupBanner({ environment: "production" });
14
- },
15
11
  action: async () => {
16
12
  const { entryPath, sourcemap } = resolveBuildConfig();
17
13
  const nodeArgs = [];
@@ -22,26 +18,9 @@ const startProductionCommand = command({
22
18
  const extraArgs = process.argv.slice(startIndex + 1);
23
19
  nodeArgs.push(...extraArgs);
24
20
  }
25
- console.log(`🚀 Starting production server...\n`);
26
- const child = spawn(process.execPath, nodeArgs, {
27
- stdio: "inherit",
28
- cwd: process.cwd(),
29
- env: process.env,
30
- detached: false
31
- });
32
- let isShuttingDown = false;
33
- const forwardSignal = (signal) => {
34
- if (isShuttingDown) return;
35
- isShuttingDown = true;
36
- child.kill(signal);
37
- };
38
- process.on("SIGTERM", () => forwardSignal("SIGTERM"));
39
- process.on("SIGINT", () => {
40
- isShuttingDown = true;
41
- });
42
- child.on("exit", (code) => {
43
- process.exit(code ?? 0);
44
- });
21
+ console.error(`🚀 Starting production server...\n`);
22
+ const { exitCode } = await superviseProductionProcess({ nodeArgs });
23
+ process.exit(exitCode);
45
24
  }
46
25
  });
47
26
 
@@ -1 +1 @@
1
- {"version":3,"file":"start-production.command.mjs","names":[],"sources":["../../../../../../../../core/src/cli/commands/start-production.command.ts"],"sourcesContent":["import { spawn } from \"child_process\";\nimport { resolveBuildConfig } from \"../../production/resolve-build-config\";\nimport { command } from \"../cli-command\";\nimport { displayStartupBanner } from \"../cli-commands.utils\";\n\nexport const startProductionCommand = command({\n name: \"start\",\n description: \"Start production server\",\n persistent: true,\n preload: {\n warlockConfig: true,\n },\n preAction: async () => {\n displayStartupBanner({ environment: \"production\" });\n },\n action: async () => {\n const { entryPath, sourcemap } = resolveBuildConfig();\n\n // Build node args\n const nodeArgs: string[] = [];\n\n // Enable source maps if configured\n if (sourcemap !== false) {\n nodeArgs.push(\"--enable-source-maps\");\n }\n\n // Add entry file\n nodeArgs.push(entryPath);\n\n // Pass through any additional flags after \"start\" command\n // process.argv = [node, cli.ts, start, ...extra]\n const startIndex = process.argv.findIndex((arg) => arg === \"start\");\n if (startIndex !== -1 && startIndex < process.argv.length - 1) {\n const extraArgs = process.argv.slice(startIndex + 1);\n nodeArgs.push(...extraArgs);\n }\n\n console.log(`🚀 Starting production server...\\n`);\n\n // Spawn child process\n // On Windows, we need to be careful with signals - the console sends Ctrl+C\n // to all processes in the group, so we just need to not interfere\n // `process.execPath`, not \"node\": the bare name needs `node` on PATH, which\n // a systemd unit, a cron job, or a slim container may not provide and a\n // PATH `node` that *is* present can be a different version than the one\n // running this CLI. execPath is the binary already executing us.\n const child = spawn(process.execPath, nodeArgs, {\n stdio: \"inherit\",\n cwd: process.cwd(),\n env: process.env,\n // Important: keep child in same process group for proper signal handling\n detached: false,\n });\n\n // Track if we're shutting down to prevent double-exit\n let isShuttingDown = false;\n\n // Forward signals to child (needed for SIGTERM, helpful for explicit forwarding)\n const forwardSignal = (signal: NodeJS.Signals) => {\n if (isShuttingDown) return;\n isShuttingDown = true;\n\n // Send signal to child\n child.kill(signal);\n };\n\n // On SIGTERM, forward it (SIGTERM doesn't auto-propagate like SIGINT on Windows)\n process.on(\"SIGTERM\", () => forwardSignal(\"SIGTERM\"));\n\n // On SIGINT (Ctrl+C), mark as shutting down but let child handle it naturally\n // On Windows, Ctrl+C is sent to both processes, so child already gets it\n process.on(\"SIGINT\", () => {\n isShuttingDown = true;\n // Give child a chance to exit gracefully before we do anything\n });\n\n // Exit with child's exit code\n child.on(\"exit\", (code) => {\n process.exit(code ?? 0);\n });\n },\n});\n"],"mappings":";;;;;;AAKA,MAAa,yBAAyB,QAAQ;CAC5C,MAAM;CACN,aAAa;CACb,YAAY;CACZ,SAAS,EACP,eAAe,KACjB;CACA,WAAW,YAAY;EACrB,qBAAqB,EAAE,aAAa,aAAa,CAAC;CACpD;CACA,QAAQ,YAAY;EAClB,MAAM,EAAE,WAAW,cAAc,mBAAmB;EAGpD,MAAM,WAAqB,CAAC;EAG5B,IAAI,cAAc,OAChB,SAAS,KAAK,sBAAsB;EAItC,SAAS,KAAK,SAAS;EAIvB,MAAM,aAAa,QAAQ,KAAK,WAAW,QAAQ,QAAQ,OAAO;EAClE,IAAI,eAAe,MAAM,aAAa,QAAQ,KAAK,SAAS,GAAG;GAC7D,MAAM,YAAY,QAAQ,KAAK,MAAM,aAAa,CAAC;GACnD,SAAS,KAAK,GAAG,SAAS;EAC5B;EAEA,QAAQ,IAAI,oCAAoC;EAShD,MAAM,QAAQ,MAAM,QAAQ,UAAU,UAAU;GAC9C,OAAO;GACP,KAAK,QAAQ,IAAI;GACjB,KAAK,QAAQ;GAEb,UAAU;EACZ,CAAC;EAGD,IAAI,iBAAiB;EAGrB,MAAM,iBAAiB,WAA2B;GAChD,IAAI,gBAAgB;GACpB,iBAAiB;GAGjB,MAAM,KAAK,MAAM;EACnB;EAGA,QAAQ,GAAG,iBAAiB,cAAc,SAAS,CAAC;EAIpD,QAAQ,GAAG,gBAAgB;GACzB,iBAAiB;EAEnB,CAAC;EAGD,MAAM,GAAG,SAAS,SAAS;GACzB,QAAQ,KAAK,QAAQ,CAAC;EACxB,CAAC;CACH;AACF,CAAC"}
1
+ {"version":3,"file":"start-production.command.mjs","names":[],"sources":["../../../../../../../../core/src/cli/commands/start-production.command.ts"],"sourcesContent":["import { superviseProductionProcess } from \"../../production/production-supervisor\";\nimport { resolveBuildConfig } from \"../../production/resolve-build-config\";\nimport { command } from \"../cli-command\";\n\nexport const startProductionCommand = command({\n name: \"start\",\n description: \"Start production server\",\n persistent: true,\n preload: {\n warlockConfig: true,\n },\n action: async () => {\n const { entryPath, sourcemap } = resolveBuildConfig();\n\n // Build node args\n const nodeArgs: string[] = [];\n\n // Enable source maps if configured\n if (sourcemap !== false) {\n nodeArgs.push(\"--enable-source-maps\");\n }\n\n // Add entry file\n nodeArgs.push(entryPath);\n\n // Pass through any additional flags after \"start\" command\n // process.argv = [node, cli.ts, start, ...extra]\n const startIndex = process.argv.findIndex((arg) => arg === \"start\");\n if (startIndex !== -1 && startIndex < process.argv.length - 1) {\n const extraArgs = process.argv.slice(startIndex + 1);\n nodeArgs.push(...extraArgs);\n }\n\n // Progress goes to stderr, never stdout. Stdout carries exactly one claim —\n // \"started\" — so that whatever greps it cannot mistake an intention for an\n // outcome. The banner that used to print here, in `preAction`, printed\n // before the child had even been spawned.\n console.error(`🚀 Starting production server...\\n`);\n\n const { exitCode } = await superviseProductionProcess({ nodeArgs });\n\n process.exit(exitCode);\n },\n});\n"],"mappings":";;;;;AAIA,MAAa,yBAAyB,QAAQ;CAC5C,MAAM;CACN,aAAa;CACb,YAAY;CACZ,SAAS,EACP,eAAe,KACjB;CACA,QAAQ,YAAY;EAClB,MAAM,EAAE,WAAW,cAAc,mBAAmB;EAGpD,MAAM,WAAqB,CAAC;EAG5B,IAAI,cAAc,OAChB,SAAS,KAAK,sBAAsB;EAItC,SAAS,KAAK,SAAS;EAIvB,MAAM,aAAa,QAAQ,KAAK,WAAW,QAAQ,QAAQ,OAAO;EAClE,IAAI,eAAe,MAAM,aAAa,QAAQ,KAAK,SAAS,GAAG;GAC7D,MAAM,YAAY,QAAQ,KAAK,MAAM,aAAa,CAAC;GACnD,SAAS,KAAK,GAAG,SAAS;EAC5B;EAMA,QAAQ,MAAM,oCAAoC;EAElD,MAAM,EAAE,aAAa,MAAM,2BAA2B,EAAE,SAAS,CAAC;EAElE,QAAQ,KAAK,QAAQ;CACvB;AACF,CAAC"}
@@ -2,22 +2,93 @@ import { toCamelCase } from "@mongez/reinforcements";
2
2
 
3
3
  //#region ../core/src/cli/parse-cli-args.ts
4
4
  /**
5
+ * Thrown when a declared boolean option is given a value that is neither
6
+ * true-ish nor false-ish.
7
+ *
8
+ * We refuse to guess. Guessing is exactly what produced #21: `--rollback=false`
9
+ * was kept as the truthy string `"false"` and dropped every table. An option
10
+ * that gates a destructive action must fail loudly on input it cannot read.
11
+ */
12
+ var CliOptionValueError = class extends Error {
13
+ constructor(optionToken, value) {
14
+ super(`Invalid value ${JSON.stringify(value)} for boolean option ${optionToken}. Expected one of: true, false, 1, 0, yes, no — or pass ${optionToken} on its own for true.`);
15
+ this.optionToken = optionToken;
16
+ this.value = value;
17
+ this.name = "CliOptionValueError";
18
+ }
19
+ };
20
+ const TRUE_VALUES = new Set([
21
+ "true",
22
+ "1",
23
+ "yes"
24
+ ]);
25
+ const FALSE_VALUES = new Set([
26
+ "false",
27
+ "0",
28
+ "no"
29
+ ]);
30
+ /**
31
+ * Collect the camelCased keys (names AND aliases) of every option the command
32
+ * declared as `type: "boolean"`.
33
+ *
34
+ * Both sides are camelCased because declared names keep their raw kebab form
35
+ * (`"pending-only"`) while the parser emits camelCase keys (`pendingOnly`).
36
+ */
37
+ function collectBooleanKeys(schema) {
38
+ const keys = /* @__PURE__ */ new Set();
39
+ for (const option of schema) {
40
+ if (option.type !== "boolean") continue;
41
+ if (option.name) keys.add(toCamelCase(option.name));
42
+ if (option.alias) keys.add(toCamelCase(option.alias));
43
+ }
44
+ return keys;
45
+ }
46
+ /**
47
+ * Turn the value written after `=` into a real boolean, or throw.
48
+ */
49
+ function toBoolean(optionToken, value) {
50
+ const normalized = value.toLowerCase();
51
+ if (TRUE_VALUES.has(normalized)) return true;
52
+ if (FALSE_VALUES.has(normalized)) return false;
53
+ throw new CliOptionValueError(optionToken, value);
54
+ }
55
+ /**
5
56
  * Parse CLI arguments from process.argv
6
57
  *
58
+ * Called with a `schema` (the resolved command's declared options), every
59
+ * option declared `type: "boolean"` is resolved as a boolean:
60
+ * `--flag` → true, `--flag=false|0|no` → false, `--flag=true|1|yes` → true,
61
+ * and `--flag <token>` leaves `<token>` as a POSITIONAL instead of swallowing
62
+ * it as the flag's value. Anything else throws {@link CliOptionValueError}.
63
+ *
64
+ * Called without a schema — which is how the command name is discovered,
65
+ * before any command object exists — behaviour is unchanged: every value stays
66
+ * a raw string and a bare `--flag` still consumes the following non-dash token.
67
+ * Nothing is blanket-coerced here on purpose: `--name=false` on a string-typed
68
+ * option must survive as the string `"false"`.
69
+ *
70
+ * Options the schema does not declare keep the schema-less behaviour.
71
+ *
7
72
  * @example
8
73
  * parseCliArgs(["node", "warlock", "migrate", "--rollback", "file.ts"])
9
74
  * // Returns: { name: "migrate", args: [], options: { rollback: "file.ts" } }
10
75
  *
11
76
  * @example
77
+ * // `rollback` declared as type: "boolean" — the file stays a positional
78
+ * parseCliArgs(["node", "warlock", "migrate", "--rollback", "file.ts"], migrateOptions)
79
+ * // Returns: { name: "migrate", args: ["file.ts"], options: { rollback: true } }
80
+ *
81
+ * @example
12
82
  * parseCliArgs(["node", "warlock", "dev", "--port=3000", "--fresh"])
13
83
  * // Returns: { name: "dev", args: [], options: { port: "3000", fresh: true } }
14
84
  */
15
- function parseCliArgs(argv) {
85
+ function parseCliArgs(argv, schema = []) {
16
86
  const potentialCommand = argv[2] || "";
17
87
  const isFirstArgOption = potentialCommand.startsWith("-");
18
88
  const command = isFirstArgOption ? "" : potentialCommand;
19
89
  const args = [];
20
90
  const options = {};
91
+ const booleanKeys = collectBooleanKeys(schema);
21
92
  const startIndex = isFirstArgOption ? 2 : 3;
22
93
  for (let i = startIndex; i < argv.length; i++) {
23
94
  const arg = argv[i];
@@ -26,11 +97,13 @@ function parseCliArgs(argv) {
26
97
  const equalIndex = withoutDashes.indexOf("=");
27
98
  if (equalIndex !== -1) {
28
99
  const key = toCamelCase(withoutDashes.slice(0, equalIndex));
29
- options[key] = withoutDashes.slice(equalIndex + 1);
100
+ const value = withoutDashes.slice(equalIndex + 1);
101
+ options[key] = booleanKeys.has(key) ? toBoolean(`--${withoutDashes.slice(0, equalIndex)}`, value) : value;
30
102
  } else {
31
103
  const key = toCamelCase(withoutDashes);
32
104
  const nextArg = argv[i + 1];
33
- if (nextArg && !nextArg.startsWith("-")) {
105
+ if (booleanKeys.has(key)) options[key] = true;
106
+ else if (nextArg && !nextArg.startsWith("-")) {
34
107
  options[key] = nextArg;
35
108
  i++;
36
109
  } else options[key] = true;
@@ -39,14 +112,18 @@ function parseCliArgs(argv) {
39
112
  const flags = arg.slice(1);
40
113
  const equalIndex = flags.indexOf("=");
41
114
  if (equalIndex !== -1) {
42
- const key = toCamelCase(flags.slice(0, equalIndex));
43
- options[key] = flags.slice(equalIndex + 1);
115
+ const rawKey = flags.slice(0, equalIndex);
116
+ const key = toCamelCase(rawKey);
117
+ const value = flags.slice(equalIndex + 1);
118
+ options[key] = booleanKeys.has(key) ? toBoolean(`-${rawKey}`, value) : value;
44
119
  } else if (flags.length === 1) {
120
+ const key = toCamelCase(flags);
45
121
  const nextArg = argv[i + 1];
46
- if (nextArg && !nextArg.startsWith("-")) {
47
- options[toCamelCase(flags)] = nextArg;
122
+ if (booleanKeys.has(key)) options[key] = true;
123
+ else if (nextArg && !nextArg.startsWith("-")) {
124
+ options[key] = nextArg;
48
125
  i++;
49
- } else options[toCamelCase(flags)] = true;
126
+ } else options[key] = true;
50
127
  } else for (const flag of flags) options[toCamelCase(flag)] = true;
51
128
  } else args.push(arg);
52
129
  }
@@ -58,5 +135,5 @@ function parseCliArgs(argv) {
58
135
  }
59
136
 
60
137
  //#endregion
61
- export { parseCliArgs };
138
+ export { CliOptionValueError, parseCliArgs };
62
139
  //# sourceMappingURL=parse-cli-args.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-cli-args.mjs","names":[],"sources":["../../../../../../../core/src/cli/parse-cli-args.ts"],"sourcesContent":["import { toCamelCase } from \"@mongez/reinforcements\";\n\nexport type ParsedCliArgs = {\n name: string;\n args: string[];\n options: Record<string, string | boolean>;\n};\n\n/**\n * Parse CLI arguments from process.argv\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"])\n * // Returns: { name: \"migrate\", args: [], options: { rollback: \"file.ts\" } }\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"dev\", \"--port=3000\", \"--fresh\"])\n * // Returns: { name: \"dev\", args: [], options: { port: \"3000\", fresh: true } }\n */\nexport function parseCliArgs(argv: string[]): ParsedCliArgs {\n // Command is at index 2 (after \"node\" and script path)\n // But if index 2 starts with \"-\", it's an option, not a command\n const potentialCommand = argv[2] || \"\";\n const isFirstArgOption = potentialCommand.startsWith(\"-\");\n const command = isFirstArgOption ? \"\" : potentialCommand;\n const args: string[] = [];\n const options: Record<string, string | boolean> = {};\n\n // Parse arguments starting from index 3 (or 2 if first arg was an option)\n const startIndex = isFirstArgOption ? 2 : 3;\n for (let i = startIndex; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg.startsWith(\"--\")) {\n // Long option: --key or --key=value\n const withoutDashes = arg.slice(2);\n const equalIndex = withoutDashes.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // --key=value format\n const key = toCamelCase(withoutDashes.slice(0, equalIndex));\n const value = withoutDashes.slice(equalIndex + 1);\n options[key] = value;\n } else {\n // --key format (check if next arg is a value)\n const key = toCamelCase(withoutDashes);\n const nextArg = argv[i + 1];\n\n // If next arg exists and doesn't start with -, treat it as value\n if (nextArg && !nextArg.startsWith(\"-\")) {\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n }\n } else if (arg.startsWith(\"-\") && arg.length > 1) {\n // Short option: -f, -t=value, or -abc (multiple flags)\n const flags = arg.slice(1);\n const equalIndex = flags.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // -t=value format\n const key = toCamelCase(flags.slice(0, equalIndex));\n const value = flags.slice(equalIndex + 1);\n options[key] = value;\n } else if (flags.length === 1) {\n // Single flag: -f\n const nextArg = argv[i + 1];\n\n if (nextArg && !nextArg.startsWith(\"-\")) {\n options[toCamelCase(flags)] = nextArg;\n i++; // Skip next arg\n } else {\n options[toCamelCase(flags)] = true;\n }\n } else {\n // Multiple flags: -abc becomes { a: true, b: true, c: true }\n for (const flag of flags) {\n options[toCamelCase(flag)] = true;\n }\n }\n } else {\n // Positional argument\n args.push(arg);\n }\n }\n\n return { name: command, args, options };\n}\n"],"mappings":";;;;;;;;;;;;;;AAmBA,SAAgB,aAAa,MAA+B;CAG1D,MAAM,mBAAmB,KAAK,MAAM;CACpC,MAAM,mBAAmB,iBAAiB,WAAW,GAAG;CACxD,MAAM,UAAU,mBAAmB,KAAK;CACxC,MAAM,OAAiB,CAAC;CACxB,MAAM,UAA4C,CAAC;CAGnD,MAAM,aAAa,mBAAmB,IAAI;CAC1C,KAAK,IAAI,IAAI,YAAY,IAAI,KAAK,QAAQ,KAAK;EAC7C,MAAM,MAAM,KAAK;EAEjB,IAAI,IAAI,WAAW,IAAI,GAAG;GAExB,MAAM,gBAAgB,IAAI,MAAM,CAAC;GACjC,MAAM,aAAa,cAAc,QAAQ,GAAG;GAE5C,IAAI,eAAe,IAAI;IAErB,MAAM,MAAM,YAAY,cAAc,MAAM,GAAG,UAAU,CAAC;IAE1D,QAAQ,OADM,cAAc,MAAM,aAAa,CAC5B;GACrB,OAAO;IAEL,MAAM,MAAM,YAAY,aAAa;IACrC,MAAM,UAAU,KAAK,IAAI;IAGzB,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KACvC,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB;EACF,OAAO,IAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG;GAEhD,MAAM,QAAQ,IAAI,MAAM,CAAC;GACzB,MAAM,aAAa,MAAM,QAAQ,GAAG;GAEpC,IAAI,eAAe,IAAI;IAErB,MAAM,MAAM,YAAY,MAAM,MAAM,GAAG,UAAU,CAAC;IAElD,QAAQ,OADM,MAAM,MAAM,aAAa,CACpB;GACrB,OAAO,IAAI,MAAM,WAAW,GAAG;IAE7B,MAAM,UAAU,KAAK,IAAI;IAEzB,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KACvC,QAAQ,YAAY,KAAK,KAAK;KAC9B;IACF,OACE,QAAQ,YAAY,KAAK,KAAK;GAElC,OAEE,KAAK,MAAM,QAAQ,OACjB,QAAQ,YAAY,IAAI,KAAK;EAGnC,OAEE,KAAK,KAAK,GAAG;CAEjB;CAEA,OAAO;EAAE,MAAM;EAAS;EAAM;CAAQ;AACxC"}
1
+ {"version":3,"file":"parse-cli-args.mjs","names":[],"sources":["../../../../../../../core/src/cli/parse-cli-args.ts"],"sourcesContent":["import { toCamelCase } from \"@mongez/reinforcements\";\n\nexport type ParsedCliArgs = {\n name: string;\n args: string[];\n options: Record<string, string | boolean>;\n};\n\n/**\n * The slice of a declared command option this parser needs.\n *\n * `CLICommand.commandOptions` (`ResolvedCLICommandOption[]`) satisfies it, but\n * the parser stays independent of the command classes so it can be unit-tested\n * and reused with a hand-written schema.\n */\nexport type CliOptionSchema = {\n name?: string;\n alias?: string;\n type?: \"string\" | \"boolean\" | \"number\";\n};\n\n/**\n * Thrown when a declared boolean option is given a value that is neither\n * true-ish nor false-ish.\n *\n * We refuse to guess. Guessing is exactly what produced #21: `--rollback=false`\n * was kept as the truthy string `\"false\"` and dropped every table. An option\n * that gates a destructive action must fail loudly on input it cannot read.\n */\nexport class CliOptionValueError extends Error {\n public constructor(\n public readonly optionToken: string,\n public readonly value: string,\n ) {\n super(\n `Invalid value ${JSON.stringify(value)} for boolean option ${optionToken}. ` +\n `Expected one of: true, false, 1, 0, yes, no — or pass ${optionToken} on its own for true.`,\n );\n\n this.name = \"CliOptionValueError\";\n }\n}\n\nconst TRUE_VALUES = new Set([\"true\", \"1\", \"yes\"]);\nconst FALSE_VALUES = new Set([\"false\", \"0\", \"no\"]);\n\n/**\n * Collect the camelCased keys (names AND aliases) of every option the command\n * declared as `type: \"boolean\"`.\n *\n * Both sides are camelCased because declared names keep their raw kebab form\n * (`\"pending-only\"`) while the parser emits camelCase keys (`pendingOnly`).\n */\nfunction collectBooleanKeys(schema: CliOptionSchema[]): Set<string> {\n const keys = new Set<string>();\n\n for (const option of schema) {\n if (option.type !== \"boolean\") continue;\n\n if (option.name) {\n keys.add(toCamelCase(option.name));\n }\n\n if (option.alias) {\n keys.add(toCamelCase(option.alias));\n }\n }\n\n return keys;\n}\n\n/**\n * Turn the value written after `=` into a real boolean, or throw.\n */\nfunction toBoolean(optionToken: string, value: string): boolean {\n const normalized = value.toLowerCase();\n\n if (TRUE_VALUES.has(normalized)) return true;\n if (FALSE_VALUES.has(normalized)) return false;\n\n throw new CliOptionValueError(optionToken, value);\n}\n\n/**\n * Parse CLI arguments from process.argv\n *\n * Called with a `schema` (the resolved command's declared options), every\n * option declared `type: \"boolean\"` is resolved as a boolean:\n * `--flag` → true, `--flag=false|0|no` → false, `--flag=true|1|yes` → true,\n * and `--flag <token>` leaves `<token>` as a POSITIONAL instead of swallowing\n * it as the flag's value. Anything else throws {@link CliOptionValueError}.\n *\n * Called without a schema — which is how the command name is discovered,\n * before any command object exists — behaviour is unchanged: every value stays\n * a raw string and a bare `--flag` still consumes the following non-dash token.\n * Nothing is blanket-coerced here on purpose: `--name=false` on a string-typed\n * option must survive as the string `\"false\"`.\n *\n * Options the schema does not declare keep the schema-less behaviour.\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"])\n * // Returns: { name: \"migrate\", args: [], options: { rollback: \"file.ts\" } }\n *\n * @example\n * // `rollback` declared as type: \"boolean\" — the file stays a positional\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"], migrateOptions)\n * // Returns: { name: \"migrate\", args: [\"file.ts\"], options: { rollback: true } }\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"dev\", \"--port=3000\", \"--fresh\"])\n * // Returns: { name: \"dev\", args: [], options: { port: \"3000\", fresh: true } }\n */\nexport function parseCliArgs(argv: string[], schema: CliOptionSchema[] = []): ParsedCliArgs {\n // Command is at index 2 (after \"node\" and script path)\n // But if index 2 starts with \"-\", it's an option, not a command\n const potentialCommand = argv[2] || \"\";\n const isFirstArgOption = potentialCommand.startsWith(\"-\");\n const command = isFirstArgOption ? \"\" : potentialCommand;\n const args: string[] = [];\n const options: Record<string, string | boolean> = {};\n const booleanKeys = collectBooleanKeys(schema);\n\n // Parse arguments starting from index 3 (or 2 if first arg was an option)\n const startIndex = isFirstArgOption ? 2 : 3;\n for (let i = startIndex; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg.startsWith(\"--\")) {\n // Long option: --key or --key=value\n const withoutDashes = arg.slice(2);\n const equalIndex = withoutDashes.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // --key=value format\n const key = toCamelCase(withoutDashes.slice(0, equalIndex));\n const value = withoutDashes.slice(equalIndex + 1);\n options[key] = booleanKeys.has(key)\n ? toBoolean(`--${withoutDashes.slice(0, equalIndex)}`, value)\n : value;\n } else {\n // --key format (check if next arg is a value)\n const key = toCamelCase(withoutDashes);\n const nextArg = argv[i + 1];\n\n // A declared boolean NEVER consumes the next token: `--rollback\n // users.ts` means \"rollback, and here is a positional\", not \"rollback\n // the file users.ts\". Swallowing it silently discarded the operator's\n // only stated scope and rolled back everything.\n if (booleanKeys.has(key)) {\n options[key] = true;\n } else if (nextArg && !nextArg.startsWith(\"-\")) {\n // If next arg exists and doesn't start with -, treat it as value\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n }\n } else if (arg.startsWith(\"-\") && arg.length > 1) {\n // Short option: -f, -t=value, or -abc (multiple flags)\n const flags = arg.slice(1);\n const equalIndex = flags.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // -t=value format\n const rawKey = flags.slice(0, equalIndex);\n const key = toCamelCase(rawKey);\n const value = flags.slice(equalIndex + 1);\n options[key] = booleanKeys.has(key) ? toBoolean(`-${rawKey}`, value) : value;\n } else if (flags.length === 1) {\n // Single flag: -f\n const key = toCamelCase(flags);\n const nextArg = argv[i + 1];\n\n if (booleanKeys.has(key)) {\n options[key] = true;\n } else if (nextArg && !nextArg.startsWith(\"-\")) {\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n } else {\n // Multiple flags: -abc becomes { a: true, b: true, c: true }\n // A bundle carries no value and never consumes the next token, so a\n // declared boolean already resolves to `true` here.\n for (const flag of flags) {\n options[toCamelCase(flag)] = true;\n }\n }\n } else {\n // Positional argument\n args.push(arg);\n }\n }\n\n return { name: command, args, options };\n}\n"],"mappings":";;;;;;;;;;;AA6BA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,AAAO,YACL,AAAgB,aAChB,AAAgB,OAChB;EACA,MACE,iBAAiB,KAAK,UAAU,KAAK,EAAE,sBAAsB,YAAY,0DACd,YAAY,sBACzE;EANgB;EACA;EAOhB,KAAK,OAAO;CACd;AACF;AAEA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAQ;CAAK;AAAK,CAAC;AAChD,MAAM,eAAe,IAAI,IAAI;CAAC;CAAS;CAAK;AAAI,CAAC;;;;;;;;AASjD,SAAS,mBAAmB,QAAwC;CAClE,MAAM,uBAAO,IAAI,IAAY;CAE7B,KAAK,MAAM,UAAU,QAAQ;EAC3B,IAAI,OAAO,SAAS,WAAW;EAE/B,IAAI,OAAO,MACT,KAAK,IAAI,YAAY,OAAO,IAAI,CAAC;EAGnC,IAAI,OAAO,OACT,KAAK,IAAI,YAAY,OAAO,KAAK,CAAC;CAEtC;CAEA,OAAO;AACT;;;;AAKA,SAAS,UAAU,aAAqB,OAAwB;CAC9D,MAAM,aAAa,MAAM,YAAY;CAErC,IAAI,YAAY,IAAI,UAAU,GAAG,OAAO;CACxC,IAAI,aAAa,IAAI,UAAU,GAAG,OAAO;CAEzC,MAAM,IAAI,oBAAoB,aAAa,KAAK;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,aAAa,MAAgB,SAA4B,CAAC,GAAkB;CAG1F,MAAM,mBAAmB,KAAK,MAAM;CACpC,MAAM,mBAAmB,iBAAiB,WAAW,GAAG;CACxD,MAAM,UAAU,mBAAmB,KAAK;CACxC,MAAM,OAAiB,CAAC;CACxB,MAAM,UAA4C,CAAC;CACnD,MAAM,cAAc,mBAAmB,MAAM;CAG7C,MAAM,aAAa,mBAAmB,IAAI;CAC1C,KAAK,IAAI,IAAI,YAAY,IAAI,KAAK,QAAQ,KAAK;EAC7C,MAAM,MAAM,KAAK;EAEjB,IAAI,IAAI,WAAW,IAAI,GAAG;GAExB,MAAM,gBAAgB,IAAI,MAAM,CAAC;GACjC,MAAM,aAAa,cAAc,QAAQ,GAAG;GAE5C,IAAI,eAAe,IAAI;IAErB,MAAM,MAAM,YAAY,cAAc,MAAM,GAAG,UAAU,CAAC;IAC1D,MAAM,QAAQ,cAAc,MAAM,aAAa,CAAC;IAChD,QAAQ,OAAO,YAAY,IAAI,GAAG,IAC9B,UAAU,KAAK,cAAc,MAAM,GAAG,UAAU,KAAK,KAAK,IAC1D;GACN,OAAO;IAEL,MAAM,MAAM,YAAY,aAAa;IACrC,MAAM,UAAU,KAAK,IAAI;IAMzB,IAAI,YAAY,IAAI,GAAG,GACrB,QAAQ,OAAO;SACV,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KAE9C,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB;EACF,OAAO,IAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG;GAEhD,MAAM,QAAQ,IAAI,MAAM,CAAC;GACzB,MAAM,aAAa,MAAM,QAAQ,GAAG;GAEpC,IAAI,eAAe,IAAI;IAErB,MAAM,SAAS,MAAM,MAAM,GAAG,UAAU;IACxC,MAAM,MAAM,YAAY,MAAM;IAC9B,MAAM,QAAQ,MAAM,MAAM,aAAa,CAAC;IACxC,QAAQ,OAAO,YAAY,IAAI,GAAG,IAAI,UAAU,IAAI,UAAU,KAAK,IAAI;GACzE,OAAO,IAAI,MAAM,WAAW,GAAG;IAE7B,MAAM,MAAM,YAAY,KAAK;IAC7B,MAAM,UAAU,KAAK,IAAI;IAEzB,IAAI,YAAY,IAAI,GAAG,GACrB,QAAQ,OAAO;SACV,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KAC9C,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB,OAIE,KAAK,MAAM,QAAQ,OACjB,QAAQ,YAAY,IAAI,KAAK;EAGnC,OAEE,KAAK,KAAK,GAAG;CAEjB;CAEA,OAAO;EAAE,MAAM;EAAS;EAAM;CAAQ;AACxC"}
@@ -76,7 +76,12 @@ type CLICommandPreload = {
76
76
  environemnt?: "production" | "development" | "test";
77
77
  /**
78
78
  * Whether to load environment variables from .env files.
79
- * Note: If `bootstrap` is true, env is loaded automatically.
79
+ *
80
+ * @deprecated No longer read — env is loaded for every command that declares
81
+ * a preload block, before `warlock.config.ts` is evaluated. It has to be:
82
+ * config files call `env()` in their module body, and loading config first
83
+ * resolved every one of those calls to its default. Setting this flag is
84
+ * harmless and does nothing; remove it. Dropped at 5.0.
80
85
  */
81
86
  env?: boolean;
82
87
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../core/src/cli/types.ts"],"mappings":";;;;;AAgB4B;AAY5B;;;;KAZY,gBAAA;;;;AAwBK;AAsBjB;;;;;;KAlCY,iBAAA;EAuDV;;;;EAlDA,IAAA;EA4EA;;;AAA0B;AAgB5B;EArFE,OAAA,EAAS,MAAM;AAAA;;;;;;;;;;AA4HP;AAGV;;;;;;;;;KAzGY,iBAAA;EAkHA;;;;;EA5GV,MAAA;EA4GiE;;AAAO;EAvGxE,QAAA;EA6H2B;;;EAxH3B,aAAA;EAiKQ;;;EA5JR,eAAA,GAAkB,eAAA;EAwHlB;;;EAnHA,WAAA;EAoIU;;;;EA9HV,GAAA;EAiJQ;;;;EA3IR,SAAA;;;;;;;;EASA,UAAA,GAAa,aAAa;AAAA;;;;;;;;;;;;;;KAgBhB,gBAAA;;;;;EAKV,IAAA;;;;;EAMA,IAAA;;;;;EAMA,KAAA;;;;EAKA,WAAA;;;;;EAMA,IAAA;;;;EAKA,YAAA;;;;;EAMA,QAAA;AAAA;AAAA,KAGU,wBAAA,GAA2B,IAAI,CAAC,gBAAA;EAC1C,IAAA;EACA,KAAA;AAAA;;;;;KAOU,gBAAA,IAAoB,IAAA,EAAM,iBAAA,YAA6B,OAAO;;;;;;;;;;;;;;;;;;;;;KAsB9D,iBAAA;;;;;EAKV,IAAA;;;;;EAMA,KAAA;;;;EAKA,WAAA;;;;;EAMA,OAAA,GAAU,iBAAA;;;;;;EAOV,UAAA;;;;;EAMA,SAAA,GAAY,gBAAA;;;;;EAMZ,MAAA,EAAQ,gBAAA;;;;;EAMR,OAAA,GAAU,gBAAA;AAAA"}
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../core/src/cli/types.ts"],"mappings":";;;;;AAgB4B;AAY5B;;;;KAZY,gBAAA;;;;AAwBK;AAsBjB;;;;;;KAlCY,iBAAA;EAuDV;;;;EAlDA,IAAA;EAiFA;;;AAA0B;AAgB5B;EA1FE,OAAA,EAAS,MAAM;AAAA;;;;;;;;;;AAiIP;AAGV;;;;;;;;;KA9GY,iBAAA;EAuHA;;;;;EAjHV,MAAA;EAiHiE;;AAAO;EA5GxE,QAAA;EAkI2B;;;EA7H3B,aAAA;EAsKQ;;;EAjKR,eAAA,GAAkB,eAAA;EA6HlB;;;EAxHA,WAAA;EAyIU;;;;;;;;;EA9HV,GAAA;;;;;EAMA,SAAA;;;;;;;;EASA,UAAA,GAAa,aAAa;AAAA;;;;;;;;;;;;;;KAgBhB,gBAAA;;;;;EAKV,IAAA;;;;;EAMA,IAAA;;;;;EAMA,KAAA;;;;EAKA,WAAA;;;;;EAMA,IAAA;;;;EAKA,YAAA;;;;;EAMA,QAAA;AAAA;AAAA,KAGU,wBAAA,GAA2B,IAAI,CAAC,gBAAA;EAC1C,IAAA;EACA,KAAA;AAAA;;;;;KAOU,gBAAA,IAAoB,IAAA,EAAM,iBAAA,YAA6B,OAAO;;;;;;;;;;;;;;;;;;;;;KAsB9D,iBAAA;;;;;EAKV,IAAA;;;;;EAMA,KAAA;;;;EAKA,WAAA;;;;;EAMA,OAAA,GAAU,iBAAA;;;;;;EAOV,UAAA;;;;;EAMA,SAAA,GAAY,gBAAA;;;;;EAMZ,MAAA,EAAQ,gBAAA;;;;;EAMR,OAAA,GAAU,gBAAA;AAAA"}
@@ -1,4 +1,4 @@
1
- import baseConfig from "@mongez/config";
1
+ import config from "@mongez/config";
2
2
 
3
3
  //#region ../core/src/config/config-getter.ts
4
4
  /**
@@ -14,15 +14,15 @@ import baseConfig from "@mongez/config";
14
14
  * const port = config.key<number>("database.port", 27017);
15
15
  * ```
16
16
  */
17
- const config = {
17
+ const config$1 = {
18
18
  key(key, defaultValue) {
19
- return baseConfig.get(key, defaultValue);
19
+ return config.get(key, defaultValue);
20
20
  },
21
21
  get(name, defaultValue) {
22
- return baseConfig.get(name, defaultValue);
22
+ return config.get(name, defaultValue);
23
23
  }
24
24
  };
25
25
 
26
26
  //#endregion
27
- export { config };
27
+ export { config$1 as config };
28
28
  //# sourceMappingURL=config-getter.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-getter.mjs","names":[],"sources":["../../../../../../../core/src/config/config-getter.ts"],"sourcesContent":["import baseConfig from \"@mongez/config\";\nimport type { ConfigKey, ConfigRegistry } from \"./types\";\n\n/**\n * Config accessor interface with typed overloads\n */\ninterface ConfigAccessor {\n /**\n * Get a config value by dot-notation key path.\n */\n key<T = any>(key: ConfigKey | (string & {}), defaultValue?: T): T;\n\n /**\n * Get an entire config group by name with type inference.\n * Returns the typed config object for known config names.\n */\n get<K extends keyof ConfigRegistry>(name: K, defaultValue?: ConfigRegistry[K]): ConfigRegistry[K];\n\n /**\n * Get an entire config group by name (dynamic string).\n */\n get<T = any>(name: string, defaultValue?: T): T;\n}\n\n/**\n * Config accessor with typed autocomplete and return type inference.\n *\n * @example\n * ```typescript\n * // Get entire config group - returns the actual config type\n * const db = config.get(\"database\"); // → DatabaseConfigurations\n *\n * // Get specific key with dot notation\n * const host = config.key(\"database.host\");\n * const port = config.key<number>(\"database.port\", 27017);\n * ```\n */\nexport const config: ConfigAccessor = {\n key(key: ConfigKey | (string & {}), defaultValue?: any): any {\n return baseConfig.get(key, defaultValue);\n },\n\n get(name: string, defaultValue?: any): any {\n return baseConfig.get(name, defaultValue);\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAqCA,MAAa,SAAyB;CACpC,IAAI,KAAgC,cAAyB;EAC3D,OAAO,WAAW,IAAI,KAAK,YAAY;CACzC;CAEA,IAAI,MAAc,cAAyB;EACzC,OAAO,WAAW,IAAI,MAAM,YAAY;CAC1C;AACF"}
1
+ {"version":3,"file":"config-getter.mjs","names":["config","baseConfig"],"sources":["../../../../../../../core/src/config/config-getter.ts"],"sourcesContent":["import baseConfig from \"@mongez/config\";\nimport type { ConfigKey, ConfigRegistry } from \"./types\";\n\n/**\n * Config accessor interface with typed overloads\n */\ninterface ConfigAccessor {\n /**\n * Get a config value by dot-notation key path.\n */\n key<T = any>(key: ConfigKey | (string & {}), defaultValue?: T): T;\n\n /**\n * Get an entire config group by name with type inference.\n * Returns the typed config object for known config names.\n */\n get<K extends keyof ConfigRegistry>(name: K, defaultValue?: ConfigRegistry[K]): ConfigRegistry[K];\n\n /**\n * Get an entire config group by name (dynamic string).\n */\n get<T = any>(name: string, defaultValue?: T): T;\n}\n\n/**\n * Config accessor with typed autocomplete and return type inference.\n *\n * @example\n * ```typescript\n * // Get entire config group - returns the actual config type\n * const db = config.get(\"database\"); // → DatabaseConfigurations\n *\n * // Get specific key with dot notation\n * const host = config.key(\"database.host\");\n * const port = config.key<number>(\"database.port\", 27017);\n * ```\n */\nexport const config: ConfigAccessor = {\n key(key: ConfigKey | (string & {}), defaultValue?: any): any {\n return baseConfig.get(key, defaultValue);\n },\n\n get(name: string, defaultValue?: any): any {\n return baseConfig.get(name, defaultValue);\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAqCA,MAAaA,WAAyB;CACpC,IAAI,KAAgC,cAAyB;EAC3D,OAAOC,OAAW,IAAI,KAAK,YAAY;CACzC;CAEA,IAAI,MAAc,cAAyB;EACzC,OAAOA,OAAW,IAAI,MAAM,YAAY;CAC1C;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { configSpecialHandlers } from "./config-special-handlers.mjs";
2
- import baseConfig from "@mongez/config";
2
+ import config from "@mongez/config";
3
3
  import { colors } from "@mongez/copper";
4
4
  import { pathToFileURL } from "node:url";
5
5
 
@@ -27,7 +27,7 @@ var ConfigLoader = class {
27
27
  console.log(colors.red(`config error: `), `Config file ${colors.yellow(file.relativePath)} does not have a default export`);
28
28
  return;
29
29
  }
30
- baseConfig.set(configName, configValue);
30
+ config.set(configName, configValue);
31
31
  await configSpecialHandlers.execute(configName, configValue);
32
32
  } catch (error) {
33
33
  throw error;
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.mjs","names":[],"sources":["../../../../../../../core/src/config/config-loader.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { colors } from \"@mongez/copper\";\r\nimport { pathToFileURL } from \"node:url\";\r\nimport type { FileManager } from \"../dev-server/file-manager\";\r\nimport { configSpecialHandlers } from \"./config-special-handlers\";\r\n\r\n/**\r\n * Special Config Handler\r\n * A function that handles special configuration loading\r\n */\r\nexport type SpecialConfigHandler = (configValue: any) => void | Promise<void>;\r\n\r\n/**\r\n * Config Loader\r\n * Dynamically loads all configuration files and registers them with @mongez/config\r\n * Supports special handlers for configs that require additional processing\r\n */\r\nexport class ConfigLoader {\r\n public async loadAll(configFiles: FileManager[]): Promise<void> {\r\n for (const file of configFiles) {\r\n await this.loadConfig(file);\r\n }\r\n }\r\n\r\n /**\r\n * Load a single configuration file.\r\n *\r\n * The ESM loader hook stamps a version token onto the URL so that each HMR\r\n * cycle gets a fresh module — no manual cache-busting needed here.\r\n */\r\n public async loadConfig(file: FileManager): Promise<void> {\r\n const configName = this.getConfigName(file.relativePath);\r\n\r\n try {\r\n const fileUrl = pathToFileURL(file.absolutePath).href;\r\n const configModule = await import(fileUrl);\r\n const configValue = configModule.default;\r\n\r\n if (configValue === undefined) {\r\n console.log(\r\n colors.red(`config error: `),\r\n `Config file ${colors.yellow(file.relativePath)} does not have a default export`,\r\n );\r\n return;\r\n }\r\n\r\n config.set(configName, configValue);\r\n await configSpecialHandlers.execute(configName, configValue);\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n public async reloadConfig(file: FileManager): Promise<void> {\r\n await this.loadConfig(file);\r\n }\r\n\r\n private getConfigName(relativePath: string): string {\r\n const match = relativePath.match(/^src\\/config\\/(.+)\\.(ts|tsx)$/);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid config file path: ${relativePath}`);\r\n }\r\n\r\n return match[1];\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;AAiBA,IAAa,eAAb,MAA0B;CACxB,MAAa,QAAQ,aAA2C;EAC9D,KAAK,MAAM,QAAQ,aACjB,MAAM,KAAK,WAAW,IAAI;CAE9B;;;;;;;CAQA,MAAa,WAAW,MAAkC;EACxD,MAAM,aAAa,KAAK,cAAc,KAAK,YAAY;EAEvD,IAAI;GAGF,MAAM,eAAc,MADO,OADX,cAAc,KAAK,YAAY,CAAC,CAAC,MAEjB,CAAC;GAEjC,IAAI,gBAAgB,QAAW;IAC7B,QAAQ,IACN,OAAO,IAAI,gBAAgB,GAC3B,eAAe,OAAO,OAAO,KAAK,YAAY,EAAE,gCAClD;IACA;GACF;GAEA,WAAO,IAAI,YAAY,WAAW;GAClC,MAAM,sBAAsB,QAAQ,YAAY,WAAW;EAC7D,SAAS,OAAO;GACd,MAAM;EACR;CACF;CAEA,MAAa,aAAa,MAAkC;EAC1D,MAAM,KAAK,WAAW,IAAI;CAC5B;CAEA,AAAQ,cAAc,cAA8B;EAClD,MAAM,QAAQ,aAAa,MAAM,+BAA+B;EAEhE,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,6BAA6B,cAAc;EAG7D,OAAO,MAAM;CACf;AACF"}
1
+ {"version":3,"file":"config-loader.mjs","names":[],"sources":["../../../../../../../core/src/config/config-loader.ts"],"sourcesContent":["import config from \"@mongez/config\";\r\nimport { colors } from \"@mongez/copper\";\r\nimport { pathToFileURL } from \"node:url\";\r\nimport type { FileManager } from \"../dev-server/file-manager\";\r\nimport { configSpecialHandlers } from \"./config-special-handlers\";\r\n\r\n/**\r\n * Special Config Handler\r\n * A function that handles special configuration loading\r\n */\r\nexport type SpecialConfigHandler = (configValue: any) => void | Promise<void>;\r\n\r\n/**\r\n * Config Loader\r\n * Dynamically loads all configuration files and registers them with @mongez/config\r\n * Supports special handlers for configs that require additional processing\r\n */\r\nexport class ConfigLoader {\r\n public async loadAll(configFiles: FileManager[]): Promise<void> {\r\n for (const file of configFiles) {\r\n await this.loadConfig(file);\r\n }\r\n }\r\n\r\n /**\r\n * Load a single configuration file.\r\n *\r\n * The ESM loader hook stamps a version token onto the URL so that each HMR\r\n * cycle gets a fresh module — no manual cache-busting needed here.\r\n */\r\n public async loadConfig(file: FileManager): Promise<void> {\r\n const configName = this.getConfigName(file.relativePath);\r\n\r\n try {\r\n const fileUrl = pathToFileURL(file.absolutePath).href;\r\n const configModule = await import(fileUrl);\r\n const configValue = configModule.default;\r\n\r\n if (configValue === undefined) {\r\n console.log(\r\n colors.red(`config error: `),\r\n `Config file ${colors.yellow(file.relativePath)} does not have a default export`,\r\n );\r\n return;\r\n }\r\n\r\n config.set(configName, configValue);\r\n await configSpecialHandlers.execute(configName, configValue);\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n public async reloadConfig(file: FileManager): Promise<void> {\r\n await this.loadConfig(file);\r\n }\r\n\r\n private getConfigName(relativePath: string): string {\r\n const match = relativePath.match(/^src\\/config\\/(.+)\\.(ts|tsx)$/);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid config file path: ${relativePath}`);\r\n }\r\n\r\n return match[1];\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;AAiBA,IAAa,eAAb,MAA0B;CACxB,MAAa,QAAQ,aAA2C;EAC9D,KAAK,MAAM,QAAQ,aACjB,MAAM,KAAK,WAAW,IAAI;CAE9B;;;;;;;CAQA,MAAa,WAAW,MAAkC;EACxD,MAAM,aAAa,KAAK,cAAc,KAAK,YAAY;EAEvD,IAAI;GAGF,MAAM,eAAc,MADO,OADX,cAAc,KAAK,YAAY,CAAC,CAAC,MAEjB,CAAC;GAEjC,IAAI,gBAAgB,QAAW;IAC7B,QAAQ,IACN,OAAO,IAAI,gBAAgB,GAC3B,eAAe,OAAO,OAAO,KAAK,YAAY,EAAE,gCAClD;IACA;GACF;GAEA,OAAO,IAAI,YAAY,WAAW;GAClC,MAAM,sBAAsB,QAAQ,YAAY,WAAW;EAC7D,SAAS,OAAO;GACd,MAAM;EACR;CACF;CAEA,MAAa,aAAa,MAAkC;EAC1D,MAAM,KAAK,WAAW,IAAI;CAC5B;CAEA,AAAQ,cAAc,cAA8B;EAClD,MAAM,QAAQ,aAAa,MAAM,+BAA+B;EAEhE,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,6BAA6B,cAAc;EAG7D,OAAO,MAAM;CACf;AACF"}
@@ -0,0 +1,27 @@
1
+ import { ConfigRegistry } from "./types.mjs";
2
+
3
+ //#region ../core/src/config/config-setter.d.ts
4
+ /**
5
+ * Register a config group under its name.
6
+ *
7
+ * The write side of the config store, kept separate from the `config` accessor
8
+ * on purpose: `config` is a read-only surface and widening it would invite app
9
+ * code to mutate configuration at runtime. Registration is a boot-time act.
10
+ *
11
+ * Exported chiefly so the production build's generated config loader has a
12
+ * specifier the consuming app actually declares — `@warlock.js/core` — rather
13
+ * than `@mongez/config`, which is core's dependency and not the app's.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import { setConfig } from "@warlock.js/core";
18
+ * import databaseConfig from "../../src/config/database";
19
+ *
20
+ * setConfig("database", databaseConfig);
21
+ * ```
22
+ */
23
+ declare function setConfig<K extends keyof ConfigRegistry>(name: K, value: ConfigRegistry[K]): void;
24
+ declare function setConfig(name: string, value: unknown): void;
25
+ //#endregion
26
+ export { setConfig };
27
+ //# sourceMappingURL=config-setter.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-setter.d.mts","names":[],"sources":["../../../../../../../core/src/config/config-setter.ts"],"mappings":";;;;;AAsBA;;;;;;;;;;;;;;;;;iBAAgB,SAAA,iBAA0B,cAAA,EAAgB,IAAA,EAAM,CAAA,EAAG,KAAA,EAAO,cAAA,CAAe,CAAA;AAAA,iBACzE,SAAA,CAAU,IAAA,UAAc,KAAc"}
@@ -0,0 +1,10 @@
1
+ import config from "@mongez/config";
2
+
3
+ //#region ../core/src/config/config-setter.ts
4
+ function setConfig(name, value) {
5
+ config.set(name, value);
6
+ }
7
+
8
+ //#endregion
9
+ export { setConfig };
10
+ //# sourceMappingURL=config-setter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-setter.mjs","names":[],"sources":["../../../../../../../core/src/config/config-setter.ts"],"sourcesContent":["import baseConfig from \"@mongez/config\";\nimport type { ConfigRegistry } from \"./types\";\n\n/**\n * Register a config group under its name.\n *\n * The write side of the config store, kept separate from the `config` accessor\n * on purpose: `config` is a read-only surface and widening it would invite app\n * code to mutate configuration at runtime. Registration is a boot-time act.\n *\n * Exported chiefly so the production build's generated config loader has a\n * specifier the consuming app actually declares — `@warlock.js/core` — rather\n * than `@mongez/config`, which is core's dependency and not the app's.\n *\n * @example\n * ```typescript\n * import { setConfig } from \"@warlock.js/core\";\n * import databaseConfig from \"../../src/config/database\";\n *\n * setConfig(\"database\", databaseConfig);\n * ```\n */\nexport function setConfig<K extends keyof ConfigRegistry>(name: K, value: ConfigRegistry[K]): void;\nexport function setConfig(name: string, value: unknown): void;\nexport function setConfig(name: string, value: unknown): void {\n baseConfig.set(name, value);\n}\n"],"mappings":";;;AAwBA,SAAgB,UAAU,MAAc,OAAsB;CAC5D,OAAW,IAAI,MAAM,KAAK;AAC5B"}
@@ -1,5 +1,6 @@
1
1
  import { config } from "./config-getter.mjs";
2
2
  import { ConfigSpecialHandlers, configSpecialHandlers } from "./config-special-handlers.mjs";
3
3
  import { registerAppConfig } from "./config-handlers.mjs";
4
+ import { setConfig } from "./config-setter.mjs";
4
5
 
5
6
  export { };
@@ -1,6 +1,6 @@
1
1
  import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
2
2
  import { BaseConnector } from "./base-connector.mjs";
3
- import baseConfig from "@mongez/config";
3
+ import config from "@mongez/config";
4
4
  import { log } from "@warlock.js/logger";
5
5
 
6
6
  //#region ../core/src/connectors/access-connector.ts
@@ -29,7 +29,7 @@ var AccessConnector = class extends BaseConnector {
29
29
  * Register the access configuration with the package.
30
30
  */
31
31
  async start() {
32
- const accessConfiguration = baseConfig.get("access");
32
+ const accessConfiguration = config.get("access");
33
33
  if (!accessConfiguration) return;
34
34
  const { setAccessConfig } = await import("@warlock.js/access");
35
35
  setAccessConfig(accessConfiguration);
@@ -1 +1 @@
1
- {"version":3,"file":"access-connector.mjs","names":["config"],"sources":["../../../../../../../core/src/connectors/access-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 * Access Connector\n *\n * Wires `@warlock.js/access` from `src/config/access.ts` at boot: reads the\n * exported config object and hands it to the package's `setAccessConfig`, which\n * validates that a resolver is present — so a misconfigured authorization layer\n * fails at STARTUP, not on the first protected request. Config files stay\n * declarative; the connector performs the side-effect.\n *\n * The package is lazy-imported (only when an access config is present), so core\n * carries no hard dependency on it — the same pattern as the notifications and\n * herald connectors.\n */\nexport class AccessConnector extends BaseConnector {\n public readonly name = \"access\";\n public readonly priority = ConnectorPriority.ACCESS;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger an access restart\n */\n protected readonly watchedFiles = [\"src/config/access.ts\"];\n\n /**\n * Register the access configuration with the package.\n */\n public async start(): Promise<void> {\n const accessConfiguration = config.get(\"access\");\n\n if (!accessConfiguration) {\n return;\n }\n\n const { setAccessConfig } = await import(\"@warlock.js/access\");\n\n setAccessConfig(accessConfiguration);\n this.active = true;\n\n log.info(\"access\", \"configured\", \"Authorization wired from config/access.ts\");\n }\n\n /**\n * Clear the active config so a dev restart re-registers from the (possibly\n * changed, or now-removed) config file. The package holds no external\n * connection of its own.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) {\n return;\n }\n\n const { resetAccessConfig } = await import(\"@warlock.js/access\");\n\n resetAccessConfig();\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkBA,IAAa,kBAAb,cAAqC,cAAc;;;cAC1B;;;sBAOW,CAAC,sBAAsB;;;;;CAKzD,MAAa,QAAuB;EAClC,MAAM,sBAAsBA,WAAO,IAAI,QAAQ;EAE/C,IAAI,CAAC,qBACH;EAGF,MAAM,EAAE,oBAAoB,MAAM,OAAO;EAEzC,gBAAgB,mBAAmB;EACnC,KAAK,SAAS;EAEd,IAAI,KAAK,UAAU,cAAc,2CAA2C;CAC9E;;;;;;CAOA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,MAAM,EAAE,sBAAsB,MAAM,OAAO;EAE3C,kBAAkB;EAClB,KAAK,SAAS;CAChB;AACF"}
1
+ {"version":3,"file":"access-connector.mjs","names":[],"sources":["../../../../../../../core/src/connectors/access-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 * Access Connector\n *\n * Wires `@warlock.js/access` from `src/config/access.ts` at boot: reads the\n * exported config object and hands it to the package's `setAccessConfig`, which\n * validates that a resolver is present — so a misconfigured authorization layer\n * fails at STARTUP, not on the first protected request. Config files stay\n * declarative; the connector performs the side-effect.\n *\n * The package is lazy-imported (only when an access config is present), so core\n * carries no hard dependency on it — the same pattern as the notifications and\n * herald connectors.\n */\nexport class AccessConnector extends BaseConnector {\n public readonly name = \"access\";\n public readonly priority = ConnectorPriority.ACCESS;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger an access restart\n */\n protected readonly watchedFiles = [\"src/config/access.ts\"];\n\n /**\n * Register the access configuration with the package.\n */\n public async start(): Promise<void> {\n const accessConfiguration = config.get(\"access\");\n\n if (!accessConfiguration) {\n return;\n }\n\n const { setAccessConfig } = await import(\"@warlock.js/access\");\n\n setAccessConfig(accessConfiguration);\n this.active = true;\n\n log.info(\"access\", \"configured\", \"Authorization wired from config/access.ts\");\n }\n\n /**\n * Clear the active config so a dev restart re-registers from the (possibly\n * changed, or now-removed) config file. The package holds no external\n * connection of its own.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) {\n return;\n }\n\n const { resetAccessConfig } = await import(\"@warlock.js/access\");\n\n resetAccessConfig();\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkBA,IAAa,kBAAb,cAAqC,cAAc;;;cAC1B;;;sBAOW,CAAC,sBAAsB;;;;;CAKzD,MAAa,QAAuB;EAClC,MAAM,sBAAsB,OAAO,IAAI,QAAQ;EAE/C,IAAI,CAAC,qBACH;EAGF,MAAM,EAAE,oBAAoB,MAAM,OAAO;EAEzC,gBAAgB,mBAAmB;EACnC,KAAK,SAAS;EAEd,IAAI,KAAK,UAAU,cAAc,2CAA2C;CAC9E;;;;;;CAOA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAGF,MAAM,EAAE,sBAAsB,MAAM,OAAO;EAE3C,kBAAkB;EAClB,KAAK,SAAS;CAChB;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
2
2
  import { BaseConnector } from "./base-connector.mjs";
3
- import baseConfig from "@mongez/config";
3
+ import config from "@mongez/config";
4
4
  import { log } from "@warlock.js/logger";
5
5
 
6
6
  //#region ../core/src/connectors/ai-connector.ts
@@ -33,7 +33,7 @@ var AiConnector = class extends BaseConnector {
33
33
  * Register the ai configuration with the package.
34
34
  */
35
35
  async start() {
36
- const aiConfiguration = baseConfig.get("ai");
36
+ const aiConfiguration = config.get("ai");
37
37
  if (!aiConfiguration) return;
38
38
  const { ai } = await import("@warlock.js/ai");
39
39
  ai.config(aiConfiguration);
@@ -1 +1 @@
1
- {"version":3,"file":"ai-connector.mjs","names":["config"],"sources":["../../../../../../../core/src/connectors/ai-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 * AI Connector\n *\n * Wires `@warlock.js/ai` from `src/config/ai.ts` at boot: reads the exported\n * config object and hands it to the package's `ai.config(...)`. Config files stay\n * declarative; the connector performs the side-effect.\n *\n * The package is lazy-imported (only when an ai config is present), so core\n * carries no hard dependency on it — the same pattern as the access,\n * notifications and herald connectors.\n *\n * Because the satellite packages' side-effect imports sit at the TOP of\n * config/ai.ts, they have already registered their surface on `ai` (ai.tools /\n * ai.mcp, ai.workspace, panoptic) by the time config-loader runs the file and\n * this connector applies the config — so this single `ai.config(...)` call also\n * fires panoptic's onConfigApplied wiring.\n */\nexport class AiConnector extends BaseConnector {\n public readonly name = \"ai\";\n public readonly priority = ConnectorPriority.AI;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger an ai restart\n */\n protected readonly watchedFiles = [\"src/config/ai.ts\"];\n\n /**\n * Register the ai configuration with the package.\n */\n public async start(): Promise<void> {\n const aiConfiguration = config.get(\"ai\");\n\n if (!aiConfiguration) return;\n\n const { ai } = await import(\"@warlock.js/ai\");\n\n ai.config(aiConfiguration);\n this.active = true;\n\n log.info(\"ai\", \"configured\", \"AI wired from config/ai.ts\");\n }\n\n /**\n * Clear the active flag so a dev restart re-registers from the (possibly\n * changed, or now-removed) config file. The package holds no external\n * connection of its own.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) return;\n\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsBA,IAAa,cAAb,cAAiC,cAAc;;;cACtB;;;sBAOW,CAAC,kBAAkB;;;;;CAKrD,MAAa,QAAuB;EAClC,MAAM,kBAAkBA,WAAO,IAAI,IAAI;EAEvC,IAAI,CAAC,iBAAiB;EAEtB,MAAM,EAAE,OAAO,MAAM,OAAO;EAE5B,GAAG,OAAO,eAAe;EACzB,KAAK,SAAS;EAEd,IAAI,KAAK,MAAM,cAAc,4BAA4B;CAC3D;;;;;;CAOA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QAAQ;EAElB,KAAK,SAAS;CAChB;AACF"}
1
+ {"version":3,"file":"ai-connector.mjs","names":[],"sources":["../../../../../../../core/src/connectors/ai-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 * AI Connector\n *\n * Wires `@warlock.js/ai` from `src/config/ai.ts` at boot: reads the exported\n * config object and hands it to the package's `ai.config(...)`. Config files stay\n * declarative; the connector performs the side-effect.\n *\n * The package is lazy-imported (only when an ai config is present), so core\n * carries no hard dependency on it — the same pattern as the access,\n * notifications and herald connectors.\n *\n * Because the satellite packages' side-effect imports sit at the TOP of\n * config/ai.ts, they have already registered their surface on `ai` (ai.tools /\n * ai.mcp, ai.workspace, panoptic) by the time config-loader runs the file and\n * this connector applies the config — so this single `ai.config(...)` call also\n * fires panoptic's onConfigApplied wiring.\n */\nexport class AiConnector extends BaseConnector {\n public readonly name = \"ai\";\n public readonly priority = ConnectorPriority.AI;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger an ai restart\n */\n protected readonly watchedFiles = [\"src/config/ai.ts\"];\n\n /**\n * Register the ai configuration with the package.\n */\n public async start(): Promise<void> {\n const aiConfiguration = config.get(\"ai\");\n\n if (!aiConfiguration) return;\n\n const { ai } = await import(\"@warlock.js/ai\");\n\n ai.config(aiConfiguration);\n this.active = true;\n\n log.info(\"ai\", \"configured\", \"AI wired from config/ai.ts\");\n }\n\n /**\n * Clear the active flag so a dev restart re-registers from the (possibly\n * changed, or now-removed) config file. The package holds no external\n * connection of its own.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) return;\n\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsBA,IAAa,cAAb,cAAiC,cAAc;;;cACtB;;;sBAOW,CAAC,kBAAkB;;;;;CAKrD,MAAa,QAAuB;EAClC,MAAM,kBAAkB,OAAO,IAAI,IAAI;EAEvC,IAAI,CAAC,iBAAiB;EAEtB,MAAM,EAAE,OAAO,MAAM,OAAO;EAE5B,GAAG,OAAO,eAAe;EACzB,KAAK,SAAS;EAEd,IAAI,KAAK,MAAM,cAAc,4BAA4B;CAC3D;;;;;;CAOA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QAAQ;EAElB,KAAK,SAAS;CAChB;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { ConnectorLifecyclePhase, ConnectorPriority } from "./types.mjs";
2
2
  import { BaseConnector } from "./base-connector.mjs";
3
- import baseConfig from "@mongez/config";
3
+ import config from "@mongez/config";
4
4
  import { cache } from "@warlock.js/cache";
5
5
 
6
6
  //#region ../core/src/connectors/cache-connector.ts
@@ -20,7 +20,7 @@ var CacheConnector = class extends BaseConnector {
20
20
  * Initialize cache connection
21
21
  */
22
22
  async start() {
23
- const cacheConfig = baseConfig.get("cache");
23
+ const cacheConfig = config.get("cache");
24
24
  if (!cacheConfig) return;
25
25
  cache.setCacheConfigurations(cacheConfig);
26
26
  await cache.init();
@@ -1 +1 @@
1
- {"version":3,"file":"cache-connector.mjs","names":["config"],"sources":["../../../../../../../core/src/connectors/cache-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { cache } from \"@warlock.js/cache\";\nimport type { CacheDriver } from \"@warlock.js/cache\";\nimport { BaseConnector } from \"./base-connector\";\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\n\n/**\n * Cache Connector\n * Manages cache engine connection lifecycle\n */\nexport class CacheConnector extends BaseConnector {\n public readonly name = \"cache\";\n public readonly priority = ConnectorPriority.CACHE;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger cache restart\n */\n protected readonly watchedFiles = [\"src/config/cache.ts\", \"src/config/cache.tsx\"];\n\n /**\n * Initialize cache connection\n */\n public async start(): Promise<void> {\n const cacheConfig = config.get(\"cache\");\n\n if (!cacheConfig) return;\n\n cache.setCacheConfigurations(cacheConfig);\n\n await cache.init();\n\n this.active = true;\n }\n\n /**\n * Shutdown cache connection\n *\n * Disconnects every loaded cache driver so external clients (e.g. a Redis\n * connection) are released instead of left dangling — mirroring the\n * database and herald connectors, which disconnect all registered\n * connections on shutdown.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) {\n return;\n }\n\n // Disconnect every driver the manager loaded (not just the current one),\n // so secondary drivers selected via `cache.use(\"...\")` also release their\n // connections.\n const drivers: CacheDriver<unknown, unknown>[] = Object.values(cache.loadedDrivers);\n\n for (const driver of drivers) {\n await driver.disconnect();\n }\n\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAa,iBAAb,cAAoC,cAAc;;;cACzB;;;sBAOW,CAAC,uBAAuB,sBAAsB;;;;;CAKhF,MAAa,QAAuB;EAClC,MAAM,cAAcA,WAAO,IAAI,OAAO;EAEtC,IAAI,CAAC,aAAa;EAElB,MAAM,uBAAuB,WAAW;EAExC,MAAM,MAAM,KAAK;EAEjB,KAAK,SAAS;CAChB;;;;;;;;;CAUA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAMF,MAAM,UAA2C,OAAO,OAAO,MAAM,aAAa;EAElF,KAAK,MAAM,UAAU,SACnB,MAAM,OAAO,WAAW;EAG1B,KAAK,SAAS;CAChB;AACF"}
1
+ {"version":3,"file":"cache-connector.mjs","names":[],"sources":["../../../../../../../core/src/connectors/cache-connector.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { cache } from \"@warlock.js/cache\";\nimport type { CacheDriver } from \"@warlock.js/cache\";\nimport { BaseConnector } from \"./base-connector\";\nimport { ConnectorLifecyclePhase, ConnectorPriority } from \"./types\";\n\n/**\n * Cache Connector\n * Manages cache engine connection lifecycle\n */\nexport class CacheConnector extends BaseConnector {\n public readonly name = \"cache\";\n public readonly priority = ConnectorPriority.CACHE;\n public readonly lifecyclePhase = ConnectorLifecyclePhase.Early;\n\n /**\n * Files that trigger cache restart\n */\n protected readonly watchedFiles = [\"src/config/cache.ts\", \"src/config/cache.tsx\"];\n\n /**\n * Initialize cache connection\n */\n public async start(): Promise<void> {\n const cacheConfig = config.get(\"cache\");\n\n if (!cacheConfig) return;\n\n cache.setCacheConfigurations(cacheConfig);\n\n await cache.init();\n\n this.active = true;\n }\n\n /**\n * Shutdown cache connection\n *\n * Disconnects every loaded cache driver so external clients (e.g. a Redis\n * connection) are released instead of left dangling — mirroring the\n * database and herald connectors, which disconnect all registered\n * connections on shutdown.\n */\n public async shutdown(): Promise<void> {\n if (!this.active) {\n return;\n }\n\n // Disconnect every driver the manager loaded (not just the current one),\n // so secondary drivers selected via `cache.use(\"...\")` also release their\n // connections.\n const drivers: CacheDriver<unknown, unknown>[] = Object.values(cache.loadedDrivers);\n\n for (const driver of drivers) {\n await driver.disconnect();\n }\n\n this.active = false;\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAa,iBAAb,cAAoC,cAAc;;;cACzB;;;sBAOW,CAAC,uBAAuB,sBAAsB;;;;;CAKhF,MAAa,QAAuB;EAClC,MAAM,cAAc,OAAO,IAAI,OAAO;EAEtC,IAAI,CAAC,aAAa;EAElB,MAAM,uBAAuB,WAAW;EAExC,MAAM,MAAM,KAAK;EAEjB,KAAK,SAAS;CAChB;;;;;;;;;CAUA,MAAa,WAA0B;EACrC,IAAI,CAAC,KAAK,QACR;EAMF,MAAM,UAA2C,OAAO,OAAO,MAAM,aAAa;EAElF,KAAK,MAAM,UAAU,SACnB,MAAM,OAAO,WAAW;EAG1B,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 baseConfig from "@mongez/config";
4
+ import config from "@mongez/config";
5
5
  import { connectToDatabase, dataSourceRegistry } from "@warlock.js/cascade";
6
6
 
7
7
  //#region ../core/src/connectors/database-connector.ts
@@ -21,7 +21,7 @@ var DatabaseConnector = class extends BaseConnector {
21
21
  * Initialize database connection
22
22
  */
23
23
  async start() {
24
- const databaseConfig = baseConfig.get("database");
24
+ const databaseConfig = config.get("database");
25
25
  if (!databaseConfig) return;
26
26
  try {
27
27
  const source = await connectToDatabase(databaseConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"database-connector.mjs","names":["config"],"sources":["../../../../../../../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,iBAAiBA,WAAO,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
+ {"version":3,"file":"database-connector.mjs","names":[],"sources":["../../../../../../../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 baseConfig from "@mongez/config";
3
+ import config from "@mongez/config";
4
4
  import { log } from "@warlock.js/logger";
5
5
 
6
6
  //#region ../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 = baseConfig.get("herald");
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":["config"],"sources":["../../../../../../../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,eAAeA,WAAO,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
+ {"version":3,"file":"herald-connector.mjs","names":[],"sources":["../../../../../../../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":["../../../../../../../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"}
1
+ {"version":3,"file":"http-connector.d.mts","names":[],"sources":["../../../../../../../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;EAmFgB;;;;;EAnDX,KAAA,IAAS,OAAA;EAwFqB;;;;;EArC9B,OAAA,IAAW,OAAA;;;;EASX,QAAA,IAAY,OAAA;;;;;;EA4BlB,aAAA,CAAc,YAAA;AAAA"}