stratal 0.0.17 → 0.0.19

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 (200) hide show
  1. package/README.md +8 -8
  2. package/dist/{base-email.provider-DypUAfWm.mjs → base-email.provider-mjynzewK.mjs} +1 -1
  3. package/dist/{base-email.provider-DypUAfWm.mjs.map → base-email.provider-mjynzewK.mjs.map} +1 -1
  4. package/dist/bin/cloudflare-workers-loader.mjs +33 -1
  5. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  6. package/dist/bin/quarry.mjs +169 -7
  7. package/dist/bin/quarry.mjs.map +1 -1
  8. package/dist/cache/index.d.mts +3 -2
  9. package/dist/cache/index.d.mts.map +1 -1
  10. package/dist/cache/index.mjs +3 -10
  11. package/dist/cache/index.mjs.map +1 -1
  12. package/dist/{colors-Y7WIFXs7.mjs → colors-DJaRDXoS.mjs} +1 -1
  13. package/dist/{colors-Y7WIFXs7.mjs.map → colors-DJaRDXoS.mjs.map} +1 -1
  14. package/dist/{command-B1CPgsrU.mjs → command-BgSlsS4M.mjs} +3 -3
  15. package/dist/command-BgSlsS4M.mjs.map +1 -0
  16. package/dist/{command-TnkPYWta.d.mts → command-DsQq56Lp.d.mts} +2 -2
  17. package/dist/{command-TnkPYWta.d.mts.map → command-DsQq56Lp.d.mts.map} +1 -1
  18. package/dist/config/index.d.mts +81 -37
  19. package/dist/config/index.d.mts.map +1 -1
  20. package/dist/config/index.mjs +135 -61
  21. package/dist/config/index.mjs.map +1 -1
  22. package/dist/{consumer-registry-Bymm6ff4.d.mts → consumer-registry-Doom7BEh.d.mts} +1 -1
  23. package/dist/{consumer-registry-Bymm6ff4.d.mts.map → consumer-registry-Doom7BEh.d.mts.map} +1 -1
  24. package/dist/controller.decorator-LZY9aHYG.mjs +66 -0
  25. package/dist/controller.decorator-LZY9aHYG.mjs.map +1 -0
  26. package/dist/cron/index.d.mts +4 -3
  27. package/dist/cron/index.d.mts.map +1 -1
  28. package/dist/cron/index.mjs +1 -3
  29. package/dist/{cron-manager-CFBamKKk.mjs → cron-manager-C30t9UZM.mjs} +29 -19
  30. package/dist/cron-manager-C30t9UZM.mjs.map +1 -0
  31. package/dist/{cron-manager-D7imGwUT.d.mts → cron-manager-RuPtFVLy.d.mts} +28 -14
  32. package/dist/cron-manager-RuPtFVLy.d.mts.map +1 -0
  33. package/dist/di/index.d.mts +2 -2
  34. package/dist/di/index.mjs +3 -3
  35. package/dist/email/index.d.mts +3 -3
  36. package/dist/email/index.mjs +87 -18
  37. package/dist/email/index.mjs.map +1 -1
  38. package/dist/{en-DaewN8hc.mjs → en-rHmW6vD9.mjs} +14 -31
  39. package/dist/en-rHmW6vD9.mjs.map +1 -0
  40. package/dist/env-CamWD-U1.d.mts +25 -0
  41. package/dist/env-CamWD-U1.d.mts.map +1 -0
  42. package/dist/errors/index.d.mts +2 -2
  43. package/dist/errors/index.mjs +2 -3
  44. package/dist/errors-B4pYgYON.mjs +1714 -0
  45. package/dist/errors-B4pYgYON.mjs.map +1 -0
  46. package/dist/{errors-DuAR5Wke.mjs → errors-BUyUfr2Z.mjs} +14 -7
  47. package/dist/errors-BUyUfr2Z.mjs.map +1 -0
  48. package/dist/events/index.d.mts +2 -2
  49. package/dist/events/index.mjs +1 -2
  50. package/dist/{events-CvUSgEuN.mjs → events-COKixqnG.mjs} +2 -2
  51. package/dist/{events-CvUSgEuN.mjs.map → events-COKixqnG.mjs.map} +1 -1
  52. package/dist/{gateway-context-CNOLkLUC.mjs → gateway-context-cqZ8wMoi.mjs} +4 -9
  53. package/dist/gateway-context-cqZ8wMoi.mjs.map +1 -0
  54. package/dist/guards/index.d.mts +14 -5
  55. package/dist/guards/index.d.mts.map +1 -1
  56. package/dist/guards/index.mjs +1 -1
  57. package/dist/{guards-DUk_Kzst.mjs → guards-DMbsAxSX.mjs} +1 -1
  58. package/dist/guards-DMbsAxSX.mjs.map +1 -0
  59. package/dist/http-method.decorator-BT3ufnz8.mjs +96 -0
  60. package/dist/http-method.decorator-BT3ufnz8.mjs.map +1 -0
  61. package/dist/i18n/index.d.mts +3 -3
  62. package/dist/i18n/index.mjs +3 -16
  63. package/dist/i18n/messages/en/index.d.mts +1 -1
  64. package/dist/i18n/messages/en/index.mjs +1 -1
  65. package/dist/i18n/utils/index.d.mts +30 -0
  66. package/dist/i18n/utils/index.d.mts.map +1 -0
  67. package/dist/i18n/utils/index.mjs +2 -0
  68. package/dist/i18n/validation/index.d.mts +1 -1
  69. package/dist/i18n/validation/index.mjs +1 -1
  70. package/dist/i18n.module-CI_prYFD.mjs +2340 -0
  71. package/dist/i18n.module-CI_prYFD.mjs.map +1 -0
  72. package/dist/{index-NGxg-KP_.d.mts → index-B437eK7p.d.mts} +59 -16
  73. package/dist/index-B437eK7p.d.mts.map +1 -0
  74. package/dist/{index-Dp6A5ywM.d.mts → index-CWRS7Ri3.d.mts} +1 -1
  75. package/dist/{index-Dp6A5ywM.d.mts.map → index-CWRS7Ri3.d.mts.map} +1 -1
  76. package/dist/{index-D_w_Rmtd.d.mts → index-DFhEeFfC.d.mts} +13 -30
  77. package/dist/{index-D_w_Rmtd.d.mts.map → index-DFhEeFfC.d.mts.map} +1 -1
  78. package/dist/index-DPFqRs8L.d.mts +4318 -0
  79. package/dist/index-DPFqRs8L.d.mts.map +1 -0
  80. package/dist/{index-DGRe6Yoa.d.mts → index-Dnqm9ZB6.d.mts} +5 -4
  81. package/dist/index-Dnqm9ZB6.d.mts.map +1 -0
  82. package/dist/index-SHx31sBJ.d.mts +101 -0
  83. package/dist/index-SHx31sBJ.d.mts.map +1 -0
  84. package/dist/index.d.mts +5 -3
  85. package/dist/index.d.mts.map +1 -1
  86. package/dist/index.mjs +1 -20
  87. package/dist/{is-command-DJVI6wEJ.mjs → is-command-C6a7WTPw.mjs} +2 -2
  88. package/dist/{is-command-DJVI6wEJ.mjs.map → is-command-C6a7WTPw.mjs.map} +1 -1
  89. package/dist/{is-seeder-D5MIEcdz.mjs → is-seeder-CebjZCDn.mjs} +1 -1
  90. package/dist/{is-seeder-D5MIEcdz.mjs.map → is-seeder-CebjZCDn.mjs.map} +1 -1
  91. package/dist/logger/index.d.mts +1 -1
  92. package/dist/logger/index.mjs +1 -1
  93. package/dist/{logger-CGT91VY6.mjs → logger-V6Ms3QnQ.mjs} +63 -45
  94. package/dist/logger-V6Ms3QnQ.mjs.map +1 -0
  95. package/dist/macroable/index.d.mts +2 -0
  96. package/dist/macroable/index.mjs +2 -0
  97. package/dist/macroable-BmufBshB.mjs +122 -0
  98. package/dist/macroable-BmufBshB.mjs.map +1 -0
  99. package/dist/module/index.d.mts +3 -4
  100. package/dist/module/index.d.mts.map +1 -1
  101. package/dist/module/index.mjs +1 -10
  102. package/dist/module-qGE_1duv.mjs +732 -0
  103. package/dist/module-qGE_1duv.mjs.map +1 -0
  104. package/dist/openapi/index.d.mts +3 -3
  105. package/dist/openapi/index.mjs +2 -15
  106. package/dist/{openapi-tools.service-B3TxYKoQ.mjs → openapi-tools.service-CYWGuhue.mjs} +4 -1
  107. package/dist/{openapi-tools.service-B3TxYKoQ.mjs.map → openapi-tools.service-CYWGuhue.mjs.map} +1 -1
  108. package/dist/{openapi.service-DGnX3Fc4.d.mts → openapi.service-Bv_NioM9.d.mts} +9 -17
  109. package/dist/openapi.service-Bv_NioM9.d.mts.map +1 -0
  110. package/dist/quarry/index.d.mts +26 -12
  111. package/dist/quarry/index.d.mts.map +1 -1
  112. package/dist/quarry/index.mjs +4 -8
  113. package/dist/{quarry-registry-B2rkO-JS.mjs → quarry-registry-DFfRRkA7.mjs} +45 -40
  114. package/dist/quarry-registry-DFfRRkA7.mjs.map +1 -0
  115. package/dist/queue/index.d.mts +2 -2
  116. package/dist/queue/index.mjs +3 -13
  117. package/dist/queue/index.mjs.map +1 -1
  118. package/dist/{queue.module-BtI8f4Jo.mjs → queue.module-P-G-nCYz.mjs} +39 -42
  119. package/dist/queue.module-P-G-nCYz.mjs.map +1 -0
  120. package/dist/r2-storage.provider-LdzK9tfG.mjs +244 -0
  121. package/dist/r2-storage.provider-LdzK9tfG.mjs.map +1 -0
  122. package/dist/{resend.provider-bXMEkdRJ.mjs → resend.provider-bwILp0WI.mjs} +2 -4
  123. package/dist/{resend.provider-bXMEkdRJ.mjs.map → resend.provider-bwILp0WI.mjs.map} +1 -1
  124. package/dist/router/index.d.mts +2 -2
  125. package/dist/router/index.mjs +7 -16
  126. package/dist/seeder/index.d.mts +3 -4
  127. package/dist/seeder/index.d.mts.map +1 -1
  128. package/dist/seeder/index.mjs +2 -6
  129. package/dist/{seeder-R7RXJC35.mjs → seeder-BcqIFa2X.mjs} +5 -5
  130. package/dist/{seeder-R7RXJC35.mjs.map → seeder-BcqIFa2X.mjs.map} +1 -1
  131. package/dist/setup-CtekcwuO.mjs +37 -0
  132. package/dist/setup-CtekcwuO.mjs.map +1 -0
  133. package/dist/signed-url-COX7cCWR.mjs +74 -0
  134. package/dist/signed-url-COX7cCWR.mjs.map +1 -0
  135. package/dist/{smtp.provider-DrbHQztF.mjs → smtp.provider-B07yuARi.mjs} +2 -4
  136. package/dist/{smtp.provider-DrbHQztF.mjs.map → smtp.provider-B07yuARi.mjs.map} +1 -1
  137. package/dist/storage/index.d.mts +39 -17
  138. package/dist/storage/index.d.mts.map +1 -1
  139. package/dist/storage/index.mjs +3 -14
  140. package/dist/storage/providers/index.d.mts +30 -69
  141. package/dist/storage/providers/index.d.mts.map +1 -1
  142. package/dist/storage/providers/index.mjs +2 -5
  143. package/dist/{storage-CZKHOhci.mjs → storage-P6X4h9So.mjs} +102 -29
  144. package/dist/storage-P6X4h9So.mjs.map +1 -0
  145. package/dist/{storage-provider.interface-0IqcdhBf.d.mts → storage-provider.interface-CC1nniHk.d.mts} +20 -15
  146. package/dist/storage-provider.interface-CC1nniHk.d.mts.map +1 -0
  147. package/dist/stratal-BCiwCFN9.mjs +533 -0
  148. package/dist/stratal-BCiwCFN9.mjs.map +1 -0
  149. package/dist/{types-DahElfUw.d.mts → types-DIWemRad.d.mts} +2 -2
  150. package/dist/types-DIWemRad.d.mts.map +1 -0
  151. package/dist/{usage-generator-CVIsENuE.mjs → usage-generator-MBcRo0Q2.mjs} +2 -2
  152. package/dist/{usage-generator-CVIsENuE.mjs.map → usage-generator-MBcRo0Q2.mjs.map} +1 -1
  153. package/dist/{validation-DQTC259A.mjs → validation-Dbg3ehdP.mjs} +2 -2
  154. package/dist/{validation-DQTC259A.mjs.map → validation-Dbg3ehdP.mjs.map} +1 -1
  155. package/dist/websocket/index.d.mts +3 -3
  156. package/dist/websocket/index.d.mts.map +1 -1
  157. package/dist/websocket/index.mjs +1 -4
  158. package/dist/workers/index.d.mts +2 -1
  159. package/dist/workers/index.d.mts.map +1 -1
  160. package/dist/workers/index.mjs +2 -20
  161. package/dist/workers/index.mjs.map +1 -1
  162. package/package.json +41 -50
  163. package/dist/application-DfPtIzxF.d.mts +0 -177
  164. package/dist/application-DfPtIzxF.d.mts.map +0 -1
  165. package/dist/command-B1CPgsrU.mjs.map +0 -1
  166. package/dist/cron-manager-CFBamKKk.mjs.map +0 -1
  167. package/dist/cron-manager-D7imGwUT.d.mts.map +0 -1
  168. package/dist/en-DaewN8hc.mjs.map +0 -1
  169. package/dist/errors-DSKapqD8.mjs +0 -707
  170. package/dist/errors-DSKapqD8.mjs.map +0 -1
  171. package/dist/errors-DuAR5Wke.mjs.map +0 -1
  172. package/dist/gateway-context-CNOLkLUC.mjs.map +0 -1
  173. package/dist/guards-DUk_Kzst.mjs.map +0 -1
  174. package/dist/i18n.module-Dn9SrFdS.mjs +0 -1841
  175. package/dist/i18n.module-Dn9SrFdS.mjs.map +0 -1
  176. package/dist/index-BFCxSp_f.d.mts +0 -2625
  177. package/dist/index-BFCxSp_f.d.mts.map +0 -1
  178. package/dist/index-DGRe6Yoa.d.mts.map +0 -1
  179. package/dist/index-NGxg-KP_.d.mts.map +0 -1
  180. package/dist/logger-CGT91VY6.mjs.map +0 -1
  181. package/dist/middleware/index.d.mts +0 -2
  182. package/dist/middleware/index.mjs +0 -5
  183. package/dist/middleware-Bl-b5pkt.mjs +0 -362
  184. package/dist/middleware-Bl-b5pkt.mjs.map +0 -1
  185. package/dist/module-registry-CmjBX6ol.d.mts +0 -121
  186. package/dist/module-registry-CmjBX6ol.d.mts.map +0 -1
  187. package/dist/module-tUtyVJ5E.mjs +0 -371
  188. package/dist/module-tUtyVJ5E.mjs.map +0 -1
  189. package/dist/openapi.service-DGnX3Fc4.d.mts.map +0 -1
  190. package/dist/quarry-registry-B2rkO-JS.mjs.map +0 -1
  191. package/dist/queue.module-BtI8f4Jo.mjs.map +0 -1
  192. package/dist/router-context-D9R1v2Ac.mjs +0 -267
  193. package/dist/router-context-D9R1v2Ac.mjs.map +0 -1
  194. package/dist/s3-storage.provider-CttzNnDR.mjs +0 -335
  195. package/dist/s3-storage.provider-CttzNnDR.mjs.map +0 -1
  196. package/dist/storage-CZKHOhci.mjs.map +0 -1
  197. package/dist/storage-provider.interface-0IqcdhBf.d.mts.map +0 -1
  198. package/dist/stratal-D5smIU1y.mjs +0 -315
  199. package/dist/stratal-D5smIU1y.mjs.map +0 -1
  200. package/dist/types-DahElfUw.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"usage-generator-CVIsENuE.mjs","names":[],"sources":["../src/quarry/usage-generator.ts"],"sourcesContent":["import { bold, cyan, dim, dimWhite, yellow } from './colors'\nimport type { ParsedSignature } from './types'\n\n/**\n * Generate formatted help/usage text from a parsed signature.\n *\n * Pure function, edge-compatible.\n */\nexport function generateUsage(signature: ParsedSignature, description?: string): string {\n const lines: string[] = []\n\n // Usage line\n lines.push(`${bold('Usage:')} ${bold(cyan('quarry ' + buildUsageLine(signature)))}`)\n\n // Description\n if (description) {\n lines.push('')\n lines.push(description)\n }\n\n // Arguments section\n if (signature.arguments.length > 0) {\n lines.push('')\n lines.push(bold(yellow('Arguments:')))\n const argRows = signature.arguments.map((arg) => {\n const label = arg.name\n const parts: string[] = []\n\n if (arg.description) parts.push(arg.description)\n\n if (arg.isArray) {\n parts.push('(variadic)')\n } else if (arg.required) {\n parts.push('(required)')\n } else if (arg.default !== undefined) {\n parts.push(dim(`(default: ${arg.default})`))\n } else {\n parts.push('(optional)')\n }\n\n return [label, parts.join(' ')] as const\n })\n lines.push(...formatTable(argRows))\n }\n\n // Options section\n if (signature.options.length > 0) {\n lines.push('')\n lines.push(bold(yellow('Options:')))\n const optRows = signature.options.map((opt) => {\n const flagParts: string[] = []\n if (opt.alias) flagParts.push(`-${opt.alias},`)\n flagParts.push(`--${opt.name}`)\n\n const label = flagParts.join(' ')\n const parts: string[] = []\n\n if (opt.description) parts.push(opt.description)\n if (!opt.isFlag && !opt.description) parts.push('Accepts a value')\n if (opt.isFlag && !opt.description) parts.push('Boolean flag')\n if (opt.isArray) parts.push('(multiple)')\n if (opt.default !== undefined) parts.push(dim(`(default: ${opt.default})`))\n\n return [label, parts.join(' ')] as const\n })\n lines.push(...formatTable(optRows))\n }\n\n return lines.join('\\n')\n}\n\nexport interface ListingOptions {\n binaryName?: string\n binaryLabel?: string\n binaryVersion?: string\n}\n\n/**\n * Generate a compact command listing with visual hierarchy.\n */\nexport function generateListing(\n commands: { name: string; description?: string; aliases: string[] }[],\n signatures: Map<string, ParsedSignature>,\n options?: ListingOptions,\n): string {\n const bin = options?.binaryName ?? 'quarry'\n const label = options?.binaryLabel ?? 'Quarry CLI'\n const version = options?.binaryVersion\n\n const lines: string[] = []\n\n // Header\n lines.push(bold(`${label}${version ? ` v${version}` : ''}`))\n lines.push('')\n\n // Usage\n lines.push(bold(yellow('Usage')))\n lines.push(` $ ${bin} <command> [options]`)\n lines.push('')\n\n // Commands\n if (commands.length === 0) {\n lines.push('No registered commands.')\n return lines.join('\\n')\n }\n\n lines.push(bold(yellow('Commands')))\n\n const termWidth = typeof process !== 'undefined'\n ? (process.stdout.columns as number | undefined) ?? 80\n : 80\n\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i]\n const sig = signatures.get(cmd.name)\n const sigParts: string[] = [cyan(cmd.name)]\n\n if (cmd.aliases.length > 0) {\n sigParts.push(cyan(`(alias: ${cmd.aliases.join(', ')})`))\n }\n\n if (sig) {\n const inlineParts: string[] = []\n for (const arg of sig.arguments) {\n inlineParts.push(formatArgPlaceholder(arg))\n }\n\n for (const opt of sig.options) {\n const flagStr = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n inlineParts.push(`[${flagStr}]`)\n }\n\n if (inlineParts.length > 0) {\n sigParts.push(dim(inlineParts.join(' ')))\n }\n }\n\n const sigLine = ' ' + sigParts.join(' ')\n lines.push(...wrapLine(sigLine, termWidth, ' '))\n\n if (cmd.description) {\n lines.push(` ${dimWhite(cmd.description)}`)\n }\n\n if (i < commands.length - 1) {\n lines.push('')\n }\n }\n\n lines.push('')\n\n // Footer\n lines.push(dimWhite(`Run ${bin} help <command> for detailed information.`))\n\n return lines.join('\\n')\n}\n\n/** Format a single argument into its placeholder representation (e.g. `<name>`, `[name=default]`). */\nfunction formatArgPlaceholder(arg: ParsedSignature['arguments'][number]): string {\n if (arg.isArray) return `<${arg.name}...>`\n if (arg.required) return `<${arg.name}>`\n if (arg.default !== undefined) return `[${arg.name}=${arg.default}]`\n return `[${arg.name}]`\n}\n\n/** Build the inline usage line showing the command name with argument and option placeholders. */\nfunction buildUsageLine(signature: ParsedSignature): string {\n const parts = [signature.name]\n\n for (const arg of signature.arguments) {\n parts.push(formatArgPlaceholder(arg))\n }\n\n for (const opt of signature.options) {\n const flagStr = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n\n if (opt.isFlag) {\n parts.push(`[${flagStr}]`)\n } else if (opt.isArray) {\n parts.push(`[${flagStr} <value...>]`)\n } else {\n parts.push(`[${flagStr} <value>]`)\n }\n }\n\n return parts.join(' ')\n}\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\\x1b\\[[0-9;]*m/g\n\n/** Remove ANSI escape sequences from a string. */\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, '')\n}\n\n// eslint-disable-next-line no-control-regex\nconst TOKEN_RE = /(?:\\x1b\\[[0-9;]*m)*[^\\s\\x1b]+(?:\\x1b\\[[0-9;]*m)*/g\n\n/** Wrap a single line at word boundaries, preserving ANSI codes across wrapped segments. */\nfunction wrapLine(text: string, maxWidth: number, continuationIndent: string): string[] {\n const visibleLen = stripAnsi(text).length\n if (visibleLen <= maxWidth) return [text]\n\n const tokens = text.match(TOKEN_RE) ?? [text]\n\n const lines: string[] = []\n let currentLine = ''\n let currentVisibleLen = 0\n\n for (const token of tokens) {\n const tokenVisible = stripAnsi(token).length\n const separator = currentLine === '' ? '' : ' '\n const separatorLen = separator.length\n\n if (currentLine !== '' && currentVisibleLen + separatorLen + tokenVisible > maxWidth) {\n lines.push(currentLine)\n currentLine = continuationIndent + token\n currentVisibleLen = continuationIndent.length + tokenVisible\n } else {\n currentLine += separator + token\n currentVisibleLen += separatorLen + tokenVisible\n }\n }\n\n if (currentLine !== '') {\n lines.push(currentLine)\n }\n\n return lines\n}\n\n/** Format label/description pairs into aligned two-column table rows. */\nfunction formatTable(rows: readonly (readonly [string, string])[]): string[] {\n if (rows.length === 0) return []\n\n const maxLabel = Math.max(...rows.map(([label]) => stripAnsi(label).length))\n const padding = 4\n\n return rows.map(([label, desc]) => {\n const visibleLen = stripAnsi(label).length\n const pad = ' '.repeat(maxLabel - visibleLen + padding)\n return ` ${label}${pad}${desc}`\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"usage-generator-MBcRo0Q2.mjs","names":[],"sources":["../src/quarry/usage-generator.ts"],"sourcesContent":["import { bold, cyan, dim, dimWhite, yellow } from './colors'\nimport type { ParsedSignature } from './types'\n\n/**\n * Generate formatted help/usage text from a parsed signature.\n *\n * Pure function, edge-compatible.\n */\nexport function generateUsage(signature: ParsedSignature, description?: string): string {\n const lines: string[] = []\n\n // Usage line\n lines.push(`${bold('Usage:')} ${bold(cyan('quarry ' + buildUsageLine(signature)))}`)\n\n // Description\n if (description) {\n lines.push('')\n lines.push(description)\n }\n\n // Arguments section\n if (signature.arguments.length > 0) {\n lines.push('')\n lines.push(bold(yellow('Arguments:')))\n const argRows = signature.arguments.map((arg) => {\n const label = arg.name\n const parts: string[] = []\n\n if (arg.description) parts.push(arg.description)\n\n if (arg.isArray) {\n parts.push('(variadic)')\n } else if (arg.required) {\n parts.push('(required)')\n } else if (arg.default !== undefined) {\n parts.push(dim(`(default: ${arg.default})`))\n } else {\n parts.push('(optional)')\n }\n\n return [label, parts.join(' ')] as const\n })\n lines.push(...formatTable(argRows))\n }\n\n // Options section\n if (signature.options.length > 0) {\n lines.push('')\n lines.push(bold(yellow('Options:')))\n const optRows = signature.options.map((opt) => {\n const flagParts: string[] = []\n if (opt.alias) flagParts.push(`-${opt.alias},`)\n flagParts.push(`--${opt.name}`)\n\n const label = flagParts.join(' ')\n const parts: string[] = []\n\n if (opt.description) parts.push(opt.description)\n if (!opt.isFlag && !opt.description) parts.push('Accepts a value')\n if (opt.isFlag && !opt.description) parts.push('Boolean flag')\n if (opt.isArray) parts.push('(multiple)')\n if (opt.default !== undefined) parts.push(dim(`(default: ${opt.default})`))\n\n return [label, parts.join(' ')] as const\n })\n lines.push(...formatTable(optRows))\n }\n\n return lines.join('\\n')\n}\n\nexport interface ListingOptions {\n binaryName?: string\n binaryLabel?: string\n binaryVersion?: string\n}\n\n/**\n * Generate a compact command listing with visual hierarchy.\n */\nexport function generateListing(\n commands: { name: string; description?: string; aliases: string[] }[],\n signatures: Map<string, ParsedSignature>,\n options?: ListingOptions,\n): string {\n const bin = options?.binaryName ?? 'quarry'\n const label = options?.binaryLabel ?? 'Quarry CLI'\n const version = options?.binaryVersion\n\n const lines: string[] = []\n\n // Header\n lines.push(bold(`${label}${version ? ` v${version}` : ''}`))\n lines.push('')\n\n // Usage\n lines.push(bold(yellow('Usage')))\n lines.push(` $ ${bin} <command> [options]`)\n lines.push('')\n\n // Commands\n if (commands.length === 0) {\n lines.push('No registered commands.')\n return lines.join('\\n')\n }\n\n lines.push(bold(yellow('Commands')))\n\n const termWidth = typeof process !== 'undefined'\n ? (process.stdout.columns as number | undefined) ?? 80\n : 80\n\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i]\n const sig = signatures.get(cmd.name)\n const sigParts: string[] = [cyan(cmd.name)]\n\n if (cmd.aliases.length > 0) {\n sigParts.push(cyan(`(alias: ${cmd.aliases.join(', ')})`))\n }\n\n if (sig) {\n const inlineParts: string[] = []\n for (const arg of sig.arguments) {\n inlineParts.push(formatArgPlaceholder(arg))\n }\n\n for (const opt of sig.options) {\n const flagStr = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n inlineParts.push(`[${flagStr}]`)\n }\n\n if (inlineParts.length > 0) {\n sigParts.push(dim(inlineParts.join(' ')))\n }\n }\n\n const sigLine = ' ' + sigParts.join(' ')\n lines.push(...wrapLine(sigLine, termWidth, ' '))\n\n if (cmd.description) {\n lines.push(` ${dimWhite(cmd.description)}`)\n }\n\n if (i < commands.length - 1) {\n lines.push('')\n }\n }\n\n lines.push('')\n\n // Footer\n lines.push(dimWhite(`Run ${bin} help <command> for detailed information.`))\n\n return lines.join('\\n')\n}\n\n/** Format a single argument into its placeholder representation (e.g. `<name>`, `[name=default]`). */\nfunction formatArgPlaceholder(arg: ParsedSignature['arguments'][number]): string {\n if (arg.isArray) return `<${arg.name}...>`\n if (arg.required) return `<${arg.name}>`\n if (arg.default !== undefined) return `[${arg.name}=${arg.default}]`\n return `[${arg.name}]`\n}\n\n/** Build the inline usage line showing the command name with argument and option placeholders. */\nfunction buildUsageLine(signature: ParsedSignature): string {\n const parts = [signature.name]\n\n for (const arg of signature.arguments) {\n parts.push(formatArgPlaceholder(arg))\n }\n\n for (const opt of signature.options) {\n const flagStr = opt.alias ? `-${opt.alias},--${opt.name}` : `--${opt.name}`\n\n if (opt.isFlag) {\n parts.push(`[${flagStr}]`)\n } else if (opt.isArray) {\n parts.push(`[${flagStr} <value...>]`)\n } else {\n parts.push(`[${flagStr} <value>]`)\n }\n }\n\n return parts.join(' ')\n}\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\\x1b\\[[0-9;]*m/g\n\n/** Remove ANSI escape sequences from a string. */\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, '')\n}\n\n// eslint-disable-next-line no-control-regex\nconst TOKEN_RE = /(?:\\x1b\\[[0-9;]*m)*[^\\s\\x1b]+(?:\\x1b\\[[0-9;]*m)*/g\n\n/** Wrap a single line at word boundaries, preserving ANSI codes across wrapped segments. */\nfunction wrapLine(text: string, maxWidth: number, continuationIndent: string): string[] {\n const visibleLen = stripAnsi(text).length\n if (visibleLen <= maxWidth) return [text]\n\n const tokens = text.match(TOKEN_RE) ?? [text]\n\n const lines: string[] = []\n let currentLine = ''\n let currentVisibleLen = 0\n\n for (const token of tokens) {\n const tokenVisible = stripAnsi(token).length\n const separator = currentLine === '' ? '' : ' '\n const separatorLen = separator.length\n\n if (currentLine !== '' && currentVisibleLen + separatorLen + tokenVisible > maxWidth) {\n lines.push(currentLine)\n currentLine = continuationIndent + token\n currentVisibleLen = continuationIndent.length + tokenVisible\n } else {\n currentLine += separator + token\n currentVisibleLen += separatorLen + tokenVisible\n }\n }\n\n if (currentLine !== '') {\n lines.push(currentLine)\n }\n\n return lines\n}\n\n/** Format label/description pairs into aligned two-column table rows. */\nfunction formatTable(rows: readonly (readonly [string, string])[]): string[] {\n if (rows.length === 0) return []\n\n const maxLabel = Math.max(...rows.map(([label]) => stripAnsi(label).length))\n const padding = 4\n\n return rows.map(([label, desc]) => {\n const visibleLen = stripAnsi(label).length\n const pad = ' '.repeat(maxLabel - visibleLen + padding)\n return ` ${label}${pad}${desc}`\n })\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { n as __reExport, t as __exportAll } from "./chunk-D1SwGrFN.mjs";
2
+ import { AsyncLocalStorage } from "node:async_hooks";
2
3
  import { OpenAPIHono, z as z$1 } from "@hono/zod-openapi";
3
4
  import { ZodError } from "zod";
4
- import { AsyncLocalStorage } from "node:async_hooks";
5
5
  //#region src/i18n/validation/validation.error-map.ts
6
6
  /**
7
7
  * Type guards for narrowing Zod v4 issue types
@@ -191,4 +191,4 @@ __reExport(validation_exports, import__hono_zod_openapi);
191
191
  //#endregion
192
192
  export { withI18n as a, z$1 as i, ZodError as n, backendErrorMap as o, validation_exports as r, runWithErrorMapContext as s, OpenAPIHono as t };
193
193
 
194
- //# sourceMappingURL=validation-DQTC259A.mjs.map
194
+ //# sourceMappingURL=validation-Dbg3ehdP.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation-DQTC259A.mjs","names":[],"sources":["../src/i18n/validation/validation.error-map.ts","../src/i18n/validation/validation.context.ts","../src/i18n/validation/with-i18n.ts","../src/i18n/validation/index.ts"],"sourcesContent":["import type {\n $ZodErrorMap,\n $ZodIssueInvalidKey,\n $ZodIssueInvalidStringFormat,\n $ZodIssueInvalidType,\n $ZodIssueInvalidUnion,\n $ZodIssueNotMultipleOf,\n $ZodIssueTooBig,\n $ZodIssueTooSmall,\n $ZodIssueUnrecognizedKeys,\n $ZodRawIssue,\n} from 'zod/v4/core'\nimport type { MessageKeys } from '../i18n.types'\nimport type { ErrorMapContext } from './validation.types'\n\n/**\n * Type guards for narrowing Zod v4 issue types\n */\nfunction isInvalidType(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidType> {\n return issue.code === 'invalid_type'\n}\n\nfunction isTooBig(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueTooBig> {\n return issue.code === 'too_big'\n}\n\nfunction isTooSmall(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueTooSmall> {\n return issue.code === 'too_small'\n}\n\nfunction isInvalidFormat(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidStringFormat> {\n return issue.code === 'invalid_format'\n}\n\nfunction isNotMultipleOf(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueNotMultipleOf> {\n return issue.code === 'not_multiple_of'\n}\n\nfunction isUnrecognizedKeys(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueUnrecognizedKeys> {\n return issue.code === 'unrecognized_keys'\n}\n\nfunction isInvalidUnion(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidUnion> {\n return issue.code === 'invalid_union'\n}\n\nfunction isInvalidKey(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidKey> {\n return issue.code === 'invalid_key'\n}\n\n/**\n * Maps Zod issue codes to zodI18n message keys\n * Adapted for Zod v4's simpler issue code system\n */\nfunction getMessageKey(issue: $ZodRawIssue): MessageKeys {\n if (isInvalidType(issue)) {\n if (issue.input === undefined) {\n return 'zodI18n.errors.required'\n }\n return 'zodI18n.errors.invalid_type'\n }\n\n if (isTooSmall(issue)) {\n const typeKey = issue.origin || 'string'\n const exactKey = issue.exact\n ? 'exact'\n : issue.inclusive\n ? 'inclusive'\n : 'not_inclusive'\n return `zodI18n.errors.too_small.${typeKey}.${exactKey}` as MessageKeys\n }\n\n if (isTooBig(issue)) {\n const typeKey = issue.origin || 'string'\n const exactKey = issue.exact\n ? 'exact'\n : issue.inclusive\n ? 'inclusive'\n : 'not_inclusive'\n return `zodI18n.errors.too_big.${typeKey}.${exactKey}` as MessageKeys\n }\n\n if (isInvalidFormat(issue)) {\n // Map v4's format to v3-style validation keys\n return `zodI18n.errors.invalid_string.${issue.format}` as MessageKeys\n }\n\n if (isNotMultipleOf(issue)) {\n return 'zodI18n.errors.not_multiple_of'\n }\n\n if (isUnrecognizedKeys(issue)) {\n return 'zodI18n.errors.unrecognized_keys'\n }\n\n if (isInvalidUnion(issue)) {\n return 'zodI18n.errors.invalid_union'\n }\n\n if (isInvalidKey(issue)) {\n // v4: Replaces invalid_enum_value, invalid_literal\n return 'zodI18n.errors.invalid_enum_value'\n }\n\n // invalid_element, invalid_value, or unknown codes\n return 'zodI18n.errors.custom.default'\n}\n\n/**\n * Extracts interpolation parameters from Zod issue\n * Uses proper type narrowing for v4\n */\nfunction getMessageParams(issue: $ZodRawIssue): Record<string, unknown> {\n const params: Record<string, unknown> = {}\n\n if (isInvalidType(issue)) {\n params.expected = issue.expected\n params.received = String(issue.input)\n return params\n }\n\n if (isUnrecognizedKeys(issue)) {\n params.keys = issue.keys.join(', ')\n return params\n }\n\n if (isInvalidKey(issue)) {\n // v4: For enums and records\n // Since v4 doesn't have options field, we'll use generic message\n return params\n }\n\n if (isInvalidFormat(issue)) {\n params.validation = issue.format\n\n // Check for specific string format issues with additional fields\n if ('prefix' in issue) {\n params.startsWith = (issue as { prefix?: string }).prefix\n }\n if ('suffix' in issue) {\n params.endsWith = (issue as { suffix?: string }).suffix\n }\n if ('includes' in issue) {\n params.includes = (issue as { includes?: string }).includes\n }\n if (issue.pattern) {\n params.pattern = issue.pattern\n }\n\n return params\n }\n\n if (isTooSmall(issue)) {\n params.minimum = issue.minimum\n params.type = issue.origin\n if (issue.origin === 'date') {\n params.minimum = new Date(Number(issue.minimum)).toLocaleDateString()\n }\n return params\n }\n\n if (isTooBig(issue)) {\n params.maximum = issue.maximum\n params.type = issue.origin\n if (issue.origin === 'date') {\n params.maximum = new Date(Number(issue.maximum)).toLocaleDateString()\n }\n return params\n }\n\n if (isNotMultipleOf(issue)) {\n params.multipleOf = issue.divisor\n return params\n }\n\n return params\n}\n\n/**\n * Creates a Zod error map that uses i18n for translation\n * Uses Zod v4 native $ZodErrorMap signature (no ctx parameter)\n */\nexport function createI18nErrorMap(getContext: () => ErrorMapContext | undefined): $ZodErrorMap {\n return (issue: $ZodRawIssue): { message: string } => {\n // Get message key and params for this issue\n const messageKey = getMessageKey(issue)\n const messageParams = getMessageParams(issue)\n\n // Get translation context\n const context = getContext()\n\n if (!context) {\n // Fallback: Use English messages directly\n // This handles config validation at startup, tests, etc.\n return { message: 'Invalid input' }\n }\n\n // Normal flow: Use context-aware i18n (respects user locale)\n return {\n message: context.t(messageKey, messageParams),\n }\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { ErrorMapContext } from './validation.types'\nimport { createI18nErrorMap } from './validation.error-map'\n\n/**\n * AsyncLocalStorage for storing request-scoped ErrorMapContext\n * Allows error map to access I18nService without passing through function calls\n */\nexport const errorMapContextStorage = new AsyncLocalStorage<ErrorMapContext>()\n\n/**\n * Gets the current error map context from AsyncLocalStorage\n */\nfunction getErrorMapContext(): ErrorMapContext | undefined {\n return errorMapContextStorage.getStore()\n}\n\n/**\n * Backend error map that accesses I18nService from AsyncLocalStorage\n * Must be initialized in router middleware after locale detection\n */\nexport const backendErrorMap = createI18nErrorMap(getErrorMapContext)\n\n/**\n * Runs a function within an error map context\n * Used by router middleware to provide I18nService to validation\n *\n * @example\n * ```typescript\n * router.use('*', async (c, next) => {\n * const i18nService = c.get('i18nService')\n * const locale = c.get('locale')\n *\n * return runWithErrorMapContext(\n * {\n * t: (key, params) => i18nService.t(key, params),\n * locale,\n * },\n * () => next()\n * )\n * })\n * ```\n */\nexport function runWithErrorMapContext<T>(\n context: ErrorMapContext,\n fn: () => T\n): T {\n return errorMapContextStorage.run(context, fn)\n}\n","import type { MessageKeys } from '../i18n.types'\nimport { errorMapContextStorage } from './validation.context'\n\n/**\n * Type-safe helper for creating custom Zod error messages with i18n support (Backend)\n *\n * Usage with .refine():\n * ```typescript\n * const schema = z.string().refine(\n * (val) => val.length > 5,\n * withI18n('validation.minLength', { min: 5 })\n * )\n * ```\n *\n * Usage with built-in validators:\n * ```typescript\n * const schema = z.string().min(5, withI18n('validation.minLength', { min: 5 }))\n * const schema = z.string().email(withI18n('validation.email'))\n * ```\n *\n * Note: This is the backend version using AsyncLocalStorage.\n * For frontend, use withI18nFrontend from the frontend validation module\n *\n * @param key - Message key from shared i18n messages (type-safe via MessageKeys)\n * @param params - Optional interpolation parameters for the message\n * @returns Zod error configuration object with translated message\n */\nexport function withI18n(\n key: MessageKeys,\n params?: Record<string, unknown>\n): { error: () => string } {\n return {\n error: () => {\n // Get i18n context from AsyncLocalStorage (backend)\n // This is set by the router middleware before validation\n const context = errorMapContextStorage.getStore()\n\n // Translate using context if available, otherwise fallback to generic message\n const message = context\n ? context.t(key, params as Record<string, string | number> | undefined)\n : 'Invalid input'\n\n return message\n },\n }\n}\n","// Consolidated zod - single source from @hono/zod-openapi (superset of zod)\nexport { OpenAPIHono, z } from '@hono/zod-openapi'\nexport type * from 'zod'\nexport { ZodError } from 'zod'\n\n// OpenAPI utilities\nexport * from '@hono/zod-openapi'\nexport type { OpenAPIObject, PathItemObject } from 'openapi3-ts/oas30'\n\n// Helpers\nexport { withI18n } from './with-i18n'\n\n// Backend utilities\nexport { backendErrorMap, runWithErrorMapContext } from './validation.context'\n\n// Types\nexport type { ErrorMapContext, I18nErrorMetadata, LocaleProvider, ZodCustomIssue } from './validation.types'\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"validation-Dbg3ehdP.mjs","names":[],"sources":["../src/i18n/validation/validation.error-map.ts","../src/i18n/validation/validation.context.ts","../src/i18n/validation/with-i18n.ts","../src/i18n/validation/index.ts"],"sourcesContent":["import type {\n $ZodErrorMap,\n $ZodIssueInvalidKey,\n $ZodIssueInvalidStringFormat,\n $ZodIssueInvalidType,\n $ZodIssueInvalidUnion,\n $ZodIssueNotMultipleOf,\n $ZodIssueTooBig,\n $ZodIssueTooSmall,\n $ZodIssueUnrecognizedKeys,\n $ZodRawIssue,\n} from 'zod/v4/core'\nimport type { MessageKeys } from '../i18n.types'\nimport type { ErrorMapContext } from './validation.types'\n\n/**\n * Type guards for narrowing Zod v4 issue types\n */\nfunction isInvalidType(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidType> {\n return issue.code === 'invalid_type'\n}\n\nfunction isTooBig(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueTooBig> {\n return issue.code === 'too_big'\n}\n\nfunction isTooSmall(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueTooSmall> {\n return issue.code === 'too_small'\n}\n\nfunction isInvalidFormat(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidStringFormat> {\n return issue.code === 'invalid_format'\n}\n\nfunction isNotMultipleOf(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueNotMultipleOf> {\n return issue.code === 'not_multiple_of'\n}\n\nfunction isUnrecognizedKeys(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueUnrecognizedKeys> {\n return issue.code === 'unrecognized_keys'\n}\n\nfunction isInvalidUnion(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidUnion> {\n return issue.code === 'invalid_union'\n}\n\nfunction isInvalidKey(issue: $ZodRawIssue): issue is $ZodRawIssue<$ZodIssueInvalidKey> {\n return issue.code === 'invalid_key'\n}\n\n/**\n * Maps Zod issue codes to zodI18n message keys\n * Adapted for Zod v4's simpler issue code system\n */\nfunction getMessageKey(issue: $ZodRawIssue): MessageKeys {\n if (isInvalidType(issue)) {\n if (issue.input === undefined) {\n return 'zodI18n.errors.required'\n }\n return 'zodI18n.errors.invalid_type'\n }\n\n if (isTooSmall(issue)) {\n const typeKey = issue.origin || 'string'\n const exactKey = issue.exact\n ? 'exact'\n : issue.inclusive\n ? 'inclusive'\n : 'not_inclusive'\n return `zodI18n.errors.too_small.${typeKey}.${exactKey}` as MessageKeys\n }\n\n if (isTooBig(issue)) {\n const typeKey = issue.origin || 'string'\n const exactKey = issue.exact\n ? 'exact'\n : issue.inclusive\n ? 'inclusive'\n : 'not_inclusive'\n return `zodI18n.errors.too_big.${typeKey}.${exactKey}` as MessageKeys\n }\n\n if (isInvalidFormat(issue)) {\n // Map v4's format to v3-style validation keys\n return `zodI18n.errors.invalid_string.${issue.format}` as MessageKeys\n }\n\n if (isNotMultipleOf(issue)) {\n return 'zodI18n.errors.not_multiple_of'\n }\n\n if (isUnrecognizedKeys(issue)) {\n return 'zodI18n.errors.unrecognized_keys'\n }\n\n if (isInvalidUnion(issue)) {\n return 'zodI18n.errors.invalid_union'\n }\n\n if (isInvalidKey(issue)) {\n // v4: Replaces invalid_enum_value, invalid_literal\n return 'zodI18n.errors.invalid_enum_value'\n }\n\n // invalid_element, invalid_value, or unknown codes\n return 'zodI18n.errors.custom.default'\n}\n\n/**\n * Extracts interpolation parameters from Zod issue\n * Uses proper type narrowing for v4\n */\nfunction getMessageParams(issue: $ZodRawIssue): Record<string, unknown> {\n const params: Record<string, unknown> = {}\n\n if (isInvalidType(issue)) {\n params.expected = issue.expected\n params.received = String(issue.input)\n return params\n }\n\n if (isUnrecognizedKeys(issue)) {\n params.keys = issue.keys.join(', ')\n return params\n }\n\n if (isInvalidKey(issue)) {\n // v4: For enums and records\n // Since v4 doesn't have options field, we'll use generic message\n return params\n }\n\n if (isInvalidFormat(issue)) {\n params.validation = issue.format\n\n // Check for specific string format issues with additional fields\n if ('prefix' in issue) {\n params.startsWith = (issue as { prefix?: string }).prefix\n }\n if ('suffix' in issue) {\n params.endsWith = (issue as { suffix?: string }).suffix\n }\n if ('includes' in issue) {\n params.includes = (issue as { includes?: string }).includes\n }\n if (issue.pattern) {\n params.pattern = issue.pattern\n }\n\n return params\n }\n\n if (isTooSmall(issue)) {\n params.minimum = issue.minimum\n params.type = issue.origin\n if (issue.origin === 'date') {\n params.minimum = new Date(Number(issue.minimum)).toLocaleDateString()\n }\n return params\n }\n\n if (isTooBig(issue)) {\n params.maximum = issue.maximum\n params.type = issue.origin\n if (issue.origin === 'date') {\n params.maximum = new Date(Number(issue.maximum)).toLocaleDateString()\n }\n return params\n }\n\n if (isNotMultipleOf(issue)) {\n params.multipleOf = issue.divisor\n return params\n }\n\n return params\n}\n\n/**\n * Creates a Zod error map that uses i18n for translation\n * Uses Zod v4 native $ZodErrorMap signature (no ctx parameter)\n */\nexport function createI18nErrorMap(getContext: () => ErrorMapContext | undefined): $ZodErrorMap {\n return (issue: $ZodRawIssue): { message: string } => {\n // Get message key and params for this issue\n const messageKey = getMessageKey(issue)\n const messageParams = getMessageParams(issue)\n\n // Get translation context\n const context = getContext()\n\n if (!context) {\n // Fallback: Use English messages directly\n // This handles config validation at startup, tests, etc.\n return { message: 'Invalid input' }\n }\n\n // Normal flow: Use context-aware i18n (respects user locale)\n return {\n message: context.t(messageKey, messageParams),\n }\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { ErrorMapContext } from './validation.types'\nimport { createI18nErrorMap } from './validation.error-map'\n\n/**\n * AsyncLocalStorage for storing request-scoped ErrorMapContext\n * Allows error map to access I18nService without passing through function calls\n */\nexport const errorMapContextStorage = new AsyncLocalStorage<ErrorMapContext>()\n\n/**\n * Gets the current error map context from AsyncLocalStorage\n */\nfunction getErrorMapContext(): ErrorMapContext | undefined {\n return errorMapContextStorage.getStore()\n}\n\n/**\n * Backend error map that accesses I18nService from AsyncLocalStorage\n * Must be initialized in router middleware after locale detection\n */\nexport const backendErrorMap = createI18nErrorMap(getErrorMapContext)\n\n/**\n * Runs a function within an error map context\n * Used by router middleware to provide I18nService to validation\n *\n * @example\n * ```typescript\n * router.use('*', async (c, next) => {\n * const i18nService = c.get('i18nService')\n * const locale = c.get('locale')\n *\n * return runWithErrorMapContext(\n * {\n * t: (key, params) => i18nService.t(key, params),\n * locale,\n * },\n * () => next()\n * )\n * })\n * ```\n */\nexport function runWithErrorMapContext<T>(\n context: ErrorMapContext,\n fn: () => T\n): T {\n return errorMapContextStorage.run(context, fn)\n}\n","import type { MessageKeys } from '../i18n.types'\nimport { errorMapContextStorage } from './validation.context'\n\n/**\n * Type-safe helper for creating custom Zod error messages with i18n support (Backend)\n *\n * Usage with .refine():\n * ```typescript\n * const schema = z.string().refine(\n * (val) => val.length > 5,\n * withI18n('validation.minLength', { min: 5 })\n * )\n * ```\n *\n * Usage with built-in validators:\n * ```typescript\n * const schema = z.string().min(5, withI18n('validation.minLength', { min: 5 }))\n * const schema = z.string().email(withI18n('validation.email'))\n * ```\n *\n * Note: This is the backend version using AsyncLocalStorage.\n * For frontend, use withI18nFrontend from the frontend validation module\n *\n * @param key - Message key from shared i18n messages (type-safe via MessageKeys)\n * @param params - Optional interpolation parameters for the message\n * @returns Zod error configuration object with translated message\n */\nexport function withI18n(\n key: MessageKeys,\n params?: Record<string, unknown>\n): { error: () => string } {\n return {\n error: () => {\n // Get i18n context from AsyncLocalStorage (backend)\n // This is set by the router middleware before validation\n const context = errorMapContextStorage.getStore()\n\n // Translate using context if available, otherwise fallback to generic message\n const message = context\n ? context.t(key, params as Record<string, string | number> | undefined)\n : 'Invalid input'\n\n return message\n },\n }\n}\n","// Consolidated zod - single source from @hono/zod-openapi (superset of zod)\nexport { OpenAPIHono, z } from '@hono/zod-openapi'\nexport type * from 'zod'\nexport { ZodError } from 'zod'\n\n// OpenAPI utilities\nexport * from '@hono/zod-openapi'\nexport type { OpenAPIObject, PathItemObject } from 'openapi3-ts/oas30'\n\n// Helpers\nexport { withI18n } from './with-i18n'\n\n// Backend utilities\nexport { backendErrorMap, runWithErrorMapContext } from './validation.context'\n\n// Types\nexport type { ErrorMapContext, I18nErrorMetadata, LocaleProvider, ZodCustomIssue } from './validation.types'\n\n"],"mappings":";;;;;;;;AAkBA,SAAS,cAAc,OAAkE;AACvF,QAAO,MAAM,SAAS;;AAGxB,SAAS,SAAS,OAA6D;AAC7E,QAAO,MAAM,SAAS;;AAGxB,SAAS,WAAW,OAA+D;AACjF,QAAO,MAAM,SAAS;;AAGxB,SAAS,gBAAgB,OAA0E;AACjG,QAAO,MAAM,SAAS;;AAGxB,SAAS,gBAAgB,OAAoE;AAC3F,QAAO,MAAM,SAAS;;AAGxB,SAAS,mBAAmB,OAAuE;AACjG,QAAO,MAAM,SAAS;;AAGxB,SAAS,eAAe,OAAmE;AACzF,QAAO,MAAM,SAAS;;AAGxB,SAAS,aAAa,OAAiE;AACrF,QAAO,MAAM,SAAS;;;;;;AAOxB,SAAS,cAAc,OAAkC;AACvD,KAAI,cAAc,MAAM,EAAE;AACxB,MAAI,MAAM,UAAU,KAAA,EAClB,QAAO;AAET,SAAO;;AAGT,KAAI,WAAW,MAAM,CAOnB,QAAO,4BANS,MAAM,UAAU,SAMW,GAL1B,MAAM,QACnB,UACA,MAAM,YACJ,cACA;AAIR,KAAI,SAAS,MAAM,CAOjB,QAAO,0BANS,MAAM,UAAU,SAMS,GALxB,MAAM,QACnB,UACA,MAAM,YACJ,cACA;AAIR,KAAI,gBAAgB,MAAM,CAExB,QAAO,iCAAiC,MAAM;AAGhD,KAAI,gBAAgB,MAAM,CACxB,QAAO;AAGT,KAAI,mBAAmB,MAAM,CAC3B,QAAO;AAGT,KAAI,eAAe,MAAM,CACvB,QAAO;AAGT,KAAI,aAAa,MAAM,CAErB,QAAO;AAIT,QAAO;;;;;;AAOT,SAAS,iBAAiB,OAA8C;CACtE,MAAM,SAAkC,EAAE;AAE1C,KAAI,cAAc,MAAM,EAAE;AACxB,SAAO,WAAW,MAAM;AACxB,SAAO,WAAW,OAAO,MAAM,MAAM;AACrC,SAAO;;AAGT,KAAI,mBAAmB,MAAM,EAAE;AAC7B,SAAO,OAAO,MAAM,KAAK,KAAK,KAAK;AACnC,SAAO;;AAGT,KAAI,aAAa,MAAM,CAGrB,QAAO;AAGT,KAAI,gBAAgB,MAAM,EAAE;AAC1B,SAAO,aAAa,MAAM;AAG1B,MAAI,YAAY,MACd,QAAO,aAAc,MAA8B;AAErD,MAAI,YAAY,MACd,QAAO,WAAY,MAA8B;AAEnD,MAAI,cAAc,MAChB,QAAO,WAAY,MAAgC;AAErD,MAAI,MAAM,QACR,QAAO,UAAU,MAAM;AAGzB,SAAO;;AAGT,KAAI,WAAW,MAAM,EAAE;AACrB,SAAO,UAAU,MAAM;AACvB,SAAO,OAAO,MAAM;AACpB,MAAI,MAAM,WAAW,OACnB,QAAO,UAAU,IAAI,KAAK,OAAO,MAAM,QAAQ,CAAC,CAAC,oBAAoB;AAEvE,SAAO;;AAGT,KAAI,SAAS,MAAM,EAAE;AACnB,SAAO,UAAU,MAAM;AACvB,SAAO,OAAO,MAAM;AACpB,MAAI,MAAM,WAAW,OACnB,QAAO,UAAU,IAAI,KAAK,OAAO,MAAM,QAAQ,CAAC,CAAC,oBAAoB;AAEvE,SAAO;;AAGT,KAAI,gBAAgB,MAAM,EAAE;AAC1B,SAAO,aAAa,MAAM;AAC1B,SAAO;;AAGT,QAAO;;;;;;AAOT,SAAgB,mBAAmB,YAA6D;AAC9F,SAAQ,UAA6C;EAEnD,MAAM,aAAa,cAAc,MAAM;EACvC,MAAM,gBAAgB,iBAAiB,MAAM;EAG7C,MAAM,UAAU,YAAY;AAE5B,MAAI,CAAC,QAGH,QAAO,EAAE,SAAS,iBAAiB;AAIrC,SAAO,EACL,SAAS,QAAQ,EAAE,YAAY,cAAc,EAC9C;;;;;;;;;AChML,MAAa,yBAAyB,IAAI,mBAAoC;;;;AAK9E,SAAS,qBAAkD;AACzD,QAAO,uBAAuB,UAAU;;;;;;AAO1C,MAAa,kBAAkB,mBAAmB,mBAAmB;;;;;;;;;;;;;;;;;;;;;AAsBrE,SAAgB,uBACd,SACA,IACG;AACH,QAAO,uBAAuB,IAAI,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBhD,SAAgB,SACd,KACA,QACyB;AACzB,QAAO,EACL,aAAa;EAGX,MAAM,UAAU,uBAAuB,UAAU;AAOjD,SAJgB,UACZ,QAAQ,EAAE,KAAK,OAAsD,GACrE;IAIP"}
@@ -1,5 +1,5 @@
1
- import { Dt as ControllerOptions, Et as RouterContext, Pt as RouterEnv, Tt as ContextQueryResult, s as ApplicationError } from "../index-BFCxSp_f.mjs";
2
- import { t as Constructor } from "../types-DahElfUw.mjs";
1
+ import { B as ContextQueryResult, Bn as ControllerOptions, V as RouterContext, Xn as RouterEnv, d as ApplicationError } from "../index-DPFqRs8L.mjs";
2
+ import { t as Constructor } from "../types-DIWemRad.mjs";
3
3
  import { Context } from "hono";
4
4
  import { WSContext, WSContext as WSContext$1, WSEvents, WSMessageReceive, WSReadyState, WSReadyState as WSReadyState$1 } from "hono/ws";
5
5
 
@@ -8,7 +8,7 @@ import { WSContext, WSContext as WSContext$1, WSEvents, WSMessageReceive, WSRead
8
8
  * Gateway options for @Gateway() decorator
9
9
  * Subset of ControllerOptions relevant to WebSocket gateways (no OpenAPI-specific fields)
10
10
  */
11
- type GatewayOptions = Pick<ControllerOptions, 'version'>;
11
+ type GatewayOptions = Pick<ControllerOptions, 'version' | 'name' | 'domain'>;
12
12
  //#endregion
13
13
  //#region src/websocket/decorators/gateway.decorator.d.ts
14
14
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/websocket/types.ts","../../src/websocket/decorators/gateway.decorator.ts","../../src/websocket/decorators/ws-event.decorator.ts","../../src/websocket/errors/websocket-body-not-available.error.ts","../../src/websocket/errors/websocket-duplicate-event-handler.error.ts","../../src/websocket/gateway-context.ts"],"mappings":";;;;;;;;;;KAMY,cAAA,GAAiB,IAAA,CAAK,iBAAA;;;;;;;;AAAlC;;;;;;;;AC+BA;;;;;;;;;;;;;;;iBAAgB,OAAA,CAAQ,KAAA,UAAe,OAAA,GAAU,cAAA,cACpB,WAAA,EAAa,MAAA,EAAQ,CAAA,KAAC,CAAA;;;;AAiBnD;;;iBAAgB,SAAA,CAAU,MAAA;;;;;;;;;ADjD1B;;;;;;;;iBE4BgB,SAAA,CAAA,GAAa,eAAA;;;;;;;;;;;;;;;iBAsBb,OAAA,CAAA,GAAW,eAAA;;;;ADD3B;;;;;;;;ACrBA;;;iBA0CgB,OAAA,CAAA,GAAW,eAAA;;AApB3B;;iBA6BgB,oBAAA,CAAqB,MAAA,EAAQ,WAAA;;;AAT7C;iBAgBgB,kBAAA,CAAmB,MAAA,EAAQ,WAAA;;;;iBAO3B,kBAAA,CAAmB,MAAA,EAAQ,WAAA;;;cCjG9B,8BAAA,SAAuC,gBAAA;EAAA,WAAA,CAAA;AAAA;;;cCAvC,mCAAA,SAA4C,gBAAA;cAC3C,SAAA,UAAmB,cAAA;AAAA;;;;;AJGjC;;;;;;;;AC+BA;;;;;;;cIba,cAAA,SAAuB,aAAA;EAAA,SACiB,EAAA,EAAI,WAAA;cAA3C,CAAA,EAAG,OAAA,CAAQ,SAAA,GAA4B,EAAA,EAAI,WAAA;EJYR;EIP/C,IAAA,CAAK,IAAA,WAAe,WAAA,GAAc,UAAA,CAAW,WAAA;EJQ5B;EIHjB,KAAA,CAAM,IAAA,WAAe,MAAA;EJG2B;EAAA,IIE5C,UAAA,CAAA,GAAc,cAAA;EJF+B;;;AAiBnD;;EINW,KAAA,CAAM,GAAA;EJMS;;;;;EIGf,KAAA,WAAgB,MAAA,oFAAA,CAA2F,GAAA,GAAM,CAAA,GAAI,kBAAA,CAAmB,CAAA,EAAG,CAAA;EHxB7H;;;;AAsBzB;EGcW,IAAA,GAAA,CAAA,GAAW,OAAA,CAAQ,CAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/websocket/types.ts","../../src/websocket/decorators/gateway.decorator.ts","../../src/websocket/decorators/ws-event.decorator.ts","../../src/websocket/errors/websocket-body-not-available.error.ts","../../src/websocket/errors/websocket-duplicate-event-handler.error.ts","../../src/websocket/gateway-context.ts"],"mappings":";;;;;;;;;;KAMY,cAAA,GAAiB,IAAA,CAAK,iBAAA;;;;;;;AAAlC;;;;;;;;AC6BA;;;;;;;;;;;;;;;;iBAAgB,OAAA,CAAQ,KAAA,UAAe,OAAA,GAAU,cAAA,cACpB,WAAA,EAAa,MAAA,EAAQ,CAAA,KAAC,CAAA;;;AAanD;;;;iBAAgB,SAAA,CAAU,MAAA;;;;;;;;AD3C1B;;;;;;;;AC6BA;iBCDgB,SAAA,CAAA,GAAa,eAAA;;;;;;;;;;;;;;;iBAsBb,OAAA,CAAA,GAAW,eAAA;;;ADP3B;;;;;;;;ACfA;;;;iBA0CgB,OAAA,CAAA,GAAW,eAAA;AApB3B;;;AAAA,iBA6BgB,oBAAA,CAAqB,MAAA,EAAQ,WAAA;;AAT7C;;iBAgBgB,kBAAA,CAAmB,MAAA,EAAQ,WAAA;;;AAP3C;iBAcgB,kBAAA,CAAmB,MAAA,EAAQ,WAAA;;;cCjG9B,8BAAA,SAAuC,gBAAA;EAAA,WAAA,CAAA;AAAA;;;cCAvC,mCAAA,SAA4C,gBAAA;cAC3C,SAAA,UAAmB,cAAA;AAAA;;;;AJGjC;;;;;;;;AC6BA;;;;;;;;cIXa,cAAA,SAAuB,aAAA;EAAA,SACiB,EAAA,EAAI,WAAA;cAA3C,CAAA,EAAG,OAAA,CAAQ,SAAA,GAA4B,EAAA,EAAI,WAAA;EJUlB;EILrC,IAAA,CAAK,IAAA,WAAe,WAAA,GAAc,UAAA,CAAW,WAAA;EJMlB;EID3B,KAAA,CAAM,IAAA,WAAe,MAAA;EJCmB;EAAA,IIIpC,UAAA,CAAA,GAAc,cAAA;EJJ+B;;AAanD;;;EIAW,KAAA,CAAM,GAAA;EJAuB;;;;ACfxC;EGwBW,KAAA,WAAgB,MAAA,oFAAA,CAA2F,GAAA,GAAM,CAAA,GAAI,kBAAA,CAAmB,CAAA,EAAG,CAAA;;;;AHFtJ;;EGcW,IAAA,GAAA,CAAA,GAAW,OAAA,CAAQ,CAAA;AAAA"}
@@ -1,5 +1,2 @@
1
- import "../errors-DSKapqD8.mjs";
2
- import "../logger-CGT91VY6.mjs";
3
- import "../router-context-D9R1v2Ac.mjs";
4
- import { a as OnMessage, c as getWsOnMessageMethod, d as isGateway, i as OnError, l as WebSocketDuplicateEventHandlerError, n as WebSocketBodyNotAvailableError, o as getWsOnCloseMethod, r as OnClose, s as getWsOnErrorMethod, t as GatewayContext, u as Gateway } from "../gateway-context-CNOLkLUC.mjs";
1
+ import { a as OnMessage, c as getWsOnMessageMethod, d as isGateway, i as OnError, l as WebSocketDuplicateEventHandlerError, n as WebSocketBodyNotAvailableError, o as getWsOnCloseMethod, r as OnClose, s as getWsOnErrorMethod, t as GatewayContext, u as Gateway } from "../gateway-context-cqZ8wMoi.mjs";
5
2
  export { Gateway, GatewayContext, OnClose, OnError, OnMessage, WebSocketBodyNotAvailableError, WebSocketDuplicateEventHandlerError, getWsOnCloseMethod, getWsOnErrorMethod, getWsOnMessageMethod, isGateway };
@@ -1,4 +1,5 @@
1
- import { Ut as StratalEnv, en as Container } from "../index-BFCxSp_f.mjs";
1
+ import { Cr as Container } from "../index-DPFqRs8L.mjs";
2
+ import { t as StratalEnv } from "../env-CamWD-U1.mjs";
2
3
  import { DurableObject, WorkerEntrypoint, WorkflowEntrypoint } from "cloudflare:workers";
3
4
 
4
5
  //#region src/workers/run-in-scope.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/workers/run-in-scope.ts","../../src/workers/stratal-durable-object.ts","../../src/workers/stratal-worker-entrypoint.ts","../../src/workers/stratal-workflow.ts"],"mappings":";;;;;;;;AASA;;iBAAsB,UAAA,GAAA,CACpB,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;;;;;AAFX;;;;;;;;;;;;;;;;;;;uBCkBsB,oBAAA,aACR,UAAA,GAAa,UAAA,UACjB,aAAA,CAAc,GAAA;EAAA,UACN,UAAA,GAAA,CACd,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;AAAA;;;;;ADvBb;;;;;;;;;;;;;;;;;;uBEgBsB,uBAAA,aACR,UAAA,GAAa,UAAA,UACjB,gBAAA,CAAiB,GAAA;EAAA,UACf,UAAA,GAAA,CACR,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;AAAA;;;;;AFrBb;;;;;;;;;;;;;;;;;;uBGgBsB,eAAA,aACR,UAAA,GAAa,UAAA,4BAEjB,kBAAA,CAAmB,GAAA,EAAK,MAAA;EAAA,UACtB,UAAA,GAAA,CACR,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/workers/run-in-scope.ts","../../src/workers/stratal-durable-object.ts","../../src/workers/stratal-worker-entrypoint.ts","../../src/workers/stratal-workflow.ts"],"mappings":";;;;;;;;;AASA;;iBAAsB,UAAA,GAAA,CACpB,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;;;;;AAFX;;;;;;;;;;;;;;;;;;;uBCkBsB,oBAAA,aACR,UAAA,GAAa,UAAA,UACjB,aAAA,CAAc,GAAA;EAAA,UACN,UAAA,GAAA,CACd,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;AAAA;;;;;ADvBb;;;;;;;;;;;;;;;;;;uBEgBsB,uBAAA,aACR,UAAA,GAAa,UAAA,UACjB,gBAAA,CAAiB,GAAA;EAAA,UACf,UAAA,GAAA,CACR,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;AAAA;;;;;AFrBb;;;;;;;;;;;;;;;;;;uBGgBsB,eAAA,aACR,UAAA,GAAa,UAAA,4BAEjB,kBAAA,CAAmB,GAAA,EAAK,MAAA;EAAA,UACtB,UAAA,GAAA,CACR,QAAA,GAAW,SAAA,EAAW,SAAA,KAAc,CAAA,GAAI,OAAA,CAAQ,CAAA,IAC/C,OAAA,CAAQ,CAAA;AAAA"}
@@ -1,23 +1,5 @@
1
- import "../errors-DSKapqD8.mjs";
2
- import { g as DI_TOKENS } from "../logger-CGT91VY6.mjs";
3
- import "../module-tUtyVJ5E.mjs";
4
- import "../events-CvUSgEuN.mjs";
5
- import "../middleware-Bl-b5pkt.mjs";
6
- import "../router-context-D9R1v2Ac.mjs";
7
- import "../colors-Y7WIFXs7.mjs";
8
- import "../command-B1CPgsrU.mjs";
9
- import "../is-command-DJVI6wEJ.mjs";
10
- import "../is-seeder-D5MIEcdz.mjs";
11
- import "../cron-manager-CFBamKKk.mjs";
12
- import "../validation-DQTC259A.mjs";
13
- import "../i18n.module-Dn9SrFdS.mjs";
14
- import "../openapi-tools.service-B3TxYKoQ.mjs";
15
- import "../guards-DUk_Kzst.mjs";
16
- import "../gateway-context-CNOLkLUC.mjs";
17
- import "../quarry-registry-B2rkO-JS.mjs";
18
- import "../queue.module-BtI8f4Jo.mjs";
19
- import "../seeder-R7RXJC35.mjs";
20
- import { t as Stratal } from "../stratal-D5smIU1y.mjs";
1
+ import { f as DI_TOKENS } from "../logger-V6Ms3QnQ.mjs";
2
+ import { t as Stratal } from "../stratal-BCiwCFN9.mjs";
21
3
  import { DurableObject, WorkerEntrypoint, WorkflowEntrypoint } from "cloudflare:workers";
22
4
  //#region src/workers/run-in-scope.ts
23
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/workers/run-in-scope.ts","../../src/workers/stratal-durable-object.ts","../../src/workers/stratal-worker-entrypoint.ts","../../src/workers/stratal-workflow.ts"],"sourcesContent":["import type { Container } from '../di/container'\nimport { Stratal } from '../stratal'\n\n/**\n * Shared helper that creates a request-scoped DI container by accessing the\n * Stratal Application via the static singleton.\n *\n * Works with Durable Objects, Workflows, and WorkerEntrypoints.\n */\nexport async function runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n): Promise<T> {\n const app = await Stratal.resolveApplication()\n const mockCtx = app.createMockRouterContext('en')\n return app.container.runInRequestScope(mockCtx, callback)\n}\n","import { DurableObject } from 'cloudflare:workers'\nimport type { Container } from '../di/container'\nimport { DI_TOKENS } from '../di/tokens'\nimport type { StratalEnv } from '../env'\nimport { runInScope } from './run-in-scope'\n\n/**\n * Base class for Durable Objects with full DI access.\n *\n * Extends Cloudflare's `DurableObject` and provides a `runInScope()` helper\n * that creates a request-scoped container with `DurableObjectState` and\n * `DurableObjectId` tokens registered.\n *\n * @example\n * ```typescript\n * import { StratalDurableObject } from 'stratal/workers'\n *\n * export class Counter extends StratalDurableObject {\n * async increment() {\n * return this.runInScope(async (container) => {\n * const svc = container.resolve(CounterService)\n * return svc.increment()\n * })\n * }\n * }\n * ```\n */\nexport abstract class StratalDurableObject<\n Env extends StratalEnv = StratalEnv\n> extends DurableObject<Env> {\n protected async runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n ): Promise<T> {\n return runInScope(async (requestContainer) => {\n requestContainer.registerValue(DI_TOKENS.DurableObjectState, this.ctx)\n requestContainer.registerValue(DI_TOKENS.DurableObjectId, this.ctx.id)\n return callback(requestContainer)\n })\n }\n}\n","import { WorkerEntrypoint } from 'cloudflare:workers'\nimport type { Container } from '../di/container'\nimport type { StratalEnv } from '../env'\nimport { runInScope } from './run-in-scope'\n\n/**\n * Base class for Cloudflare WorkerEntrypoints (Service Bindings / RPC) with full DI access.\n *\n * Extends Cloudflare's `WorkerEntrypoint` and provides a `runInScope()` helper\n * that creates a request-scoped DI container.\n *\n * @example\n * ```typescript\n * import { StratalWorkerEntrypoint } from 'stratal/workers'\n *\n * export class AuthRpc extends StratalWorkerEntrypoint {\n * async verifyToken(token: string) {\n * return this.runInScope(async (container) => {\n * const auth = container.resolve(AuthService)\n * return auth.verify(token)\n * })\n * }\n * }\n * ```\n */\nexport abstract class StratalWorkerEntrypoint<\n Env extends StratalEnv = StratalEnv\n> extends WorkerEntrypoint<Env> {\n protected runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n ): Promise<T> {\n return runInScope(callback)\n }\n}\n","import { WorkflowEntrypoint } from 'cloudflare:workers'\nimport type { Container } from '../di/container'\nimport type { StratalEnv } from '../env'\nimport { runInScope } from './run-in-scope'\n\n/**\n * Base class for Cloudflare Workflows with full DI access.\n *\n * Extends Cloudflare's `WorkflowEntrypoint` and provides a `runInScope()` helper\n * that creates a request-scoped DI container.\n *\n * @example\n * ```typescript\n * import { StratalWorkflow } from 'stratal/workers'\n *\n * export class MyWorkflow extends StratalWorkflow<Env, { userId: string }> {\n * async run(event: WorkflowEvent<{ userId: string }>, step: WorkflowStep) {\n * await this.runInScope(async (container) => {\n * const svc = container.resolve(UserService)\n * await svc.process(event.payload.userId)\n * })\n * }\n * }\n * ```\n */\nexport abstract class StratalWorkflow<\n Env extends StratalEnv = StratalEnv,\n Params = unknown\n> extends WorkflowEntrypoint<Env, Params> {\n protected runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n ): Promise<T> {\n return runInScope(callback)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,eAAsB,WACpB,UACY;CACZ,MAAM,MAAM,MAAM,QAAQ,oBAAoB;CAC9C,MAAM,UAAU,IAAI,wBAAwB,KAAK;AACjD,QAAO,IAAI,UAAU,kBAAkB,SAAS,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;ACa3D,IAAsB,uBAAtB,cAEU,cAAmB;CAC3B,MAAgB,WACd,UACY;AACZ,SAAO,WAAW,OAAO,qBAAqB;AAC5C,oBAAiB,cAAc,UAAU,oBAAoB,KAAK,IAAI;AACtE,oBAAiB,cAAc,UAAU,iBAAiB,KAAK,IAAI,GAAG;AACtE,UAAO,SAAS,iBAAiB;IACjC;;;;;;;;;;;;;;;;;;;;;;;;;ACZN,IAAsB,0BAAtB,cAEU,iBAAsB;CAC9B,WACE,UACY;AACZ,SAAO,WAAW,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;ACN/B,IAAsB,kBAAtB,cAGU,mBAAgC;CACxC,WACE,UACY;AACZ,SAAO,WAAW,SAAS"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/workers/run-in-scope.ts","../../src/workers/stratal-durable-object.ts","../../src/workers/stratal-worker-entrypoint.ts","../../src/workers/stratal-workflow.ts"],"sourcesContent":["import type { Container } from '../di/container'\nimport { Stratal } from '../stratal'\n\n/**\n * Shared helper that creates a request-scoped DI container by accessing the\n * Stratal Application via the static singleton.\n *\n * Works with Durable Objects, Workflows, and WorkerEntrypoints.\n */\nexport async function runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n): Promise<T> {\n const app = await Stratal.resolveApplication()\n const mockCtx = app.createMockRouterContext('en')\n return app.container.runInRequestScope(mockCtx, callback)\n}\n","import { DurableObject } from 'cloudflare:workers'\nimport type { Container } from '../di/container'\nimport { DI_TOKENS } from '../di/tokens'\nimport type { StratalEnv } from '../env'\nimport { runInScope } from './run-in-scope'\n\n/**\n * Base class for Durable Objects with full DI access.\n *\n * Extends Cloudflare's `DurableObject` and provides a `runInScope()` helper\n * that creates a request-scoped container with `DurableObjectState` and\n * `DurableObjectId` tokens registered.\n *\n * @example\n * ```typescript\n * import { StratalDurableObject } from 'stratal/workers'\n *\n * export class Counter extends StratalDurableObject {\n * async increment() {\n * return this.runInScope(async (container) => {\n * const svc = container.resolve(CounterService)\n * return svc.increment()\n * })\n * }\n * }\n * ```\n */\nexport abstract class StratalDurableObject<\n Env extends StratalEnv = StratalEnv\n> extends DurableObject<Env> {\n protected async runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n ): Promise<T> {\n return runInScope(async (requestContainer) => {\n requestContainer.registerValue(DI_TOKENS.DurableObjectState, this.ctx)\n requestContainer.registerValue(DI_TOKENS.DurableObjectId, this.ctx.id)\n return callback(requestContainer)\n })\n }\n}\n","import { WorkerEntrypoint } from 'cloudflare:workers'\nimport type { Container } from '../di/container'\nimport type { StratalEnv } from '../env'\nimport { runInScope } from './run-in-scope'\n\n/**\n * Base class for Cloudflare WorkerEntrypoints (Service Bindings / RPC) with full DI access.\n *\n * Extends Cloudflare's `WorkerEntrypoint` and provides a `runInScope()` helper\n * that creates a request-scoped DI container.\n *\n * @example\n * ```typescript\n * import { StratalWorkerEntrypoint } from 'stratal/workers'\n *\n * export class AuthRpc extends StratalWorkerEntrypoint {\n * async verifyToken(token: string) {\n * return this.runInScope(async (container) => {\n * const auth = container.resolve(AuthService)\n * return auth.verify(token)\n * })\n * }\n * }\n * ```\n */\nexport abstract class StratalWorkerEntrypoint<\n Env extends StratalEnv = StratalEnv\n> extends WorkerEntrypoint<Env> {\n protected runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n ): Promise<T> {\n return runInScope(callback)\n }\n}\n","import { WorkflowEntrypoint } from 'cloudflare:workers'\nimport type { Container } from '../di/container'\nimport type { StratalEnv } from '../env'\nimport { runInScope } from './run-in-scope'\n\n/**\n * Base class for Cloudflare Workflows with full DI access.\n *\n * Extends Cloudflare's `WorkflowEntrypoint` and provides a `runInScope()` helper\n * that creates a request-scoped DI container.\n *\n * @example\n * ```typescript\n * import { StratalWorkflow } from 'stratal/workers'\n *\n * export class MyWorkflow extends StratalWorkflow<Env, { userId: string }> {\n * async run(event: WorkflowEvent<{ userId: string }>, step: WorkflowStep) {\n * await this.runInScope(async (container) => {\n * const svc = container.resolve(UserService)\n * await svc.process(event.payload.userId)\n * })\n * }\n * }\n * ```\n */\nexport abstract class StratalWorkflow<\n Env extends StratalEnv = StratalEnv,\n Params = unknown\n> extends WorkflowEntrypoint<Env, Params> {\n protected runInScope<T>(\n callback: (container: Container) => T | Promise<T>\n ): Promise<T> {\n return runInScope(callback)\n }\n}\n"],"mappings":";;;;;;;;;;AASA,eAAsB,WACpB,UACY;CACZ,MAAM,MAAM,MAAM,QAAQ,oBAAoB;CAC9C,MAAM,UAAU,IAAI,wBAAwB,KAAK;AACjD,QAAO,IAAI,UAAU,kBAAkB,SAAS,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;ACa3D,IAAsB,uBAAtB,cAEU,cAAmB;CAC3B,MAAgB,WACd,UACY;AACZ,SAAO,WAAW,OAAO,qBAAqB;AAC5C,oBAAiB,cAAc,UAAU,oBAAoB,KAAK,IAAI;AACtE,oBAAiB,cAAc,UAAU,iBAAiB,KAAK,IAAI,GAAG;AACtE,UAAO,SAAS,iBAAiB;IACjC;;;;;;;;;;;;;;;;;;;;;;;;;ACZN,IAAsB,0BAAtB,cAEU,iBAAsB;CAC9B,WACE,UACY;AACZ,SAAO,WAAW,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;ACN/B,IAAsB,kBAAtB,cAGU,mBAAgC;CACxC,WACE,UACY;AACZ,SAAO,WAAW,SAAS"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stratal",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "A modular Cloudflare Workers framework with dependency injection, queue-based events, and type-safe configuration",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,7 +34,8 @@
34
34
  "provenance": true
35
35
  },
36
36
  "bin": {
37
- "quarry": "./dist/bin/quarry.mjs"
37
+ "quarry": "./dist/bin/quarry.mjs",
38
+ "stratal": "./dist/bin/quarry.mjs"
38
39
  },
39
40
  "files": [
40
41
  "dist",
@@ -85,13 +86,17 @@
85
86
  "types": "./dist/i18n/messages/en/index.d.mts",
86
87
  "import": "./dist/i18n/messages/en/index.mjs"
87
88
  },
89
+ "./i18n/utils": {
90
+ "types": "./dist/i18n/utils/index.d.mts",
91
+ "import": "./dist/i18n/utils/index.mjs"
92
+ },
88
93
  "./logger": {
89
94
  "types": "./dist/logger/index.d.mts",
90
95
  "import": "./dist/logger/index.mjs"
91
96
  },
92
- "./middleware": {
93
- "types": "./dist/middleware/index.d.mts",
94
- "import": "./dist/middleware/index.mjs"
97
+ "./macroable": {
98
+ "types": "./dist/macroable/index.d.mts",
99
+ "import": "./dist/macroable/index.mjs"
95
100
  },
96
101
  "./module": {
97
102
  "types": "./dist/module/index.d.mts",
@@ -150,44 +155,32 @@
150
155
  "test:watch": "vitest",
151
156
  "test:integration": "vitest run --project workerd",
152
157
  "test:coverage": "vitest run --coverage",
153
- "lint": "npx eslint .",
154
- "lint:fix": "npx eslint --fix ."
158
+ "lint": "npx oxlint .",
159
+ "lint:fix": "npx oxlint --fix ."
155
160
  },
156
161
  "dependencies": {
157
162
  "@hono/swagger-ui": "^0.6.1",
158
- "@hono/zod-openapi": "^1.2.3",
159
- "@intlify/core-base": "^11.3.0",
160
- "@intlify/message-compiler": "^11.3.0",
161
- "@modelcontextprotocol/sdk": "^1.27.1",
163
+ "@hono/zod-openapi": "^1.3.0",
164
+ "@intlify/core-base": "^11.4.0",
165
+ "@intlify/message-compiler": "^11.4.0",
166
+ "@modelcontextprotocol/sdk": "^1.29.0",
162
167
  "@swc-node/register": "^1.11.1",
163
- "@swc/core": "^1.15.18",
164
- "@xmldom/xmldom": "^0.8.11",
168
+ "@swc/core": "^1.15.32",
169
+ "@swc/helpers": "^0.5.21",
165
170
  "clipanion": "^4.0.0-rc.4",
166
- "hono": "^4.12.8",
171
+ "hono": "^4.12.15",
167
172
  "tsyringe": "^4.10.0",
168
173
  "zod": "^4.3.6"
169
174
  },
170
175
  "peerDependencies": {
171
- "@aws-sdk/client-s3": "^3.700.0",
172
- "@aws-sdk/lib-storage": "^3.700.0",
173
- "@aws-sdk/s3-request-presigner": "^3.700.0",
174
- "@react-email/components": "^1.0.0",
175
- "nodemailer": ">=7.0.0",
176
- "react": "^19.0.0",
177
- "react-dom": "^19.0.0",
178
- "reflect-metadata": "^0.2.2",
179
- "resend": "^6.0.0"
176
+ "@react-email/components": ">=1",
177
+ "nodemailer": ">=7",
178
+ "react": ">=19",
179
+ "react-dom": ">=19",
180
+ "reflect-metadata": ">=0.2",
181
+ "resend": ">=6"
180
182
  },
181
183
  "peerDependenciesMeta": {
182
- "@aws-sdk/client-s3": {
183
- "optional": true
184
- },
185
- "@aws-sdk/lib-storage": {
186
- "optional": true
187
- },
188
- "@aws-sdk/s3-request-presigner": {
189
- "optional": true
190
- },
191
184
  "@react-email/components": {
192
185
  "optional": true
193
186
  },
@@ -205,27 +198,25 @@
205
198
  }
206
199
  },
207
200
  "devDependencies": {
208
- "@aws-sdk/client-s3": "3.1014.0",
209
- "@aws-sdk/lib-storage": "^3.1014.0",
210
- "@aws-sdk/s3-request-presigner": "3.1014.0",
211
- "@cloudflare/vitest-pool-workers": "^0.13.3",
212
- "@cloudflare/workers-types": "4.20260317.1",
213
- "@react-email/components": "^1.0.10",
201
+ "@cloudflare/vitest-pool-workers": "^0.15.0",
202
+ "@cloudflare/workers-types": "4.20260426.1",
203
+ "@react-email/components": "^1.0.12",
214
204
  "@stratal/testing": "workspace:*",
215
- "@types/node": "^25.5.0",
216
- "@types/nodemailer": "^7.0.11",
205
+ "@types/node": "^25.6.0",
206
+ "@types/nodemailer": "^8.0.0",
217
207
  "@types/react": "^19.2.14",
218
208
  "@types/react-dom": "^19.2.3",
219
- "@vitest/coverage-v8": "^4.1.0",
220
- "@vitest/runner": "~4.1.0",
221
- "@vitest/snapshot": "~4.1.0",
222
- "nodemailer": "^8.0.3",
223
- "react": "^19.2.4",
224
- "react-dom": "^19.2.4",
209
+ "@vitest/coverage-v8": "^4.1.5",
210
+ "@vitest/runner": "~4.1.5",
211
+ "@vitest/snapshot": "~4.1.5",
212
+ "jsonc-parser": "^3.3.1",
213
+ "nodemailer": "^8.0.7",
214
+ "react": "^19.2.5",
215
+ "react-dom": "^19.2.5",
225
216
  "reflect-metadata": "^0.2.2",
226
- "resend": "^6.9.4",
227
- "tsdown": "^0.21.4",
228
- "typescript": "^5.9.3",
229
- "vitest": "~4.1.0"
217
+ "resend": "^6.12.2",
218
+ "tsdown": "^0.21.10",
219
+ "typescript": "^6.0.3",
220
+ "vitest": "~4.1.5"
230
221
  }
231
222
  }
@@ -1,177 +0,0 @@
1
- import { Et as RouterContext, Lt as VersioningOptions, U as HonoApp, Ut as StratalEnv, at as DynamicModule, en as Container, lt as ModuleClass } from "./index-BFCxSp_f.mjs";
2
- import { l as LogLevel } from "./index-Dp6A5ywM.mjs";
3
-
4
- //#region src/execution-context.d.ts
5
- interface StratalExecutionContext {
6
- waitUntil(promise: Promise<unknown>): void;
7
- }
8
- //#endregion
9
- //#region src/quarry/types.d.ts
10
- /**
11
- * Flat input object for programmatic command invocation.
12
- */
13
- type CommandInput = Record<string, unknown>;
14
- /**
15
- * Result of a command execution.
16
- */
17
- interface CommandResult {
18
- exitCode: number;
19
- output: string[];
20
- errors: string[];
21
- }
22
- /**
23
- * User-facing Quarry interface. Only exposes the `call()` method.
24
- *
25
- * Inject via `@inject(DI_TOKENS.Quarry)` and type as `Quarry`.
26
- */
27
- interface Quarry {
28
- call(name: string, input?: CommandInput): Promise<CommandResult>;
29
- }
30
- /**
31
- * Internal mutable state stored on Command instances via Symbol key.
32
- * @internal
33
- */
34
- interface CommandInternals {
35
- inputs: CommandInput;
36
- output: string[];
37
- errors: string[];
38
- exitCode: number;
39
- quarry: Quarry | null;
40
- }
41
- /**
42
- * A parsed argument from a Laravel-style signature string.
43
- */
44
- interface ParsedArgument {
45
- name: string;
46
- required: boolean;
47
- default?: string;
48
- description?: string;
49
- isArray: boolean;
50
- }
51
- /**
52
- * A parsed option from a Laravel-style signature string.
53
- */
54
- interface ParsedOption {
55
- name: string;
56
- alias?: string;
57
- isFlag: boolean;
58
- isArray: boolean;
59
- default?: string;
60
- description?: string;
61
- }
62
- /**
63
- * Fully parsed command signature.
64
- */
65
- interface ParsedSignature {
66
- name: string;
67
- arguments: ParsedArgument[];
68
- options: ParsedOption[];
69
- }
70
- //#endregion
71
- //#region src/application.d.ts
72
- interface ApplicationConfig {
73
- /** Root application module */
74
- module: ModuleClass | DynamicModule;
75
- /** Logging configuration. Defaults: level=INFO, formatter='json' */
76
- logging?: {
77
- level?: LogLevel;
78
- formatter?: 'json' | 'pretty';
79
- };
80
- /**
81
- * API versioning configuration.
82
- * When provided, enables URI-based versioning for controllers.
83
- */
84
- versioning?: VersioningOptions;
85
- }
86
- interface ApplicationOptions extends ApplicationConfig {
87
- env: StratalEnv;
88
- ctx: StratalExecutionContext;
89
- }
90
- /**
91
- * Application
92
- *
93
- * Main application class managing the two-tier container hierarchy:
94
- * - Global Container: All services (singletons via tsyringe native)
95
- * - Request Container: Child of global, context-enriched instances per request
96
- *
97
- * @example
98
- * ```typescript
99
- * const app = new Application({ module: AppModule, env, ctx })
100
- * await app.initialize()
101
- *
102
- * // Access container via getter
103
- * const service = app.container.resolve(MY_TOKEN)
104
- *
105
- * // Handle HTTP request (via HonoApp)
106
- * // Handle queue batch
107
- * await app.handleQueue(batch, 'my-queue')
108
- * ```
109
- */
110
- declare class Application {
111
- /**
112
- * Unified Container - manages all DI operations
113
- */
114
- private _container;
115
- private honoApp;
116
- private moduleRegistry;
117
- private consumerRegistry;
118
- private cronManager;
119
- private quarry;
120
- private initialized;
121
- readonly env: StratalEnv;
122
- private readonly appConfig;
123
- constructor({
124
- env,
125
- ctx,
126
- ...config
127
- }: ApplicationOptions);
128
- /**
129
- * Get the Container instance
130
- */
131
- get container(): Container;
132
- /**
133
- * Get the HonoApp instance
134
- */
135
- get hono(): HonoApp;
136
- initialize(): Promise<void>;
137
- /**
138
- * Resolve a service from the container
139
- */
140
- resolve<T>(token: symbol): T;
141
- /**
142
- * Handle queue batch processing
143
- */
144
- handleQueue(batch: MessageBatch, queueName: string): Promise<void>;
145
- /**
146
- * Handle scheduled cron trigger
147
- */
148
- handleScheduled(controller: ScheduledController): Promise<void>;
149
- /**
150
- * Create mock RouterContext for queue/cron/seeder processing
151
- */
152
- createMockRouterContext(locale?: string): RouterContext;
153
- shutdown(): Promise<void>;
154
- /**
155
- * Execute a command by name in a request-scoped container.
156
- */
157
- handleCommand(name: string, input?: CommandInput): Promise<CommandResult>;
158
- private registerCommands;
159
- private registerSeeders;
160
- private registerQueueConsumers;
161
- private registerCronJobs;
162
- /**
163
- * Auto-wire `@Listener()` classes with the EventRegistry.
164
- */
165
- private registerEventListeners;
166
- /**
167
- * Register LoggerService and dependencies
168
- */
169
- private registerLoggerService;
170
- /**
171
- * Register core services with explicit scope
172
- */
173
- private registerCoreServices;
174
- }
175
- //#endregion
176
- export { CommandInternals as a, ParsedOption as c, StratalExecutionContext as d, CommandInput as i, ParsedSignature as l, ApplicationConfig as n, CommandResult as o, ApplicationOptions as r, ParsedArgument as s, Application as t, Quarry as u };
177
- //# sourceMappingURL=application-DfPtIzxF.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"application-DfPtIzxF.d.mts","names":[],"sources":["../src/execution-context.ts","../src/quarry/types.ts","../src/application.ts"],"mappings":";;;;UAAiB,uBAAA;EACf,SAAA,CAAU,OAAA,EAAS,OAAA;AAAA;;;;;;KCET,YAAA,GAAe,MAAA;ADH3B;;;AAAA,UCQiB,aAAA;EACf,QAAA;EACA,MAAA;EACA,MAAA;AAAA;;;;;AARF;UAgBiB,MAAA;EACf,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;AAAA;;AAZpD;;;UAmBiB,gBAAA;EACf,MAAA,EAAQ,YAAA;EACR,MAAA;EACA,MAAA;EACA,QAAA;EACA,MAAA,EAAQ,MAAA;AAAA;;;;UAMO,cAAA;EACf,IAAA;EACA,QAAA;EACA,OAAA;EACA,WAAA;EACA,OAAA;AAAA;;;;UAMe,YAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA;EACA,OAAA;EACA,OAAA;EACA,WAAA;AAAA;;;;UAMe,eAAA;EACf,IAAA;EACA,SAAA,EAAW,cAAA;EACX,OAAA,EAAS,YAAA;AAAA;;;UC1BM,iBAAA;EFrCL;EEuCV,MAAA,EAAQ,WAAA,GAAc,aAAA;EFvCa;EEyCnC,OAAA;IACE,KAAA,GAAQ,QAAA;IACR,SAAA;EAAA;EDzCoB;;;;EC+CtB,UAAA,GAAa,iBAAA;AAAA;AAAA,UAGE,kBAAA,SAA2B,iBAAA;EAC1C,GAAA,EAAK,UAAA;EACL,GAAA,EAAK,uBAAA;AAAA;;;;ADpCP;;;;;;;;;;;;;;;;AAQA;cCmDa,WAAA;;;;UAIH,UAAA;EAAA,QAEA,OAAA;EAAA,QACA,cAAA;EAAA,QACA,gBAAA;EAAA,QACA,WAAA;EAAA,QACA,MAAA;EAAA,QACA,WAAA;EAAA,SAEC,GAAA,EAAK,UAAA;EAAA,iBACG,SAAA;;IAEH,GAAA;IAAK,GAAA;IAAA,GAAQ;EAAA,GAAU,kBAAA;;;;MA+BjC,SAAA,CAAA,GAAa,SAAA;EDpFjB;;;EAAA,IC2FI,IAAA,CAAA,GAAQ,OAAA;EAIN,UAAA,CAAA,GAAc,OAAA;EDvFL;;;ECmIf,OAAA,GAAA,CAAW,KAAA,WAAgB,CAAA;EDlI3B;;;EC+IM,WAAA,CAAY,KAAA,EAAO,YAAA,EAAc,SAAA,WAAoB,OAAA;ED3I3D;;;EC+JM,eAAA,CAAgB,UAAA,EAAY,mBAAA,GAAsB,OAAA;EDxJzC;;;ECyKf,uBAAA,CAAwB,MAAA,YAAgB,aAAA;EAQlC,QAAA,CAAA,GAAY,OAAA;ED/KlB;;;EC8LM,aAAA,CAAc,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;EAAA,QAOzD,gBAAA;EAAA,QA0BA,eAAA;EAAA,QASA,sBAAA;EAAA,QAOA,gBAAA;;AAxQV;;UAkRU,sBAAA;EAhRA;;;EAAA,QAqSA,qBAAA;EA3RsB;;;EAAA,QA+StB,oBAAA;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"command-B1CPgsrU.mjs","names":[],"sources":["../src/quarry/constants.ts","../src/quarry/errors/command.error.ts","../src/quarry/command.ts"],"sourcesContent":["/**\n * Symbol key for storing internal mutable state on Command instances.\n * Keeps internal state hidden from user-facing autocomplete.\n */\nexport const COMMAND_INTERNALS = Symbol.for('stratal:command:internals')\n","/**\n * User-facing command error with a plain English message.\n *\n * Quarry catches this in `call()` and puts the message into `CommandResult.errors`.\n * Does NOT extend `ApplicationError` (which requires i18n keys + error codes).\n * Not routed through GlobalErrorHandler.\n */\nexport class CommandError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CommandError'\n }\n}\n","import 'reflect-metadata'\n\nimport { bold, cyan, dim, green, red, yellow } from './colors'\nimport { COMMAND_INTERNALS } from './constants'\nimport { CommandError } from './errors/command.error'\nimport type { CommandInput, CommandInternals, CommandResult } from './types'\n\n/**\n * Abstract base class for Quarry commands.\n *\n * Subclasses define a static `command` signature string and implement `handle()`.\n *\n * @example\n * ```typescript\n * export class GreetCommand extends Command {\n * static command = 'greet {name : The name to greet} {--loud}'\n * static description = 'Greet someone'\n *\n * async handle(): Promise<void> {\n * const name = this.string('name')\n * const loud = this.boolean('loud')\n * this.info(loud ? `HELLO, ${name.toUpperCase()}!` : `Hello, ${name}!`)\n * }\n * }\n * ```\n */\nexport abstract class Command {\n /**\n * Laravel-style command signature string.\n *\n * **Command names:**\n * - `'greet'` — flat command (`quarry greet`)\n * - `'task add'` — subcommand hierarchy via spaces (`quarry task add`)\n * - `'task:add'` — namespaced flat command via colons (`quarry task:add`)\n *\n * **Arguments:**\n * - `{name}` — required argument\n * - `{name?}` — optional argument\n * - `{name=default}` — argument with default value\n * - `{name*}` — array/variadic argument\n * - `{name : description}` — argument with description\n *\n * **Options:**\n * - `{--flag}` — boolean flag\n * - `{--name=}` — option that accepts a value\n * - `{--name=default}` — option with default value\n * - `{--name=*}` — array option (multiple values)\n * - `{--A|name}` — option with single-char alias\n * - `{--name= : description}` — option with description\n *\n * @example\n * ```typescript\n * // Namespaced flat command: `quarry users:create ...`\n * static command = 'users:create {email : The user email} {--A|admin} {--R|role= : Assign a role}'\n *\n * // Subcommand hierarchy: `quarry users create ...`\n * static command = 'users create {email : The user email} {--A|admin} {--R|role= : Assign a role}'\n * ```\n */\n static command: string\n /** Human-readable description */\n static description?: string\n /** Alternative command names */\n static aliases?: string[];\n\n [COMMAND_INTERNALS]: CommandInternals\n\n constructor() {\n this[COMMAND_INTERNALS] = {\n inputs: {},\n output: [],\n errors: [],\n exitCode: 0,\n quarry: null,\n }\n }\n\n /**\n * Implement this method with the command's logic.\n * Return a number to set the exit code, or void for exit code 0.\n */\n // eslint-disable-next-line @typescript-eslint/no-invalid-void-type\n abstract handle(): number | void | Promise<number | void>\n\n // ── Input Accessors ──────────────────────────────────────────────\n\n /**\n * Get an input value with generic type.\n */\n input<T>(name: string): T {\n return this[COMMAND_INTERNALS].inputs[name] as T\n }\n\n /**\n * Get a string input. Throws CommandError if present but not a string.\n */\n string(name: string): string {\n const value = this[COMMAND_INTERNALS].inputs[name]\n if (value === undefined || value === null) {\n return ''\n }\n if (typeof value !== 'string') {\n throw new CommandError(`Input \"${name}\" expected a string, got ${typeof value}`)\n }\n return value\n }\n\n /**\n * Get a boolean input. Throws CommandError if present but not a boolean.\n */\n boolean(name: string): boolean {\n const value = this[COMMAND_INTERNALS].inputs[name]\n if (value === undefined || value === null) {\n return false\n }\n if (typeof value !== 'boolean') {\n throw new CommandError(`Input \"${name}\" expected a boolean, got ${typeof value}`)\n }\n return value\n }\n\n /**\n * Get a number input. Coerces strings to numbers. Throws CommandError on NaN.\n */\n number(name: string): number {\n const value = this[COMMAND_INTERNALS].inputs[name]\n if (value === undefined || value === null) {\n return 0\n }\n const num = typeof value === 'string' ? Number(value) : value\n if (typeof num !== 'number' || Number.isNaN(num)) {\n throw new CommandError(`Input \"${name}\" expected a number, got ${typeof value}`)\n }\n return num\n }\n\n /**\n * Get an array input. Throws CommandError if present but not an array.\n */\n array(name: string): string[] {\n const value = this[COMMAND_INTERNALS].inputs[name]\n if (value === undefined || value === null) {\n return []\n }\n if (!Array.isArray(value)) {\n throw new CommandError(`Input \"${name}\" expected an array, got ${typeof value}`)\n }\n return value as string[]\n }\n\n // ── Output Helpers ───────────────────────────────────────────────\n\n /** Write an informational message to output */\n info(message: string): void {\n this[COMMAND_INTERNALS].output.push(cyan(message))\n }\n\n /** Write a success message to output */\n success(message: string): void {\n this[COMMAND_INTERNALS].output.push(`${green(bold('✔'))} ${green(message)}`)\n }\n\n /** Write a warning message to output */\n warn(message: string): void {\n this[COMMAND_INTERNALS].output.push(`${yellow(bold('⚠'))} ${yellow(message)}`)\n }\n\n /** Write an error message to errors */\n error(message: string): void {\n this[COMMAND_INTERNALS].errors.push(red(message))\n }\n\n /** Write a plain line to output */\n line(message?: string): void {\n this[COMMAND_INTERNALS].output.push(message ?? '')\n }\n\n /** Write an empty line to output */\n newLine(): void {\n this[COMMAND_INTERNALS].output.push('')\n }\n\n /** Write a comment-style line to output */\n comment(message: string): void {\n this[COMMAND_INTERNALS].output.push(dim(`// ${message}`))\n }\n\n /** Write a formatted table to output */\n table(headers: string[], rows: string[][]): void {\n const colWidths = headers.map((h, i) => {\n const maxRow = rows.reduce((max, row) => Math.max(max, (row[i] ?? '').length), 0)\n return Math.max(h.length, maxRow)\n })\n\n const formatRow = (cells: string[]) =>\n cells.map((cell, i) => cell.padEnd(colWidths[i])).join(' ')\n\n this[COMMAND_INTERNALS].output.push(bold(formatRow(headers)))\n this[COMMAND_INTERNALS].output.push(dim(colWidths.map((w) => '-'.repeat(w)).join(' ')))\n for (const row of rows) {\n this[COMMAND_INTERNALS].output.push(formatRow(row))\n }\n }\n\n /** Write an error message and set exit code */\n fail(message: string, exitCode = 1): void {\n this[COMMAND_INTERNALS].errors.push(`${red(bold('✖'))} ${red(message)}`)\n this[COMMAND_INTERNALS].exitCode = exitCode\n }\n\n // ── Command Calling ──────────────────────────────────────────────\n\n /**\n * Call another command from within this command.\n * Delegates to Quarry.call() via internal reference.\n */\n async call(name: string, input?: CommandInput): Promise<CommandResult> {\n const internals = this[COMMAND_INTERNALS]\n if (!internals.quarry) {\n throw new CommandError('Cannot call commands: Quarry reference not set')\n }\n const result = await internals.quarry.call(name, input)\n\n // Forward child output/errors into parent (like Clipanion context switches)\n internals.output.push(...result.output)\n internals.errors.push(...result.errors)\n\n return result\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cron-manager-CFBamKKk.mjs","names":[],"sources":["../src/cron/errors/cron-execution.error.ts","../src/cron/cron-manager.ts"],"sourcesContent":["import { ApplicationError } from '../../errors'\nimport { ERROR_CODES } from '../../errors'\n\n/**\n * Error thrown when one or more cron jobs fail execution\n *\n * This error aggregates failures from multiple jobs that share the same schedule.\n */\nexport class CronExecutionError extends ApplicationError {\n\tconstructor(\n\t\tschedule: string,\n\t\tfailedJobsCount: number,\n\t\tjobNames: string\n\t) {\n\t\tsuper(\n\t\t\t'errors.cronExecutionFailed',\n\t\t\tERROR_CODES.SYSTEM.CRON_EXECUTION_FAILED,\n\t\t\t{\n\t\t\t\tschedule,\n\t\t\t\tcount: failedJobsCount,\n\t\t\t\tjobs: jobNames\n\t\t\t}\n\t\t)\n\t}\n}\n","import { Transient } from '../di/decorators'\nimport type { CronJob } from './cron-job'\nimport { CronExecutionError } from './errors/cron-execution.error'\n\n/**\n * Manages cron job registration and execution\n *\n * CronManager is a singleton service that:\n * - Registers cron jobs from modules\n * - Routes scheduled events to matching jobs\n * - Handles errors during job execution\n *\n * Jobs are grouped by their cron expression, allowing multiple jobs\n * to run on the same schedule.\n */\n@Transient()\nexport class CronManager {\n\t/**\n\t * Map of cron expressions to jobs\n\t * Key: Cron expression (e.g., '0 2 * * *')\n\t * Value: Array of jobs matching that expression\n\t */\n\tprivate jobs = new Map<string, CronJob[]>()\n\n\t/**\n\t * Register a cron job\n\t *\n\t * Jobs with the same schedule are grouped together and executed\n\t * sequentially when the trigger fires.\n\t *\n\t * @param job - CronJob instance to register\n\t */\n\tregisterJob(job: CronJob): void {\n\t\tconst existing = this.jobs.get(job.schedule) ?? []\n\t\texisting.push(job)\n\t\tthis.jobs.set(job.schedule, existing)\n\t}\n\n\t/**\n\t * Execute all jobs matching the triggered cron expression\n\t *\n\t * Jobs are executed sequentially. If a job fails:\n\t * - Its onError() hook is called (if defined)\n\t * - Execution continues with the next job\n\t * - Errors are collected and logged\n\t *\n\t * @param controller - Cloudflare ScheduledController\n\t */\n\tasync executeScheduled(controller: ScheduledController): Promise<void> {\n\t\tconst { cron } = controller\n\t\tconst matchingJobs = this.jobs.get(cron) ?? []\n\n\t\tif (matchingJobs.length === 0) {\n\t\t\treturn\n\t\t}\n\n\t\tconst errors: { job: string; error: Error }[] = []\n\n\t\tfor (const job of matchingJobs) {\n\t\t\tconst jobName = job.constructor.name\n\n\t\t\ttry {\n\t\t\t\tawait job.execute(controller)\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error as Error\n\t\t\t\terrors.push({ job: jobName, error: err })\n\n\t\t\t\t// Call job's error handler if defined\n\t\t\t\tif (job.onError) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait job.onError(err, controller)\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// If onError() itself fails, we just continue\n\t\t\t\t\t\t// The error will be logged by GlobalErrorHandler\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If any jobs failed, throw an aggregate error\n\t\t// This ensures the error is logged by GlobalErrorHandler\n\t\tif (errors.length > 0) {\n\t\t\tconst jobNames = errors\n\t\t\t\t.map(({ job, error }) => `${job}: ${error.message}`)\n\t\t\t\t.join('; ')\n\n\t\t\tthrow new CronExecutionError(cron, errors.length, jobNames)\n\t\t}\n\t}\n\n\t/**\n\t * Get all registered jobs for a specific cron expression\n\t *\n\t * @param schedule - Cron expression\n\t * @returns Array of jobs for that schedule, or empty array if none\n\t */\n\tgetJobsForSchedule(schedule: string): CronJob[] {\n\t\treturn this.jobs.get(schedule) ?? []\n\t}\n\n\t/**\n\t * Get all registered cron expressions\n\t *\n\t * @returns Array of unique cron expressions\n\t */\n\tgetAllSchedules(): string[] {\n\t\treturn Array.from(this.jobs.keys())\n\t}\n\n\t/**\n\t * Get total number of registered jobs across all schedules\n\t *\n\t * @returns Total job count\n\t */\n\tgetTotalJobCount(): number {\n\t\tlet count = 0\n\t\tfor (const jobs of this.jobs.values()) {\n\t\t\tcount += jobs.length\n\t\t}\n\t\treturn count\n\t}\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,qBAAb,cAAwC,iBAAiB;CACxD,YACC,UACA,iBACA,UACC;AACD,QACC,8BACA,YAAY,OAAO,uBACnB;GACC;GACA,OAAO;GACP,MAAM;GACN,CACD;;;;;ACNI,IAAA,cAAA,MAAM,YAAY;;;;;;CAMxB,uBAAe,IAAI,KAAwB;;;;;;;;;CAU3C,YAAY,KAAoB;EAC/B,MAAM,WAAW,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,EAAE;AAClD,WAAS,KAAK,IAAI;AAClB,OAAK,KAAK,IAAI,IAAI,UAAU,SAAS;;;;;;;;;;;;CAatC,MAAM,iBAAiB,YAAgD;EACtE,MAAM,EAAE,SAAS;EACjB,MAAM,eAAe,KAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AAE9C,MAAI,aAAa,WAAW,EAC3B;EAGD,MAAM,SAA0C,EAAE;AAElD,OAAK,MAAM,OAAO,cAAc;GAC/B,MAAM,UAAU,IAAI,YAAY;AAEhC,OAAI;AACH,UAAM,IAAI,QAAQ,WAAW;YACrB,OAAO;IACf,MAAM,MAAM;AACZ,WAAO,KAAK;KAAE,KAAK;KAAS,OAAO;KAAK,CAAC;AAGzC,QAAI,IAAI,QACP,KAAI;AACH,WAAM,IAAI,QAAQ,KAAK,WAAW;YAC3B;;;AAUX,MAAI,OAAO,SAAS,GAAG;GACtB,MAAM,WAAW,OACf,KAAK,EAAE,KAAK,YAAY,GAAG,IAAI,IAAI,MAAM,UAAU,CACnD,KAAK,KAAK;AAEZ,SAAM,IAAI,mBAAmB,MAAM,OAAO,QAAQ,SAAS;;;;;;;;;CAU7D,mBAAmB,UAA6B;AAC/C,SAAO,KAAK,KAAK,IAAI,SAAS,IAAI,EAAE;;;;;;;CAQrC,kBAA4B;AAC3B,SAAO,MAAM,KAAK,KAAK,KAAK,MAAM,CAAC;;;;;;;CAQpC,mBAA2B;EAC1B,IAAI,QAAQ;AACZ,OAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,CACpC,UAAS,KAAK;AAEf,SAAO;;;0BAxGR,WAAW,CAAA,EAAA,YAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cron-manager-D7imGwUT.d.mts","names":[],"sources":["../src/cron/cron-job.ts","../src/cron/cron-manager.ts"],"mappings":";;AA2BA;;;;;;;;;;;;;;;;;;;;;;;;;;UAAiB,OAAA;ECXO;;;;;;;EAAA,SDmBd,QAAA;ECbD;;;;;;EDqBR,OAAA,CAAQ,UAAA,EAAY,mBAAA,GAAsB,OAAA;ECKe;;;;;;;;EDKzD,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,UAAA,EAAY,mBAAA,GAAsB,OAAA;AAAA;;;AA1B1D;;;;;;;;;;;AAAA,cCXa,WAAA;ED2BQ;;;;;EAAA,QCrBZ,IAAA;ED+B2B;;;;;;;;ECrBnC,WAAA,CAAY,GAAA,EAAK,OAAA;EAhBM;;;;;;;;;;EAgCjB,gBAAA,CAAiB,UAAA,EAAY,mBAAA,GAAsB,OAAA;EAhB7C;;;;;;EAgEZ,kBAAA,CAAmB,QAAA,WAAmB,OAAA;EAAA;;;;;EAStC,eAAA,CAAA;;;;;;EASA,gBAAA,CAAA;AAAA"}