stratal 0.0.16 → 0.0.18

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 (181) hide show
  1. package/README.md +4 -0
  2. package/dist/bin/cloudflare-workers-loader.mjs +33 -1
  3. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  4. package/dist/bin/quarry.mjs +183 -55
  5. package/dist/bin/quarry.mjs.map +1 -1
  6. package/dist/cache/index.d.mts +2 -2
  7. package/dist/cache/index.d.mts.map +1 -1
  8. package/dist/cache/index.mjs +3 -11
  9. package/dist/cache/index.mjs.map +1 -1
  10. package/dist/{colors-DJaRDXoS.mjs → colors-BTAnQRGU.mjs} +1 -1
  11. package/dist/{colors-DJaRDXoS.mjs.map → colors-BTAnQRGU.mjs.map} +1 -1
  12. package/dist/{command-B-QH-Vu3.d.mts → command-B1YuV-UZ.d.mts} +2 -2
  13. package/dist/{command-B-QH-Vu3.d.mts.map → command-B1YuV-UZ.d.mts.map} +1 -1
  14. package/dist/{command-BvCOD6df.mjs → command-DjGqCYHv.mjs} +7 -4
  15. package/dist/command-DjGqCYHv.mjs.map +1 -0
  16. package/dist/config/index.d.mts +2 -2
  17. package/dist/config/index.mjs +12 -20
  18. package/dist/config/index.mjs.map +1 -1
  19. package/dist/consumer-registry-BkuHXR_u.d.mts +142 -0
  20. package/dist/consumer-registry-BkuHXR_u.d.mts.map +1 -0
  21. package/dist/cron/index.d.mts +3 -116
  22. package/dist/cron/index.d.mts.map +1 -1
  23. package/dist/cron/index.mjs +1 -4
  24. package/dist/{cron-manager-DR7fiG6o.mjs → cron-manager-1KnZvojs.mjs} +3 -3
  25. package/dist/{cron-manager-DR7fiG6o.mjs.map → cron-manager-1KnZvojs.mjs.map} +1 -1
  26. package/dist/cron-manager-BnEZquBL.d.mts +117 -0
  27. package/dist/cron-manager-BnEZquBL.d.mts.map +1 -0
  28. package/dist/di/index.d.mts +2 -2
  29. package/dist/di/index.mjs +3 -4
  30. package/dist/email/index.d.mts +3 -3
  31. package/dist/email/index.mjs +8 -17
  32. package/dist/email/index.mjs.map +1 -1
  33. package/dist/{en-DaewN8hc.mjs → en-3QnZwP-u.mjs} +10 -1
  34. package/dist/en-3QnZwP-u.mjs.map +1 -0
  35. package/dist/errors/index.d.mts +2 -2
  36. package/dist/errors/index.mjs +2 -4
  37. package/dist/errors--RBIvDXr.mjs +1560 -0
  38. package/dist/errors--RBIvDXr.mjs.map +1 -0
  39. package/dist/{errors-H3TZnVeX.mjs → errors-B7hCnXgB.mjs} +2 -2
  40. package/dist/{errors-H3TZnVeX.mjs.map → errors-B7hCnXgB.mjs.map} +1 -1
  41. package/dist/events/index.d.mts +2 -2
  42. package/dist/events/index.mjs +1 -3
  43. package/dist/{events-CXl-o1Ad.mjs → events-UTJliZhl.mjs} +2 -3
  44. package/dist/{events-CXl-o1Ad.mjs.map → events-UTJliZhl.mjs.map} +1 -1
  45. package/dist/{gateway-context-BkZ4UKaX.mjs → gateway-context-BdBFoQd8.mjs} +66 -10
  46. package/dist/gateway-context-BdBFoQd8.mjs.map +1 -0
  47. package/dist/guards/index.d.mts +3 -3
  48. package/dist/guards/index.d.mts.map +1 -1
  49. package/dist/guards/index.mjs +1 -1
  50. package/dist/{guards-DUk_Kzst.mjs → guards-MtDgcHnF.mjs} +1 -1
  51. package/dist/{guards-DUk_Kzst.mjs.map → guards-MtDgcHnF.mjs.map} +1 -1
  52. package/dist/i18n/index.d.mts +3 -3
  53. package/dist/i18n/index.mjs +3 -16
  54. package/dist/i18n/messages/en/index.d.mts +1 -1
  55. package/dist/i18n/messages/en/index.mjs +1 -1
  56. package/dist/i18n/utils/index.d.mts +30 -0
  57. package/dist/i18n/utils/index.d.mts.map +1 -0
  58. package/dist/i18n/utils/index.mjs +2 -0
  59. package/dist/i18n/validation/index.d.mts +1 -1
  60. package/dist/i18n/validation/index.mjs +1 -1
  61. package/dist/i18n.module-BpLLLCTg.mjs +2462 -0
  62. package/dist/i18n.module-BpLLLCTg.mjs.map +1 -0
  63. package/dist/{index-D_w_Rmtd.d.mts → index-BDh9J2KD.d.mts} +10 -1
  64. package/dist/{index-D_w_Rmtd.d.mts.map → index-BDh9J2KD.d.mts.map} +1 -1
  65. package/dist/{index-Dp6A5ywM.d.mts → index-BR23zDMy.d.mts} +1 -1
  66. package/dist/{index-Dp6A5ywM.d.mts.map → index-BR23zDMy.d.mts.map} +1 -1
  67. package/dist/index-BrmS34sa.d.mts +4287 -0
  68. package/dist/index-BrmS34sa.d.mts.map +1 -0
  69. package/dist/{index-D9iYu2Yc.d.mts → index-DPxmo6AY.d.mts} +5 -144
  70. package/dist/index-DPxmo6AY.d.mts.map +1 -0
  71. package/dist/{index-DVhdhLvE.d.mts → index-Dfpd_ypO.d.mts} +38 -9
  72. package/dist/index-Dfpd_ypO.d.mts.map +1 -0
  73. package/dist/index.d.mts +4 -3
  74. package/dist/index.d.mts.map +1 -1
  75. package/dist/index.mjs +1 -20
  76. package/dist/{is-command-BfCgWAcQ.mjs → is-command-PvULqiTa.mjs} +2 -2
  77. package/dist/{is-command-BfCgWAcQ.mjs.map → is-command-PvULqiTa.mjs.map} +1 -1
  78. package/dist/{is-seeder-CebjZCDn.mjs → is-seeder-BN9Ej1r7.mjs} +1 -1
  79. package/dist/{is-seeder-CebjZCDn.mjs.map → is-seeder-BN9Ej1r7.mjs.map} +1 -1
  80. package/dist/logger/index.d.mts +1 -1
  81. package/dist/logger/index.mjs +1 -2
  82. package/dist/{logger-BR1-s1Um.mjs → logger-c0ftIK4G.mjs} +170 -4
  83. package/dist/logger-c0ftIK4G.mjs.map +1 -0
  84. package/dist/module/index.d.mts +3 -119
  85. package/dist/module/index.d.mts.map +1 -1
  86. package/dist/module/index.mjs +1 -11
  87. package/dist/module-C3YZ-kZN.mjs +719 -0
  88. package/dist/module-C3YZ-kZN.mjs.map +1 -0
  89. package/dist/openapi/index.d.mts +54 -54
  90. package/dist/openapi/index.d.mts.map +1 -1
  91. package/dist/openapi/index.mjs +3 -16
  92. package/dist/openapi-tools.service-B77QXD56.mjs +197 -0
  93. package/dist/openapi-tools.service-B77QXD56.mjs.map +1 -0
  94. package/dist/openapi.service-6yj0BUY4.d.mts +50 -0
  95. package/dist/openapi.service-6yj0BUY4.d.mts.map +1 -0
  96. package/dist/quarry/index.d.mts +124 -29
  97. package/dist/quarry/index.d.mts.map +1 -1
  98. package/dist/quarry/index.mjs +5 -7
  99. package/dist/quarry-registry-CQCIlYTO.mjs +686 -0
  100. package/dist/quarry-registry-CQCIlYTO.mjs.map +1 -0
  101. package/dist/queue/index.d.mts +2 -1
  102. package/dist/queue/index.mjs +3 -14
  103. package/dist/queue/index.mjs.map +1 -1
  104. package/dist/{queue.module-BZvmeAMj.mjs → queue.module-DIjD6nr-.mjs} +39 -42
  105. package/dist/queue.module-DIjD6nr-.mjs.map +1 -0
  106. package/dist/{resend.provider-BCCACQAU.mjs → resend.provider-Bvw36rQy.mjs} +1 -4
  107. package/dist/{resend.provider-BCCACQAU.mjs.map → resend.provider-Bvw36rQy.mjs.map} +1 -1
  108. package/dist/router/index.d.mts +2 -2
  109. package/dist/router/index.mjs +5 -16
  110. package/dist/{s3-storage.provider-BLlzQYiJ.mjs → s3-storage.provider-BAhHDMI3.mjs} +16 -9
  111. package/dist/s3-storage.provider-BAhHDMI3.mjs.map +1 -0
  112. package/dist/seeder/index.d.mts +3 -4
  113. package/dist/seeder/index.d.mts.map +1 -1
  114. package/dist/seeder/index.mjs +2 -7
  115. package/dist/{seeder-Cupi5jl-.mjs → seeder-D7VXULXB.mjs} +20 -17
  116. package/dist/seeder-D7VXULXB.mjs.map +1 -0
  117. package/dist/setup-BRIN-iYT.mjs +37 -0
  118. package/dist/setup-BRIN-iYT.mjs.map +1 -0
  119. package/dist/{smtp.provider-B8XtOcHU.mjs → smtp.provider-CAwpvzvD.mjs} +1 -4
  120. package/dist/{smtp.provider-B8XtOcHU.mjs.map → smtp.provider-CAwpvzvD.mjs.map} +1 -1
  121. package/dist/storage/index.d.mts +2 -195
  122. package/dist/storage/index.d.mts.map +1 -1
  123. package/dist/storage/index.mjs +2 -14
  124. package/dist/storage/providers/index.d.mts +273 -0
  125. package/dist/storage/providers/index.d.mts.map +1 -0
  126. package/dist/storage/providers/index.mjs +2 -0
  127. package/dist/{storage-By_ow2o_.mjs → storage-CJ-QOwNv.mjs} +8 -9
  128. package/dist/storage-CJ-QOwNv.mjs.map +1 -0
  129. package/dist/storage-provider.interface-YRtyYBxV.d.mts +203 -0
  130. package/dist/storage-provider.interface-YRtyYBxV.d.mts.map +1 -0
  131. package/dist/stratal-B7G4i9-N.mjs +502 -0
  132. package/dist/stratal-B7G4i9-N.mjs.map +1 -0
  133. package/dist/{types-DahElfUw.d.mts → types-CN0zONAZ.d.mts} +2 -2
  134. package/dist/types-CN0zONAZ.d.mts.map +1 -0
  135. package/dist/{usage-generator-C9hWziY4.mjs → usage-generator-Cl1HPlUp.mjs} +2 -2
  136. package/dist/{usage-generator-C9hWziY4.mjs.map → usage-generator-Cl1HPlUp.mjs.map} +1 -1
  137. package/dist/{validation-Bh875Lyg.mjs → validation-B4bePOa_.mjs} +5 -5
  138. package/dist/{validation-Bh875Lyg.mjs.map → validation-B4bePOa_.mjs.map} +1 -1
  139. package/dist/websocket/index.d.mts +2 -2
  140. package/dist/websocket/index.d.mts.map +1 -1
  141. package/dist/websocket/index.mjs +1 -5
  142. package/dist/workers/index.d.mts +1 -1
  143. package/dist/workers/index.d.mts.map +1 -1
  144. package/dist/workers/index.mjs +2 -20
  145. package/dist/workers/index.mjs.map +1 -1
  146. package/package.json +39 -31
  147. package/dist/application-zG8b-pol.d.mts +0 -116
  148. package/dist/application-zG8b-pol.d.mts.map +0 -1
  149. package/dist/command-BvCOD6df.mjs.map +0 -1
  150. package/dist/decorate-D5j-d9_z.mjs +0 -171
  151. package/dist/decorate-D5j-d9_z.mjs.map +0 -1
  152. package/dist/en-DaewN8hc.mjs.map +0 -1
  153. package/dist/errors-CtCi1wn6.mjs +0 -707
  154. package/dist/errors-CtCi1wn6.mjs.map +0 -1
  155. package/dist/gateway-context-BkZ4UKaX.mjs.map +0 -1
  156. package/dist/i18n.module-W8OJxg3d.mjs +0 -1791
  157. package/dist/i18n.module-W8OJxg3d.mjs.map +0 -1
  158. package/dist/index-BJWm863C.d.mts +0 -2616
  159. package/dist/index-BJWm863C.d.mts.map +0 -1
  160. package/dist/index-D9iYu2Yc.d.mts.map +0 -1
  161. package/dist/index-DVhdhLvE.d.mts.map +0 -1
  162. package/dist/logger-BR1-s1Um.mjs.map +0 -1
  163. package/dist/middleware/index.d.mts +0 -2
  164. package/dist/middleware/index.mjs +0 -6
  165. package/dist/middleware-C0Ebzswy.mjs +0 -362
  166. package/dist/middleware-C0Ebzswy.mjs.map +0 -1
  167. package/dist/module-BgdxxzBe.mjs +0 -370
  168. package/dist/module-BgdxxzBe.mjs.map +0 -1
  169. package/dist/quarry-registry-DCwqVcRp.mjs +0 -310
  170. package/dist/quarry-registry-DCwqVcRp.mjs.map +0 -1
  171. package/dist/queue.module-BZvmeAMj.mjs.map +0 -1
  172. package/dist/router-context-BEJe9HEB.mjs +0 -264
  173. package/dist/router-context-BEJe9HEB.mjs.map +0 -1
  174. package/dist/s3-storage.provider-BLlzQYiJ.mjs.map +0 -1
  175. package/dist/seeder-Cupi5jl-.mjs.map +0 -1
  176. package/dist/storage-By_ow2o_.mjs.map +0 -1
  177. package/dist/stratal-CE0iTz4f.mjs +0 -305
  178. package/dist/stratal-CE0iTz4f.mjs.map +0 -1
  179. package/dist/types-CLhOhYsQ.d.mts +0 -64
  180. package/dist/types-CLhOhYsQ.d.mts.map +0 -1
  181. package/dist/types-DahElfUw.d.mts.map +0 -1
package/README.md CHANGED
@@ -80,6 +80,10 @@ Stratal provides [Agent Skills](https://agentskills.io) for AI coding assistants
80
80
  npx skills add strataljs/stratal
81
81
  ```
82
82
 
83
+ | Skill | Description |
84
+ |---|---|
85
+ | `stratal` | Build Cloudflare Workers apps with the Stratal framework — modules, DI, controllers, routing, OpenAPI, queues, cron, events, seeders, CLI, auth, database, RBAC, testing, and more |
86
+
83
87
  ## Quick Start
84
88
 
85
89
  Define a module with a controller and wire it up as a Cloudflare Worker:
@@ -1,21 +1,37 @@
1
1
  #!/usr/bin/env -S node --no-warnings
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
2
4
  //#region src/bin/cloudflare-workers-loader.ts
3
5
  /**
4
- * ESM loader hook that provides a virtual `cloudflare:workers` module.
6
+ * ESM loader hook that provides a virtual `cloudflare:workers` module
7
+ * and handles Vite-style `?raw` imports (returning file contents as a string).
5
8
  *
6
9
  * When registered via `node --import` or `register()`, this intercepts
7
10
  * `import('cloudflare:workers')` and returns a module that reads `env`
8
11
  * and `waitUntil` from `globalThis.__stratalPlatformProxy`.
9
12
  */
10
13
  const VIRTUAL_URL = "cloudflare-workers:virtual";
14
+ const RAW_SUFFIX = "?raw";
11
15
  async function resolve(specifier, context, nextResolve) {
12
16
  if (specifier === "cloudflare:workers") return {
13
17
  url: VIRTUAL_URL,
14
18
  shortCircuit: true
15
19
  };
20
+ if (specifier.endsWith(RAW_SUFFIX)) return {
21
+ url: (await nextResolve(specifier.slice(0, -4), context)).url + RAW_SUFFIX,
22
+ shortCircuit: true
23
+ };
16
24
  return nextResolve(specifier, context);
17
25
  }
18
26
  async function load(url, context, nextLoad) {
27
+ if (url.endsWith(RAW_SUFFIX)) {
28
+ const content = readFileSync(fileURLToPath(url.slice(0, -4)), "utf-8");
29
+ return {
30
+ format: "module",
31
+ shortCircuit: true,
32
+ source: `export default ${JSON.stringify(content)}`
33
+ };
34
+ }
19
35
  if (url === VIRTUAL_URL) return {
20
36
  format: "module",
21
37
  shortCircuit: true,
@@ -24,6 +40,22 @@ const proxy = globalThis.__stratalPlatformProxy;
24
40
  if (!proxy) throw new Error('globalThis.__stratalPlatformProxy not set — Quarry CLI must initialize it before importing the app entry.');
25
41
  export const env = proxy.env;
26
42
  export const waitUntil = proxy.waitUntil;
43
+ export const exports = {}
44
+ export class DurableObject {
45
+ constructor(ctx, env) { this.ctx = ctx; this.env = env; }
46
+ }
47
+ export class WorkerEntrypoint {
48
+ constructor(ctx, env) { this.ctx = ctx; this.env = env; }
49
+ }
50
+ export class WorkflowEntrypoint {
51
+ constructor(ctx, env) { this.ctx = ctx; this.env = env; }
52
+ }
53
+ export class WorkflowStep {}
54
+ export class RpcTarget {}
55
+ export const RpcStub = function(value) { return value; };
56
+ export function withEnv(newEnv, fn) { return fn(); }
57
+ export function withExports(newExports, fn) { return fn(); }
58
+ export function withEnvAndExports(newEnv, newExports, fn) { return fn(); }
27
59
  `
28
60
  };
29
61
  return nextLoad(url, context);
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare-workers-loader.mjs","names":[],"sources":["../../src/bin/cloudflare-workers-loader.ts"],"sourcesContent":["/**\n * ESM loader hook that provides a virtual `cloudflare:workers` module.\n *\n * When registered via `node --import` or `register()`, this intercepts\n * `import('cloudflare:workers')` and returns a module that reads `env`\n * and `waitUntil` from `globalThis.__stratalPlatformProxy`.\n */\n\nconst VIRTUAL_URL = 'cloudflare-workers:virtual'\n\ninterface ResolveContext {\n parentURL?: string\n conditions: string[]\n}\n\ninterface ResolveResult {\n url: string\n shortCircuit?: boolean\n}\n\ntype NextResolve = (specifier: string, context: ResolveContext) => Promise<ResolveResult>\n\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve,\n): Promise<ResolveResult> {\n if (specifier === 'cloudflare:workers') {\n return { url: VIRTUAL_URL, shortCircuit: true }\n }\n return nextResolve(specifier, context)\n}\n\ninterface LoadContext {\n format?: string\n conditions: string[]\n}\n\ninterface LoadResult {\n format: string\n source: string\n shortCircuit?: boolean\n}\n\ntype NextLoad = (url: string, context: LoadContext) => Promise<LoadResult>\n\nexport async function load(\n url: string,\n context: LoadContext,\n nextLoad: NextLoad,\n): Promise<LoadResult> {\n if (url === VIRTUAL_URL) {\n return {\n format: 'module',\n shortCircuit: true,\n source: `\nconst proxy = globalThis.__stratalPlatformProxy;\nif (!proxy) throw new Error('globalThis.__stratalPlatformProxy not set — Quarry CLI must initialize it before importing the app entry.');\nexport const env = proxy.env;\nexport const waitUntil = proxy.waitUntil;\n`,\n }\n }\n return nextLoad(url, context)\n}\n"],"mappings":";;;;;;;;;AAQA,MAAM,cAAc;AAcpB,eAAsB,QACpB,WACA,SACA,aACwB;AACxB,KAAI,cAAc,qBAChB,QAAO;EAAE,KAAK;EAAa,cAAc;EAAM;AAEjD,QAAO,YAAY,WAAW,QAAQ;;AAgBxC,eAAsB,KACpB,KACA,SACA,UACqB;AACrB,KAAI,QAAQ,YACV,QAAO;EACL,QAAQ;EACR,cAAc;EACd,QAAQ;;;;;;EAMT;AAEH,QAAO,SAAS,KAAK,QAAQ"}
1
+ {"version":3,"file":"cloudflare-workers-loader.mjs","names":[],"sources":["../../src/bin/cloudflare-workers-loader.ts"],"sourcesContent":["/**\n * ESM loader hook that provides a virtual `cloudflare:workers` module\n * and handles Vite-style `?raw` imports (returning file contents as a string).\n *\n * When registered via `node --import` or `register()`, this intercepts\n * `import('cloudflare:workers')` and returns a module that reads `env`\n * and `waitUntil` from `globalThis.__stratalPlatformProxy`.\n */\n\nimport { readFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\n\nconst VIRTUAL_URL = 'cloudflare-workers:virtual'\nconst RAW_SUFFIX = '?raw'\n\ninterface ResolveContext {\n parentURL?: string\n conditions: string[]\n}\n\ninterface ResolveResult {\n url: string\n shortCircuit?: boolean\n}\n\ntype NextResolve = (specifier: string, context: ResolveContext) => Promise<ResolveResult>\n\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve,\n): Promise<ResolveResult> {\n if (specifier === 'cloudflare:workers') {\n return { url: VIRTUAL_URL, shortCircuit: true }\n }\n if (specifier.endsWith(RAW_SUFFIX)) {\n const base = specifier.slice(0, -RAW_SUFFIX.length)\n const resolved = await nextResolve(base, context)\n return { url: resolved.url + RAW_SUFFIX, shortCircuit: true }\n }\n return nextResolve(specifier, context)\n}\n\ninterface LoadContext {\n format?: string\n conditions: string[]\n}\n\ninterface LoadResult {\n format: string\n source: string\n shortCircuit?: boolean\n}\n\ntype NextLoad = (url: string, context: LoadContext) => Promise<LoadResult>\n\nexport async function load(\n url: string,\n context: LoadContext,\n nextLoad: NextLoad,\n): Promise<LoadResult> {\n if (url.endsWith(RAW_SUFFIX)) {\n const fileUrl = url.slice(0, -RAW_SUFFIX.length)\n const filePath = fileURLToPath(fileUrl)\n const content = readFileSync(filePath, 'utf-8')\n return {\n format: 'module',\n shortCircuit: true,\n source: `export default ${JSON.stringify(content)}`,\n }\n }\n if (url === VIRTUAL_URL) {\n return {\n format: 'module',\n shortCircuit: true,\n source: `\nconst proxy = globalThis.__stratalPlatformProxy;\nif (!proxy) throw new Error('globalThis.__stratalPlatformProxy not set — Quarry CLI must initialize it before importing the app entry.');\nexport const env = proxy.env;\nexport const waitUntil = proxy.waitUntil;\nexport const exports = {}\nexport class DurableObject {\n constructor(ctx, env) { this.ctx = ctx; this.env = env; }\n}\nexport class WorkerEntrypoint {\n constructor(ctx, env) { this.ctx = ctx; this.env = env; }\n}\nexport class WorkflowEntrypoint {\n constructor(ctx, env) { this.ctx = ctx; this.env = env; }\n}\nexport class WorkflowStep {}\nexport class RpcTarget {}\nexport const RpcStub = function(value) { return value; };\nexport function withEnv(newEnv, fn) { return fn(); }\nexport function withExports(newExports, fn) { return fn(); }\nexport function withEnvAndExports(newEnv, newExports, fn) { return fn(); }\n`,\n }\n }\n return nextLoad(url, context)\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,cAAc;AACpB,MAAM,aAAa;AAcnB,eAAsB,QACpB,WACA,SACA,aACwB;AACxB,KAAI,cAAc,qBAChB,QAAO;EAAE,KAAK;EAAa,cAAc;EAAM;AAEjD,KAAI,UAAU,SAAS,WAAW,CAGhC,QAAO;EAAE,MADQ,MAAM,YADV,UAAU,MAAM,GAAG,GAAmB,EACV,QAAQ,EAC1B,MAAM;EAAY,cAAc;EAAM;AAE/D,QAAO,YAAY,WAAW,QAAQ;;AAgBxC,eAAsB,KACpB,KACA,SACA,UACqB;AACrB,KAAI,IAAI,SAAS,WAAW,EAAE;EAG5B,MAAM,UAAU,aADC,cADD,IAAI,MAAM,GAAG,GAAmB,CACT,EACA,QAAQ;AAC/C,SAAO;GACL,QAAQ;GACR,cAAc;GACd,QAAQ,kBAAkB,KAAK,UAAU,QAAQ;GAClD;;AAEH,KAAI,QAAQ,YACV,QAAO;EACL,QAAQ;EACR,cAAc;EACd,QAAQ;;;;;;;;;;;;;;;;;;;;;;EAsBT;AAEH,QAAO,SAAS,KAAK,QAAQ"}
@@ -1,10 +1,136 @@
1
1
  #!/usr/bin/env -S node --no-warnings
2
2
  import { createRequire, register } from "node:module";
3
3
  import "reflect-metadata";
4
- import { existsSync } from "node:fs";
4
+ import { existsSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
5
6
  import { dirname, join, resolve } from "node:path";
6
7
  import { pathToFileURL } from "node:url";
7
8
  import { Command, Option } from "clipanion";
9
+ //#region src/i18n/messages/en/errors.ts
10
+ /**
11
+ * System Error Messages - English
12
+ *
13
+ * Error messages used by packages/modules infrastructure.
14
+ * These are automatically merged with application-specific messages.
15
+ */
16
+ const errors = {
17
+ internalError: "An internal error occurred",
18
+ notFound: "Resource not found",
19
+ unauthorized: "Unauthorized. Please sign in.",
20
+ forbidden: "Access denied",
21
+ honoAppAlreadyConfigured: "HonoApp has already been configured and can only be configured once",
22
+ routeNotFound: "Route not found: {method} {path}",
23
+ routeAccessDenied: "Resource not found",
24
+ controllerMethodNotFound: "Method {methodName} not found on {controllerName}",
25
+ controllerRegistration: "Failed to register controller {controllerName}: {reason}",
26
+ duplicateRouteName: "Duplicate route name \"{name}\". Already registered by {existingHandler}, cannot register {newHandler}.",
27
+ routeNameNotFound: "Route \"{name}\" not found in registry.",
28
+ missingRouteParam: "Missing required parameter \"{param}\" for route \"{name}\" (path: {path}).",
29
+ routerUseScopeViolation: "router.use() can only be called on the root Router, not inside group() callbacks. Use router.middleware() for scoped middleware.",
30
+ missingEnvironmentVariable: "Environment variable \"{variable}\" is required but not set.",
31
+ websocketBodyNotAvailable: "body() is not available in WebSocket gateways. Use WebSocket messages instead.",
32
+ websocketDuplicateEventHandler: "@{decorator}() is already applied to '{existingMethod}'. Only one method per gateway can handle this event.",
33
+ contextNotInitialized: "Context has not been initialized",
34
+ userNotAuthenticated: "User is not authenticated",
35
+ insufficientPermissions: "Insufficient permissions to perform this action",
36
+ requestContainerNotInitialized: "Request container has not been initialized",
37
+ requestScopeOperationNotAllowed: "{methodName}() cannot be called on this container scope. Check if you are calling it on the correct container (global vs request-scoped).",
38
+ conditionalBindingFallback: "Conditional binding predicate returned false for token \"{token}\" but no fallback was provided and no existing registration exists.",
39
+ configNotInitialized: "Configuration service has not been initialized",
40
+ configModuleNotInitialized: "ConfigModule.forRoot() was not called before module initialization",
41
+ stratalNotInitialized: "Stratal has not been instantiated. Ensure you export a Stratal instance as the default export.",
42
+ moduleAlreadyRegistered: "Module {moduleName} is already registered",
43
+ moduleDependencyNotFound: "Module dependency {dependency} not found for module {moduleName}",
44
+ moduleCircularDependency: "Circular dependency detected: {cycle}",
45
+ invalidModuleProvider: "Invalid module provider configuration: {provider}",
46
+ databaseGeneric: "Database error occurred",
47
+ databaseRecordNotFound: "Record not found in database",
48
+ databaseUniqueConstraint: "Record already exists",
49
+ databaseForeignKeyConstraint: "Related record not found",
50
+ databaseConnectionFailed: "Failed to connect to database",
51
+ databaseTimeout: "Database query timeout",
52
+ databaseNullConstraint: "Required field is missing",
53
+ databaseTooManyConnections: "Too many database connections",
54
+ databaseTransactionConflict: "Transaction conflict or deadlock",
55
+ databaseConstraintFailed: "A database constraint was violated",
56
+ databaseTableNotFound: "The specified table does not exist in the database",
57
+ databaseColumnNotFound: "The specified column does not exist in the table",
58
+ databaseInvalidQuery: "The database query is invalid or malformed",
59
+ invalidErrorCodeRange: "Invalid error code range: {code}",
60
+ queueBindingNotFound: "Queue binding {queueName} not found in environment",
61
+ queueProviderNotSupported: "Queue provider \"{provider}\" is not supported. Valid providers: cloudflare, sync",
62
+ cronExecutionFailed: "{count} cron job(s) failed for schedule \"{schedule}\": {jobs}",
63
+ localeNotSupported: "Locale '{locale}' is not supported. Supported locales: {supportedLocales}",
64
+ translationMissing: "Translation missing for key '{key}' in locale '{locale}'",
65
+ containerNotInitialized: "Application container has not been initialized. Ensure Application.initialize() has been called.",
66
+ domainMismatch: "The requested domain does not match any configured route",
67
+ invalidSignature: "The URL signature is invalid or has expired",
68
+ schemaValidation: "Schema validation failed",
69
+ responseValidation: "Response validation failed",
70
+ openapiValidation: "OpenAPI validation failed: {details}",
71
+ openapiRouteRegistration: "Failed to register OpenAPI route {path}: {reason}",
72
+ email: {
73
+ resendApiKeyMissing: "Resend API key not configured. Set RESEND_EMAIL_API_KEY environment variable.",
74
+ smtpConfigurationMissing: "SMTP configuration missing. Set SMTP_URL environment variable.",
75
+ smtpHostMissing: "SMTP host not configured. Check SMTP_URL format (smtp://user:pass@host:port).",
76
+ smtpConnectionFailed: "Failed to connect to SMTP server {smtpHost}:{smtpPort}",
77
+ resendApiFailed: "Resend API error",
78
+ providerNotSupported: "Unsupported email provider: {provider}. Supported providers: resend, smtp"
79
+ },
80
+ storage: {
81
+ fileNotFound: "File at path \"{path}\" was not found",
82
+ invalidDisk: "Storage disk \"{disk}\" is not configured",
83
+ invalidFileType: "File type \"{mimeType}\" is not allowed",
84
+ fileTooLarge: "File size {size} exceeds maximum allowed size of {maxSize}",
85
+ presignedUrlInvalidExpiry: "Expiry must be between {min} and {max} seconds",
86
+ diskNotConfigured: "Disk \"{disk}\" is not configured",
87
+ providerNotSupported: "Storage provider \"{provider}\" is not supported",
88
+ responseBodyMissing: "No body in storage response for path: {path}"
89
+ },
90
+ cache: {
91
+ getFailed: "Failed to retrieve value from cache for key '{key}'",
92
+ putFailed: "Failed to store value in cache for key '{key}'",
93
+ deleteFailed: "Failed to delete value from cache for key '{key}'",
94
+ listFailed: "Failed to list cache keys"
95
+ },
96
+ auth: {
97
+ tokenRequired: "Verification token is required",
98
+ invalidToken: "Invalid or expired verification token",
99
+ verificationFailed: "Verification failed. Please try again.",
100
+ userNotFound: "User not found. Please check your credentials.",
101
+ invalidCredentials: "Invalid email or password",
102
+ invalidPassword: "Invalid password",
103
+ invalidEmail: "Invalid email address",
104
+ sessionExpired: "Your session has expired. Please sign in again.",
105
+ emailNotVerified: "Please verify your email address before signing in",
106
+ passwordTooShort: "Password must be at least {minLength} characters",
107
+ passwordTooLong: "Password must be at most {maxLength} characters",
108
+ accountAlreadyExists: "An account with this email already exists",
109
+ failedToCreateUser: "Failed to create user account. Please try again.",
110
+ failedToCreateSession: "Failed to create session. Please try again.",
111
+ failedToGetSession: "Failed to retrieve session. Please try again.",
112
+ failedToUpdateUser: "Failed to update user information. Please try again.",
113
+ failedToGetUserInfo: "Failed to retrieve user information. Please try again.",
114
+ socialAccountLinked: "This social account is already linked to another user",
115
+ providerNotFound: "Authentication provider not found",
116
+ userEmailNotFound: "User email address not found",
117
+ accountNotFound: "Account not found",
118
+ credentialAccountNotFound: "Credential account not found",
119
+ cannotUnlinkLastAccount: "Cannot unlink your last account",
120
+ userAlreadyHasPassword: "User already has a password set",
121
+ emailCannotBeUpdated: "Email address cannot be updated at this time",
122
+ tokenExpired: "The verification token has expired. Please request a new verification email."
123
+ },
124
+ seederNameCollision: "Seeder name collision: \"{name}\" is already registered. Use distinct class names for each seeder.",
125
+ seederNotRegistered: "Seeder \"{name}\" is not registered",
126
+ migration: {
127
+ failed: "Migration {migrationName} failed: {error}",
128
+ checksumMismatch: "Migration {migrationName} checksum mismatch (expected: {expected}, actual: {actual})",
129
+ alreadyApplied: "Migration {migrationName} has already been applied",
130
+ notFound: "Migration {migrationName} not found"
131
+ }
132
+ };
133
+ //#endregion
8
134
  //#region src/bin/commands/dynamic-command.ts
9
135
  /** Create Clipanion command classes from Quarry-registered commands. */
10
136
  function createDynamicCommands(quarry, parseSignature, app) {
@@ -14,6 +140,7 @@ function createDynamicCommands(quarry, parseSignature, app) {
14
140
  const signature = parseSignature(commandClass.command);
15
141
  const paths = [entry.name.split(" ")];
16
142
  if (commandClass.aliases) for (const alias of commandClass.aliases) paths.push(alias.split(" "));
143
+ if (entry.name === "help") paths.push([]);
17
144
  class DynCmd extends Command {
18
145
  static paths = paths;
19
146
  static usage = commandClass.description ? Command.Usage({ description: commandClass.description }) : void 0;
@@ -59,55 +186,6 @@ function createDynamicCommands(quarry, parseSignature, app) {
59
186
  return commands;
60
187
  }
61
188
  //#endregion
62
- //#region src/quarry/errors/command-not-found.error.ts
63
- /**
64
- * Thrown when a command is not found in the Quarry registry.
65
- */
66
- var CommandNotFoundError = class extends Error {
67
- constructor(name) {
68
- super(`Command "${name}" is not registered.`);
69
- this.name = "CommandNotFoundError";
70
- }
71
- };
72
- //#endregion
73
- //#region src/bin/commands/help-command.ts
74
- /** Create the built-in `help`/`list` Clipanion command that delegates to Quarry's usage generator. */
75
- function createHelpCommand(quarry) {
76
- class HelpCommand extends Command {
77
- static paths = [
78
- [],
79
- ["help"],
80
- ["list"]
81
- ];
82
- static usage = Command.Usage({ description: "Show help for a command" });
83
- commandPath = Option.Rest();
84
- async execute() {
85
- const commandName = this.commandPath.join(" ");
86
- if (this.help || !commandName) {
87
- const listing = await quarry.listUsage({
88
- binaryName: this.cli.binaryName,
89
- binaryLabel: this.cli.binaryLabel,
90
- binaryVersion: this.cli.binaryVersion
91
- });
92
- this.context.stdout.write(listing + "\n");
93
- return 0;
94
- }
95
- try {
96
- const usage = await quarry.usage(commandName);
97
- this.context.stdout.write(usage + "\n");
98
- return 0;
99
- } catch (error) {
100
- if (error instanceof CommandNotFoundError) {
101
- this.context.stderr.write(`Unknown command: ${commandName}\n`);
102
- return 1;
103
- }
104
- throw error;
105
- }
106
- }
107
- }
108
- return HelpCommand;
109
- }
110
- //#endregion
111
189
  //#region src/bin/quarry.ts
112
190
  const require = createRequire(import.meta.url);
113
191
  register(pathToFileURL(join(dirname(require.resolve("@swc-node/register")), "esm/esm.mjs")), pathToFileURL("./"));
@@ -127,9 +205,53 @@ if (!existsSync(entryPath)) {
127
205
  console.error(" npx quarry ./path/to/entry.ts <command> [options]");
128
206
  process.exit(1);
129
207
  }
208
+ function stripDurableObjects(config) {
209
+ delete config.durable_objects;
210
+ delete config.migrations;
211
+ if (config.env && typeof config.env === "object") for (const envConfig of Object.values(config.env)) {
212
+ delete envConfig.durable_objects;
213
+ delete envConfig.migrations;
214
+ }
215
+ }
216
+ async function createStrippedConfig(cwdRequire) {
217
+ const configName = [
218
+ "wrangler.jsonc",
219
+ "wrangler.json",
220
+ "wrangler.toml"
221
+ ].find((c) => existsSync(resolve(process.cwd(), c)));
222
+ if (!configName) return void 0;
223
+ const raw = readFileSync(resolve(process.cwd(), configName), "utf-8");
224
+ let config;
225
+ if (configName.endsWith(".toml")) {
226
+ const { parse } = await import(cwdRequire.resolve("smol-toml"));
227
+ config = parse(raw);
228
+ } else {
229
+ const { parse: parseJsonc } = await import(cwdRequire.resolve("jsonc-parser"));
230
+ config = parseJsonc(raw);
231
+ }
232
+ stripDurableObjects(config);
233
+ const tmpPath = resolve(tmpdir(), `quarry-wrangler-${Date.now()}.json`);
234
+ writeFileSync(tmpPath, JSON.stringify(config, null, 2));
235
+ return tmpPath;
236
+ }
237
+ function discoverEnvFiles() {
238
+ const cwd = process.cwd();
239
+ return readdirSync(cwd).filter((file) => (/^\.dev\.vars($|\.)/.test(file) || /^\.env($|\.)/.test(file)) && !file.endsWith(".example") && !file.endsWith(".sample")).sort((a, b) => {
240
+ const aIsDevVars = a.startsWith(".dev.vars");
241
+ if (aIsDevVars !== b.startsWith(".dev.vars")) return aIsDevVars ? 1 : -1;
242
+ const aIsLocal = a.endsWith(".local");
243
+ if (aIsLocal !== b.endsWith(".local")) return aIsLocal ? 1 : -1;
244
+ return a.localeCompare(b);
245
+ }).map((file) => join(cwd, file));
246
+ }
130
247
  async function main() {
131
- const { getPlatformProxy } = await import(createRequire(join(process.cwd(), "package.json")).resolve("wrangler"));
132
- const { env, ctx, dispose } = await getPlatformProxy();
248
+ const cwdRequire = createRequire(join(process.cwd(), "package.json"));
249
+ const { getPlatformProxy } = await import(cwdRequire.resolve("wrangler"));
250
+ const tmpConfigPath = await createStrippedConfig(cwdRequire);
251
+ const { env, ctx, dispose } = await getPlatformProxy({
252
+ envFiles: discoverEnvFiles(),
253
+ configPath: tmpConfigPath
254
+ });
133
255
  let app;
134
256
  try {
135
257
  globalThis.__stratalPlatformProxy = {
@@ -150,16 +272,22 @@ async function main() {
150
272
  binaryLabel: "Quarry CLI",
151
273
  binaryVersion: require("../../package.json").version
152
274
  });
153
- cli.register(createHelpCommand(quarry));
154
275
  for (const cmd of createDynamicCommands(quarry, parseSignature, app)) cli.register(cmd);
155
276
  await cli.runExit(process.argv.slice(2), { ...Cli.defaultContext });
156
277
  } finally {
157
278
  await app?.shutdown();
158
279
  await dispose();
280
+ if (tmpConfigPath) try {
281
+ unlinkSync(tmpConfigPath);
282
+ } catch {}
159
283
  }
160
284
  }
161
- main().catch((error) => {
162
- console.error("Fatal error:", error instanceof Error ? error.message : String(error));
285
+ main().catch(async (error) => {
286
+ const { ConfigValidationError } = await import("stratal/config");
287
+ const { StratalNotInitializedError } = await import("stratal/errors");
288
+ const message = error instanceof StratalNotInitializedError ? errors.stratalNotInitialized : error instanceof Error ? error.message : String(error);
289
+ console.error("Fatal error:", message);
290
+ if (error instanceof ConfigValidationError) console.error(error.errors.message);
163
291
  process.exit(1);
164
292
  });
165
293
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"quarry.mjs","names":[],"sources":["../../src/bin/commands/dynamic-command.ts","../../src/quarry/errors/command-not-found.error.ts","../../src/bin/commands/help-command.ts","../../src/bin/quarry.ts"],"sourcesContent":["import { Command, type CommandClass, Option, type Usage } from 'clipanion'\n\nimport type { Application } from 'stratal'\nimport type { QuarryRegistry } from 'stratal/quarry'\nimport type { ParsedSignature } from 'stratal/quarry'\n\n/** Create Clipanion command classes from Quarry-registered commands. */\nexport function createDynamicCommands(\n quarry: QuarryRegistry,\n parseSignature: (command: string) => ParsedSignature,\n app: Application,\n) {\n const commands: CommandClass[] = []\n\n for (const entry of quarry.list()) {\n const commandClass = quarry.get(entry.name)! as unknown as { command: string; description?: string; aliases?: string[] }\n const signature = parseSignature(commandClass.command)\n\n const paths: string[][] = [entry.name.split(' ')]\n if (commandClass.aliases) {\n for (const alias of commandClass.aliases) {\n paths.push(alias.split(' '))\n }\n }\n\n class DynCmd extends Command {\n static override paths = paths\n static override usage: Usage | undefined = commandClass.description\n ? Command.Usage({ description: commandClass.description })\n : undefined\n\n async execute(): Promise<number> {\n const input: Record<string, unknown> = {}\n\n for (const arg of signature.arguments) {\n const value = (this as Record<string, unknown>)[arg.name]\n if (value !== undefined) input[arg.name] = value\n }\n\n for (const opt of signature.options) {\n const value = (this as Record<string, unknown>)[opt.name]\n if (value !== undefined) input[opt.name] = value\n }\n\n const result = await app.handleCommand(entry.name, input)\n\n for (const line of result.output) {\n this.context.stdout.write(line + '\\n')\n }\n\n for (const err of result.errors) {\n this.context.stderr.write(err + '\\n')\n }\n\n return result.exitCode\n }\n }\n\n // Define Clipanion options/arguments as class property defaults\n const proto = DynCmd.prototype as unknown as Record<string, unknown>\n for (const arg of signature.arguments) {\n if (arg.isArray) {\n proto[arg.name] = Option.Rest({ name: arg.name, required: arg.required ? 1 : 0 })\n } else {\n proto[arg.name] = Option.String({ name: arg.name, required: arg.required })\n }\n }\n\n for (const opt of signature.options) {\n const optName = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n const optDescParts: string[] = []\n if (opt.description) optDescParts.push(opt.description)\n if (opt.default !== undefined) optDescParts.push(`(default: ${opt.default})`)\n const optDesc = optDescParts.length > 0 ? optDescParts.join(' ') : undefined\n\n if (opt.isFlag) {\n proto[opt.name] = Option.Boolean(optName, { description: optDesc })\n } else if (opt.isArray) {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.Array(optName, [opt.default], { description: optDesc })\n } else {\n proto[opt.name] = Option.Array(optName, { description: optDesc })\n }\n } else {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.String(optName, opt.default, { description: optDesc })\n } else {\n proto[opt.name] = Option.String(optName, { description: optDesc })\n }\n }\n }\n\n commands.push(DynCmd)\n }\n\n return commands\n}\n","/**\n * Thrown when a command is not found in the Quarry registry.\n */\nexport class CommandNotFoundError extends Error {\n constructor(name: string) {\n super(`Command \"${name}\" is not registered.`)\n this.name = 'CommandNotFoundError'\n }\n}\n","import { Command, Option, type Usage } from 'clipanion'\nimport { CommandNotFoundError } from '../../quarry/errors/command-not-found.error'\nimport type { QuarryRegistry } from '../../quarry/quarry-registry'\n\n/** Create the built-in `help`/`list` Clipanion command that delegates to Quarry's usage generator. */\nexport function createHelpCommand(quarry: QuarryRegistry) {\n class HelpCommand extends Command {\n static override paths = [[], ['help'], ['list']]\n static override usage: Usage = Command.Usage({ description: 'Show help for a command' })\n\n commandPath = Option.Rest()\n\n async execute(): Promise<number> {\n const commandName = this.commandPath.join(' ')\n\n if (this.help || !commandName) {\n const listing = await quarry.listUsage({\n binaryName: this.cli.binaryName,\n binaryLabel: this.cli.binaryLabel,\n binaryVersion: this.cli.binaryVersion,\n })\n this.context.stdout.write(listing + '\\n')\n return 0\n }\n\n try {\n const usage = await quarry.usage(commandName)\n this.context.stdout.write(usage + '\\n')\n return 0\n } catch (error) {\n if (error instanceof CommandNotFoundError) {\n this.context.stderr.write(`Unknown command: ${commandName}\\n`)\n return 1\n }\n throw error\n }\n }\n }\n\n return HelpCommand\n}\n","import 'reflect-metadata'\n\nimport { existsSync } from 'node:fs'\nimport { createRequire, register } from 'node:module'\nimport { dirname, join, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport type { QuarryRegistry } from 'stratal/quarry'\n\nimport { type Application } from '../application'\nimport { createDynamicCommands } from './commands/dynamic-command'\nimport { createHelpCommand } from './commands/help-command'\n\nconst require = createRequire(import.meta.url)\n\n// Register @swc-node/register for TypeScript + decorator support\nconst swcRegisterPath = join(dirname(require.resolve('@swc-node/register')), 'esm/esm.mjs')\nregister(pathToFileURL(swcRegisterPath), pathToFileURL('./'))\n\n// Register cloudflare:workers virtual module loader\nregister(new URL('./cloudflare-workers-loader.mjs', import.meta.url), pathToFileURL('./'))\n\nconst DEFAULT_ENTRY = './src/index.ts'\n\n// Determine entry file: if first arg looks like a file path, use it; otherwise use default\nconst firstArg = process.argv[2]\nlet entryFile = DEFAULT_ENTRY\n\nif (firstArg && (firstArg.includes('/') || firstArg.includes('\\\\') || /\\.(ts|js|mts|mjs)$/.test(firstArg))) {\n entryFile = firstArg\n // Remove the entry file from argv so Clipanion sees: [node, script, command, ...options]\n process.argv.splice(2, 1)\n}\n\n// Resolve and validate the entry file\nconst entryPath = resolve(process.cwd(), entryFile)\n\nif (!existsSync(entryPath)) {\n console.error(`Error: Entry file not found: ${entryFile}`)\n console.error('')\n console.error('Create src/index.ts with a default Stratal export, or specify a custom path:')\n console.error(' npx quarry ./path/to/entry.ts <command> [options]')\n process.exit(1)\n}\n\nasync function main(): Promise<void> {\n const cwdRequire = createRequire(join(process.cwd(), 'package.json'))\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n const { getPlatformProxy } = await import(cwdRequire.resolve('wrangler')) as typeof import('wrangler')\n const { env, ctx, dispose } = await getPlatformProxy()\n\n let app: Application | undefined\n try {\n // Store platform proxy on globalThis so the cloudflare:workers virtual module can read it\n (globalThis as Record<string, unknown>).__stratalPlatformProxy = {\n env,\n waitUntil: ctx.waitUntil.bind(ctx),\n }\n\n // Import user's entry file — triggers `new Stratal(...)` + full Application init\n await import(pathToFileURL(entryPath).href)\n\n // Parallel import of stratal modules\n const [\n { Stratal },\n { DI_TOKENS },\n { parseSignature },\n ] = await Promise.all([\n import('stratal'),\n import('stratal/di'),\n import('stratal/quarry'),\n ])\n\n app = await Stratal.resolveApplication()\n const quarry = app.container.resolve<QuarryRegistry>(DI_TOKENS.Quarry)\n\n // Build Clipanion CLI\n const { Cli } = await import('clipanion')\n const pkg = require('../../package.json') as { version: string }\n\n const cli = new Cli({\n binaryName: 'quarry',\n binaryLabel: 'Quarry CLI',\n binaryVersion: pkg.version,\n })\n\n cli.register(createHelpCommand(quarry))\n\n for (const cmd of createDynamicCommands(quarry, parseSignature, app)) {\n cli.register(cmd)\n }\n\n await cli.runExit(process.argv.slice(2), { ...Cli.defaultContext })\n } finally {\n await app?.shutdown()\n await dispose()\n }\n}\n\nmain().catch((error: unknown) => {\n console.error('Fatal error:', error instanceof Error ? error.message : String(error))\n process.exit(1)\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"quarry.mjs","names":["errorMessages"],"sources":["../../src/i18n/messages/en/errors.ts","../../src/bin/commands/dynamic-command.ts","../../src/bin/quarry.ts"],"sourcesContent":["/**\n * System Error Messages - English\n *\n * Error messages used by packages/modules infrastructure.\n * These are automatically merged with application-specific messages.\n */\n\nexport const errors = {\n // Generic errors\n internalError: 'An internal error occurred',\n notFound: 'Resource not found',\n unauthorized: 'Unauthorized. Please sign in.',\n forbidden: 'Access denied',\n\n // Router errors\n honoAppAlreadyConfigured: 'HonoApp has already been configured and can only be configured once',\n routeNotFound: 'Route not found: {method} {path}',\n routeAccessDenied: 'Resource not found',\n controllerMethodNotFound: 'Method {methodName} not found on {controllerName}',\n controllerRegistration: 'Failed to register controller {controllerName}: {reason}',\n duplicateRouteName: 'Duplicate route name \"{name}\". Already registered by {existingHandler}, cannot register {newHandler}.',\n routeNameNotFound: 'Route \"{name}\" not found in registry.',\n missingRouteParam: 'Missing required parameter \"{param}\" for route \"{name}\" (path: {path}).',\n routerUseScopeViolation: 'router.use() can only be called on the root Router, not inside group() callbacks. Use router.middleware() for scoped middleware.',\n missingEnvironmentVariable: 'Environment variable \"{variable}\" is required but not set.',\n\n // WebSocket errors\n websocketBodyNotAvailable: 'body() is not available in WebSocket gateways. Use WebSocket messages instead.',\n websocketDuplicateEventHandler: '@{decorator}() is already applied to \\'{existingMethod}\\'. Only one method per gateway can handle this event.',\n\n // Context errors\n contextNotInitialized: 'Context has not been initialized',\n userNotAuthenticated: 'User is not authenticated',\n insufficientPermissions: 'Insufficient permissions to perform this action',\n requestContainerNotInitialized: 'Request container has not been initialized',\n requestScopeOperationNotAllowed: '{methodName}() cannot be called on this container scope. Check if you are calling it on the correct container (global vs request-scoped).',\n conditionalBindingFallback: 'Conditional binding predicate returned false for token \"{token}\" but no fallback was provided and no existing registration exists.',\n\n // Configuration errors\n configNotInitialized: 'Configuration service has not been initialized',\n configModuleNotInitialized: 'ConfigModule.forRoot() was not called before module initialization',\n stratalNotInitialized: 'Stratal has not been instantiated. Ensure you export a Stratal instance as the default export.',\n\n // Module errors\n moduleAlreadyRegistered: 'Module {moduleName} is already registered',\n moduleDependencyNotFound: 'Module dependency {dependency} not found for module {moduleName}',\n moduleCircularDependency: 'Circular dependency detected: {cycle}',\n invalidModuleProvider: 'Invalid module provider configuration: {provider}',\n\n // Database errors\n databaseGeneric: 'Database error occurred',\n databaseRecordNotFound: 'Record not found in database',\n databaseUniqueConstraint: 'Record already exists',\n databaseForeignKeyConstraint: 'Related record not found',\n databaseConnectionFailed: 'Failed to connect to database',\n databaseTimeout: 'Database query timeout',\n databaseNullConstraint: 'Required field is missing',\n databaseTooManyConnections: 'Too many database connections',\n databaseTransactionConflict: 'Transaction conflict or deadlock',\n databaseConstraintFailed: 'A database constraint was violated',\n databaseTableNotFound: 'The specified table does not exist in the database',\n databaseColumnNotFound: 'The specified column does not exist in the table',\n databaseInvalidQuery: 'The database query is invalid or malformed',\n invalidErrorCodeRange: 'Invalid error code range: {code}',\n\n // Queue errors\n queueBindingNotFound: 'Queue binding {queueName} not found in environment',\n queueProviderNotSupported: 'Queue provider \"{provider}\" is not supported. Valid providers: cloudflare, sync',\n\n // Cron errors\n cronExecutionFailed: '{count} cron job(s) failed for schedule \"{schedule}\": {jobs}',\n\n // i18n errors\n localeNotSupported: \"Locale '{locale}' is not supported. Supported locales: {supportedLocales}\",\n translationMissing: \"Translation missing for key '{key}' in locale '{locale}'\",\n\n // Container errors\n containerNotInitialized: 'Application container has not been initialized. Ensure Application.initialize() has been called.',\n\n // Domain routing errors\n domainMismatch: 'The requested domain does not match any configured route',\n\n // Signature errors\n invalidSignature: 'The URL signature is invalid or has expired',\n\n // Schema validation errors\n schemaValidation: 'Schema validation failed',\n responseValidation: 'Response validation failed',\n\n // OpenAPI errors\n openapiValidation: 'OpenAPI validation failed: {details}',\n openapiRouteRegistration: 'Failed to register OpenAPI route {path}: {reason}',\n\n // Email errors\n email: {\n resendApiKeyMissing: 'Resend API key not configured. Set RESEND_EMAIL_API_KEY environment variable.',\n smtpConfigurationMissing: 'SMTP configuration missing. Set SMTP_URL environment variable.',\n smtpHostMissing: 'SMTP host not configured. Check SMTP_URL format (smtp://user:pass@host:port).',\n smtpConnectionFailed: 'Failed to connect to SMTP server {smtpHost}:{smtpPort}',\n resendApiFailed: 'Resend API error',\n providerNotSupported: 'Unsupported email provider: {provider}. Supported providers: resend, smtp'\n },\n\n // Storage errors\n storage: {\n fileNotFound: 'File at path \"{path}\" was not found',\n invalidDisk: 'Storage disk \"{disk}\" is not configured',\n invalidFileType: 'File type \"{mimeType}\" is not allowed',\n fileTooLarge: 'File size {size} exceeds maximum allowed size of {maxSize}',\n presignedUrlInvalidExpiry: 'Expiry must be between {min} and {max} seconds',\n diskNotConfigured: 'Disk \"{disk}\" is not configured',\n providerNotSupported: 'Storage provider \"{provider}\" is not supported',\n responseBodyMissing: 'No body in storage response for path: {path}'\n },\n\n // Cache errors\n cache: {\n getFailed: \"Failed to retrieve value from cache for key '{key}'\",\n putFailed: \"Failed to store value in cache for key '{key}'\",\n deleteFailed: \"Failed to delete value from cache for key '{key}'\",\n listFailed: 'Failed to list cache keys'\n },\n\n // Authentication errors\n auth: {\n tokenRequired: 'Verification token is required',\n invalidToken: 'Invalid or expired verification token',\n verificationFailed: 'Verification failed. Please try again.',\n userNotFound: 'User not found. Please check your credentials.',\n invalidCredentials: 'Invalid email or password',\n invalidPassword: 'Invalid password',\n invalidEmail: 'Invalid email address',\n sessionExpired: 'Your session has expired. Please sign in again.',\n emailNotVerified: 'Please verify your email address before signing in',\n passwordTooShort: 'Password must be at least {minLength} characters',\n passwordTooLong: 'Password must be at most {maxLength} characters',\n accountAlreadyExists: 'An account with this email already exists',\n failedToCreateUser: 'Failed to create user account. Please try again.',\n failedToCreateSession: 'Failed to create session. Please try again.',\n failedToGetSession: 'Failed to retrieve session. Please try again.',\n failedToUpdateUser: 'Failed to update user information. Please try again.',\n failedToGetUserInfo: 'Failed to retrieve user information. Please try again.',\n socialAccountLinked: 'This social account is already linked to another user',\n providerNotFound: 'Authentication provider not found',\n userEmailNotFound: 'User email address not found',\n accountNotFound: 'Account not found',\n credentialAccountNotFound: 'Credential account not found',\n cannotUnlinkLastAccount: 'Cannot unlink your last account',\n userAlreadyHasPassword: 'User already has a password set',\n emailCannotBeUpdated: 'Email address cannot be updated at this time',\n tokenExpired: 'The verification token has expired. Please request a new verification email.'\n },\n\n // Seeder errors\n seederNameCollision: 'Seeder name collision: \"{name}\" is already registered. Use distinct class names for each seeder.',\n seederNotRegistered: 'Seeder \"{name}\" is not registered',\n\n // Migration errors\n migration: {\n failed: 'Migration {migrationName} failed: {error}',\n checksumMismatch: 'Migration {migrationName} checksum mismatch (expected: {expected}, actual: {actual})',\n alreadyApplied: 'Migration {migrationName} has already been applied',\n notFound: 'Migration {migrationName} not found',\n },\n} as const\n","import { Command, type CommandClass, Option, type Usage } from 'clipanion'\n\nimport type { Application } from 'stratal'\nimport type { ParsedSignature, QuarryRegistry } from 'stratal/quarry'\n\n/** Create Clipanion command classes from Quarry-registered commands. */\nexport function createDynamicCommands(\n quarry: QuarryRegistry,\n parseSignature: (command: string) => ParsedSignature,\n app: Application,\n) {\n const commands: CommandClass[] = []\n\n for (const entry of quarry.list()) {\n const commandClass = quarry.get(entry.name)! as unknown as { command: string; description?: string; aliases?: string[] }\n const signature = parseSignature(commandClass.command)\n\n const paths: string[][] = [entry.name.split(' ')]\n if (commandClass.aliases) {\n for (const alias of commandClass.aliases) {\n paths.push(alias.split(' '))\n }\n }\n\n // Allow bare `npx quarry` (no arguments) to invoke the help command\n if (entry.name === 'help') {\n paths.push([])\n }\n\n class DynCmd extends Command {\n static override paths = paths\n static override usage: Usage | undefined = commandClass.description\n ? Command.Usage({ description: commandClass.description })\n : undefined\n\n async execute(): Promise<number> {\n const input: Record<string, unknown> = {}\n\n for (const arg of signature.arguments) {\n const value = (this as Record<string, unknown>)[arg.name]\n if (value !== undefined) input[arg.name] = value\n }\n\n for (const opt of signature.options) {\n const value = (this as Record<string, unknown>)[opt.name]\n if (value !== undefined) input[opt.name] = value\n }\n\n const result = await app.handleCommand(entry.name, input)\n\n for (const line of result.output) {\n this.context.stdout.write(line + '\\n')\n }\n\n for (const err of result.errors) {\n this.context.stderr.write(err + '\\n')\n }\n\n return result.exitCode\n }\n }\n\n // Define Clipanion options/arguments as class property defaults\n const proto = DynCmd.prototype as unknown as Record<string, unknown>\n for (const arg of signature.arguments) {\n if (arg.isArray) {\n proto[arg.name] = Option.Rest({ name: arg.name, required: arg.required ? 1 : 0 })\n } else {\n proto[arg.name] = Option.String({ name: arg.name, required: arg.required })\n }\n }\n\n for (const opt of signature.options) {\n const optName = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n const optDescParts: string[] = []\n if (opt.description) optDescParts.push(opt.description)\n if (opt.default !== undefined) optDescParts.push(`(default: ${opt.default})`)\n const optDesc = optDescParts.length > 0 ? optDescParts.join(' ') : undefined\n\n if (opt.isFlag) {\n proto[opt.name] = Option.Boolean(optName, { description: optDesc })\n } else if (opt.isArray) {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.Array(optName, [opt.default], { description: optDesc })\n } else {\n proto[opt.name] = Option.Array(optName, { description: optDesc })\n }\n } else {\n if (opt.default !== undefined) {\n proto[opt.name] = Option.String(optName, opt.default, { description: optDesc })\n } else {\n proto[opt.name] = Option.String(optName, { description: optDesc })\n }\n }\n }\n\n commands.push(DynCmd)\n }\n\n return commands\n}\n","import 'reflect-metadata'\n\nimport { existsSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { createRequire, register } from 'node:module'\nimport { tmpdir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport type { QuarryRegistry } from 'stratal/quarry'\n\nimport { type Application } from '../application'\nimport { errors as errorMessages } from '../i18n/messages/en/errors'\nimport { createDynamicCommands } from './commands/dynamic-command'\n\nconst require = createRequire(import.meta.url)\n\n// Register @swc-node/register for TypeScript + decorator support\nconst swcRegisterPath = join(dirname(require.resolve('@swc-node/register')), 'esm/esm.mjs')\nregister(pathToFileURL(swcRegisterPath), pathToFileURL('./'))\n\n// Register cloudflare:workers virtual module loader\nregister(new URL('./cloudflare-workers-loader.mjs', import.meta.url), pathToFileURL('./'))\n\nconst DEFAULT_ENTRY = './src/index.ts'\n\n// Determine entry file: if first arg looks like a file path, use it; otherwise use default\nconst firstArg = process.argv[2]\nlet entryFile = DEFAULT_ENTRY\n\nif (firstArg && (firstArg.includes('/') || firstArg.includes('\\\\') || /\\.(ts|js|mts|mjs)$/.test(firstArg))) {\n entryFile = firstArg\n // Remove the entry file from argv so Clipanion sees: [node, script, command, ...options]\n process.argv.splice(2, 1)\n}\n\n// Resolve and validate the entry file\nconst entryPath = resolve(process.cwd(), entryFile)\n\nif (!existsSync(entryPath)) {\n console.error(`Error: Entry file not found: ${entryFile}`)\n console.error('')\n console.error('Create src/index.ts with a default Stratal export, or specify a custom path:')\n console.error(' npx quarry ./path/to/entry.ts <command> [options]')\n process.exit(1)\n}\n\nfunction stripDurableObjects(config: Record<string, unknown>): void {\n delete config.durable_objects\n delete config.migrations\n if (config.env && typeof config.env === 'object') {\n for (const envConfig of Object.values(config.env as Record<string, Record<string, unknown>>)) {\n delete envConfig.durable_objects\n delete envConfig.migrations\n }\n }\n}\n\nasync function createStrippedConfig(cwdRequire: NodeRequire): Promise<string | undefined> {\n const candidates = ['wrangler.jsonc', 'wrangler.json', 'wrangler.toml']\n const configName = candidates.find(c => existsSync(resolve(process.cwd(), c)))\n if (!configName) return undefined\n\n const configPath = resolve(process.cwd(), configName)\n const raw = readFileSync(configPath, 'utf-8')\n\n let config: Record<string, unknown>\n if (configName.endsWith('.toml')) {\n const { parse } = await import(cwdRequire.resolve('smol-toml')) as { parse: (input: string) => Record<string, unknown> }\n config = parse(raw)\n } else {\n const { parse: parseJsonc } = await import(cwdRequire.resolve('jsonc-parser')) as { parse: (input: string) => Record<string, unknown> }\n config = parseJsonc(raw)\n }\n\n stripDurableObjects(config)\n\n const tmpPath = resolve(tmpdir(), `quarry-wrangler-${Date.now()}.json`)\n writeFileSync(tmpPath, JSON.stringify(config, null, 2))\n return tmpPath\n}\n\nfunction discoverEnvFiles(): string[] {\n const cwd = process.cwd()\n const files = readdirSync(cwd)\n return files\n .filter(file => (/^\\.dev\\.vars($|\\.)/.test(file) || /^\\.env($|\\.)/.test(file)) && !file.endsWith('.example') && !file.endsWith('.sample'))\n .sort((a, b) => {\n // Load .env files before .dev.vars so .dev.vars takes precedence\n const aIsDevVars = a.startsWith('.dev.vars')\n const bIsDevVars = b.startsWith('.dev.vars')\n if (aIsDevVars !== bIsDevVars) return aIsDevVars ? 1 : -1\n // Within each group, .local files load last (highest precedence)\n const aIsLocal = a.endsWith('.local')\n const bIsLocal = b.endsWith('.local')\n if (aIsLocal !== bIsLocal) return aIsLocal ? 1 : -1\n return a.localeCompare(b)\n })\n .map(file => join(cwd, file))\n}\n\nasync function main(): Promise<void> {\n const cwdRequire = createRequire(join(process.cwd(), 'package.json'))\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n const { getPlatformProxy } = await import(cwdRequire.resolve('wrangler')) as typeof import('wrangler')\n\n const tmpConfigPath = await createStrippedConfig(cwdRequire)\n const envFiles = discoverEnvFiles()\n const { env, ctx, dispose } = await getPlatformProxy({\n envFiles, configPath: tmpConfigPath,\n })\n\n let app: Application | undefined\n try {\n // Store platform proxy on globalThis so the cloudflare:workers virtual module can read it\n (globalThis as Record<string, unknown>).__stratalPlatformProxy = {\n env,\n waitUntil: ctx.waitUntil.bind(ctx),\n }\n\n // Import user's entry file — triggers `new Stratal(...)` + full Application init\n await import(pathToFileURL(entryPath).href)\n\n // Parallel import of stratal modules\n const [\n { Stratal },\n { DI_TOKENS },\n { parseSignature },\n ] = await Promise.all([\n import('stratal'),\n import('stratal/di'),\n import('stratal/quarry'),\n ])\n\n app = await Stratal.resolveApplication()\n const quarry = app.container.resolve<QuarryRegistry>(DI_TOKENS.Quarry)\n\n // Build Clipanion CLI\n const { Cli } = await import('clipanion')\n const pkg = require('../../package.json') as { version: string }\n\n const cli = new Cli({\n binaryName: 'quarry',\n binaryLabel: 'Quarry CLI',\n binaryVersion: pkg.version,\n })\n\n for (const cmd of createDynamicCommands(quarry, parseSignature, app)) {\n cli.register(cmd)\n }\n\n await cli.runExit(process.argv.slice(2), { ...Cli.defaultContext })\n } finally {\n await app?.shutdown()\n await dispose()\n if (tmpConfigPath) {\n try { unlinkSync(tmpConfigPath) } catch {\n //\n }\n }\n }\n}\n\nmain().catch(async (error: unknown) => {\n const { ConfigValidationError } = await import('stratal/config')\n const { StratalNotInitializedError } = await import('stratal/errors')\n\n const message = error instanceof StratalNotInitializedError\n ? errorMessages.stratalNotInitialized\n : error instanceof Error ? error.message : String(error)\n console.error('Fatal error:', message)\n if (error instanceof ConfigValidationError) {\n console.error(error.errors.message)\n }\n process.exit(1)\n})\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { Ht as StratalEnv, s as ApplicationError } from "../index-BJWm863C.mjs";
2
- import { i as LoggerService } from "../index-Dp6A5ywM.mjs";
1
+ import { d as ApplicationError, ir as StratalEnv } from "../index-BrmS34sa.mjs";
2
+ import { i as LoggerService } from "../index-BR23zDMy.mjs";
3
3
 
4
4
  //#region src/cache/cache.module.d.ts
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cache/cache.module.ts","../../src/cache/cache.tokens.ts","../../src/cache/errors/cache-get.error.ts","../../src/cache/errors/cache-put.error.ts","../../src/cache/errors/cache-delete.error.ts","../../src/cache/errors/cache-list.error.ts","../../src/cache/services/cache.service.ts"],"mappings":";;;;;;;;;AAgBA;;;;;;cAMa,WAAA;;;cCtBA,YAAA;EAAA,SAEH,YAAA;AAAA;AAAA,KAEE,UAAA,WAAqB,YAAA,eAA2B,YAAA;;;;;;;ADY5D;;cEPa,aAAA,SAAsB,gBAAA;cACrB,GAAA;AAAA;;;;;;;AFMd;;cGPa,aAAA,SAAsB,gBAAA;cACrB,GAAA;AAAA;;;;;;;AHMd;;cIPa,gBAAA,SAAyB,gBAAA;cACxB,GAAA;AAAA;;;;;;;AJMd;cKRa,cAAA,SAAuB,gBAAA;EAAA,WAAA,CAAA;AAAA;;;;;;ALQpC;;;;;;;;AChBA;;;;;AAIA;;;;;;;;ACKA;;;;;;;;;cIsCa,YAAA;EAAA,iBAIyC,GAAA;EAAA,iBACI,MAAA;EAAA,QAJhD,EAAA;cAG4C,GAAA,EAAK,UAAA,EACD,MAAA,EAAQ,aAAA;;;;;;;;EAYhE,KAAA,CAAM,EAAA,EAAI,WAAA;;;AFvDZ;;;;;;;;;;;;ACDA;;;;;;;;ACsCA;;;;EAgDE,WAAA,CAAY,EAAA,EAAI,WAAA,GAAc,YAAA;EA9BpB;;;;;;;;EA8CJ,GAAA,CAAI,GAAA,UAAa,aAAA,YAAyB,qBAAA,WAAgC,OAAA;EAC1E,GAAA,yBAAA,CAA6B,GAAA,UAAa,aAAA,WAAwB,qBAAA,WAAgC,OAAA,CAAQ,aAAA;EAC1G,GAAA,CAAI,GAAA,UAAa,aAAA,kBAA+B,qBAAA,kBAAuC,OAAA,CAAQ,WAAA;EAC/F,GAAA,CAAI,GAAA,UAAa,aAAA,aAA0B,qBAAA,aAAkC,OAAA,CAAQ,cAAA;EAAA;;;;;;;;EAkCrF,eAAA,oBAAA,CACJ,GAAA,UACA,aAAA,YAAyB,qBAAA,WACxB,OAAA,CAAQ,gCAAA,SAAyC,QAAA;EAC9C,eAAA,6CAAA,CACJ,GAAA,UACA,aAAA,WAAwB,qBAAA,WACvB,OAAA,CAAQ,gCAAA,CAAiC,aAAA,EAAe,QAAA;EACrD,eAAA,oBAAA,CACJ,GAAA,UACA,aAAA,kBAA+B,qBAAA,kBAC9B,OAAA,CAAQ,gCAAA,CAAiC,WAAA,EAAa,QAAA;EACnD,eAAA,oBAAA,CACJ,GAAA,UACA,aAAA,aAA0B,qBAAA,aACzB,OAAA,CAAQ,gCAAA,CAAiC,cAAA,EAAgB,QAAA;EAJhB;;;;;;;;;;;;;;;;;;;;EAuDtC,GAAA,CACJ,GAAA,UACA,KAAA,WAAgB,WAAA,GAAc,eAAA,GAAkB,cAAA,EAChD,OAAA,GAAU,qBAAA,GACT,OAAA;EAtKiD;;;;;;EAuL9C,MAAA,CAAO,GAAA,WAAc,OAAA;EAtL6B;;;;;;;;;;;;;;;;;;;;;;EAwNlD,IAAA,oBAAA,CACJ,OAAA,GAAU,sBAAA,GACT,OAAA,CAAQ,qBAAA,CAAsB,QAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cache/cache.module.ts","../../src/cache/cache.tokens.ts","../../src/cache/errors/cache-get.error.ts","../../src/cache/errors/cache-put.error.ts","../../src/cache/errors/cache-delete.error.ts","../../src/cache/errors/cache-list.error.ts","../../src/cache/services/cache.service.ts"],"mappings":";;;;;;;;AAgBA;;;;;;;cAMa,WAAA;;;cCtBA,YAAA;EAAA,SAEH,YAAA;AAAA;AAAA,KAEE,UAAA,WAAqB,YAAA,eAA2B,YAAA;;;;;;ADY5D;;;cEPa,aAAA,SAAsB,gBAAA;cACrB,GAAA;AAAA;;;;;;AFMd;;;cGPa,aAAA,SAAsB,gBAAA;cACrB,GAAA;AAAA;;;;;;AHMd;;;cIPa,gBAAA,SAAyB,gBAAA;cACxB,GAAA;AAAA;;;;;;AJMd;;cKRa,cAAA,SAAuB,gBAAA;EAAA,WAAA,CAAA;AAAA;;;;;ALQpC;;;;;;;;AChBA;;;;;AAIA;;;;;;;;ACKA;;;;;;;;;;cIsCa,YAAA;EAAA,iBAIyC,GAAA;EAAA,iBACI,MAAA;EAAA,QAJhD,EAAA;cAG4C,GAAA,EAAK,UAAA,EACD,MAAA,EAAQ,aAAA;EH3Cf;;;;;;;EGuDjD,KAAA,CAAM,EAAA,EAAI,WAAA;;AFvDZ;;;;;;;;;;;;ACDA;;;;;;;;ACsCA;;;;;EAgDE,WAAA,CAAY,EAAA,EAAI,WAAA,GAAc,YAAA;EAAd;;;;;;;;EAgBV,GAAA,CAAI,GAAA,UAAa,aAAA,YAAyB,qBAAA,WAAgC,OAAA;EAC1E,GAAA,yBAAA,CAA6B,GAAA,UAAa,aAAA,WAAwB,qBAAA,WAAgC,OAAA,CAAQ,aAAA;EAC1G,GAAA,CAAI,GAAA,UAAa,aAAA,kBAA+B,qBAAA,kBAAuC,OAAA,CAAQ,WAAA;EAC/F,GAAA,CAAI,GAAA,UAAa,aAAA,aAA0B,qBAAA,aAAkC,OAAA,CAAQ,cAAA;EAAR;;;;;;;;EAkC7E,eAAA,oBAAA,CACJ,GAAA,UACA,aAAA,YAAyB,qBAAA,WACxB,OAAA,CAAQ,gCAAA,SAAyC,QAAA;EAC9C,eAAA,6CAAA,CACJ,GAAA,UACA,aAAA,WAAwB,qBAAA,WACvB,OAAA,CAAQ,gCAAA,CAAiC,aAAA,EAAe,QAAA;EACrD,eAAA,oBAAA,CACJ,GAAA,UACA,aAAA,kBAA+B,qBAAA,kBAC9B,OAAA,CAAQ,gCAAA,CAAiC,WAAA,EAAa,QAAA;EACnD,eAAA,oBAAA,CACJ,GAAA,UACA,aAAA,aAA0B,qBAAA,aACzB,OAAA,CAAQ,gCAAA,CAAiC,cAAA,EAAgB,QAAA;EAJH;;;;;;;;;;;;;;;;;;;;EAuDnD,GAAA,CACJ,GAAA,UACA,KAAA,WAAgB,WAAA,GAAc,eAAA,GAAkB,cAAA,EAChD,OAAA,GAAU,qBAAA,GACT,OAAA;EArKqD;;;;;;EAsLlD,MAAA,CAAO,GAAA,WAAc,OAAA;EA1K3B;;;;;;;;;;;;;;;;;;;;;;EA4MM,IAAA,oBAAA,CACJ,OAAA,GAAU,sBAAA,GACT,OAAA,CAAQ,qBAAA,CAAsB,QAAA;AAAA"}
@@ -1,14 +1,6 @@
1
- import { S as ApplicationError, b as ERROR_CODES } from "../errors-CtCi1wn6.mjs";
2
- import { i as Transient, l as DI_TOKENS, n as __decorateParam, r as __decorateMetadata, t as __decorate } from "../decorate-D5j-d9_z.mjs";
3
- import { s as LOGGER_TOKENS } from "../logger-BR1-s1Um.mjs";
4
- import { r as Module } from "../module-BgdxxzBe.mjs";
5
- import "../events-CXl-o1Ad.mjs";
6
- import "../colors-DJaRDXoS.mjs";
7
- import "../command-BvCOD6df.mjs";
8
- import "../is-command-BfCgWAcQ.mjs";
9
- import "../is-seeder-CebjZCDn.mjs";
10
- import "../middleware-C0Ebzswy.mjs";
11
- import "../router-context-BEJe9HEB.mjs";
1
+ import { H as ApplicationError, k as ERROR_CODES } from "../errors--RBIvDXr.mjs";
2
+ import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "../logger-c0ftIK4G.mjs";
3
+ import { S as Module } from "../module-C3YZ-kZN.mjs";
12
4
  import { inject } from "tsyringe";
13
5
  //#region src/cache/cache.tokens.ts
14
6
  const CACHE_TOKENS = { CacheService: Symbol.for("stratal:cache:service") };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/cache/cache.tokens.ts","../../src/cache/errors/cache-get.error.ts","../../src/cache/errors/cache-put.error.ts","../../src/cache/errors/cache-delete.error.ts","../../src/cache/errors/cache-list.error.ts","../../src/cache/services/cache.service.ts","../../src/cache/cache.module.ts"],"sourcesContent":["export const CACHE_TOKENS = {\n CacheService: Symbol.for('stratal:cache:service'),\n} as const\n\nexport type CacheToken = (typeof CACHE_TOKENS)[keyof typeof CACHE_TOKENS]\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache get operation fails\n *\n * Raw error details are logged via LoggerService for security.\n * Only the key is included in the user-facing error message.\n */\nexport class CacheGetError extends ApplicationError {\n constructor(key: string) {\n super('errors.cache.getFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, { key })\n }\n}\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache put operation fails\n *\n * Raw error details are logged via LoggerService for security.\n * Only the key is included in the user-facing error message.\n */\nexport class CachePutError extends ApplicationError {\n constructor(key: string) {\n super('errors.cache.putFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, { key })\n }\n}\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache delete operation fails\n *\n * Raw error details are logged via LoggerService for security.\n * Only the key is included in the user-facing error message.\n */\nexport class CacheDeleteError extends ApplicationError {\n constructor(key: string) {\n super('errors.cache.deleteFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, { key })\n }\n}\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache list operation fails\n *\n * Raw error details are logged via LoggerService for security.\n */\nexport class CacheListError extends ApplicationError {\n constructor() {\n super('errors.cache.listFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, {})\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type StratalEnv } from '../../env'\nimport { LOGGER_TOKENS, type LoggerService } from '../../logger'\nimport { CACHE_TOKENS } from '../cache.tokens'\nimport {\n CacheDeleteError,\n CacheGetError,\n CacheListError,\n CachePutError,\n} from '../errors'\n\n/**\n * Cache Service\n *\n * Type-safe wrapper around Cloudflare KV namespaces for caching operations.\n *\n * **Features:**\n * - Mirrors all KVNamespace methods with full type safety\n * - Supports multiple KV bindings via `withBinding()`\n * - Automatic error handling with logging\n * - Security: Raw errors are logged, not exposed to users\n *\n * **Usage:**\n * ```typescript\n * class MyService {\n * private readonly uploadsCache: CacheService\n *\n * constructor(\n * @inject(CACHE_TOKENS.CacheService) private readonly cache: CacheService,\n * @inject(DI_TOKENS.CloudflareEnv) private readonly env: Env\n * ) {\n * // Initialize specialized caches in constructor\n * this.uploadsCache = this.cache.withBinding(this.env.UPLOADS_CACHE)\n * }\n *\n * async cacheData(key: string, value: string) {\n * await this.cache.put(key, value, { expirationTtl: 3600 })\n * await this.uploadsCache.put(`upload:${key}`, value)\n * }\n * }\n * ```\n *\n * @see https://developers.cloudflare.com/kv/api/\n */\n@Transient(CACHE_TOKENS.CacheService)\nexport class CacheService {\n private kv: KVNamespace\n\n constructor(\n @inject(DI_TOKENS.CloudflareEnv) private readonly env: StratalEnv,\n @inject(LOGGER_TOKENS.LoggerService) private readonly logger: LoggerService\n ) {\n this.kv = env.CACHE\n }\n\n /**\n * Set the KV namespace binding\n *\n * Used internally by `withBinding()` to configure different KV instances.\n *\n * @param kv - KV namespace to use\n */\n setKV(kv: KVNamespace): void {\n this.kv = kv\n }\n\n /**\n * Create a new CacheService instance with a different KV binding\n *\n * **Pattern:** Returns a new instance (immutable)\n *\n * **Best Practice:** Initialize specialized caches as class properties in constructor\n *\n * @example\n * ```typescript\n * class MyService {\n * private readonly uploadsCache: CacheService\n * private readonly systemCache: CacheService\n *\n * constructor(\n * @inject(CACHE_TOKENS.CacheService) private readonly cache: CacheService,\n * @inject(DI_TOKENS.CloudflareEnv) private readonly env: Env\n * ) {\n * this.uploadsCache = this.cache.withBinding(this.env.UPLOADS_CACHE)\n * this.systemCache = this.cache.withBinding(this.env.SYSTEM_CONFIG_KV)\n * }\n * }\n * ```\n *\n * @param kv - KV namespace to use\n * @returns New CacheService instance with the specified binding\n */\n withBinding(kv: KVNamespace): CacheService {\n const instance = new CacheService(this.env, this.logger)\n instance.setKV(kv)\n return instance\n }\n\n // ==================== GET METHODS ====================\n\n /**\n * Get a value from cache\n *\n * @param key - Cache key\n * @param typeOrOptions - Type string or options object (defaults to 'text')\n * @returns Value in specified type, or null if not found\n * @throws {CacheGetError} If operation fails\n */\n async get(key: string, typeOrOptions?: 'text' | KVNamespaceGetOptions<'text'>): Promise<string | null>\n async get<ExpectedValue = unknown>(key: string, typeOrOptions: 'json' | KVNamespaceGetOptions<'json'>): Promise<ExpectedValue | null>\n async get(key: string, typeOrOptions: 'arrayBuffer' | KVNamespaceGetOptions<'arrayBuffer'>): Promise<ArrayBuffer | null>\n async get(key: string, typeOrOptions: 'stream' | KVNamespaceGetOptions<'stream'>): Promise<ReadableStream | null>\n\n async get<ExpectedValue = unknown>(\n key: string,\n typeOrOptions?: string | KVNamespaceGetOptions<'text' | 'json' | 'arrayBuffer' | 'stream'>\n ): Promise<string | ExpectedValue | ArrayBuffer | ReadableStream | null> {\n try {\n if (typeof typeOrOptions === 'string') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.get(key, typeOrOptions as any)\n }\n\n if (typeOrOptions) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.get(key, typeOrOptions as any)\n }\n\n return await this.kv.get(key)\n } catch (error) {\n this.logger.error('Cache get operation failed', { key, error })\n throw new CacheGetError(key)\n }\n }\n\n // ==================== GET WITH METADATA METHODS ====================\n\n /**\n * Get a value with metadata from cache\n *\n * @param key - Cache key\n * @param typeOrOptions - Type string or options object (defaults to 'text')\n * @returns Object with value, metadata, and cacheStatus\n * @throws {CacheGetError} If operation fails\n */\n async getWithMetadata<Metadata = unknown>(\n key: string,\n typeOrOptions?: 'text' | KVNamespaceGetOptions<'text'>\n ): Promise<KVNamespaceGetWithMetadataResult<string, Metadata>>\n async getWithMetadata<ExpectedValue = unknown, Metadata = unknown>(\n key: string,\n typeOrOptions: 'json' | KVNamespaceGetOptions<'json'>\n ): Promise<KVNamespaceGetWithMetadataResult<ExpectedValue, Metadata>>\n async getWithMetadata<Metadata = unknown>(\n key: string,\n typeOrOptions: 'arrayBuffer' | KVNamespaceGetOptions<'arrayBuffer'>\n ): Promise<KVNamespaceGetWithMetadataResult<ArrayBuffer, Metadata>>\n async getWithMetadata<Metadata = unknown>(\n key: string,\n typeOrOptions: 'stream' | KVNamespaceGetOptions<'stream'>\n ): Promise<KVNamespaceGetWithMetadataResult<ReadableStream, Metadata>>\n\n async getWithMetadata<ExpectedValue = unknown, Metadata = unknown>(\n key: string,\n typeOrOptions?: string | KVNamespaceGetOptions<'text' | 'json' | 'arrayBuffer' | 'stream'>\n ): Promise<\n KVNamespaceGetWithMetadataResult<\n string | ExpectedValue | ArrayBuffer | ReadableStream,\n Metadata\n >\n > {\n try {\n if (typeof typeOrOptions === 'string') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.getWithMetadata(key, typeOrOptions as any)\n }\n\n if (typeOrOptions) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.getWithMetadata(key, typeOrOptions as any)\n }\n\n return await this.kv.getWithMetadata(key)\n } catch (error) {\n this.logger.error('Cache getWithMetadata operation failed', { key, error })\n throw new CacheGetError(key)\n }\n }\n\n // ==================== PUT METHOD ====================\n\n /**\n * Store a value in cache\n *\n * @param key - Cache key\n * @param value - Value to store (string, ArrayBuffer, ArrayBufferView, or ReadableStream)\n * @param options - Put options (expiration, expirationTtl, metadata)\n * @throws {CachePutError} If operation fails\n *\n * @example\n * ```typescript\n * // Simple put\n * await cache.put('key', 'value')\n *\n * // With TTL\n * await cache.put('key', 'value', { expirationTtl: 3600 })\n *\n * // With metadata\n * await cache.put('key', 'value', { metadata: { created: Date.now() } })\n * ```\n */\n async put(\n key: string,\n value: string | ArrayBuffer | ArrayBufferView | ReadableStream,\n options?: KVNamespacePutOptions\n ): Promise<void> {\n try {\n await this.kv.put(key, value as string, options)\n } catch (error) {\n this.logger.error('Cache put operation failed', { key, error })\n throw new CachePutError(key)\n }\n }\n\n // ==================== DELETE METHODS ====================\n\n /**\n * Delete a value from cache\n *\n * @param key - Cache key to delete\n * @throws {CacheDeleteError} If operation fails\n */\n async delete(key: string): Promise<void> {\n try {\n await this.kv.delete(key)\n } catch (error) {\n this.logger.error('Cache delete operation failed', { key, error })\n throw new CacheDeleteError(key)\n }\n }\n\n\n // ==================== LIST METHOD ====================\n\n /**\n * List keys in cache\n *\n * @param options - List options (limit, prefix, cursor)\n * @returns List result with keys and pagination info\n * @throws {CacheListError} If operation fails\n *\n * @example\n * ```typescript\n * // List all keys\n * const result = await cache.list()\n *\n * // List with prefix\n * const result = await cache.list({ prefix: 'user:' })\n *\n * // Paginated list\n * const result = await cache.list({ limit: 100 })\n * if (!result.list_complete) {\n * const nextPage = await cache.list({ cursor: result.cursor })\n * }\n * ```\n */\n async list<Metadata = unknown>(\n options?: KVNamespaceListOptions\n ): Promise<KVNamespaceListResult<Metadata>> {\n try {\n return await this.kv.list<Metadata>(options)\n } catch (error) {\n this.logger.error('Cache list operation failed', { options, error })\n throw new CacheListError()\n }\n }\n}\n","/**\n * Cache Module\n *\n * Provides key-value caching capabilities using Cloudflare KV namespaces.\n *\n * **Features:**\n * - Type-safe KV wrapper with full method coverage\n * - Multiple KV binding support via `withBinding()`\n * - Automatic error handling with security-focused logging\n * - Singleton service for optimal performance\n */\n\nimport { Module } from '../module'\nimport { CACHE_TOKENS } from './cache.tokens'\nimport { CacheService } from './services'\n\n@Module({\n providers: [\n // Singleton - CacheService has no request dependencies\n { provide: CACHE_TOKENS.CacheService, useClass: CacheService },\n ],\n})\nexport class CacheModule {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/cache/cache.tokens.ts","../../src/cache/errors/cache-get.error.ts","../../src/cache/errors/cache-put.error.ts","../../src/cache/errors/cache-delete.error.ts","../../src/cache/errors/cache-list.error.ts","../../src/cache/services/cache.service.ts","../../src/cache/cache.module.ts"],"sourcesContent":["export const CACHE_TOKENS = {\n CacheService: Symbol.for('stratal:cache:service'),\n} as const\n\nexport type CacheToken = (typeof CACHE_TOKENS)[keyof typeof CACHE_TOKENS]\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache get operation fails\n *\n * Raw error details are logged via LoggerService for security.\n * Only the key is included in the user-facing error message.\n */\nexport class CacheGetError extends ApplicationError {\n constructor(key: string) {\n super('errors.cache.getFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, { key })\n }\n}\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache put operation fails\n *\n * Raw error details are logged via LoggerService for security.\n * Only the key is included in the user-facing error message.\n */\nexport class CachePutError extends ApplicationError {\n constructor(key: string) {\n super('errors.cache.putFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, { key })\n }\n}\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache delete operation fails\n *\n * Raw error details are logged via LoggerService for security.\n * Only the key is included in the user-facing error message.\n */\nexport class CacheDeleteError extends ApplicationError {\n constructor(key: string) {\n super('errors.cache.deleteFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, { key })\n }\n}\n","import { ERROR_CODES } from '../../errors'\nimport { ApplicationError } from '../../errors'\n\n/**\n * Error thrown when a cache list operation fails\n *\n * Raw error details are logged via LoggerService for security.\n */\nexport class CacheListError extends ApplicationError {\n constructor() {\n super('errors.cache.listFailed', ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR, {})\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type StratalEnv } from '../../env'\nimport { LOGGER_TOKENS, type LoggerService } from '../../logger'\nimport { CACHE_TOKENS } from '../cache.tokens'\nimport {\n CacheDeleteError,\n CacheGetError,\n CacheListError,\n CachePutError,\n} from '../errors'\n\n/**\n * Cache Service\n *\n * Type-safe wrapper around Cloudflare KV namespaces for caching operations.\n *\n * **Features:**\n * - Mirrors all KVNamespace methods with full type safety\n * - Supports multiple KV bindings via `withBinding()`\n * - Automatic error handling with logging\n * - Security: Raw errors are logged, not exposed to users\n *\n * **Usage:**\n * ```typescript\n * class MyService {\n * private readonly uploadsCache: CacheService\n *\n * constructor(\n * @inject(CACHE_TOKENS.CacheService) private readonly cache: CacheService,\n * @inject(DI_TOKENS.CloudflareEnv) private readonly env: Env\n * ) {\n * // Initialize specialized caches in constructor\n * this.uploadsCache = this.cache.withBinding(this.env.UPLOADS_CACHE)\n * }\n *\n * async cacheData(key: string, value: string) {\n * await this.cache.put(key, value, { expirationTtl: 3600 })\n * await this.uploadsCache.put(`upload:${key}`, value)\n * }\n * }\n * ```\n *\n * @see https://developers.cloudflare.com/kv/api/\n */\n@Transient(CACHE_TOKENS.CacheService)\nexport class CacheService {\n private kv: KVNamespace\n\n constructor(\n @inject(DI_TOKENS.CloudflareEnv) private readonly env: StratalEnv,\n @inject(LOGGER_TOKENS.LoggerService) private readonly logger: LoggerService\n ) {\n this.kv = env.CACHE\n }\n\n /**\n * Set the KV namespace binding\n *\n * Used internally by `withBinding()` to configure different KV instances.\n *\n * @param kv - KV namespace to use\n */\n setKV(kv: KVNamespace): void {\n this.kv = kv\n }\n\n /**\n * Create a new CacheService instance with a different KV binding\n *\n * **Pattern:** Returns a new instance (immutable)\n *\n * **Best Practice:** Initialize specialized caches as class properties in constructor\n *\n * @example\n * ```typescript\n * class MyService {\n * private readonly uploadsCache: CacheService\n * private readonly systemCache: CacheService\n *\n * constructor(\n * @inject(CACHE_TOKENS.CacheService) private readonly cache: CacheService,\n * @inject(DI_TOKENS.CloudflareEnv) private readonly env: Env\n * ) {\n * this.uploadsCache = this.cache.withBinding(this.env.UPLOADS_CACHE)\n * this.systemCache = this.cache.withBinding(this.env.SYSTEM_CONFIG_KV)\n * }\n * }\n * ```\n *\n * @param kv - KV namespace to use\n * @returns New CacheService instance with the specified binding\n */\n withBinding(kv: KVNamespace): CacheService {\n const instance = new CacheService(this.env, this.logger)\n instance.setKV(kv)\n return instance\n }\n\n // ==================== GET METHODS ====================\n\n /**\n * Get a value from cache\n *\n * @param key - Cache key\n * @param typeOrOptions - Type string or options object (defaults to 'text')\n * @returns Value in specified type, or null if not found\n * @throws {CacheGetError} If operation fails\n */\n async get(key: string, typeOrOptions?: 'text' | KVNamespaceGetOptions<'text'>): Promise<string | null>\n async get<ExpectedValue = unknown>(key: string, typeOrOptions: 'json' | KVNamespaceGetOptions<'json'>): Promise<ExpectedValue | null>\n async get(key: string, typeOrOptions: 'arrayBuffer' | KVNamespaceGetOptions<'arrayBuffer'>): Promise<ArrayBuffer | null>\n async get(key: string, typeOrOptions: 'stream' | KVNamespaceGetOptions<'stream'>): Promise<ReadableStream | null>\n\n async get<ExpectedValue = unknown>(\n key: string,\n typeOrOptions?: string | KVNamespaceGetOptions<'text' | 'json' | 'arrayBuffer' | 'stream'>\n ): Promise<string | ExpectedValue | ArrayBuffer | ReadableStream | null> {\n try {\n if (typeof typeOrOptions === 'string') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.get(key, typeOrOptions as any)\n }\n\n if (typeOrOptions) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.get(key, typeOrOptions as any)\n }\n\n return await this.kv.get(key)\n } catch (error) {\n this.logger.error('Cache get operation failed', { key, error })\n throw new CacheGetError(key)\n }\n }\n\n // ==================== GET WITH METADATA METHODS ====================\n\n /**\n * Get a value with metadata from cache\n *\n * @param key - Cache key\n * @param typeOrOptions - Type string or options object (defaults to 'text')\n * @returns Object with value, metadata, and cacheStatus\n * @throws {CacheGetError} If operation fails\n */\n async getWithMetadata<Metadata = unknown>(\n key: string,\n typeOrOptions?: 'text' | KVNamespaceGetOptions<'text'>\n ): Promise<KVNamespaceGetWithMetadataResult<string, Metadata>>\n async getWithMetadata<ExpectedValue = unknown, Metadata = unknown>(\n key: string,\n typeOrOptions: 'json' | KVNamespaceGetOptions<'json'>\n ): Promise<KVNamespaceGetWithMetadataResult<ExpectedValue, Metadata>>\n async getWithMetadata<Metadata = unknown>(\n key: string,\n typeOrOptions: 'arrayBuffer' | KVNamespaceGetOptions<'arrayBuffer'>\n ): Promise<KVNamespaceGetWithMetadataResult<ArrayBuffer, Metadata>>\n async getWithMetadata<Metadata = unknown>(\n key: string,\n typeOrOptions: 'stream' | KVNamespaceGetOptions<'stream'>\n ): Promise<KVNamespaceGetWithMetadataResult<ReadableStream, Metadata>>\n\n async getWithMetadata<ExpectedValue = unknown, Metadata = unknown>(\n key: string,\n typeOrOptions?: string | KVNamespaceGetOptions<'text' | 'json' | 'arrayBuffer' | 'stream'>\n ): Promise<\n KVNamespaceGetWithMetadataResult<\n string | ExpectedValue | ArrayBuffer | ReadableStream,\n Metadata\n >\n > {\n try {\n if (typeof typeOrOptions === 'string') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.getWithMetadata(key, typeOrOptions as any)\n }\n\n if (typeOrOptions) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- bridging KV overloaded API\n return await this.kv.getWithMetadata(key, typeOrOptions as any)\n }\n\n return await this.kv.getWithMetadata(key)\n } catch (error) {\n this.logger.error('Cache getWithMetadata operation failed', { key, error })\n throw new CacheGetError(key)\n }\n }\n\n // ==================== PUT METHOD ====================\n\n /**\n * Store a value in cache\n *\n * @param key - Cache key\n * @param value - Value to store (string, ArrayBuffer, ArrayBufferView, or ReadableStream)\n * @param options - Put options (expiration, expirationTtl, metadata)\n * @throws {CachePutError} If operation fails\n *\n * @example\n * ```typescript\n * // Simple put\n * await cache.put('key', 'value')\n *\n * // With TTL\n * await cache.put('key', 'value', { expirationTtl: 3600 })\n *\n * // With metadata\n * await cache.put('key', 'value', { metadata: { created: Date.now() } })\n * ```\n */\n async put(\n key: string,\n value: string | ArrayBuffer | ArrayBufferView | ReadableStream,\n options?: KVNamespacePutOptions\n ): Promise<void> {\n try {\n await this.kv.put(key, value as string, options)\n } catch (error) {\n this.logger.error('Cache put operation failed', { key, error })\n throw new CachePutError(key)\n }\n }\n\n // ==================== DELETE METHODS ====================\n\n /**\n * Delete a value from cache\n *\n * @param key - Cache key to delete\n * @throws {CacheDeleteError} If operation fails\n */\n async delete(key: string): Promise<void> {\n try {\n await this.kv.delete(key)\n } catch (error) {\n this.logger.error('Cache delete operation failed', { key, error })\n throw new CacheDeleteError(key)\n }\n }\n\n\n // ==================== LIST METHOD ====================\n\n /**\n * List keys in cache\n *\n * @param options - List options (limit, prefix, cursor)\n * @returns List result with keys and pagination info\n * @throws {CacheListError} If operation fails\n *\n * @example\n * ```typescript\n * // List all keys\n * const result = await cache.list()\n *\n * // List with prefix\n * const result = await cache.list({ prefix: 'user:' })\n *\n * // Paginated list\n * const result = await cache.list({ limit: 100 })\n * if (!result.list_complete) {\n * const nextPage = await cache.list({ cursor: result.cursor })\n * }\n * ```\n */\n async list<Metadata = unknown>(\n options?: KVNamespaceListOptions\n ): Promise<KVNamespaceListResult<Metadata>> {\n try {\n return await this.kv.list<Metadata>(options)\n } catch (error) {\n this.logger.error('Cache list operation failed', { options, error })\n throw new CacheListError()\n }\n }\n}\n","/**\n * Cache Module\n *\n * Provides key-value caching capabilities using Cloudflare KV namespaces.\n *\n * **Features:**\n * - Type-safe KV wrapper with full method coverage\n * - Multiple KV binding support via `withBinding()`\n * - Automatic error handling with security-focused logging\n * - Singleton service for optimal performance\n */\n\nimport { Module } from '../module'\nimport { CACHE_TOKENS } from './cache.tokens'\nimport { CacheService } from './services'\n\n@Module({\n providers: [\n // Singleton - CacheService has no request dependencies\n { provide: CACHE_TOKENS.CacheService, useClass: CacheService },\n ],\n})\nexport class CacheModule {}\n"],"mappings":";;;;;AAAA,MAAa,eAAe,EAC1B,cAAc,OAAO,IAAI,wBAAwB,EAClD;;;;;;;;;ACOD,IAAa,gBAAb,cAAmC,iBAAiB;CAClD,YAAY,KAAa;AACvB,QAAM,0BAA0B,YAAY,OAAO,sBAAsB,EAAE,KAAK,CAAC;;;;;;;;;;;ACFrF,IAAa,gBAAb,cAAmC,iBAAiB;CAClD,YAAY,KAAa;AACvB,QAAM,0BAA0B,YAAY,OAAO,sBAAsB,EAAE,KAAK,CAAC;;;;;;;;;;;ACFrF,IAAa,mBAAb,cAAsC,iBAAiB;CACrD,YAAY,KAAa;AACvB,QAAM,6BAA6B,YAAY,OAAO,sBAAsB,EAAE,KAAK,CAAC;;;;;;;;;;ACHxF,IAAa,iBAAb,cAAoC,iBAAiB;CACnD,cAAc;AACZ,QAAM,2BAA2B,YAAY,OAAO,sBAAsB,EAAE,CAAC;;;;;;ACqC1E,IAAA,eAAA,gBAAA,MAAM,aAAa;CACxB;CAEA,YACE,KACA,QACA;AAFkD,OAAA,MAAA;AACI,OAAA,SAAA;AAEtD,OAAK,KAAK,IAAI;;;;;;;;;CAUhB,MAAM,IAAuB;AAC3B,OAAK,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BZ,YAAY,IAA+B;EACzC,MAAM,WAAW,IAAA,cAAiB,KAAK,KAAK,KAAK,OAAO;AACxD,WAAS,MAAM,GAAG;AAClB,SAAO;;CAkBT,MAAM,IACJ,KACA,eACuE;AACvE,MAAI;AACF,OAAI,OAAO,kBAAkB,SAE3B,QAAO,MAAM,KAAK,GAAG,IAAI,KAAK,cAAqB;AAGrD,OAAI,cAEF,QAAO,MAAM,KAAK,GAAG,IAAI,KAAK,cAAqB;AAGrD,UAAO,MAAM,KAAK,GAAG,IAAI,IAAI;WACtB,OAAO;AACd,QAAK,OAAO,MAAM,8BAA8B;IAAE;IAAK;IAAO,CAAC;AAC/D,SAAM,IAAI,cAAc,IAAI;;;CA+BhC,MAAM,gBACJ,KACA,eAMA;AACA,MAAI;AACF,OAAI,OAAO,kBAAkB,SAE3B,QAAO,MAAM,KAAK,GAAG,gBAAgB,KAAK,cAAqB;AAGjE,OAAI,cAEF,QAAO,MAAM,KAAK,GAAG,gBAAgB,KAAK,cAAqB;AAGjE,UAAO,MAAM,KAAK,GAAG,gBAAgB,IAAI;WAClC,OAAO;AACd,QAAK,OAAO,MAAM,0CAA0C;IAAE;IAAK;IAAO,CAAC;AAC3E,SAAM,IAAI,cAAc,IAAI;;;;;;;;;;;;;;;;;;;;;;;CA0BhC,MAAM,IACJ,KACA,OACA,SACe;AACf,MAAI;AACF,SAAM,KAAK,GAAG,IAAI,KAAK,OAAiB,QAAQ;WACzC,OAAO;AACd,QAAK,OAAO,MAAM,8BAA8B;IAAE;IAAK;IAAO,CAAC;AAC/D,SAAM,IAAI,cAAc,IAAI;;;;;;;;;CAYhC,MAAM,OAAO,KAA4B;AACvC,MAAI;AACF,SAAM,KAAK,GAAG,OAAO,IAAI;WAClB,OAAO;AACd,QAAK,OAAO,MAAM,iCAAiC;IAAE;IAAK;IAAO,CAAC;AAClE,SAAM,IAAI,iBAAiB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;CA6BnC,MAAM,KACJ,SAC0C;AAC1C,MAAI;AACF,UAAO,MAAM,KAAK,GAAG,KAAe,QAAQ;WACrC,OAAO;AACd,QAAK,OAAO,MAAM,+BAA+B;IAAE;IAAS;IAAO,CAAC;AACpE,SAAM,IAAI,gBAAgB;;;;;CArO/B,UAAU,aAAa,aAAa;oBAKhC,OAAO,UAAU,cAAc,CAAA;oBAC/B,OAAO,cAAc,cAAc,CAAA;;;;;;;;;;;;;;;;AC9BjC,IAAA,cAAA,MAAM,YAAY;0BANxB,OAAO,EACN,WAAW,CAET;CAAE,SAAS,aAAa;CAAc,UAAU;CAAc,CAC/D,EACF,CAAC,CAAA,EAAA,YAAA"}
@@ -13,4 +13,4 @@ const dimWhite = (s) => isEnabled() ? `\x1b[2;37m${s}\x1b[22;39m` : s;
13
13
  //#endregion
14
14
  export { green as a, dimWhite as i, cyan as n, red as o, dim as r, yellow as s, bold as t };
15
15
 
16
- //# sourceMappingURL=colors-DJaRDXoS.mjs.map
16
+ //# sourceMappingURL=colors-BTAnQRGU.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"colors-DJaRDXoS.mjs","names":[],"sources":["../src/quarry/colors.ts"],"sourcesContent":["/** Minimal ANSI color helpers that respect the `NO_COLOR` convention. */\nconst isEnabled = () => typeof process !== 'undefined' ? !process.env.NO_COLOR : true\n\n/** Create an ANSI formatter that wraps text with the given open/close SGR codes. */\nconst code = (open: number, close: number) => (s: string) =>\n isEnabled() ? `\\x1b[${open}m${s}\\x1b[${close}m` : s\n\nexport const bold = code(1, 22)\nexport const dim = code(2, 22)\nexport const cyan = code(36, 39)\nexport const green = code(32, 39)\nexport const red = code(31, 39)\nexport const yellow = code(33, 39)\nexport const dimWhite = (s: string) =>\n isEnabled() ? `\\x1b[2;37m${s}\\x1b[22;39m` : s\n"],"mappings":";;AACA,MAAM,kBAAkB,OAAO,YAAY,cAAc,CAAC,QAAQ,IAAI,WAAW;;AAGjF,MAAM,QAAQ,MAAc,WAAmB,MAC7C,WAAW,GAAG,QAAQ,KAAK,GAAG,EAAE,OAAO,MAAM,KAAK;AAEpD,MAAa,OAAO,KAAK,GAAG,GAAG;AAC/B,MAAa,MAAM,KAAK,GAAG,GAAG;AAC9B,MAAa,OAAO,KAAK,IAAI,GAAG;AAChC,MAAa,QAAQ,KAAK,IAAI,GAAG;AACjC,MAAa,MAAM,KAAK,IAAI,GAAG;AAC/B,MAAa,SAAS,KAAK,IAAI,GAAG;AAClC,MAAa,YAAY,MACvB,WAAW,GAAG,aAAa,EAAE,eAAe"}
1
+ {"version":3,"file":"colors-BTAnQRGU.mjs","names":[],"sources":["../src/quarry/colors.ts"],"sourcesContent":["/** Minimal ANSI color helpers that respect the `NO_COLOR` convention. */\nconst isEnabled = () => typeof process !== 'undefined' ? !process.env.NO_COLOR : true\n\n/** Create an ANSI formatter that wraps text with the given open/close SGR codes. */\nconst code = (open: number, close: number) => (s: string) =>\n isEnabled() ? `\\x1b[${open}m${s}\\x1b[${close}m` : s\n\nexport const bold = code(1, 22)\nexport const dim = code(2, 22)\nexport const cyan = code(36, 39)\nexport const green = code(32, 39)\nexport const red = code(31, 39)\nexport const yellow = code(33, 39)\nexport const dimWhite = (s: string) =>\n isEnabled() ? `\\x1b[2;37m${s}\\x1b[22;39m` : s\n"],"mappings":";;AACA,MAAM,kBAAkB,OAAO,YAAY,cAAc,CAAC,QAAQ,IAAI,WAAW;;AAGjF,MAAM,QAAQ,MAAc,WAAmB,MAC7C,WAAW,GAAG,QAAQ,KAAK,GAAG,EAAE,OAAO,MAAM,KAAK;AAEpD,MAAa,OAAO,KAAK,GAAG,GAAG;AAC/B,MAAa,MAAM,KAAK,GAAG,GAAG;AAC9B,MAAa,OAAO,KAAK,IAAI,GAAG;AAChC,MAAa,QAAQ,KAAK,IAAI,GAAG;AACjC,MAAa,MAAM,KAAK,IAAI,GAAG;AAC/B,MAAa,SAAS,KAAK,IAAI,GAAG;AAClC,MAAa,YAAY,MACvB,WAAW,GAAG,aAAa,EAAE,eAAe"}
@@ -1,4 +1,4 @@
1
- import { n as CommandInternals, r as CommandResult, t as CommandInput } from "./types-CLhOhYsQ.mjs";
1
+ import { an as CommandInput, on as CommandInternals, sn as CommandResult } from "./index-BrmS34sa.mjs";
2
2
  //#region src/quarry/constants.d.ts
3
3
  /**
4
4
  * Symbol key for storing internal mutable state on Command instances.
@@ -117,4 +117,4 @@ declare abstract class Command {
117
117
  }
118
118
  //#endregion
119
119
  export { Command as t };
120
- //# sourceMappingURL=command-B-QH-Vu3.d.mts.map
120
+ //# sourceMappingURL=command-B1YuV-UZ.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-B-QH-Vu3.d.mts","names":[],"sources":["../src/quarry/constants.ts","../src/quarry/command.ts"],"mappings":";;;;;;cAIa,iBAAA;;;;AAAb;;;;;;;;ACsBA;;;;;;;;;;uBAAsB,OAAA;EA8LmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAA,OA7JhD,OAAA;EA4HC;EAAA,OA1HD,WAAA;EA+HD;EAAA,OA7HC,OAAA;EAAA,CAEN,iBAAA,GAAoB,gBAAA;;EA4IC;;;;EAAA,SA3Hb,MAAA,CAAA,mBAA0B,OAAA;EAsIa;;;EA/HhD,KAAA,GAAA,CAAS,IAAA,WAAe,CAAA;;;;EAOxB,MAAA,CAAO,IAAA;;;;EAcP,OAAA,CAAQ,IAAA;;;;EAcR,MAAA,CAAO,IAAA;;;;EAeP,KAAA,CAAM,IAAA;;EAcN,IAAA,CAAK,OAAA;;EAKL,OAAA,CAAQ,OAAA;;EAKR,IAAA,CAAK,OAAA;;EAKL,KAAA,CAAM,OAAA;;EAKN,IAAA,CAAK,OAAA;;EAKL,OAAA,CAAA;;EAKA,OAAA,CAAQ,OAAA;;EAKR,KAAA,CAAM,OAAA,YAAmB,IAAA;;EAiBzB,IAAA,CAAK,OAAA,UAAiB,QAAA;;;;;EAWhB,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;AAAA"}
1
+ {"version":3,"file":"command-B1YuV-UZ.d.mts","names":[],"sources":["../src/quarry/constants.ts","../src/quarry/command.ts"],"mappings":";;;;;;cAIa,iBAAA;;;;AAAb;;;;;;;;ACsBA;;;;;;;;;;uBAAsB,OAAA;EA8LmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAA,OA7JhD,OAAA;EA4HC;EAAA,OA1HD,WAAA;EA+HD;EAAA,OA7HC,OAAA;EAAA,CAEN,iBAAA,GAAoB,gBAAA;;EA4IC;;;;EAAA,SA3Hb,MAAA,CAAA,mBAA0B,OAAA;EAsIa;;;EA/HhD,KAAA,GAAA,CAAS,IAAA,WAAe,CAAA;;;;EAOxB,MAAA,CAAO,IAAA;;;;EAcP,OAAA,CAAQ,IAAA;;;;EAcR,MAAA,CAAO,IAAA;;;;EAeP,KAAA,CAAM,IAAA;;EAcN,IAAA,CAAK,OAAA;;EAKL,OAAA,CAAQ,OAAA;;EAKR,IAAA,CAAK,OAAA;;EAKL,KAAA,CAAM,OAAA;;EAKN,IAAA,CAAK,OAAA;;EAKL,OAAA,CAAA;;EAKA,OAAA,CAAQ,OAAA;;EAKR,KAAA,CAAM,OAAA,YAAmB,IAAA;;EAiBzB,IAAA,CAAK,OAAA,UAAiB,QAAA;;;;;EAWhB,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;AAAA"}