stratal 0.0.18 → 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 (172) hide show
  1. package/README.md +8 -8
  2. package/dist/{base-email.provider-Cuw4OAB0.mjs → base-email.provider-mjynzewK.mjs} +1 -1
  3. package/dist/{base-email.provider-Cuw4OAB0.mjs.map → base-email.provider-mjynzewK.mjs.map} +1 -1
  4. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  5. package/dist/bin/quarry.mjs +21 -36
  6. package/dist/bin/quarry.mjs.map +1 -1
  7. package/dist/cache/index.d.mts +3 -2
  8. package/dist/cache/index.d.mts.map +1 -1
  9. package/dist/cache/index.mjs +3 -3
  10. package/dist/{colors-BTAnQRGU.mjs → colors-DJaRDXoS.mjs} +1 -1
  11. package/dist/{colors-BTAnQRGU.mjs.map → colors-DJaRDXoS.mjs.map} +1 -1
  12. package/dist/{command-DjGqCYHv.mjs → command-BgSlsS4M.mjs} +2 -2
  13. package/dist/{command-DjGqCYHv.mjs.map → command-BgSlsS4M.mjs.map} +1 -1
  14. package/dist/{command-B1YuV-UZ.d.mts → command-DsQq56Lp.d.mts} +2 -2
  15. package/dist/{command-B1YuV-UZ.d.mts.map → command-DsQq56Lp.d.mts.map} +1 -1
  16. package/dist/config/index.d.mts +81 -37
  17. package/dist/config/index.d.mts.map +1 -1
  18. package/dist/config/index.mjs +126 -45
  19. package/dist/config/index.mjs.map +1 -1
  20. package/dist/{consumer-registry-BkuHXR_u.d.mts → consumer-registry-Doom7BEh.d.mts} +1 -1
  21. package/dist/{consumer-registry-BkuHXR_u.d.mts.map → consumer-registry-Doom7BEh.d.mts.map} +1 -1
  22. package/dist/controller.decorator-LZY9aHYG.mjs +66 -0
  23. package/dist/controller.decorator-LZY9aHYG.mjs.map +1 -0
  24. package/dist/cron/index.d.mts +4 -3
  25. package/dist/cron/index.d.mts.map +1 -1
  26. package/dist/cron/index.mjs +1 -1
  27. package/dist/{cron-manager-1KnZvojs.mjs → cron-manager-C30t9UZM.mjs} +29 -19
  28. package/dist/cron-manager-C30t9UZM.mjs.map +1 -0
  29. package/dist/{cron-manager-BnEZquBL.d.mts → cron-manager-RuPtFVLy.d.mts} +27 -13
  30. package/dist/cron-manager-RuPtFVLy.d.mts.map +1 -0
  31. package/dist/di/index.d.mts +1 -1
  32. package/dist/di/index.mjs +2 -2
  33. package/dist/email/index.d.mts +3 -3
  34. package/dist/email/index.mjs +87 -10
  35. package/dist/email/index.mjs.map +1 -1
  36. package/dist/{en-3QnZwP-u.mjs → en-rHmW6vD9.mjs} +5 -31
  37. package/dist/en-rHmW6vD9.mjs.map +1 -0
  38. package/dist/env-CamWD-U1.d.mts +25 -0
  39. package/dist/env-CamWD-U1.d.mts.map +1 -0
  40. package/dist/errors/index.d.mts +1 -1
  41. package/dist/errors/index.mjs +1 -1
  42. package/dist/{errors--RBIvDXr.mjs → errors-B4pYgYON.mjs} +161 -7
  43. package/dist/errors-B4pYgYON.mjs.map +1 -0
  44. package/dist/{errors-B7hCnXgB.mjs → errors-BUyUfr2Z.mjs} +14 -7
  45. package/dist/errors-BUyUfr2Z.mjs.map +1 -0
  46. package/dist/events/index.d.mts +2 -2
  47. package/dist/events/index.mjs +1 -1
  48. package/dist/{events-UTJliZhl.mjs → events-COKixqnG.mjs} +2 -2
  49. package/dist/{events-UTJliZhl.mjs.map → events-COKixqnG.mjs.map} +1 -1
  50. package/dist/{gateway-context-BdBFoQd8.mjs → gateway-context-cqZ8wMoi.mjs} +4 -65
  51. package/dist/gateway-context-cqZ8wMoi.mjs.map +1 -0
  52. package/dist/guards/index.d.mts +14 -5
  53. package/dist/guards/index.d.mts.map +1 -1
  54. package/dist/guards/index.mjs +1 -1
  55. package/dist/{guards-MtDgcHnF.mjs → guards-DMbsAxSX.mjs} +1 -1
  56. package/dist/guards-DMbsAxSX.mjs.map +1 -0
  57. package/dist/http-method.decorator-BT3ufnz8.mjs +96 -0
  58. package/dist/http-method.decorator-BT3ufnz8.mjs.map +1 -0
  59. package/dist/i18n/index.d.mts +3 -3
  60. package/dist/i18n/index.mjs +2 -2
  61. package/dist/i18n/messages/en/index.d.mts +1 -1
  62. package/dist/i18n/messages/en/index.mjs +1 -1
  63. package/dist/i18n/utils/index.mjs +1 -1
  64. package/dist/i18n/validation/index.d.mts +1 -1
  65. package/dist/i18n/validation/index.mjs +1 -1
  66. package/dist/{i18n.module-BpLLLCTg.mjs → i18n.module-CI_prYFD.mjs} +74 -196
  67. package/dist/i18n.module-CI_prYFD.mjs.map +1 -0
  68. package/dist/{index-Dfpd_ypO.d.mts → index-B437eK7p.d.mts} +26 -12
  69. package/dist/index-B437eK7p.d.mts.map +1 -0
  70. package/dist/{index-BR23zDMy.d.mts → index-CWRS7Ri3.d.mts} +1 -1
  71. package/dist/{index-BR23zDMy.d.mts.map → index-CWRS7Ri3.d.mts.map} +1 -1
  72. package/dist/{index-BDh9J2KD.d.mts → index-DFhEeFfC.d.mts} +4 -30
  73. package/dist/{index-BDh9J2KD.d.mts.map → index-DFhEeFfC.d.mts.map} +1 -1
  74. package/dist/{index-BrmS34sa.d.mts → index-DPFqRs8L.d.mts} +70 -39
  75. package/dist/index-DPFqRs8L.d.mts.map +1 -0
  76. package/dist/{index-DPxmo6AY.d.mts → index-Dnqm9ZB6.d.mts} +5 -4
  77. package/dist/index-Dnqm9ZB6.d.mts.map +1 -0
  78. package/dist/index-SHx31sBJ.d.mts +101 -0
  79. package/dist/index-SHx31sBJ.d.mts.map +1 -0
  80. package/dist/index.d.mts +3 -2
  81. package/dist/index.d.mts.map +1 -1
  82. package/dist/index.mjs +1 -1
  83. package/dist/{is-command-PvULqiTa.mjs → is-command-C6a7WTPw.mjs} +2 -2
  84. package/dist/{is-command-PvULqiTa.mjs.map → is-command-C6a7WTPw.mjs.map} +1 -1
  85. package/dist/{is-seeder-BN9Ej1r7.mjs → is-seeder-CebjZCDn.mjs} +1 -1
  86. package/dist/{is-seeder-BN9Ej1r7.mjs.map → is-seeder-CebjZCDn.mjs.map} +1 -1
  87. package/dist/logger/index.d.mts +1 -1
  88. package/dist/logger/index.mjs +1 -1
  89. package/dist/{logger-c0ftIK4G.mjs → logger-V6Ms3QnQ.mjs} +38 -20
  90. package/dist/{logger-c0ftIK4G.mjs.map → logger-V6Ms3QnQ.mjs.map} +1 -1
  91. package/dist/macroable/index.d.mts +2 -0
  92. package/dist/macroable/index.mjs +2 -0
  93. package/dist/macroable-BmufBshB.mjs +122 -0
  94. package/dist/macroable-BmufBshB.mjs.map +1 -0
  95. package/dist/module/index.d.mts +2 -2
  96. package/dist/module/index.mjs +1 -1
  97. package/dist/{module-C3YZ-kZN.mjs → module-qGE_1duv.mjs} +31 -18
  98. package/dist/module-qGE_1duv.mjs.map +1 -0
  99. package/dist/openapi/index.d.mts +3 -3
  100. package/dist/openapi/index.mjs +2 -2
  101. package/dist/{openapi-tools.service-B77QXD56.mjs → openapi-tools.service-CYWGuhue.mjs} +4 -1
  102. package/dist/{openapi-tools.service-B77QXD56.mjs.map → openapi-tools.service-CYWGuhue.mjs.map} +1 -1
  103. package/dist/{openapi.service-6yj0BUY4.d.mts → openapi.service-Bv_NioM9.d.mts} +3 -3
  104. package/dist/{openapi.service-6yj0BUY4.d.mts.map → openapi.service-Bv_NioM9.d.mts.map} +1 -1
  105. package/dist/quarry/index.d.mts +7 -7
  106. package/dist/quarry/index.d.mts.map +1 -1
  107. package/dist/quarry/index.mjs +4 -4
  108. package/dist/{quarry-registry-CQCIlYTO.mjs → quarry-registry-DFfRRkA7.mjs} +17 -15
  109. package/dist/quarry-registry-DFfRRkA7.mjs.map +1 -0
  110. package/dist/queue/index.d.mts +2 -2
  111. package/dist/queue/index.mjs +2 -2
  112. package/dist/{queue.module-DIjD6nr-.mjs → queue.module-P-G-nCYz.mjs} +4 -4
  113. package/dist/{queue.module-DIjD6nr-.mjs.map → queue.module-P-G-nCYz.mjs.map} +1 -1
  114. package/dist/r2-storage.provider-LdzK9tfG.mjs +244 -0
  115. package/dist/r2-storage.provider-LdzK9tfG.mjs.map +1 -0
  116. package/dist/{resend.provider-Bvw36rQy.mjs → resend.provider-bwILp0WI.mjs} +2 -2
  117. package/dist/{resend.provider-Bvw36rQy.mjs.map → resend.provider-bwILp0WI.mjs.map} +1 -1
  118. package/dist/router/index.d.mts +2 -2
  119. package/dist/router/index.mjs +7 -5
  120. package/dist/seeder/index.d.mts +3 -3
  121. package/dist/seeder/index.mjs +2 -2
  122. package/dist/{seeder-D7VXULXB.mjs → seeder-BcqIFa2X.mjs} +5 -5
  123. package/dist/{seeder-D7VXULXB.mjs.map → seeder-BcqIFa2X.mjs.map} +1 -1
  124. package/dist/{setup-BRIN-iYT.mjs → setup-CtekcwuO.mjs} +1 -1
  125. package/dist/{setup-BRIN-iYT.mjs.map → setup-CtekcwuO.mjs.map} +1 -1
  126. package/dist/signed-url-COX7cCWR.mjs +74 -0
  127. package/dist/signed-url-COX7cCWR.mjs.map +1 -0
  128. package/dist/{smtp.provider-CAwpvzvD.mjs → smtp.provider-B07yuARi.mjs} +2 -2
  129. package/dist/{smtp.provider-CAwpvzvD.mjs.map → smtp.provider-B07yuARi.mjs.map} +1 -1
  130. package/dist/storage/index.d.mts +39 -17
  131. package/dist/storage/index.d.mts.map +1 -1
  132. package/dist/storage/index.mjs +3 -3
  133. package/dist/storage/providers/index.d.mts +30 -70
  134. package/dist/storage/providers/index.d.mts.map +1 -1
  135. package/dist/storage/providers/index.mjs +2 -2
  136. package/dist/{storage-CJ-QOwNv.mjs → storage-P6X4h9So.mjs} +101 -27
  137. package/dist/storage-P6X4h9So.mjs.map +1 -0
  138. package/dist/{storage-provider.interface-YRtyYBxV.d.mts → storage-provider.interface-CC1nniHk.d.mts} +20 -21
  139. package/dist/storage-provider.interface-CC1nniHk.d.mts.map +1 -0
  140. package/dist/{stratal-B7G4i9-N.mjs → stratal-BCiwCFN9.mjs} +57 -26
  141. package/dist/stratal-BCiwCFN9.mjs.map +1 -0
  142. package/dist/{types-CN0zONAZ.d.mts → types-DIWemRad.d.mts} +1 -1
  143. package/dist/types-DIWemRad.d.mts.map +1 -0
  144. package/dist/{usage-generator-Cl1HPlUp.mjs → usage-generator-MBcRo0Q2.mjs} +2 -2
  145. package/dist/{usage-generator-Cl1HPlUp.mjs.map → usage-generator-MBcRo0Q2.mjs.map} +1 -1
  146. package/dist/{validation-B4bePOa_.mjs → validation-Dbg3ehdP.mjs} +1 -1
  147. package/dist/{validation-B4bePOa_.mjs.map → validation-Dbg3ehdP.mjs.map} +1 -1
  148. package/dist/websocket/index.d.mts +3 -3
  149. package/dist/websocket/index.mjs +1 -1
  150. package/dist/workers/index.d.mts +2 -1
  151. package/dist/workers/index.d.mts.map +1 -1
  152. package/dist/workers/index.mjs +2 -2
  153. package/package.json +27 -39
  154. package/dist/cron-manager-1KnZvojs.mjs.map +0 -1
  155. package/dist/cron-manager-BnEZquBL.d.mts.map +0 -1
  156. package/dist/en-3QnZwP-u.mjs.map +0 -1
  157. package/dist/errors--RBIvDXr.mjs.map +0 -1
  158. package/dist/errors-B7hCnXgB.mjs.map +0 -1
  159. package/dist/gateway-context-BdBFoQd8.mjs.map +0 -1
  160. package/dist/guards-MtDgcHnF.mjs.map +0 -1
  161. package/dist/i18n.module-BpLLLCTg.mjs.map +0 -1
  162. package/dist/index-BrmS34sa.d.mts.map +0 -1
  163. package/dist/index-DPxmo6AY.d.mts.map +0 -1
  164. package/dist/index-Dfpd_ypO.d.mts.map +0 -1
  165. package/dist/module-C3YZ-kZN.mjs.map +0 -1
  166. package/dist/quarry-registry-CQCIlYTO.mjs.map +0 -1
  167. package/dist/s3-storage.provider-BAhHDMI3.mjs +0 -343
  168. package/dist/s3-storage.provider-BAhHDMI3.mjs.map +0 -1
  169. package/dist/storage-CJ-QOwNv.mjs.map +0 -1
  170. package/dist/storage-provider.interface-YRtyYBxV.d.mts.map +0 -1
  171. package/dist/stratal-B7G4i9-N.mjs.map +0 -1
  172. package/dist/types-CN0zONAZ.d.mts.map +0 -1
@@ -3,8 +3,11 @@
3
3
  * OpenAPI Module DI Tokens
4
4
  */
5
5
  const OPENAPI_TOKENS = {
6
+ /** Static options provided via forRoot() */
6
7
  Options: Symbol.for("stratal:openapi:options"),
8
+ /** Request-scoped config service that supports runtime overrides */
7
9
  ConfigService: Symbol.for("stratal:openapi:config:service"),
10
+ /** OpenAPI service that generates specs and serves endpoints */
8
11
  OpenAPIService: Symbol.for("stratal:openapi:service")
9
12
  };
10
13
  //#endregion
@@ -194,4 +197,4 @@ var OpenApiToolsService = class OpenApiToolsService {
194
197
  //#endregion
195
198
  export { OPENAPI_TOKENS as n, OpenApiToolsService as t };
196
199
 
197
- //# sourceMappingURL=openapi-tools.service-B77QXD56.mjs.map
200
+ //# sourceMappingURL=openapi-tools.service-CYWGuhue.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi-tools.service-B77QXD56.mjs","names":[],"sources":["../src/openapi/openapi.tokens.ts","../src/openapi/services/openapi-tools.service.ts"],"sourcesContent":["/**\n * OpenAPI Module DI Tokens\n */\nexport const OPENAPI_TOKENS = {\n /** Static options provided via forRoot() */\n Options: Symbol.for('stratal:openapi:options'),\n\n /** Request-scoped config service that supports runtime overrides */\n ConfigService: Symbol.for('stratal:openapi:config:service'),\n\n /** OpenAPI service that generates specs and serves endpoints */\n OpenAPIService: Symbol.for('stratal:openapi:service'),\n} as const\n","import { type OpenAPIObject } from \"../../i18n/validation\"\nimport type { HttpMethod } from '../../router/types'\n\ntype JsonSchema = Record<string, unknown>\n\nexport interface ToolDefinition {\n name: string\n description: string\n inputSchema: JsonSchema\n method: string\n path: string\n pathParams: string[]\n}\n\nexport interface ToolExecutionResult {\n status: number\n body: string\n headers: Record<string, string>\n}\n\nexport interface ToolFilter {\n tags?: string[]\n pathPrefix?: string\n}\n\nexport type Dispatcher = (method: string, url: string, options?: {\n body?: unknown\n headers?: Record<string, string>\n}) => Promise<Response>\n\ninterface OperationObject {\n operationId?: string\n summary?: string\n description?: string\n tags?: string[]\n parameters?: ParameterObject[]\n requestBody?: RequestBodyObject\n}\n\ninterface ParameterObject {\n name: string\n in: string\n required?: boolean\n schema?: JsonSchema\n description?: string\n}\n\ninterface RequestBodyObject {\n required?: boolean\n content?: Record<string, { schema?: JsonSchema }>\n}\n\n/**\n * Converts an OpenAPI 3.0 spec into callable tool definitions.\n *\n * Plain class (no DI) — reusable across MCP, CLI, and custom tooling.\n */\nexport class OpenApiToolsService {\n private static readonly HTTP_METHODS: Set<string> = new Set<HttpMethod>(['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'])\n\n private tools: ToolDefinition[] = []\n private toolMap = new Map<string, ToolDefinition>()\n private dispatcher?: Dispatcher\n\n private spec: OpenAPIObject\n\n constructor(spec: OpenAPIObject, options?: { dispatcher?: Dispatcher }) {\n this.spec = spec\n this.dispatcher = options?.dispatcher\n this.tools = this.buildTools()\n for (const tool of this.tools) {\n this.toolMap.set(tool.name, tool)\n }\n }\n\n getTools(filter?: ToolFilter): ToolDefinition[] {\n let tools = this.tools\n\n if (filter?.tags?.length) {\n const tagSet = new Set(filter.tags)\n tools = tools.filter((t) => {\n const op = this.getOperation(t.method, t.path)\n return op?.tags?.some((tag) => tagSet.has(tag)) ?? false\n })\n }\n\n if (filter?.pathPrefix) {\n const prefix = filter.pathPrefix\n tools = tools.filter((t) => t.path.startsWith(prefix))\n }\n\n return tools\n }\n\n getTool(name: string): ToolDefinition | undefined {\n return this.toolMap.get(name)\n }\n\n async executeTool(name: string, args: Record<string, unknown>): Promise<ToolExecutionResult> {\n const tool = this.toolMap.get(name)\n if (!tool) {\n throw new Error(`Tool not found: ${name}`)\n }\n if (!this.dispatcher) {\n throw new Error('No dispatcher configured')\n }\n\n // Interpolate path params\n let url = tool.path\n for (const param of tool.pathParams) {\n const value = args[`path_${param}`]\n if (value === undefined) {\n throw new Error(`Missing required path parameter: ${param}`)\n }\n url = url.replace(`{${param}}`, encodeURIComponent(value != null && typeof value === 'object' ? JSON.stringify(value) : String(value as string | number | boolean)))\n }\n\n // Collect query params\n const queryParts: string[] = []\n for (const key of Object.keys(args)) {\n if (key.startsWith('query_')) {\n const paramName = key.slice(6)\n const value = args[key]\n queryParts.push(`${encodeURIComponent(paramName)}=${encodeURIComponent(value != null && typeof value === 'object' ? JSON.stringify(value) : String(value as string | number | boolean))}`)\n }\n }\n if (queryParts.length > 0) {\n url += `?${queryParts.join('&')}`\n }\n\n const body = args.body\n const response = await this.dispatcher(\n tool.method.toUpperCase(),\n url,\n body !== undefined ? { body } : undefined,\n )\n\n const responseHeaders: Record<string, string> = {}\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value\n })\n\n return {\n status: response.status,\n body: await response.text(),\n headers: responseHeaders,\n }\n }\n\n private buildTools(): ToolDefinition[] {\n const tools: ToolDefinition[] = []\n const paths = this.spec.paths\n\n for (const [path, pathItem] of Object.entries(paths)) {\n for (const [method, operation] of Object.entries(pathItem)) {\n if (!operation || typeof operation !== 'object') continue\n if (!OpenApiToolsService.HTTP_METHODS.has(method.toLowerCase())) continue\n\n const op = operation as OperationObject\n const name = op.operationId ?? this.generateName(method, path)\n const description = this.buildDescription(op, method, path)\n const pathItemParams = (pathItem as Record<string, unknown>).parameters as ParameterObject[] | undefined\n const mergedParameters = this.mergeParameters(pathItemParams, op.parameters)\n const { schema, pathParams } = this.buildInputSchema({ ...op, parameters: mergedParameters })\n\n tools.push({ name, description, inputSchema: schema, method: method.toUpperCase(), path, pathParams })\n }\n }\n\n return tools\n }\n\n private generateName(method: string, path: string): string {\n const snake = path\n .replace(/[{}]/g, '')\n .replace(/[^a-zA-Z0-9]+/g, '_')\n .replace(/^_|_$/g, '')\n .toLowerCase()\n return `${method.toLowerCase()}_${snake}`\n }\n\n private buildDescription(op: OperationObject, method: string, path: string): string {\n if (op.summary && op.description) {\n return `${op.summary} — ${op.description}`\n }\n return op.summary ?? op.description ?? `${method.toUpperCase()} ${path}`\n }\n\n private buildInputSchema(op: OperationObject): { schema: JsonSchema; pathParams: string[] } {\n const properties: Record<string, JsonSchema> = {}\n const required: string[] = []\n const pathParams: string[] = []\n\n // Parameters (path + query)\n for (const param of op.parameters ?? []) {\n const resolvedParam = this.resolveRef(param) as ParameterObject\n const paramSchema = resolvedParam.schema ? this.resolveRef(resolvedParam.schema) as JsonSchema : { type: 'string' }\n\n if (resolvedParam.in === 'path') {\n pathParams.push(resolvedParam.name)\n const key = `path_${resolvedParam.name}`\n properties[key] = { ...paramSchema }\n if (resolvedParam.description) properties[key].description = resolvedParam.description\n required.push(key)\n } else if (resolvedParam.in === 'query') {\n const key = `query_${resolvedParam.name}`\n properties[key] = { ...paramSchema }\n if (resolvedParam.description) properties[key].description = resolvedParam.description\n if (resolvedParam.required) required.push(key)\n }\n }\n\n // Request body\n const resolvedBody = op.requestBody ? this.resolveRef(op.requestBody) as RequestBodyObject : undefined\n if (resolvedBody) {\n const jsonContent = resolvedBody.content?.['application/json']\n if (jsonContent?.schema) {\n properties.body = this.resolveRef(jsonContent.schema) as JsonSchema\n } else {\n properties.body = { type: 'object' }\n }\n const needsBody = resolvedBody.required === true\n if (needsBody) {\n required.push('body')\n }\n }\n\n const schema: JsonSchema = { type: 'object', properties }\n if (required.length > 0) {\n schema.required = required\n }\n\n return { schema, pathParams }\n }\n\n private mergeParameters(pathLevel?: ParameterObject[], opLevel?: ParameterObject[]): ParameterObject[] {\n const resolvedPathLevel = pathLevel?.map((p) => this.resolveRef(p) as ParameterObject)\n const resolvedOpLevel = opLevel?.map((p) => this.resolveRef(p) as ParameterObject)\n\n if (!resolvedPathLevel?.length) return resolvedOpLevel ?? []\n if (!resolvedOpLevel?.length) return resolvedPathLevel\n\n const opKeys = new Set(resolvedOpLevel.map((p) => `${p.in}:${p.name}`))\n const inherited = resolvedPathLevel.filter((p) => !opKeys.has(`${p.in}:${p.name}`))\n return [...inherited, ...resolvedOpLevel]\n }\n\n private resolveRef(obj: unknown, seen = new Set<string>()): unknown {\n if (!obj || typeof obj !== 'object') return obj\n const record = obj as Record<string, unknown>\n\n if (typeof record.$ref === 'string') {\n const refPath = record.$ref\n if (seen.has(refPath)) return obj\n seen.add(refPath)\n\n const resolved = this.lookupRef(refPath)\n if (!resolved) return obj\n return this.resolveRef(resolved, seen)\n }\n\n // Recursively walk all properties and resolve nested $refs\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(record)) {\n if (Array.isArray(value)) {\n result[key] = value.map((item) => this.resolveRef(item, seen))\n } else if (value && typeof value === 'object') {\n result[key] = this.resolveRef(value, seen)\n } else {\n result[key] = value\n }\n }\n return result\n }\n\n private lookupRef(refPath: string): unknown {\n const components = this.spec.components as Record<string, Record<string, unknown>> | undefined\n if (!components) return undefined\n\n const match = /^#\\/components\\/(\\w+)\\/(.+)$/.exec(refPath)\n if (!match) return undefined\n\n const [, section, name] = match\n const sectionObj = components[section]\n if (typeof sectionObj !== 'object') return undefined\n return sectionObj[name]\n }\n\n private getOperation(method: string, path: string): OperationObject | undefined {\n const paths = this.spec.paths as Record<string, Record<string, unknown>> | undefined\n return paths?.[path]?.[method.toLowerCase()] as OperationObject | undefined\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"openapi-tools.service-CYWGuhue.mjs","names":[],"sources":["../src/openapi/openapi.tokens.ts","../src/openapi/services/openapi-tools.service.ts"],"sourcesContent":["/**\n * OpenAPI Module DI Tokens\n */\nexport const OPENAPI_TOKENS = {\n /** Static options provided via forRoot() */\n Options: Symbol.for('stratal:openapi:options'),\n\n /** Request-scoped config service that supports runtime overrides */\n ConfigService: Symbol.for('stratal:openapi:config:service'),\n\n /** OpenAPI service that generates specs and serves endpoints */\n OpenAPIService: Symbol.for('stratal:openapi:service'),\n} as const\n","import { type OpenAPIObject } from \"../../i18n/validation\"\nimport type { HttpMethod } from '../../router/types'\n\ntype JsonSchema = Record<string, unknown>\n\nexport interface ToolDefinition {\n name: string\n description: string\n inputSchema: JsonSchema\n method: string\n path: string\n pathParams: string[]\n}\n\nexport interface ToolExecutionResult {\n status: number\n body: string\n headers: Record<string, string>\n}\n\nexport interface ToolFilter {\n tags?: string[]\n pathPrefix?: string\n}\n\nexport type Dispatcher = (method: string, url: string, options?: {\n body?: unknown\n headers?: Record<string, string>\n}) => Promise<Response>\n\ninterface OperationObject {\n operationId?: string\n summary?: string\n description?: string\n tags?: string[]\n parameters?: ParameterObject[]\n requestBody?: RequestBodyObject\n}\n\ninterface ParameterObject {\n name: string\n in: string\n required?: boolean\n schema?: JsonSchema\n description?: string\n}\n\ninterface RequestBodyObject {\n required?: boolean\n content?: Record<string, { schema?: JsonSchema }>\n}\n\n/**\n * Converts an OpenAPI 3.0 spec into callable tool definitions.\n *\n * Plain class (no DI) — reusable across MCP, CLI, and custom tooling.\n */\nexport class OpenApiToolsService {\n private static readonly HTTP_METHODS: Set<string> = new Set<HttpMethod>(['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'])\n\n private tools: ToolDefinition[] = []\n private toolMap = new Map<string, ToolDefinition>()\n private dispatcher?: Dispatcher\n\n private spec: OpenAPIObject\n\n constructor(spec: OpenAPIObject, options?: { dispatcher?: Dispatcher }) {\n this.spec = spec\n this.dispatcher = options?.dispatcher\n this.tools = this.buildTools()\n for (const tool of this.tools) {\n this.toolMap.set(tool.name, tool)\n }\n }\n\n getTools(filter?: ToolFilter): ToolDefinition[] {\n let tools = this.tools\n\n if (filter?.tags?.length) {\n const tagSet = new Set(filter.tags)\n tools = tools.filter((t) => {\n const op = this.getOperation(t.method, t.path)\n return op?.tags?.some((tag) => tagSet.has(tag)) ?? false\n })\n }\n\n if (filter?.pathPrefix) {\n const prefix = filter.pathPrefix\n tools = tools.filter((t) => t.path.startsWith(prefix))\n }\n\n return tools\n }\n\n getTool(name: string): ToolDefinition | undefined {\n return this.toolMap.get(name)\n }\n\n async executeTool(name: string, args: Record<string, unknown>): Promise<ToolExecutionResult> {\n const tool = this.toolMap.get(name)\n if (!tool) {\n throw new Error(`Tool not found: ${name}`)\n }\n if (!this.dispatcher) {\n throw new Error('No dispatcher configured')\n }\n\n // Interpolate path params\n let url = tool.path\n for (const param of tool.pathParams) {\n const value = args[`path_${param}`]\n if (value === undefined) {\n throw new Error(`Missing required path parameter: ${param}`)\n }\n url = url.replace(`{${param}}`, encodeURIComponent(value != null && typeof value === 'object' ? JSON.stringify(value) : String(value as string | number | boolean)))\n }\n\n // Collect query params\n const queryParts: string[] = []\n for (const key of Object.keys(args)) {\n if (key.startsWith('query_')) {\n const paramName = key.slice(6)\n const value = args[key]\n queryParts.push(`${encodeURIComponent(paramName)}=${encodeURIComponent(value != null && typeof value === 'object' ? JSON.stringify(value) : String(value as string | number | boolean))}`)\n }\n }\n if (queryParts.length > 0) {\n url += `?${queryParts.join('&')}`\n }\n\n const body = args.body\n const response = await this.dispatcher(\n tool.method.toUpperCase(),\n url,\n body !== undefined ? { body } : undefined,\n )\n\n const responseHeaders: Record<string, string> = {}\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value\n })\n\n return {\n status: response.status,\n body: await response.text(),\n headers: responseHeaders,\n }\n }\n\n private buildTools(): ToolDefinition[] {\n const tools: ToolDefinition[] = []\n const paths = this.spec.paths\n\n for (const [path, pathItem] of Object.entries(paths)) {\n for (const [method, operation] of Object.entries(pathItem)) {\n if (!operation || typeof operation !== 'object') continue\n if (!OpenApiToolsService.HTTP_METHODS.has(method.toLowerCase())) continue\n\n const op = operation as OperationObject\n const name = op.operationId ?? this.generateName(method, path)\n const description = this.buildDescription(op, method, path)\n const pathItemParams = (pathItem as Record<string, unknown>).parameters as ParameterObject[] | undefined\n const mergedParameters = this.mergeParameters(pathItemParams, op.parameters)\n const { schema, pathParams } = this.buildInputSchema({ ...op, parameters: mergedParameters })\n\n tools.push({ name, description, inputSchema: schema, method: method.toUpperCase(), path, pathParams })\n }\n }\n\n return tools\n }\n\n private generateName(method: string, path: string): string {\n const snake = path\n .replace(/[{}]/g, '')\n .replace(/[^a-zA-Z0-9]+/g, '_')\n .replace(/^_|_$/g, '')\n .toLowerCase()\n return `${method.toLowerCase()}_${snake}`\n }\n\n private buildDescription(op: OperationObject, method: string, path: string): string {\n if (op.summary && op.description) {\n return `${op.summary} — ${op.description}`\n }\n return op.summary ?? op.description ?? `${method.toUpperCase()} ${path}`\n }\n\n private buildInputSchema(op: OperationObject): { schema: JsonSchema; pathParams: string[] } {\n const properties: Record<string, JsonSchema> = {}\n const required: string[] = []\n const pathParams: string[] = []\n\n // Parameters (path + query)\n for (const param of op.parameters ?? []) {\n const resolvedParam = this.resolveRef(param) as ParameterObject\n const paramSchema = resolvedParam.schema ? this.resolveRef(resolvedParam.schema) as JsonSchema : { type: 'string' }\n\n if (resolvedParam.in === 'path') {\n pathParams.push(resolvedParam.name)\n const key = `path_${resolvedParam.name}`\n properties[key] = { ...paramSchema }\n if (resolvedParam.description) properties[key].description = resolvedParam.description\n required.push(key)\n } else if (resolvedParam.in === 'query') {\n const key = `query_${resolvedParam.name}`\n properties[key] = { ...paramSchema }\n if (resolvedParam.description) properties[key].description = resolvedParam.description\n if (resolvedParam.required) required.push(key)\n }\n }\n\n // Request body\n const resolvedBody = op.requestBody ? this.resolveRef(op.requestBody) as RequestBodyObject : undefined\n if (resolvedBody) {\n const jsonContent = resolvedBody.content?.['application/json']\n if (jsonContent?.schema) {\n properties.body = this.resolveRef(jsonContent.schema) as JsonSchema\n } else {\n properties.body = { type: 'object' }\n }\n const needsBody = resolvedBody.required === true\n if (needsBody) {\n required.push('body')\n }\n }\n\n const schema: JsonSchema = { type: 'object', properties }\n if (required.length > 0) {\n schema.required = required\n }\n\n return { schema, pathParams }\n }\n\n private mergeParameters(pathLevel?: ParameterObject[], opLevel?: ParameterObject[]): ParameterObject[] {\n const resolvedPathLevel = pathLevel?.map((p) => this.resolveRef(p) as ParameterObject)\n const resolvedOpLevel = opLevel?.map((p) => this.resolveRef(p) as ParameterObject)\n\n if (!resolvedPathLevel?.length) return resolvedOpLevel ?? []\n if (!resolvedOpLevel?.length) return resolvedPathLevel\n\n const opKeys = new Set(resolvedOpLevel.map((p) => `${p.in}:${p.name}`))\n const inherited = resolvedPathLevel.filter((p) => !opKeys.has(`${p.in}:${p.name}`))\n return [...inherited, ...resolvedOpLevel]\n }\n\n private resolveRef(obj: unknown, seen = new Set<string>()): unknown {\n if (!obj || typeof obj !== 'object') return obj\n const record = obj as Record<string, unknown>\n\n if (typeof record.$ref === 'string') {\n const refPath = record.$ref\n if (seen.has(refPath)) return obj\n seen.add(refPath)\n\n const resolved = this.lookupRef(refPath)\n if (!resolved) return obj\n return this.resolveRef(resolved, seen)\n }\n\n // Recursively walk all properties and resolve nested $refs\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(record)) {\n if (Array.isArray(value)) {\n result[key] = value.map((item) => this.resolveRef(item, seen))\n } else if (value && typeof value === 'object') {\n result[key] = this.resolveRef(value, seen)\n } else {\n result[key] = value\n }\n }\n return result\n }\n\n private lookupRef(refPath: string): unknown {\n const components = this.spec.components as Record<string, Record<string, unknown>> | undefined\n if (!components) return undefined\n\n const match = /^#\\/components\\/(\\w+)\\/(.+)$/.exec(refPath)\n if (!match) return undefined\n\n const [, section, name] = match\n const sectionObj = components[section]\n if (typeof sectionObj !== 'object') return undefined\n return sectionObj[name]\n }\n\n private getOperation(method: string, path: string): OperationObject | undefined {\n const paths = this.spec.paths as Record<string, Record<string, unknown>> | undefined\n return paths?.[path]?.[method.toLowerCase()] as OperationObject | undefined\n }\n}\n"],"mappings":";;;;AAGA,MAAa,iBAAiB;;CAE5B,SAAS,OAAO,IAAI,0BAA0B;;CAG9C,eAAe,OAAO,IAAI,iCAAiC;;CAG3D,gBAAgB,OAAO,IAAI,0BAA0B;CACtD;;;;;;;;AC6CD,IAAa,sBAAb,MAAa,oBAAoB;CAC/B,OAAwB,eAA4B,IAAI,IAAgB;EAAC;EAAO;EAAQ;EAAO;EAAU;EAAS;EAAQ;EAAW;EAAQ,CAAC;CAE9I,QAAkC,EAAE;CACpC,0BAAkB,IAAI,KAA6B;CACnD;CAEA;CAEA,YAAY,MAAqB,SAAuC;AACtE,OAAK,OAAO;AACZ,OAAK,aAAa,SAAS;AAC3B,OAAK,QAAQ,KAAK,YAAY;AAC9B,OAAK,MAAM,QAAQ,KAAK,MACtB,MAAK,QAAQ,IAAI,KAAK,MAAM,KAAK;;CAIrC,SAAS,QAAuC;EAC9C,IAAI,QAAQ,KAAK;AAEjB,MAAI,QAAQ,MAAM,QAAQ;GACxB,MAAM,SAAS,IAAI,IAAI,OAAO,KAAK;AACnC,WAAQ,MAAM,QAAQ,MAAM;AAE1B,WADW,KAAK,aAAa,EAAE,QAAQ,EAAE,KAChC,EAAE,MAAM,MAAM,QAAQ,OAAO,IAAI,IAAI,CAAC,IAAI;KACnD;;AAGJ,MAAI,QAAQ,YAAY;GACtB,MAAM,SAAS,OAAO;AACtB,WAAQ,MAAM,QAAQ,MAAM,EAAE,KAAK,WAAW,OAAO,CAAC;;AAGxD,SAAO;;CAGT,QAAQ,MAA0C;AAChD,SAAO,KAAK,QAAQ,IAAI,KAAK;;CAG/B,MAAM,YAAY,MAAc,MAA6D;EAC3F,MAAM,OAAO,KAAK,QAAQ,IAAI,KAAK;AACnC,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,mBAAmB,OAAO;AAE5C,MAAI,CAAC,KAAK,WACR,OAAM,IAAI,MAAM,2BAA2B;EAI7C,IAAI,MAAM,KAAK;AACf,OAAK,MAAM,SAAS,KAAK,YAAY;GACnC,MAAM,QAAQ,KAAK,QAAQ;AAC3B,OAAI,UAAU,KAAA,EACZ,OAAM,IAAI,MAAM,oCAAoC,QAAQ;AAE9D,SAAM,IAAI,QAAQ,IAAI,MAAM,IAAI,mBAAmB,SAAS,QAAQ,OAAO,UAAU,WAAW,KAAK,UAAU,MAAM,GAAG,OAAO,MAAmC,CAAC,CAAC;;EAItK,MAAM,aAAuB,EAAE;AAC/B,OAAK,MAAM,OAAO,OAAO,KAAK,KAAK,CACjC,KAAI,IAAI,WAAW,SAAS,EAAE;GAC5B,MAAM,YAAY,IAAI,MAAM,EAAE;GAC9B,MAAM,QAAQ,KAAK;AACnB,cAAW,KAAK,GAAG,mBAAmB,UAAU,CAAC,GAAG,mBAAmB,SAAS,QAAQ,OAAO,UAAU,WAAW,KAAK,UAAU,MAAM,GAAG,OAAO,MAAmC,CAAC,GAAG;;AAG9L,MAAI,WAAW,SAAS,EACtB,QAAO,IAAI,WAAW,KAAK,IAAI;EAGjC,MAAM,OAAO,KAAK;EAClB,MAAM,WAAW,MAAM,KAAK,WAC1B,KAAK,OAAO,aAAa,EACzB,KACA,SAAS,KAAA,IAAY,EAAE,MAAM,GAAG,KAAA,EACjC;EAED,MAAM,kBAA0C,EAAE;AAClD,WAAS,QAAQ,SAAS,OAAO,QAAQ;AACvC,mBAAgB,OAAO;IACvB;AAEF,SAAO;GACL,QAAQ,SAAS;GACjB,MAAM,MAAM,SAAS,MAAM;GAC3B,SAAS;GACV;;CAGH,aAAuC;EACrC,MAAM,QAA0B,EAAE;EAClC,MAAM,QAAQ,KAAK,KAAK;AAExB,OAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,MAAM,CAClD,MAAK,MAAM,CAAC,QAAQ,cAAc,OAAO,QAAQ,SAAS,EAAE;AAC1D,OAAI,CAAC,aAAa,OAAO,cAAc,SAAU;AACjD,OAAI,CAAC,oBAAoB,aAAa,IAAI,OAAO,aAAa,CAAC,CAAE;GAEjE,MAAM,KAAK;GACX,MAAM,OAAO,GAAG,eAAe,KAAK,aAAa,QAAQ,KAAK;GAC9D,MAAM,cAAc,KAAK,iBAAiB,IAAI,QAAQ,KAAK;GAC3D,MAAM,iBAAkB,SAAqC;GAC7D,MAAM,mBAAmB,KAAK,gBAAgB,gBAAgB,GAAG,WAAW;GAC5E,MAAM,EAAE,QAAQ,eAAe,KAAK,iBAAiB;IAAE,GAAG;IAAI,YAAY;IAAkB,CAAC;AAE7F,SAAM,KAAK;IAAE;IAAM;IAAa,aAAa;IAAQ,QAAQ,OAAO,aAAa;IAAE;IAAM;IAAY,CAAC;;AAI1G,SAAO;;CAGT,aAAqB,QAAgB,MAAsB;EACzD,MAAM,QAAQ,KACX,QAAQ,SAAS,GAAG,CACpB,QAAQ,kBAAkB,IAAI,CAC9B,QAAQ,UAAU,GAAG,CACrB,aAAa;AAChB,SAAO,GAAG,OAAO,aAAa,CAAC,GAAG;;CAGpC,iBAAyB,IAAqB,QAAgB,MAAsB;AAClF,MAAI,GAAG,WAAW,GAAG,YACnB,QAAO,GAAG,GAAG,QAAQ,KAAK,GAAG;AAE/B,SAAO,GAAG,WAAW,GAAG,eAAe,GAAG,OAAO,aAAa,CAAC,GAAG;;CAGpE,iBAAyB,IAAmE;EAC1F,MAAM,aAAyC,EAAE;EACjD,MAAM,WAAqB,EAAE;EAC7B,MAAM,aAAuB,EAAE;AAG/B,OAAK,MAAM,SAAS,GAAG,cAAc,EAAE,EAAE;GACvC,MAAM,gBAAgB,KAAK,WAAW,MAAM;GAC5C,MAAM,cAAc,cAAc,SAAS,KAAK,WAAW,cAAc,OAAO,GAAiB,EAAE,MAAM,UAAU;AAEnH,OAAI,cAAc,OAAO,QAAQ;AAC/B,eAAW,KAAK,cAAc,KAAK;IACnC,MAAM,MAAM,QAAQ,cAAc;AAClC,eAAW,OAAO,EAAE,GAAG,aAAa;AACpC,QAAI,cAAc,YAAa,YAAW,KAAK,cAAc,cAAc;AAC3E,aAAS,KAAK,IAAI;cACT,cAAc,OAAO,SAAS;IACvC,MAAM,MAAM,SAAS,cAAc;AACnC,eAAW,OAAO,EAAE,GAAG,aAAa;AACpC,QAAI,cAAc,YAAa,YAAW,KAAK,cAAc,cAAc;AAC3E,QAAI,cAAc,SAAU,UAAS,KAAK,IAAI;;;EAKlD,MAAM,eAAe,GAAG,cAAc,KAAK,WAAW,GAAG,YAAY,GAAwB,KAAA;AAC7F,MAAI,cAAc;GAChB,MAAM,cAAc,aAAa,UAAU;AAC3C,OAAI,aAAa,OACf,YAAW,OAAO,KAAK,WAAW,YAAY,OAAO;OAErD,YAAW,OAAO,EAAE,MAAM,UAAU;AAGtC,OADkB,aAAa,aAAa,KAE1C,UAAS,KAAK,OAAO;;EAIzB,MAAM,SAAqB;GAAE,MAAM;GAAU;GAAY;AACzD,MAAI,SAAS,SAAS,EACpB,QAAO,WAAW;AAGpB,SAAO;GAAE;GAAQ;GAAY;;CAG/B,gBAAwB,WAA+B,SAAgD;EACrG,MAAM,oBAAoB,WAAW,KAAK,MAAM,KAAK,WAAW,EAAE,CAAoB;EACtF,MAAM,kBAAkB,SAAS,KAAK,MAAM,KAAK,WAAW,EAAE,CAAoB;AAElF,MAAI,CAAC,mBAAmB,OAAQ,QAAO,mBAAmB,EAAE;AAC5D,MAAI,CAAC,iBAAiB,OAAQ,QAAO;EAErC,MAAM,SAAS,IAAI,IAAI,gBAAgB,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,EAAE,OAAO,CAAC;AAEvE,SAAO,CAAC,GADU,kBAAkB,QAAQ,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,GAAG,GAAG,EAAE,OAAO,CAC9D,EAAE,GAAG,gBAAgB;;CAG3C,WAAmB,KAAc,uBAAO,IAAI,KAAa,EAAW;AAClE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;EAC5C,MAAM,SAAS;AAEf,MAAI,OAAO,OAAO,SAAS,UAAU;GACnC,MAAM,UAAU,OAAO;AACvB,OAAI,KAAK,IAAI,QAAQ,CAAE,QAAO;AAC9B,QAAK,IAAI,QAAQ;GAEjB,MAAM,WAAW,KAAK,UAAU,QAAQ;AACxC,OAAI,CAAC,SAAU,QAAO;AACtB,UAAO,KAAK,WAAW,UAAU,KAAK;;EAIxC,MAAM,SAAkC,EAAE;AAC1C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,OAAO,MAAM,KAAK,SAAS,KAAK,WAAW,MAAM,KAAK,CAAC;WACrD,SAAS,OAAO,UAAU,SACnC,QAAO,OAAO,KAAK,WAAW,OAAO,KAAK;MAE1C,QAAO,OAAO;AAGlB,SAAO;;CAGT,UAAkB,SAA0B;EAC1C,MAAM,aAAa,KAAK,KAAK;AAC7B,MAAI,CAAC,WAAY,QAAO,KAAA;EAExB,MAAM,QAAQ,+BAA+B,KAAK,QAAQ;AAC1D,MAAI,CAAC,MAAO,QAAO,KAAA;EAEnB,MAAM,GAAG,SAAS,QAAQ;EAC1B,MAAM,aAAa,WAAW;AAC9B,MAAI,OAAO,eAAe,SAAU,QAAO,KAAA;AAC3C,SAAO,WAAW;;CAGpB,aAAqB,QAAgB,MAA2C;AAE9E,SADc,KAAK,KAAK,QACT,QAAQ,OAAO,aAAa"}
@@ -1,5 +1,5 @@
1
- import { Cr as Container, Yn as RouterEnv } from "./index-BrmS34sa.mjs";
2
- import { n as OpenAPIObject, t as OpenAPIHono } from "./index-Dfpd_ypO.mjs";
1
+ import { Cr as Container, Xn as RouterEnv } from "./index-DPFqRs8L.mjs";
2
+ import { n as OpenAPIObject, t as OpenAPIHono } from "./index-B437eK7p.mjs";
3
3
 
4
4
  //#region src/openapi/services/openapi.service.d.ts
5
5
  /**
@@ -47,4 +47,4 @@ declare class OpenAPIService {
47
47
  }
48
48
  //#endregion
49
49
  export { OpenAPIService as t };
50
- //# sourceMappingURL=openapi.service-6yj0BUY4.d.mts.map
50
+ //# sourceMappingURL=openapi.service-Bv_NioM9.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.service-6yj0BUY4.d.mts","names":[],"sources":["../src/openapi/services/openapi.service.ts"],"mappings":";;;;;AA0BA;;;;;;;;;;;;;;cACa,cAAA;EAMH;;;;EAAR,OAAA,CAAQ,GAAA,EAAK,WAAA,CAAY,SAAA,GAAY,SAAA,EAAW,SAAA,GAAY,aAAA;EAqCxC;;;EAApB,cAAA,CAAe,GAAA,EAAK,WAAA,CAAY,SAAA,GAAY,SAAA,EAAW,SAAA;EAAA,QA4C/C,eAAA;EAAA;;;EAAA,QAQA,4BAAA;EA2EA;;;EAAA,QAjDA,YAAA;;;;UAoBA,aAAA;;;;UA6BA,iBAAA;AAAA"}
1
+ {"version":3,"file":"openapi.service-Bv_NioM9.d.mts","names":[],"sources":["../src/openapi/services/openapi.service.ts"],"mappings":";;;;;AA0BA;;;;;;;;;;;;;;cACa,cAAA;EAMH;;;;EAAR,OAAA,CAAQ,GAAA,EAAK,WAAA,CAAY,SAAA,GAAY,SAAA,EAAW,SAAA,GAAY,aAAA;EAqCxC;;;EAApB,cAAA,CAAe,GAAA,EAAK,WAAA,CAAY,SAAA,GAAY,SAAA,EAAW,SAAA;EAAA,QA4C/C,eAAA;EAAA;;;EAAA,QAQA,4BAAA;EA2EA;;;EAAA,QAjDA,YAAA;;;;UAoBA,aAAA;;;;UA6BA,iBAAA;AAAA"}
@@ -1,9 +1,9 @@
1
- import { Cr as Container, J as RouteRegistry, Qt as ModuleRegistry, X as Application, an as CommandInput, cn as ParsedArgument, dn as Quarry, ln as ParsedOption, sn as CommandResult, un as ParsedSignature } from "../index-BrmS34sa.mjs";
2
- import { t as Constructor } from "../types-CN0zONAZ.mjs";
3
- import { t as CronManager } from "../cron-manager-BnEZquBL.mjs";
4
- import { t as ConsumerRegistry } from "../consumer-registry-BkuHXR_u.mjs";
5
- import { t as OpenAPIService } from "../openapi.service-6yj0BUY4.mjs";
6
- import { t as Command } from "../command-B1YuV-UZ.mjs";
1
+ import { $t as ModuleRegistry, Cr as Container, J as RouteRegistry, X as Application, cn as CommandResult, dn as ParsedSignature, fn as Quarry, ln as ParsedArgument, on as CommandInput, un as ParsedOption } from "../index-DPFqRs8L.mjs";
2
+ import { t as Constructor } from "../types-DIWemRad.mjs";
3
+ import { t as CronManager } from "../cron-manager-RuPtFVLy.mjs";
4
+ import { t as ConsumerRegistry } from "../consumer-registry-Doom7BEh.mjs";
5
+ import { t as OpenAPIService } from "../openapi.service-Bv_NioM9.mjs";
6
+ import { t as Command } from "../command-DsQq56Lp.mjs";
7
7
 
8
8
  //#region src/quarry/commands/api.command.d.ts
9
9
  declare class ApiCommand extends Command {
@@ -115,7 +115,7 @@ declare class McpToolsCommand extends Command {
115
115
  static command: string;
116
116
  static description: string;
117
117
  constructor(app: Application, openAPIService: OpenAPIService);
118
- handle(): number | undefined;
118
+ handle(): Promise<number | undefined>;
119
119
  }
120
120
  //#endregion
121
121
  //#region src/quarry/commands/queue-list.command.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/quarry/commands/api.command.ts","../../src/quarry/commands/event-list.command.ts","../../src/quarry/quarry-registry.ts","../../src/quarry/commands/help.command.ts","../../src/quarry/commands/mcp-serve.command.ts","../../src/quarry/commands/mcp-tools.command.ts","../../src/quarry/commands/queue-list.command.ts","../../src/quarry/commands/route-list.command.ts","../../src/quarry/commands/schedule-list.command.ts","../../src/quarry/errors/command-not-found.error.ts","../../src/quarry/errors/command.error.ts","../../src/quarry/is-command.ts","../../src/quarry/signature-parser.ts","../../src/quarry/usage-generator.ts"],"mappings":";;;;;;;;cAMa,UAAA,SAAmB,OAAA;EAAA,QAKqB,GAAA;EAAA,OAJ5C,OAAA;EAAA,OACA,WAAA;EAAA,OACA,OAAA;cAE4C,GAAA,EAAK,WAAA;EAIlD,MAAA,CAAA,GAAU,OAAA;EAAA,QAUF,SAAA;AAAA;;;cCnBH,gBAAA,SAAyB,OAAA;EAAA,QAIkB,OAAA;EAAA,OAH/C,OAAA;EAAA,OACA,WAAA;cAE+C,OAAA,EAAS,cAAA;EAI/D,MAAA,CAAA;AAAA;;;;;;;ADRF;;;;;cEkBa,cAAA,YAA0B,MAAA;EAAA,iBAKqB,SAAA;EAAA,QAJlD,QAAA;EAAA,QACA,UAAA;EAAA,QACA,OAAA;cAEkD,SAAA,EAAW,SAAA;EFrB9D;;;;EE2BD,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;EFpBlD;;;EEqFN,GAAA,CAAI,IAAA;EF3EmB;;;EEmFvB,GAAA,CAAI,IAAA,WAAe,WAAA,CAAY,OAAA;EDtGpB;;;EC8GX,GAAA,CAAA,GAAO,GAAA,SAAY,WAAA,CAAY,OAAA;ED9GK;;;ECqHpC,IAAA,CAAA;IAAU,IAAA;IAAc,WAAA;IAAsB,OAAA;EAAA;ED7GxC;;;ECuIA,SAAA,CAAU,OAAA;IAAY,UAAA;IAAqB,WAAA;IAAsB,aAAA;EAAA,IAA2B,OAAA;EAxH7B;;;EAmI/D,KAAA,CAAM,IAAA,WAAe,OAAA;EApDI;;;;EAwE/B,QAAA,CAAS,YAAA,EAAc,WAAA,CAAY,OAAA;EAAA,QAkC3B,WAAA;EAAA,QAQA,WAAA;EAAA,QAIA,aAAA;AAAA;;;cC5NG,WAAA,SAAoB,OAAA;EAAA,QAKe,cAAA;EAAA,OAJvC,OAAA;EAAA,OACA,WAAA;EAAA,OACA,OAAA;cAEuC,cAAA,EAAgB,cAAA;EAIxD,MAAA,CAAA,GAAU,OAAA;AAAA;;;cCJL,eAAA,SAAwB,OAAA;EAAA,QAKM,GAAA;EAAA,QACQ,cAAA;EAAA,OAL1C,OAAA;EAAA,OACA,WAAA;cAGkC,GAAA,EAAK,WAAA,EACG,cAAA,EAAgB,cAAA;EAK3D,MAAA,CAAA,GAAU,OAAA;AAAA;;;cCdL,eAAA,SAAwB,OAAA;EAAA,QAKM,GAAA;EAAA,QACQ,cAAA;EAAA,OAL1C,OAAA;EAAA,OACA,WAAA;cAGkC,GAAA,EAAK,WAAA,EACG,cAAA,EAAgB,cAAA;EAKjE,MAAA,CAAA;AAAA;;;cCdW,gBAAA,SAAyB,OAAA;EAAA,QAIoB,SAAA;EAAA,OAHjD,OAAA;EAAA,OACA,WAAA;cAEiD,SAAA,EAAW,gBAAA;EAInE,MAAA,CAAA;AAAA;;;;;;;;;ANPF;;;;;;;;;cOca,gBAAA,SAAyB,OAAA;EAAA,QAIqB,QAAA;EAAA,OAHlD,OAAA;EAAA,OACA,WAAA;cAEkD,QAAA,EAAU,aAAA;EAInE,MAAA,CAAA;EAAA,QAsCQ,SAAA;AAAA;;;cC7DG,mBAAA,SAA4B,OAAA;EAAA,QAIK,IAAA;EAAA,OAHrC,OAAA;EAAA,OACA,WAAA;cAEqC,IAAA,EAAM,WAAA;EAIlD,MAAA,CAAA;AAAA;;;;;;cCVW,oBAAA,SAA6B,KAAA;cAC5B,IAAA;AAAA;;;;;;;;;;cCGD,YAAA,SAAqB,KAAA;cACpB,OAAA;AAAA;;;;;;;;iBCAE,SAAA,CAAU,MAAA,EAAQ,WAAA;;;;;;;;;;AXFlC;;;;iBYQgB,cAAA,CAAe,SAAA,WAAoB,eAAA;;;;;;;;iBCNnC,aAAA,CAAc,SAAA,EAAW,eAAA,EAAiB,WAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/quarry/commands/api.command.ts","../../src/quarry/commands/event-list.command.ts","../../src/quarry/quarry-registry.ts","../../src/quarry/commands/help.command.ts","../../src/quarry/commands/mcp-serve.command.ts","../../src/quarry/commands/mcp-tools.command.ts","../../src/quarry/commands/queue-list.command.ts","../../src/quarry/commands/route-list.command.ts","../../src/quarry/commands/schedule-list.command.ts","../../src/quarry/errors/command-not-found.error.ts","../../src/quarry/errors/command.error.ts","../../src/quarry/is-command.ts","../../src/quarry/signature-parser.ts","../../src/quarry/usage-generator.ts"],"mappings":";;;;;;;;cAMa,UAAA,SAAmB,OAAA;EAAA,QAKqB,GAAA;EAAA,OAJ5C,OAAA;EAAA,OACA,WAAA;EAAA,OACA,OAAA;cAE4C,GAAA,EAAK,WAAA;EAIlD,MAAA,CAAA,GAAU,OAAA;EAAA,QAUF,SAAA;AAAA;;;cCnBH,gBAAA,SAAyB,OAAA;EAAA,QAIkB,OAAA;EAAA,OAH/C,OAAA;EAAA,OACA,WAAA;cAE+C,OAAA,EAAS,cAAA;EAI/D,MAAA,CAAA;AAAA;;;;;;;ADRF;;;;;cEkBa,cAAA,YAA0B,MAAA;EAAA,iBAKqB,SAAA;EAAA,QAJlD,QAAA;EAAA,QACA,UAAA;EAAA,QACA,OAAA;cAEkD,SAAA,EAAW,SAAA;EFrB9D;;;;EE2BD,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,YAAA,GAAe,OAAA,CAAQ,aAAA;EFpBlD;;;EEqFN,GAAA,CAAI,IAAA;EF3EmB;;;EEmFvB,GAAA,CAAI,IAAA,WAAe,WAAA,CAAY,OAAA;EDtGpB;;;EC8GX,GAAA,CAAA,GAAO,GAAA,SAAY,WAAA,CAAY,OAAA;ED9GK;;;ECqHpC,IAAA,CAAA;IAAU,IAAA;IAAc,WAAA;IAAsB,OAAA;EAAA;ED7GxC;;;ECuIA,SAAA,CAAU,OAAA;IAAY,UAAA;IAAqB,WAAA;IAAsB,aAAA;EAAA,IAA2B,OAAA;EAxH7B;;;EAmI/D,KAAA,CAAM,IAAA,WAAe,OAAA;EApDI;;;;EAwE/B,QAAA,CAAS,YAAA,EAAc,WAAA,CAAY,OAAA;EAAA,QAkC3B,WAAA;EAAA,QAQA,WAAA;EAAA,QAIA,aAAA;AAAA;;;cC5NG,WAAA,SAAoB,OAAA;EAAA,QAKe,cAAA;EAAA,OAJvC,OAAA;EAAA,OACA,WAAA;EAAA,OACA,OAAA;cAEuC,cAAA,EAAgB,cAAA;EAIxD,MAAA,CAAA,GAAU,OAAA;AAAA;;;cCJL,eAAA,SAAwB,OAAA;EAAA,QAKM,GAAA;EAAA,QACQ,cAAA;EAAA,OAL1C,OAAA;EAAA,OACA,WAAA;cAGkC,GAAA,EAAK,WAAA,EACG,cAAA,EAAgB,cAAA;EAK3D,MAAA,CAAA,GAAU,OAAA;AAAA;;;cCdL,eAAA,SAAwB,OAAA;EAAA,QAKM,GAAA;EAAA,QACQ,cAAA;EAAA,OAL1C,OAAA;EAAA,OACA,WAAA;cAGkC,GAAA,EAAK,WAAA,EACG,cAAA,EAAgB,cAAA;EAK3D,MAAA,CAAA,GAAU,OAAA;AAAA;;;cCdL,gBAAA,SAAyB,OAAA;EAAA,QAIoB,SAAA;EAAA,OAHjD,OAAA;EAAA,OACA,WAAA;cAEiD,SAAA,EAAW,gBAAA;EAInE,MAAA,CAAA;AAAA;;;;;;;;;ANPF;;;;;;;;;cOca,gBAAA,SAAyB,OAAA;EAAA,QAIqB,QAAA;EAAA,OAHlD,OAAA;EAAA,OACA,WAAA;cAEkD,QAAA,EAAU,aAAA;EAInE,MAAA,CAAA;EAAA,QAsCQ,SAAA;AAAA;;;cC7DG,mBAAA,SAA4B,OAAA;EAAA,QAIK,IAAA;EAAA,OAHrC,OAAA;EAAA,OACA,WAAA;cAEqC,IAAA,EAAM,WAAA;EAIlD,MAAA,CAAA;AAAA;;;;;;cCVW,oBAAA,SAA6B,KAAA;cAC5B,IAAA;AAAA;;;;;;;;;;cCGD,YAAA,SAAqB,KAAA;cACpB,OAAA;AAAA;;;;;;;;iBCAE,SAAA,CAAU,MAAA,EAAQ,WAAA;;;;;;;;;;AXFlC;;;;iBYQgB,cAAA,CAAe,SAAA,WAAoB,eAAA;;;;;;;;iBCNnC,aAAA,CAAc,SAAA,EAAW,eAAA,EAAiB,WAAA"}
@@ -1,5 +1,5 @@
1
- import { n as CommandError, t as Command } from "../command-DjGqCYHv.mjs";
2
- import { t as isCommand } from "../is-command-PvULqiTa.mjs";
3
- import { a as QueueListCommand, c as HelpCommand, d as ApiCommand, i as RouteListCommand, l as CommandNotFoundError, n as parseSignature, o as McpToolsCommand, r as ScheduleListCommand, s as McpServeCommand, t as QuarryRegistry, u as EventListCommand } from "../quarry-registry-CQCIlYTO.mjs";
4
- import { t as generateUsage } from "../usage-generator-Cl1HPlUp.mjs";
1
+ import { n as CommandError, t as Command } from "../command-BgSlsS4M.mjs";
2
+ import { t as isCommand } from "../is-command-C6a7WTPw.mjs";
3
+ import { a as QueueListCommand, c as HelpCommand, d as ApiCommand, i as RouteListCommand, l as CommandNotFoundError, n as parseSignature, o as McpToolsCommand, r as ScheduleListCommand, s as McpServeCommand, t as QuarryRegistry, u as EventListCommand } from "../quarry-registry-DFfRRkA7.mjs";
4
+ import { t as generateUsage } from "../usage-generator-MBcRo0Q2.mjs";
5
5
  export { ApiCommand, Command, CommandError, CommandNotFoundError, EventListCommand, HelpCommand, McpServeCommand, McpToolsCommand, QuarryRegistry, QueueListCommand, RouteListCommand, ScheduleListCommand, generateUsage, isCommand, parseSignature };
@@ -1,9 +1,9 @@
1
- import { V as ROUTER_TOKENS, r as createCliExceptionContext } from "./errors--RBIvDXr.mjs";
2
- import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata } from "./logger-c0ftIK4G.mjs";
3
- import { r as getListenerHandlers } from "./events-UTJliZhl.mjs";
4
- import { a as green, n as cyan, o as red, s as yellow, t as bold } from "./colors-BTAnQRGU.mjs";
5
- import { n as CommandError, r as COMMAND_INTERNALS, t as Command } from "./command-DjGqCYHv.mjs";
6
- import { n as OPENAPI_TOKENS, t as OpenApiToolsService } from "./openapi-tools.service-B77QXD56.mjs";
1
+ import { V as ROUTER_TOKENS, r as createCliExceptionContext } from "./errors-B4pYgYON.mjs";
2
+ import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata } from "./logger-V6Ms3QnQ.mjs";
3
+ import { r as getListenerHandlers } from "./events-COKixqnG.mjs";
4
+ import { a as green, n as cyan, o as red, s as yellow, t as bold } from "./colors-DJaRDXoS.mjs";
5
+ import { n as CommandError, r as COMMAND_INTERNALS, t as Command } from "./command-BgSlsS4M.mjs";
6
+ import { n as OPENAPI_TOKENS, t as OpenApiToolsService } from "./openapi-tools.service-CYWGuhue.mjs";
7
7
  import { inject } from "tsyringe";
8
8
  import { z } from "zod";
9
9
  //#region src/quarry/commands/api.command.ts
@@ -45,7 +45,7 @@ let ApiCommand = class ApiCommand extends Command {
45
45
  headers,
46
46
  body: data || void 0
47
47
  });
48
- const response = await this.app.hono.fetch(request, this.app.env);
48
+ const response = await (await this.app.ensureHono()).fetch(request, this.app.env);
49
49
  const body = await response.text();
50
50
  const statusText = `${response.status} ${response.statusText}`;
51
51
  let coloredStatus;
@@ -179,7 +179,8 @@ let McpServeCommand = class McpServeCommand extends Command {
179
179
  const colonIdx = h.indexOf(":");
180
180
  if (colonIdx > 0) headers[h.slice(0, colonIdx).trim()] = h.slice(colonIdx + 1).trim();
181
181
  }
182
- const spec = this.openAPIService.getSpec(this.app.hono, this.app.container);
182
+ const hono = await this.app.ensureHono();
183
+ const spec = this.openAPIService.getSpec(hono, this.app.container);
183
184
  const service = new OpenApiToolsService(spec, { dispatcher: baseUrl ? async (method, url, opts) => {
184
185
  const fullUrl = `${baseUrl}${url}`;
185
186
  try {
@@ -206,7 +207,7 @@ let McpServeCommand = class McpServeCommand extends Command {
206
207
  body: opts?.body !== void 0 ? JSON.stringify(opts.body) : void 0
207
208
  });
208
209
  try {
209
- return await this.app.hono.fetch(request, this.app.env);
210
+ return await hono.fetch(request, this.app.env);
210
211
  } catch (error) {
211
212
  throw new Error(`MCP dispatch failed: ${method} ${url} — ${error instanceof Error ? error.message : String(error)}`, { cause: error });
212
213
  }
@@ -267,10 +268,11 @@ let McpToolsCommand = class McpToolsCommand extends Command {
267
268
  this.app = app;
268
269
  this.openAPIService = openAPIService;
269
270
  }
270
- handle() {
271
+ async handle() {
271
272
  const tags = this.array("tag");
272
273
  const pathPrefix = this.string("path");
273
- const service = new OpenApiToolsService(this.openAPIService.getSpec(this.app.hono, this.app.container));
274
+ const hono = await this.app.ensureHono();
275
+ const service = new OpenApiToolsService(this.openAPIService.getSpec(hono, this.app.container));
274
276
  const filter = {
275
277
  tags: tags.length > 0 ? tags : void 0,
276
278
  pathPrefix: pathPrefix || void 0
@@ -378,7 +380,7 @@ let ScheduleListCommand = class ScheduleListCommand extends Command {
378
380
  const rows = [];
379
381
  for (const schedule of schedules) {
380
382
  const jobs = this.cron.getJobsForSchedule(schedule);
381
- for (const job of jobs) rows.push([schedule, job.constructor.name]);
383
+ for (const { jobClass } of jobs) rows.push([schedule, jobClass.name]);
382
384
  }
383
385
  this.table(["Schedule", "Job"], rows);
384
386
  }
@@ -624,7 +626,7 @@ let QuarryRegistry = class QuarryRegistry {
624
626
  */
625
627
  async listUsage(options) {
626
628
  const commands = this.list();
627
- const { generateListing } = await import("./usage-generator-Cl1HPlUp.mjs").then((n) => n.n);
629
+ const { generateListing } = await import("./usage-generator-MBcRo0Q2.mjs").then((n) => n.n);
628
630
  return generateListing(commands, this.signatures, options);
629
631
  }
630
632
  /**
@@ -636,7 +638,7 @@ let QuarryRegistry = class QuarryRegistry {
636
638
  if (!CommandClass) throw new CommandNotFoundError(name);
637
639
  const signature = this.signatures.get(resolvedName);
638
640
  const staticCommand = CommandClass;
639
- const { generateUsage } = await import("./usage-generator-Cl1HPlUp.mjs").then((n) => n.n);
641
+ const { generateUsage } = await import("./usage-generator-MBcRo0Q2.mjs").then((n) => n.n);
640
642
  return generateUsage(signature, staticCommand.description);
641
643
  }
642
644
  /**
@@ -683,4 +685,4 @@ QuarryRegistry = __decorate([
683
685
  //#endregion
684
686
  export { QueueListCommand as a, HelpCommand as c, ApiCommand as d, RouteListCommand as i, CommandNotFoundError as l, parseSignature as n, McpToolsCommand as o, ScheduleListCommand as r, McpServeCommand as s, QuarryRegistry as t, EventListCommand as u };
685
687
 
686
- //# sourceMappingURL=quarry-registry-CQCIlYTO.mjs.map
688
+ //# sourceMappingURL=quarry-registry-DFfRRkA7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quarry-registry-DFfRRkA7.mjs","names":[],"sources":["../src/quarry/commands/api.command.ts","../src/quarry/commands/event-list.command.ts","../src/quarry/errors/command-not-found.error.ts","../src/quarry/commands/help.command.ts","../src/quarry/commands/mcp-serve.command.ts","../src/quarry/commands/mcp-tools.command.ts","../src/quarry/commands/queue-list.command.ts","../src/quarry/commands/route-list.command.ts","../src/quarry/commands/schedule-list.command.ts","../src/quarry/command-internals.ts","../src/quarry/signature-parser.ts","../src/quarry/quarry-registry.ts"],"sourcesContent":["import { inject } from 'tsyringe'\nimport type { Application } from '../../application'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { Command } from '../command'\nimport { bold, cyan, green, red, yellow } from '../colors'\n\nexport class ApiCommand extends Command {\n static command = 'api {route?} {--method= : HTTP method} {--data= : JSON request body} {--header=* : Headers (Key:Value)} {--query=* : Query params (key=value)}'\n static description = 'Call an API route directly'\n static aliases = ['api:call']\n\n constructor(@inject(DI_TOKENS.Application) private app: Application) {\n super()\n }\n\n async handle(): Promise<number | undefined> {\n const route = this.string('route')\n\n if (!route) {\n return (await this.call('route:list')).exitCode\n }\n\n return this.callRoute(route)\n }\n\n private async callRoute(route: string): Promise<number> {\n const method = (this.string('method') || 'GET').toUpperCase()\n const data = this.string('data')\n const headerArgs = this.array('header')\n const queryArgs = this.array('query')\n\n const headers: Record<string, string> = {}\n if (data) {\n headers['Content-Type'] = 'application/json'\n }\n for (const h of headerArgs) {\n const colonIdx = h.indexOf(':')\n if (colonIdx > 0) {\n headers[h.slice(0, colonIdx).trim()] = h.slice(colonIdx + 1).trim()\n }\n }\n\n // Build query string\n let url = route\n if (queryArgs.length > 0) {\n const parts = queryArgs.map((q) => {\n const eqIdx = q.indexOf('=')\n if (eqIdx > 0) {\n return `${encodeURIComponent(q.slice(0, eqIdx))}=${encodeURIComponent(q.slice(eqIdx + 1))}`\n }\n return encodeURIComponent(q)\n })\n url += `?${parts.join('&')}`\n }\n\n const request = new Request(`http://localhost${url}`, {\n method,\n headers,\n body: data || undefined,\n })\n\n const hono = await this.app.ensureHono()\n const response = await hono.fetch(request, this.app.env)\n const body = await response.text()\n\n // Color-coded status\n const statusText = `${response.status} ${response.statusText}`\n let coloredStatus: string\n if (response.status >= 200 && response.status < 300) {\n coloredStatus = green(bold(statusText))\n } else if (response.status >= 300 && response.status < 400) {\n coloredStatus = yellow(bold(statusText))\n } else {\n coloredStatus = red(bold(statusText))\n }\n\n this.line(`${cyan(method)} ${route} ${coloredStatus}`)\n this.newLine()\n\n // Response headers\n const headerLines: string[] = []\n response.headers.forEach((value, key) => {\n headerLines.push(` ${key}: ${value}`)\n })\n if (headerLines.length > 0) {\n this.line(bold('Headers:'))\n for (const hl of headerLines) {\n this.line(hl)\n }\n this.newLine()\n }\n\n // Body\n if (body) {\n this.line(bold('Body:'))\n try {\n this.line(JSON.stringify(JSON.parse(body), null, 2))\n } catch {\n this.line(body)\n }\n }\n\n return response.status >= 400 ? 1 : 0\n }\n}\n","import { inject } from 'tsyringe'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { getListenerHandlers } from '../../events'\nimport type { ModuleRegistry } from '../../module/module-registry'\nimport { Command } from '../command'\n\nexport class EventListCommand extends Command {\n static command = 'event:list'\n static description = 'List all registered event listeners'\n\n constructor(@inject(DI_TOKENS.ModuleRegistry) private modules: ModuleRegistry) {\n super()\n }\n\n handle(): number | undefined {\n const listeners = this.modules.getAllListeners()\n\n if (listeners.length === 0) {\n this.info('No event listeners found')\n return 0\n }\n\n const rows: string[][] = []\n\n for (const ListenerClass of listeners) {\n const handlers = getListenerHandlers(ListenerClass)\n for (const { methodName, event, options } of handlers) {\n rows.push([\n event,\n ListenerClass.name,\n methodName,\n String(options?.priority ?? 0),\n options?.blocking ? 'Yes' : 'No',\n ])\n }\n }\n\n if (rows.length === 0) {\n this.info('No event handlers found')\n return 0\n }\n\n this.table(['Event', 'Listener', 'Method', 'Priority', 'Blocking'], rows)\n\n return undefined\n }\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 { inject } from 'tsyringe'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { Command } from '../command'\nimport { CommandNotFoundError } from '../errors/command-not-found.error'\nimport type { QuarryRegistry } from '../quarry-registry'\n\nexport class HelpCommand extends Command {\n static command = 'help {command?}'\n static description = 'Show help for a command or list all commands'\n static aliases = ['list']\n\n constructor(@inject(DI_TOKENS.Quarry) private quarryRegistry: QuarryRegistry) {\n super()\n }\n\n async handle(): Promise<number | undefined> {\n const commandName = this.string('command')\n\n if (!commandName) {\n const listing = await this.quarryRegistry.listUsage()\n this.line(listing)\n return 0\n }\n\n try {\n const usage = await this.quarryRegistry.usage(commandName)\n this.line(usage)\n return 0\n } catch (error) {\n if (error instanceof CommandNotFoundError) {\n this.fail(`Unknown command: ${commandName}`)\n return 1\n }\n throw error\n }\n }\n}\n","import { inject } from 'tsyringe'\nimport { z } from 'zod'\nimport type { Application } from '../../application'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { OPENAPI_TOKENS } from '../../openapi/openapi.tokens'\nimport type { Dispatcher } from '../../openapi/services/openapi-tools.service'\nimport { OpenApiToolsService } from '../../openapi/services/openapi-tools.service'\nimport type { OpenAPIService } from '../../openapi/services/openapi.service'\nimport type { IOpenAPIConfigService } from '../../openapi/types'\nimport { Command } from '../command'\n\nexport class McpServeCommand extends Command {\n static command = 'mcp:serve {--url= : Base URL for external dispatch} {--header=* : Headers (Key:Value)} {--tag=* : Only expose routes with these OpenAPI tags} {--path= : Only expose routes matching this path prefix}'\n static description = 'Start an MCP stdio server exposing API routes as tools'\n\n constructor(\n @inject(DI_TOKENS.Application) private app: Application,\n @inject(OPENAPI_TOKENS.OpenAPIService) private openAPIService: OpenAPIService,\n ) {\n super()\n }\n\n async handle(): Promise<number | undefined> {\n const { McpServer } = await import('@modelcontextprotocol/sdk/server/mcp.js')\n const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js')\n\n const baseUrl = this.string('url')\n const headerArgs = this.array('header')\n const tags = this.array('tag')\n const pathPrefix = this.string('path')\n\n const headers: Record<string, string> = {}\n for (const h of headerArgs) {\n const colonIdx = h.indexOf(':')\n if (colonIdx > 0) {\n headers[h.slice(0, colonIdx).trim()] = h.slice(colonIdx + 1).trim()\n }\n }\n\n const hono = await this.app.ensureHono()\n const spec = this.openAPIService.getSpec(hono, this.app.container)\n\n const dispatcher: Dispatcher = baseUrl\n ? async (method, url, opts) => {\n const fullUrl = `${baseUrl}${url}`\n try {\n return await fetch(fullUrl, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...opts?.headers,\n },\n body: opts?.body !== undefined ? JSON.stringify(opts.body) : undefined,\n })\n } catch (error) {\n throw new Error(`MCP dispatch failed: ${method} ${fullUrl} — ${error instanceof Error ? error.message : String(error)}`, { cause: error })\n }\n }\n : async (method, url, opts) => {\n const request = new Request(`http://localhost${url}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...opts?.headers,\n },\n body: opts?.body !== undefined ? JSON.stringify(opts.body) : undefined,\n })\n try {\n return await hono.fetch(request, this.app.env)\n } catch (error) {\n throw new Error(`MCP dispatch failed: ${method} ${url} — ${error instanceof Error ? error.message : String(error)}`, { cause: error })\n }\n }\n\n const service = new OpenApiToolsService(spec, { dispatcher })\n const filter = {\n tags: tags.length > 0 ? tags : undefined,\n pathPrefix: pathPrefix || undefined,\n }\n const tools = service.getTools(filter)\n\n const configService = this.app.container.resolve<IOpenAPIConfigService>(OPENAPI_TOKENS.ConfigService)\n const config = configService.getEffectiveConfig()\n\n const server = new McpServer({\n name: config.info.title,\n version: config.info.version,\n })\n\n // Register each tool\n for (const tool of tools) {\n const inputSchema = z.fromJSONSchema(tool.inputSchema)\n server.registerTool(tool.name, { description: tool.description, inputSchema }, async (args) => {\n const result = await service.executeTool(tool.name, args as Record<string, unknown>)\n return {\n content: [{ type: 'text' as const, text: `Status: ${result.status}\\n\\n${result.body}` }],\n }\n })\n }\n\n // Expose OpenAPI spec as a resource\n server.registerResource(\n 'openapi-spec',\n 'openapi://spec',\n { description: 'Full OpenAPI specification', mimeType: 'application/json' },\n () => ({\n contents: [{\n uri: 'openapi://spec',\n mimeType: 'application/json',\n text: JSON.stringify(spec, null, 2),\n }],\n }),\n )\n\n const transport = new StdioServerTransport()\n const closed = new Promise<void>((resolve) => { transport.onclose = resolve })\n await server.connect(transport)\n\n // Write info to stderr (stdout is reserved for MCP JSON-RPC)\n process.stderr.write(`MCP server started with ${tools.length} tool(s)\\n`)\n\n // Keep process alive until client disconnects\n await closed\n\n return 0\n }\n}\n","import { inject } from 'tsyringe'\nimport type { Application } from '../../application'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { OPENAPI_TOKENS } from '../../openapi/openapi.tokens'\nimport type { OpenAPIService } from '../../openapi/services/openapi.service'\nimport { OpenApiToolsService } from '../../openapi/services/openapi-tools.service'\nimport { Command } from '../command'\n\nexport class McpToolsCommand extends Command {\n static command = 'mcp:tools {--tag=* : Filter by OpenAPI tags} {--path= : Filter by path prefix}'\n static description = 'List API routes that would be exposed as MCP tools'\n\n constructor(\n @inject(DI_TOKENS.Application) private app: Application,\n @inject(OPENAPI_TOKENS.OpenAPIService) private openAPIService: OpenAPIService,\n ) {\n super()\n }\n\n async handle(): Promise<number | undefined> {\n const tags = this.array('tag')\n const pathPrefix = this.string('path')\n\n const hono = await this.app.ensureHono()\n const spec = this.openAPIService.getSpec(hono, this.app.container)\n\n const service = new OpenApiToolsService(spec)\n const filter = {\n tags: tags.length > 0 ? tags : undefined,\n pathPrefix: pathPrefix || undefined,\n }\n const tools = service.getTools(filter)\n\n if (tools.length === 0) {\n this.info('No tools found')\n return 0\n }\n\n this.table(\n ['Name', 'Method', 'Path', 'Description'],\n tools.map((t) => [t.name, t.method, t.path, t.description]),\n )\n\n return 0\n }\n}\n","import { inject } from 'tsyringe'\nimport { DI_TOKENS } from '../../di/tokens'\nimport type { ConsumerRegistry } from '../../queue/consumer-registry'\nimport { Command } from '../command'\n\nexport class QueueListCommand extends Command {\n static command = 'queue:list'\n static description = 'List all registered queue consumers'\n\n constructor(@inject(DI_TOKENS.ConsumerRegistry) private consumers: ConsumerRegistry) {\n super()\n }\n\n handle(): number | undefined {\n const consumers = this.consumers.getAllConsumers()\n\n if (consumers.length === 0) {\n this.info('No queue consumers found')\n return 0\n }\n\n this.table(\n ['Consumer', 'Message Types'],\n consumers.map(c => [c.constructor.name, c.messageTypes.join(', ')]),\n )\n\n return undefined\n }\n}\n","import { inject } from 'tsyringe'\nimport type { RouteRegistry, RegisteredRoute } from '../../router/route-registry'\nimport { ROUTER_TOKENS } from '../../router/router.tokens'\nimport { Command } from '../command'\n\n/**\n * List all registered routes from RouteRegistry.\n *\n * By default, hidden routes (hideFromDocs) are excluded.\n * Use `--hidden` to include them.\n *\n * @example\n * ```bash\n * quarry route:list\n * quarry route:list --method=GET\n * quarry route:list --path=/users\n * quarry route:list --name=users\n * quarry route:list --hidden\n * ```\n */\nexport class RouteListCommand extends Command {\n static command = 'route:list {--method= : Filter by HTTP method} {--path= : Filter by path substring} {--name= : Filter by route name} {--hidden : Include hidden routes}'\n static description = 'List all registered routes'\n\n constructor(@inject(ROUTER_TOKENS.RouteRegistry) private registry: RouteRegistry) {\n super()\n }\n\n handle(): number | undefined {\n const methodFilter = this.string('method').toUpperCase()\n const pathFilter = this.string('path')\n const nameFilter = this.string('name')\n const showHidden = this.boolean('hidden')\n\n let routes = this.registry.all()\n\n // Filter hidden routes (default: exclude)\n if (!showHidden) {\n routes = routes.filter(r => !r.hidden)\n }\n\n if (methodFilter) {\n routes = routes.filter(r => r.method.toUpperCase() === methodFilter)\n }\n\n if (pathFilter) {\n routes = routes.filter(r => r.path.includes(pathFilter))\n }\n\n if (nameFilter) {\n routes = routes.filter(r => r.name?.includes(nameFilter))\n }\n\n if (routes.length === 0) {\n this.info('No routes found')\n return 0\n }\n\n this.table(\n ['Method', 'Path', 'Name', 'Handler', 'Domain'],\n routes.map(r => this.formatRow(r)),\n )\n\n return undefined\n }\n\n private formatRow(route: RegisteredRoute): string[] {\n return [\n route.method.toUpperCase(),\n route.path,\n route.name ?? '-',\n `${route.controller}.${route.action}`,\n route.domain ?? '-',\n ]\n }\n}\n","import { inject } from 'tsyringe'\nimport { DI_TOKENS } from '../../di/tokens'\nimport type { CronManager } from '../../cron/cron-manager'\nimport { Command } from '../command'\n\nexport class ScheduleListCommand extends Command {\n static command = 'schedule:list'\n static description = 'List all registered cron jobs'\n\n constructor(@inject(DI_TOKENS.Cron) private cron: CronManager) {\n super()\n }\n\n handle(): number | undefined {\n const schedules = this.cron.getAllSchedules()\n\n if (schedules.length === 0) {\n this.info('No cron jobs found')\n return 0\n }\n\n const rows: string[][] = []\n\n for (const schedule of schedules) {\n const jobs = this.cron.getJobsForSchedule(schedule)\n for (const { jobClass } of jobs) {\n rows.push([schedule, jobClass.name])\n }\n }\n\n this.table(['Schedule', 'Job'], rows)\n\n return undefined\n }\n}\n","import type { Command } from './command'\nimport { COMMAND_INTERNALS } from './constants'\nimport type { CommandInput, CommandInternals, CommandResult } from './types'\n\n/** @internal Set the flat input values before calling handle() */\nexport function setCommandInputs(command: Command, values: CommandInput): void {\n command[COMMAND_INTERNALS].inputs = { ...values }\n}\n\n/** @internal Set the Quarry reference for this.call() support */\nexport function setCommandQuarry(\n command: Command,\n quarry: { call(name: string, input?: CommandInput): Promise<CommandResult> },\n): void {\n command[COMMAND_INTERNALS].quarry = quarry\n}\n\n/** @internal Collect the result after handle() completes */\nexport function getCommandResult(command: Command): CommandResult {\n const internals: CommandInternals = command[COMMAND_INTERNALS]\n return {\n exitCode: internals.exitCode,\n output: [...internals.output],\n errors: [...internals.errors],\n }\n}\n\n/** @internal Reset state between invocations */\nexport function resetCommandState(command: Command): void {\n const internals: CommandInternals = command[COMMAND_INTERNALS]\n internals.inputs = {}\n internals.output = []\n internals.errors = []\n internals.exitCode = 0\n}\n","import { CommandError } from './errors/command.error'\nimport type { ParsedArgument, ParsedOption, ParsedSignature } from './types'\n\n/**\n * Parse a Laravel-style command signature string.\n *\n * Signature syntax:\n * command-name {arg} ... — flat command\n * group subcommand {arg} ... — subcommand hierarchy (space-separated)\n * namespace:command {arg} ... — namespaced flat command (colon-separated)\n * {--flag} {--name=} {--name=default} {--name=*} {--A|name} {--name= : desc}\n *\n * Pure function, zero dependencies, edge-compatible.\n */\nexport function parseSignature(signature: string): ParsedSignature {\n const tokens = extractTokens(signature)\n const name = extractCommandName(signature)\n const args: ParsedArgument[] = []\n const options: ParsedOption[] = []\n\n for (const token of tokens) {\n const inner = token.slice(1, -1).trim() // strip { }\n\n if (inner.startsWith('--')) {\n options.push(parseOption(inner))\n } else {\n args.push(parseArgument(inner))\n }\n }\n\n return { name, arguments: args, options }\n}\n\nfunction extractCommandName(signature: string): string {\n const match = /^[\\w:.-]+(?:\\s+[\\w:.-]+)*/.exec(signature)\n if (!match) {\n throw new CommandError(`Invalid signature: cannot extract command name from \"${signature}\"`)\n }\n return match[0]\n}\n\nfunction extractTokens(signature: string): string[] {\n const tokens: string[] = []\n const regex = /\\{[^}]+\\}/g\n let match: RegExpExecArray | null\n\n while ((match = regex.exec(signature)) !== null) {\n tokens.push(match[0])\n }\n\n return tokens\n}\n\nfunction parseArgument(inner: string): ParsedArgument {\n const { value, description } = splitDescription(inner)\n\n // {name*} — array/variadic argument\n if (value.endsWith('*')) {\n return {\n name: value.slice(0, -1).trim(),\n required: true,\n isArray: true,\n description,\n }\n }\n\n // {name=default} — argument with default value\n const eqIdx = value.indexOf('=')\n if (eqIdx !== -1) {\n return {\n name: value.slice(0, eqIdx).trim(),\n required: false,\n default: value.slice(eqIdx + 1).trim(),\n isArray: false,\n description,\n }\n }\n\n // {name?} — optional argument\n if (value.endsWith('?')) {\n return {\n name: value.slice(0, -1).trim(),\n required: false,\n isArray: false,\n description,\n }\n }\n\n // {name} — required argument\n return {\n name: value.trim(),\n required: true,\n isArray: false,\n description,\n }\n}\n\nfunction parseOption(inner: string): ParsedOption {\n // Remove leading --\n const withoutDashes = inner.slice(2)\n const { value, description } = splitDescription(withoutDashes)\n\n // Check for alias: {--A|name...}\n let alias: string | undefined\n let optBody = value\n\n const pipeIdx = optBody.indexOf('|')\n if (pipeIdx !== -1) {\n alias = optBody.slice(0, pipeIdx).trim()\n optBody = optBody.slice(pipeIdx + 1).trim()\n }\n\n // {--name=*} — array option\n if (optBody.endsWith('=*')) {\n return {\n name: optBody.slice(0, -2).trim(),\n alias,\n isFlag: false,\n isArray: true,\n description,\n }\n }\n\n // {--name=default} — option with default value\n const eqIdx = optBody.indexOf('=')\n if (eqIdx !== -1) {\n const name = optBody.slice(0, eqIdx).trim()\n const defaultValue = optBody.slice(eqIdx + 1).trim()\n\n return {\n name,\n alias,\n isFlag: false,\n isArray: false,\n default: defaultValue || undefined,\n description,\n }\n }\n\n // {--flag} — boolean flag\n return {\n name: optBody.trim(),\n alias,\n isFlag: true,\n isArray: false,\n description,\n }\n}\n\nfunction splitDescription(value: string): { value: string; description?: string } {\n const colonIdx = value.indexOf(' : ')\n if (colonIdx === -1) {\n return { value }\n }\n\n return {\n value: value.slice(0, colonIdx).trim(),\n description: value.slice(colonIdx + 3).trim(),\n }\n}\n","import { inject } from 'tsyringe'\nimport type { Container } from '../di/container'\nimport { Transient } from '../di/decorators'\nimport { DI_TOKENS } from '../di/tokens'\nimport { createCliExceptionContext } from '../errors/exception-context'\nimport type { ExceptionHandler } from '../errors/exception-handler'\nimport type { Constructor } from '../types'\nimport { type Command } from './command'\nimport { getCommandResult, setCommandInputs, setCommandQuarry } from './command-internals'\nimport { CommandNotFoundError } from './errors/command-not-found.error'\nimport { CommandError } from './errors/command.error'\nimport { parseSignature } from './signature-parser'\nimport type { CommandInput, CommandResult, ParsedSignature, Quarry } from './types'\n\n/**\n * QuarryRegistry — edge-compatible programmatic API for running commands.\n *\n * Registered as a singleton via DI_TOKENS.Quarry.\n * Commands are auto-discovered from module providers and registered at bootstrap.\n * Command constructors are stored at bootstrap; fresh instances are resolved per `call()`.\n *\n * Users should inject and type as `Quarry` (the interface), which only exposes `call()`.\n */\n@Transient(DI_TOKENS.Quarry)\nexport class QuarryRegistry implements Quarry {\n private commands = new Map<string, Constructor<Command>>()\n private signatures = new Map<string, ParsedSignature>()\n private aliases = new Map<string, string>()\n\n constructor(@inject(DI_TOKENS.Container) private readonly container: Container) { }\n\n /**\n * Execute a command by name with optional flat input.\n * A fresh command instance is resolved from the container per invocation.\n */\n async call(name: string, input?: CommandInput): Promise<CommandResult> {\n const resolvedName = this.resolveName(name)\n const CommandClass = this.commands.get(resolvedName)\n\n if (!CommandClass) {\n throw new CommandNotFoundError(name)\n }\n\n const signature = this.signatures.get(resolvedName)!\n const mergedInput = this.applyDefaults(input ?? {}, signature)\n\n // Validate required arguments\n for (const arg of signature.arguments) {\n if (arg.required && (mergedInput[arg.name] === undefined || mergedInput[arg.name] === null)) {\n throw new CommandError(`Missing required argument: ${arg.name}`)\n }\n }\n\n let command: Command | undefined\n\n try {\n // Resolve a fresh instance per invocation to avoid shared mutable state\n command = this.container.resolve<Command>(CommandClass)\n\n setCommandQuarry(command, this)\n setCommandInputs(command, mergedInput)\n\n const exitCode = await command.handle()\n const result = getCommandResult(command)\n\n if (typeof exitCode === 'number') {\n return { ...result, exitCode }\n }\n\n return result\n } catch (error) {\n if (error instanceof CommandError) {\n if (command) {\n const result = getCommandResult(command)\n return {\n exitCode: result.exitCode === 0 ? 1 : result.exitCode,\n output: result.output,\n errors: [...result.errors, error.message],\n }\n }\n return { exitCode: 1, output: [], errors: [error.message] }\n }\n\n const errorMessage = this.handleError(error, resolvedName)\n\n if (command) {\n const result = getCommandResult(command)\n return {\n exitCode: result.exitCode === 0 ? 1 : result.exitCode,\n output: result.output,\n errors: [...result.errors, errorMessage],\n }\n }\n return { exitCode: 1, output: [], errors: [errorMessage] }\n }\n }\n\n /**\n * Check if a command exists by name or alias.\n */\n has(name: string): boolean {\n const resolved = this.resolveName(name)\n return this.commands.has(resolved)\n }\n\n /**\n * Get a command constructor by name or alias.\n */\n get(name: string): Constructor<Command> | undefined {\n const resolved = this.resolveName(name)\n return this.commands.get(resolved)\n }\n\n /**\n * Get all registered command constructors.\n */\n all(): Map<string, Constructor<Command>> {\n return new Map(this.commands)\n }\n\n /**\n * List all commands with their descriptions and aliases.\n */\n list(): { name: string; description?: string; aliases: string[] }[] {\n const result: { name: string; description?: string; aliases: string[] }[] = []\n\n for (const [name, CommandClass] of this.commands) {\n const staticCommand = CommandClass as unknown as typeof Command\n const commandAliases: string[] = []\n\n for (const [alias, target] of this.aliases) {\n if (target === name) {\n commandAliases.push(alias)\n }\n }\n\n result.push({\n name,\n description: staticCommand.description,\n aliases: commandAliases,\n })\n }\n\n return result.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n /**\n * Generate a compact listing of all commands with visual hierarchy and colors.\n */\n async listUsage(options?: { binaryName?: string; binaryLabel?: string; binaryVersion?: string }): Promise<string> {\n const commands = this.list()\n\n // Dynamic import to keep usage-generator tree-shakeable\n const { generateListing } = await import('./usage-generator')\n return generateListing(commands, this.signatures, options)\n }\n\n /**\n * Get auto-generated usage text for a command.\n */\n async usage(name: string): Promise<string> {\n const resolvedName = this.resolveName(name)\n const CommandClass = this.commands.get(resolvedName)\n\n if (!CommandClass) {\n throw new CommandNotFoundError(name)\n }\n\n const signature = this.signatures.get(resolvedName)!\n const staticCommand = CommandClass as unknown as typeof Command\n\n // Dynamic import to keep usage-generator tree-shakeable\n const { generateUsage } = await import('./usage-generator')\n return generateUsage(signature, staticCommand.description)\n }\n\n /**\n * Register a command constructor with the registry.\n * @internal Called by Application during bootstrap.\n */\n register(commandClass: Constructor<Command>): void {\n const staticCommand = commandClass as unknown as typeof Command\n\n if (!staticCommand.command) {\n throw new CommandError(`Command class ${commandClass.name} is missing static \"command\" signature`)\n }\n\n const signature = parseSignature(staticCommand.command)\n const name = signature.name\n\n if (this.commands.has(name) || this.aliases.has(name)) {\n throw new CommandError(`Duplicate command name: \"${name}\" is already registered`)\n }\n\n // Validate all aliases before any mutation\n if (staticCommand.aliases) {\n for (const alias of staticCommand.aliases) {\n if (this.commands.has(alias) || this.aliases.has(alias)) {\n throw new CommandError(`Duplicate alias: \"${alias}\" conflicts with an existing command or alias`)\n }\n }\n }\n\n // All checks passed — safe to mutate\n this.commands.set(name, commandClass)\n this.signatures.set(name, signature)\n\n if (staticCommand.aliases) {\n for (const alias of staticCommand.aliases) {\n this.aliases.set(alias, name)\n }\n }\n }\n\n private handleError(error: unknown, commandName: string): string {\n const handler = this.container.resolve<ExceptionHandler>(DI_TOKENS.ExceptionHandler)\n const ctx = createCliExceptionContext(commandName)\n // Fire-and-forget — reporting happens via waitUntil internally\n void handler.handle(error, ctx)\n return error instanceof Error ? error.message : String(error)\n }\n\n private resolveName(name: string): string {\n return this.aliases.get(name) ?? name\n }\n\n private applyDefaults(input: CommandInput, signature: ParsedSignature): CommandInput {\n const result = { ...input }\n\n // Apply argument defaults\n for (const arg of signature.arguments) {\n if (result[arg.name] === undefined && arg.default !== undefined) {\n result[arg.name] = arg.default\n }\n }\n\n // Apply option defaults\n for (const opt of signature.options) {\n if (result[opt.name] === undefined) {\n if (opt.default !== undefined) {\n result[opt.name] = opt.default\n } else if (opt.isFlag) {\n result[opt.name] = false\n }\n }\n }\n\n return result\n }\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { n as IQueueConsumer, r as QueueMessage, t as ConsumerRegistry } from "../consumer-registry-BkuHXR_u.mjs";
2
- import { _ as QueueNames, a as InjectQueue, c as QueueModule, d as SyncQueueProvider, f as CloudflareQueueProvider, g as QueueName, h as IQueueSender, i as QueueToken, l as QueueModuleOptions, m as DispatchMessage, n as QueueBindingNotFoundError, o as QueueRegistry, p as IQueueProvider, r as QUEUE_TOKENS, s as QueueProviderFactory, t as QueueProviderNotSupportedError, u as QueueSender, v as QueueManager } from "../index-DPxmo6AY.mjs";
1
+ import { n as IQueueConsumer, r as QueueMessage, t as ConsumerRegistry } from "../consumer-registry-Doom7BEh.mjs";
2
+ import { _ as QueueNames, a as InjectQueue, c as QueueModule, d as SyncQueueProvider, f as CloudflareQueueProvider, g as QueueName, h as IQueueSender, i as QueueToken, l as QueueModuleOptions, m as DispatchMessage, n as QueueBindingNotFoundError, o as QueueRegistry, p as IQueueProvider, r as QUEUE_TOKENS, s as QueueProviderFactory, t as QueueProviderNotSupportedError, u as QueueSender, v as QueueManager } from "../index-Dnqm9ZB6.mjs";
3
3
  export { CloudflareQueueProvider, ConsumerRegistry, DispatchMessage, IQueueConsumer, IQueueProvider, IQueueSender, InjectQueue, QUEUE_TOKENS, QueueBindingNotFoundError, QueueManager, QueueMessage, QueueModule, QueueModuleOptions, QueueName, QueueNames, QueueProviderFactory, QueueProviderNotSupportedError, QueueRegistry, QueueSender, QueueToken, SyncQueueProvider };
@@ -1,5 +1,5 @@
1
- import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata } from "../logger-c0ftIK4G.mjs";
2
- import { a as QueueProviderNotSupportedError, c as QUEUE_TOKENS, i as CloudflareQueueProvider, l as QueueSender, n as QueueProviderFactory, o as QueueBindingNotFoundError, r as SyncQueueProvider, s as QueueRegistry, t as QueueModule, u as ConsumerRegistry } from "../queue.module-DIjD6nr-.mjs";
1
+ import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata } from "../logger-V6Ms3QnQ.mjs";
2
+ import { a as QueueProviderNotSupportedError, c as QUEUE_TOKENS, i as CloudflareQueueProvider, l as QueueSender, n as QueueProviderFactory, o as QueueBindingNotFoundError, r as SyncQueueProvider, s as QueueRegistry, t as QueueModule, u as ConsumerRegistry } from "../queue.module-P-G-nCYz.mjs";
3
3
  import { inject } from "tsyringe";
4
4
  //#region src/queue/queue-manager.ts
5
5
  let QueueManager = class QueueManager {
@@ -1,6 +1,6 @@
1
- import { A as Scope, H as ApplicationError, k as ERROR_CODES, w as I18N_TOKENS } from "./errors--RBIvDXr.mjs";
2
- import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata } from "./logger-c0ftIK4G.mjs";
3
- import { S as Module } from "./module-C3YZ-kZN.mjs";
1
+ import { A as Scope, H as ApplicationError, k as ERROR_CODES, w as I18N_TOKENS } from "./errors-B4pYgYON.mjs";
2
+ import { a as __decorate, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata } from "./logger-V6Ms3QnQ.mjs";
3
+ import { C as Module } from "./module-qGE_1duv.mjs";
4
4
  import { inject } from "tsyringe";
5
5
  //#region src/queue/consumer-registry.ts
6
6
  let ConsumerRegistry = class ConsumerRegistry {
@@ -397,4 +397,4 @@ QueueModule = _QueueModule = __decorate([Module({ providers: [
397
397
  //#endregion
398
398
  export { QueueProviderNotSupportedError as a, QUEUE_TOKENS as c, CloudflareQueueProvider as i, QueueSender as l, QueueProviderFactory as n, QueueBindingNotFoundError as o, SyncQueueProvider as r, QueueRegistry as s, QueueModule as t, ConsumerRegistry as u };
399
399
 
400
- //# sourceMappingURL=queue.module-DIjD6nr-.mjs.map
400
+ //# sourceMappingURL=queue.module-P-G-nCYz.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue.module-DIjD6nr-.mjs","names":[],"sources":["../src/queue/consumer-registry.ts","../src/queue/queue-sender.ts","../src/queue/queue.tokens.ts","../src/queue/queue-registry.ts","../src/queue/errors/queue-binding-not-found.error.ts","../src/queue/errors/queue-provider-not-supported.error.ts","../src/queue/providers/cloudflare-queue.provider.ts","../src/queue/providers/sync-queue.provider.ts","../src/queue/services/queue-provider-factory.ts","../src/queue/queue.module.ts"],"sourcesContent":["import { Transient } from '../di/decorators'\nimport { DI_TOKENS } from '../di/tokens'\nimport type { IQueueConsumer } from './queue-consumer'\n\n/**\n * Consumer Registry\n *\n * Singleton service that holds all registered queue consumers indexed by message type.\n * Consumers declare the message types they handle, and this registry routes messages\n * to the appropriate consumers based on their types.\n *\n * **Message-Type Routing:**\n * - Consumers declare `messageTypes` array (e.g., `['email.send', 'email.batch.send']`)\n * - When a message arrives, consumers matching the message type are invoked\n * - A consumer can handle messages from ANY queue (routing is by type, not queue)\n * - Use `'*'` as a wildcard to handle all message types\n *\n * @example Consumer registration\n * ```typescript\n * // In consumer.ts\n * @Transient()\n * export class EmailConsumer implements IQueueConsumer {\n * readonly messageTypes = ['email.send', 'email.batch.send']\n * // ...\n * }\n *\n * // In module.ts\n * @Module({\n * consumers: [EmailConsumer]\n * })\n *\n * // Application auto-registers via ConsumerRegistry\n * this.consumerRegistry.register(consumer)\n * ```\n */\n@Transient(DI_TOKENS.ConsumerRegistry)\nexport class ConsumerRegistry {\n /** Map from message type to consumers handling that type */\n private consumersByType = new Map<string, IQueueConsumer[]>()\n\n /** Set of all registered consumers (for iteration) */\n private allConsumers = new Set<IQueueConsumer>()\n\n /**\n * Register a queue consumer\n *\n * Indexes the consumer by each of its declared message types.\n *\n * @param consumer - Queue consumer to register\n */\n register(consumer: IQueueConsumer): void {\n if (this.allConsumers.has(consumer)) {\n return // Already registered\n }\n\n this.allConsumers.add(consumer)\n\n for (const messageType of consumer.messageTypes) {\n const existing = this.consumersByType.get(messageType) ?? []\n existing.push(consumer)\n this.consumersByType.set(messageType, existing)\n }\n }\n\n /**\n * Get all consumers that can handle a specific message type\n *\n * Returns consumers that either:\n * - Explicitly declare the message type\n * - Use '*' wildcard to handle all types\n *\n * @param messageType - The message type to find consumers for\n * @returns Array of consumers that can handle this message type\n */\n getConsumers(messageType: string): IQueueConsumer[] {\n const exactMatch = this.consumersByType.get(messageType) ?? []\n const wildcardMatch = this.consumersByType.get('*') ?? []\n\n // Combine and dedupe\n const combined = new Set([...exactMatch, ...wildcardMatch])\n return Array.from(combined)\n }\n\n /**\n * Check if any consumers can handle a message type\n *\n * @param messageType - The message type to check\n * @returns true if at least one consumer can handle this type\n */\n hasConsumers(messageType: string): boolean {\n return this.getConsumers(messageType).length > 0\n }\n\n /**\n * Get all registered message types\n *\n * @returns Array of message types with registered consumers\n */\n getMessageTypes(): string[] {\n return Array.from(this.consumersByType.keys())\n }\n\n /**\n * Get all registered consumers\n *\n * @returns Array of all registered consumers\n */\n getAllConsumers(): IQueueConsumer[] {\n return Array.from(this.allConsumers)\n }\n}\n","import type { II18nService } from '../i18n/i18n.types'\nimport type { IQueueProvider } from './providers'\nimport type { QueueMessage } from './queue-consumer'\nimport type { DispatchMessage, IQueueSender } from './queue-sender.interface'\n\n/**\n * Queue Sender\n *\n * Implementation of IQueueSender bound to a specific queue name.\n * Created by QueueRegistry for each registered queue.\n *\n * Automatically enriches messages with:\n * - `id`: UUID generated via crypto.randomUUID()\n * - `timestamp`: Current time in milliseconds\n * - `metadata.locale`: Current locale from I18n context\n *\n * @example\n * ```typescript\n * // Created by QueueRegistry, not directly instantiated\n * const sender = registry.getQueue('notifications-queue')\n *\n * await sender.dispatch({\n * type: 'email.send',\n * payload: { to: 'user@example.com', subject: 'Hello' }\n * })\n * ```\n */\nexport class QueueSender implements IQueueSender {\n constructor(\n private readonly queueName: string,\n private readonly provider: IQueueProvider,\n private readonly i18n: II18nService\n ) {}\n\n /**\n * Dispatch a message to this queue.\n *\n * @param message - Message to dispatch (without id/timestamp)\n */\n async dispatch<T>(message: DispatchMessage<T>): Promise<void> {\n const metadata = { ...message.metadata }\n\n if (!metadata.locale) {\n const locale = this.i18n.getLocale()\n if (locale) {\n metadata.locale = locale\n }\n }\n\n const fullMessage: QueueMessage<T> = {\n id: crypto.randomUUID(),\n timestamp: Date.now(),\n ...message,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined\n }\n\n await this.provider.send(this.queueName, fullMessage)\n }\n}\n","export const QUEUE_TOKENS = {\n QueueProviderFactory: Symbol.for('stratal:queue:provider:factory'),\n QueueRegistry: Symbol.for('stratal:queue:registry'),\n QueueModuleOptions: Symbol.for('stratal:queue:options'),\n} as const\n\nexport type QueueToken = (typeof QUEUE_TOKENS)[keyof typeof QUEUE_TOKENS]\n","import { inject } from 'tsyringe'\nimport { Transient } from '../di/decorators'\nimport { I18N_TOKENS } from '../i18n/i18n.tokens'\nimport type { II18nService } from '../i18n/i18n.types'\nimport type { IQueueProvider } from './providers'\nimport type { IQueueSender } from './queue-sender.interface'\nimport { QueueSender } from './queue-sender'\nimport { QUEUE_TOKENS } from './queue.tokens'\nimport { type QueueProviderFactory } from './services'\n\n/**\n * Queue Registry\n *\n * Request-scoped factory service for creating QueueSender instances.\n * Caches senders per queue name within the request scope.\n *\n * This service is used internally by QueueModule.registerQueue() to provide\n * IQueueSender instances for each registered queue.\n *\n * **Why request-scoped?**\n * - Needs access to I18nService for locale-aware message metadata\n * - Provider is created once per request for consistency\n * - Queue senders are cached per request to avoid recreating them\n *\n * @example\n * ```typescript\n * // Used internally by QueueModule.registerQueue()\n * QueueModule.registerQueue('notifications-queue')\n *\n * // The module creates a factory provider:\n * {\n * provide: 'notifications-queue',\n * useFactory: (registry: QueueRegistry) => registry.getQueue('notifications-queue'),\n * inject: [QUEUE_TOKENS.QueueRegistry],\n * }\n * ```\n */\n@Transient(QUEUE_TOKENS.QueueRegistry)\nexport class QueueRegistry {\n private readonly provider: IQueueProvider\n private readonly senders = new Map<string, IQueueSender>()\n\n constructor(\n @inject(QUEUE_TOKENS.QueueProviderFactory) providerFactory: QueueProviderFactory,\n @inject(I18N_TOKENS.I18nService) private readonly i18n: II18nService\n ) {\n this.provider = providerFactory.create()\n }\n\n /**\n * Get or create a QueueSender for the specified queue name.\n *\n * Senders are cached per queue name within the request scope.\n *\n * @param queueName - The queue name to get a sender for\n * @returns QueueSender bound to the specified queue\n */\n getQueue(queueName: string): IQueueSender {\n let sender = this.senders.get(queueName)\n\n if (!sender) {\n sender = new QueueSender(queueName, this.provider, this.i18n)\n this.senders.set(queueName, sender)\n }\n\n return sender\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * QueueBindingNotFoundError\n *\n * Thrown when attempting to access a Cloudflare Queue binding that hasn't been configured.\n * This typically indicates that the queue binding is missing from wrangler.jsonc\n * or the environment variables are not properly set.\n */\nexport class QueueBindingNotFoundError extends ApplicationError {\n constructor(queueName: string, bindingName: string) {\n super(\n 'errors.queueBindingNotFound',\n ERROR_CODES.SYSTEM.QUEUE_BINDING_NOT_FOUND,\n { queueName, bindingName }\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * QueueProviderNotSupportedError\n *\n * Thrown when attempting to use a queue provider that is not supported.\n * Valid providers are: 'cloudflare', 'sync'\n *\n * This typically indicates an invalid QUEUE_PROVIDER environment variable.\n */\nexport class QueueProviderNotSupportedError extends ApplicationError {\n constructor(provider: string) {\n super(\n 'errors.queueProviderNotSupported',\n ERROR_CODES.SYSTEM.QUEUE_PROVIDER_NOT_SUPPORTED,\n { provider }\n )\n }\n}\n","import { inject } from 'tsyringe'\nimport { type StratalEnv } from '../../env'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { QueueBindingNotFoundError } from '../errors'\nimport type { QueueMessage } from '../queue-consumer'\nimport type { IQueueProvider } from './queue-provider.interface'\n\n/**\n * Cloudflare Queue Provider\n *\n * Sends messages to Cloudflare Queues by resolving bindings from the environment.\n * Used in production environments where Cloudflare Workers handle queue processing.\n *\n * **Binding Resolution:**\n * Queue names are converted to binding names:\n * - `notifications-queue` → `NOTIFICATIONS_QUEUE`\n *\n * @example\n * ```typescript\n * const provider = new CloudflareQueueProvider(env)\n * await provider.send('notifications-queue', message)\n * ```\n */\n@Transient()\nexport class CloudflareQueueProvider implements IQueueProvider {\n constructor(\n @inject(DI_TOKENS.CloudflareEnv) private readonly env: StratalEnv\n ) { }\n\n /**\n * Send a message to a Cloudflare Queue\n *\n * @param queueName - Queue name (e.g., 'notifications-queue')\n * @param message - Complete message with id, timestamp, and payload\n * @throws {QueueBindingNotFoundError} If queue binding is not configured\n */\n async send<T>(queueName: string, message: QueueMessage<T>): Promise<void> {\n const queue = this.getQueue(queueName)\n await queue.send(message)\n }\n\n /**\n * Resolve queue binding from Cloudflare environment\n *\n * Converts kebab-case queue name to UPPER_SNAKE_CASE binding name.\n *\n * @param queueName - Queue name (e.g., 'notifications-queue')\n * @returns Cloudflare Queue binding\n * @throws {QueueBindingNotFoundError} If binding not found in env\n */\n private getQueue(queueName: string): Queue {\n const bindingName = queueName.toUpperCase().replace(/-/g, '_')\n const queue = (this.env as unknown as Record<string, unknown>)[bindingName] as Queue | undefined\n\n if (!queue) {\n throw new QueueBindingNotFoundError(queueName, bindingName)\n }\n\n return queue\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type ConsumerRegistry } from '../consumer-registry'\nimport type { QueueMessage } from '../queue-consumer'\nimport type { IQueueProvider } from './queue-provider.interface'\n\n/**\n * Sync Queue Provider\n *\n * Processes messages immediately by finding matching consumers and calling\n * their handle() method directly. Used for testing and development where\n * real queue infrastructure is not available.\n *\n * **Behavior:**\n * - Messages are processed synchronously when send() is called\n * - Matching consumers are found via ConsumerRegistry by message type\n * - All matching consumers are called sequentially\n * - Errors are re-thrown after onError() is called (fail-fast for testing)\n *\n * **Consumer Matching:**\n * - Consumers are matched by message type, not queue name\n * - Wildcard ('*') matches all message types\n *\n * @example Testing with sync provider\n * ```typescript\n * const provider = new SyncQueueProvider(registry)\n * await provider.send('notifications-queue', {\n * id: '123',\n * timestamp: Date.now(),\n * type: 'email.send',\n * payload: { to: 'test@example.com' }\n * })\n * // Consumer's handle() is called immediately!\n * ```\n */\n@Transient()\nexport class SyncQueueProvider implements IQueueProvider {\n constructor(\n @inject(DI_TOKENS.ConsumerRegistry) private readonly registry: ConsumerRegistry\n ) {}\n\n /**\n * Process a message synchronously\n *\n * Finds all matching consumers by message type and calls their handle() method.\n * If any consumer throws, onError() is called and the error is re-thrown.\n *\n * @param _queueName - Queue name (not used for routing, consumers match by message type)\n * @param message - Complete message with id, timestamp, and payload\n * @throws Re-throws any error from consumer.handle() after calling onError()\n */\n async send<T>(_queueName: string, message: QueueMessage<T>): Promise<void> {\n // Consumers are matched by message type, not queue name\n const consumers = this.registry.getConsumers(message.type)\n\n // Process synchronously - call each matching consumer\n for (const consumer of consumers) {\n try {\n await consumer.handle(message)\n } catch (error) {\n const errorInstance = error instanceof Error\n ? error\n : new Error(String(error))\n\n // Call onError hook if defined\n if (consumer.onError) {\n await consumer.onError(errorInstance, message)\n }\n\n // Re-throw for fail-fast behavior in tests\n throw errorInstance\n }\n }\n }\n}\n","import { inject } from 'tsyringe'\nimport { type StratalEnv } from '../../env'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type ConsumerRegistry } from '../consumer-registry'\nimport { QueueProviderNotSupportedError } from '../errors'\nimport { CloudflareQueueProvider, SyncQueueProvider, type IQueueProvider } from '../providers'\nimport type { QueueModuleOptions } from '../queue.module'\nimport { QUEUE_TOKENS } from '../queue.tokens'\n\n/**\n * Queue Provider Factory\n *\n * Creates the appropriate queue provider based on configuration provided\n * via QueueModule.forRootAsync().\n *\n * **Provider Selection:**\n * - `cloudflare`: Production provider using Cloudflare Queue bindings\n * - `sync`: Testing provider that processes messages immediately\n *\n * @example\n * ```typescript\n * // Configuration via QueueModule.forRootAsync()\n * QueueModule.forRootAsync({\n * inject: [CONFIG_TOKENS.ConfigService],\n * useFactory: (config) => ({ provider: config.get('queue').provider })\n * })\n *\n * // Factory usage (internal)\n * const factory = container.resolve(QueueProviderFactory)\n * const provider = factory.create()\n * ```\n */\n@Transient(QUEUE_TOKENS.QueueProviderFactory)\nexport class QueueProviderFactory {\n constructor(\n @inject(DI_TOKENS.CloudflareEnv) private readonly env: StratalEnv,\n @inject(DI_TOKENS.ConsumerRegistry) private readonly registry: ConsumerRegistry,\n @inject(QUEUE_TOKENS.QueueModuleOptions, { isOptional: true }) private readonly options?: QueueModuleOptions,\n ) { }\n\n /**\n * Create a queue provider based on module configuration\n *\n * @returns Queue provider instance\n * @throws {QueueProviderNotSupportedError} If provider type is not supported\n */\n create(): IQueueProvider {\n const providerType = this.options?.provider ?? 'cloudflare'\n\n switch (providerType) {\n case 'cloudflare':\n return new CloudflareQueueProvider(this.env)\n\n case 'sync':\n return new SyncQueueProvider(this.registry)\n\n default:\n throw new QueueProviderNotSupportedError(providerType)\n }\n }\n}\n","/**\n * Queue Module\n *\n * Provides declarative queue infrastructure with provider abstraction.\n *\n * **Usage:**\n * ```typescript\n * // 1. Configure provider (once, in app root)\n * QueueModule.forRootAsync({\n * inject: [CONFIG_TOKENS.ConfigService],\n * useFactory: (config) => ({ provider: config.get('queue').provider })\n * })\n *\n * // 2. Register queues (queue name IS the injection token)\n * QueueModule.registerQueue('notifications-queue')\n * QueueModule.registerQueue('batch-notifications-queue')\n *\n * // 3. Inject and use\n * constructor(@InjectQueue('notifications-queue') private queue: IQueueSender) {}\n * await this.queue.dispatch({ type: 'email.send', payload: {...} })\n * ```\n *\n * **Providers:**\n * - `cloudflare`: Production provider using Cloudflare Queue bindings\n * - `sync`: Testing provider that processes messages immediately\n */\n\nimport { DI_TOKENS } from '../di/tokens'\nimport { Scope } from '../di/types'\nimport { Module } from '../module'\nimport type { AsyncModuleOptions, DynamicModule, InjectionToken } from '../module/types'\nimport { ConsumerRegistry } from './consumer-registry'\nimport type { QueueName } from './queue-name'\nimport { QueueRegistry } from './queue-registry'\nimport type { IQueueSender } from './queue-sender.interface'\nimport { QUEUE_TOKENS } from './queue.tokens'\nimport { QueueProviderFactory } from './services'\n\n/**\n * Queue module configuration options\n */\nexport interface QueueModuleOptions {\n /**\n * Queue provider type\n * - 'cloudflare': Production provider using Cloudflare Queue bindings\n * - 'sync': Testing provider that processes messages immediately\n */\n provider: 'cloudflare' | 'sync'\n}\n\n@Module({\n providers: [\n { provide: DI_TOKENS.ConsumerRegistry, useClass: ConsumerRegistry, scope: Scope.Singleton },\n { provide: QUEUE_TOKENS.QueueProviderFactory, useClass: QueueProviderFactory, scope: Scope.Singleton },\n { provide: QUEUE_TOKENS.QueueRegistry, useClass: QueueRegistry },\n ],\n})\nexport class QueueModule {\n /**\n * Configure queue infrastructure with async factory.\n *\n * Use when provider configuration depends on other services like ConfigService.\n *\n * @param options - Async configuration with factory and inject tokens\n * @returns Dynamic module with queue infrastructure\n *\n * @example\n * ```typescript\n * QueueModule.forRootAsync({\n * inject: [CONFIG_TOKENS.ConfigService],\n * useFactory: (config: IConfigService) => ({\n * provider: config.get('queue').provider\n * })\n * })\n * ```\n */\n static forRootAsync(options: AsyncModuleOptions<QueueModuleOptions>): DynamicModule {\n return {\n module: QueueModule,\n providers: [\n {\n provide: QUEUE_TOKENS.QueueModuleOptions,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n /**\n * Register a queue for injection.\n *\n * The queue name serves as both the identifier and the DI injection token.\n * Queue names are typed via module augmentation of QueueNames interface.\n *\n * @param name - Queue name (typed with autocomplete if QueueNames is augmented)\n * @returns Dynamic module that provides the queue sender\n *\n * @example\n * ```typescript\n * // In AppModule imports\n * QueueModule.registerQueue('notifications-queue')\n *\n * // Then inject using the queue name\n * constructor(@InjectQueue('notifications-queue') private queue: IQueueSender) {}\n * ```\n */\n static registerQueue(name: QueueName): DynamicModule {\n return {\n module: QueueModule,\n providers: [\n {\n provide: name as InjectionToken<IQueueSender>,\n useFactory: (registry: QueueRegistry) => registry.getQueue(name),\n inject: [QUEUE_TOKENS.QueueRegistry],\n },\n ],\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"queue.module-P-G-nCYz.mjs","names":[],"sources":["../src/queue/consumer-registry.ts","../src/queue/queue-sender.ts","../src/queue/queue.tokens.ts","../src/queue/queue-registry.ts","../src/queue/errors/queue-binding-not-found.error.ts","../src/queue/errors/queue-provider-not-supported.error.ts","../src/queue/providers/cloudflare-queue.provider.ts","../src/queue/providers/sync-queue.provider.ts","../src/queue/services/queue-provider-factory.ts","../src/queue/queue.module.ts"],"sourcesContent":["import { Transient } from '../di/decorators'\nimport { DI_TOKENS } from '../di/tokens'\nimport type { IQueueConsumer } from './queue-consumer'\n\n/**\n * Consumer Registry\n *\n * Singleton service that holds all registered queue consumers indexed by message type.\n * Consumers declare the message types they handle, and this registry routes messages\n * to the appropriate consumers based on their types.\n *\n * **Message-Type Routing:**\n * - Consumers declare `messageTypes` array (e.g., `['email.send', 'email.batch.send']`)\n * - When a message arrives, consumers matching the message type are invoked\n * - A consumer can handle messages from ANY queue (routing is by type, not queue)\n * - Use `'*'` as a wildcard to handle all message types\n *\n * @example Consumer registration\n * ```typescript\n * // In consumer.ts\n * @Transient()\n * export class EmailConsumer implements IQueueConsumer {\n * readonly messageTypes = ['email.send', 'email.batch.send']\n * // ...\n * }\n *\n * // In module.ts\n * @Module({\n * consumers: [EmailConsumer]\n * })\n *\n * // Application auto-registers via ConsumerRegistry\n * this.consumerRegistry.register(consumer)\n * ```\n */\n@Transient(DI_TOKENS.ConsumerRegistry)\nexport class ConsumerRegistry {\n /** Map from message type to consumers handling that type */\n private consumersByType = new Map<string, IQueueConsumer[]>()\n\n /** Set of all registered consumers (for iteration) */\n private allConsumers = new Set<IQueueConsumer>()\n\n /**\n * Register a queue consumer\n *\n * Indexes the consumer by each of its declared message types.\n *\n * @param consumer - Queue consumer to register\n */\n register(consumer: IQueueConsumer): void {\n if (this.allConsumers.has(consumer)) {\n return // Already registered\n }\n\n this.allConsumers.add(consumer)\n\n for (const messageType of consumer.messageTypes) {\n const existing = this.consumersByType.get(messageType) ?? []\n existing.push(consumer)\n this.consumersByType.set(messageType, existing)\n }\n }\n\n /**\n * Get all consumers that can handle a specific message type\n *\n * Returns consumers that either:\n * - Explicitly declare the message type\n * - Use '*' wildcard to handle all types\n *\n * @param messageType - The message type to find consumers for\n * @returns Array of consumers that can handle this message type\n */\n getConsumers(messageType: string): IQueueConsumer[] {\n const exactMatch = this.consumersByType.get(messageType) ?? []\n const wildcardMatch = this.consumersByType.get('*') ?? []\n\n // Combine and dedupe\n const combined = new Set([...exactMatch, ...wildcardMatch])\n return Array.from(combined)\n }\n\n /**\n * Check if any consumers can handle a message type\n *\n * @param messageType - The message type to check\n * @returns true if at least one consumer can handle this type\n */\n hasConsumers(messageType: string): boolean {\n return this.getConsumers(messageType).length > 0\n }\n\n /**\n * Get all registered message types\n *\n * @returns Array of message types with registered consumers\n */\n getMessageTypes(): string[] {\n return Array.from(this.consumersByType.keys())\n }\n\n /**\n * Get all registered consumers\n *\n * @returns Array of all registered consumers\n */\n getAllConsumers(): IQueueConsumer[] {\n return Array.from(this.allConsumers)\n }\n}\n","import type { II18nService } from '../i18n/i18n.types'\nimport type { IQueueProvider } from './providers'\nimport type { QueueMessage } from './queue-consumer'\nimport type { DispatchMessage, IQueueSender } from './queue-sender.interface'\n\n/**\n * Queue Sender\n *\n * Implementation of IQueueSender bound to a specific queue name.\n * Created by QueueRegistry for each registered queue.\n *\n * Automatically enriches messages with:\n * - `id`: UUID generated via crypto.randomUUID()\n * - `timestamp`: Current time in milliseconds\n * - `metadata.locale`: Current locale from I18n context\n *\n * @example\n * ```typescript\n * // Created by QueueRegistry, not directly instantiated\n * const sender = registry.getQueue('notifications-queue')\n *\n * await sender.dispatch({\n * type: 'email.send',\n * payload: { to: 'user@example.com', subject: 'Hello' }\n * })\n * ```\n */\nexport class QueueSender implements IQueueSender {\n constructor(\n private readonly queueName: string,\n private readonly provider: IQueueProvider,\n private readonly i18n: II18nService\n ) {}\n\n /**\n * Dispatch a message to this queue.\n *\n * @param message - Message to dispatch (without id/timestamp)\n */\n async dispatch<T>(message: DispatchMessage<T>): Promise<void> {\n const metadata = { ...message.metadata }\n\n if (!metadata.locale) {\n const locale = this.i18n.getLocale()\n if (locale) {\n metadata.locale = locale\n }\n }\n\n const fullMessage: QueueMessage<T> = {\n id: crypto.randomUUID(),\n timestamp: Date.now(),\n ...message,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined\n }\n\n await this.provider.send(this.queueName, fullMessage)\n }\n}\n","export const QUEUE_TOKENS = {\n QueueProviderFactory: Symbol.for('stratal:queue:provider:factory'),\n QueueRegistry: Symbol.for('stratal:queue:registry'),\n QueueModuleOptions: Symbol.for('stratal:queue:options'),\n} as const\n\nexport type QueueToken = (typeof QUEUE_TOKENS)[keyof typeof QUEUE_TOKENS]\n","import { inject } from 'tsyringe'\nimport { Transient } from '../di/decorators'\nimport { I18N_TOKENS } from '../i18n/i18n.tokens'\nimport type { II18nService } from '../i18n/i18n.types'\nimport type { IQueueProvider } from './providers'\nimport type { IQueueSender } from './queue-sender.interface'\nimport { QueueSender } from './queue-sender'\nimport { QUEUE_TOKENS } from './queue.tokens'\nimport { type QueueProviderFactory } from './services'\n\n/**\n * Queue Registry\n *\n * Request-scoped factory service for creating QueueSender instances.\n * Caches senders per queue name within the request scope.\n *\n * This service is used internally by QueueModule.registerQueue() to provide\n * IQueueSender instances for each registered queue.\n *\n * **Why request-scoped?**\n * - Needs access to I18nService for locale-aware message metadata\n * - Provider is created once per request for consistency\n * - Queue senders are cached per request to avoid recreating them\n *\n * @example\n * ```typescript\n * // Used internally by QueueModule.registerQueue()\n * QueueModule.registerQueue('notifications-queue')\n *\n * // The module creates a factory provider:\n * {\n * provide: 'notifications-queue',\n * useFactory: (registry: QueueRegistry) => registry.getQueue('notifications-queue'),\n * inject: [QUEUE_TOKENS.QueueRegistry],\n * }\n * ```\n */\n@Transient(QUEUE_TOKENS.QueueRegistry)\nexport class QueueRegistry {\n private readonly provider: IQueueProvider\n private readonly senders = new Map<string, IQueueSender>()\n\n constructor(\n @inject(QUEUE_TOKENS.QueueProviderFactory) providerFactory: QueueProviderFactory,\n @inject(I18N_TOKENS.I18nService) private readonly i18n: II18nService\n ) {\n this.provider = providerFactory.create()\n }\n\n /**\n * Get or create a QueueSender for the specified queue name.\n *\n * Senders are cached per queue name within the request scope.\n *\n * @param queueName - The queue name to get a sender for\n * @returns QueueSender bound to the specified queue\n */\n getQueue(queueName: string): IQueueSender {\n let sender = this.senders.get(queueName)\n\n if (!sender) {\n sender = new QueueSender(queueName, this.provider, this.i18n)\n this.senders.set(queueName, sender)\n }\n\n return sender\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * QueueBindingNotFoundError\n *\n * Thrown when attempting to access a Cloudflare Queue binding that hasn't been configured.\n * This typically indicates that the queue binding is missing from wrangler.jsonc\n * or the environment variables are not properly set.\n */\nexport class QueueBindingNotFoundError extends ApplicationError {\n constructor(queueName: string, bindingName: string) {\n super(\n 'errors.queueBindingNotFound',\n ERROR_CODES.SYSTEM.QUEUE_BINDING_NOT_FOUND,\n { queueName, bindingName }\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * QueueProviderNotSupportedError\n *\n * Thrown when attempting to use a queue provider that is not supported.\n * Valid providers are: 'cloudflare', 'sync'\n *\n * This typically indicates an invalid QUEUE_PROVIDER environment variable.\n */\nexport class QueueProviderNotSupportedError extends ApplicationError {\n constructor(provider: string) {\n super(\n 'errors.queueProviderNotSupported',\n ERROR_CODES.SYSTEM.QUEUE_PROVIDER_NOT_SUPPORTED,\n { provider }\n )\n }\n}\n","import { inject } from 'tsyringe'\nimport { type StratalEnv } from '../../env'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { QueueBindingNotFoundError } from '../errors'\nimport type { QueueMessage } from '../queue-consumer'\nimport type { IQueueProvider } from './queue-provider.interface'\n\n/**\n * Cloudflare Queue Provider\n *\n * Sends messages to Cloudflare Queues by resolving bindings from the environment.\n * Used in production environments where Cloudflare Workers handle queue processing.\n *\n * **Binding Resolution:**\n * Queue names are converted to binding names:\n * - `notifications-queue` → `NOTIFICATIONS_QUEUE`\n *\n * @example\n * ```typescript\n * const provider = new CloudflareQueueProvider(env)\n * await provider.send('notifications-queue', message)\n * ```\n */\n@Transient()\nexport class CloudflareQueueProvider implements IQueueProvider {\n constructor(\n @inject(DI_TOKENS.CloudflareEnv) private readonly env: StratalEnv\n ) { }\n\n /**\n * Send a message to a Cloudflare Queue\n *\n * @param queueName - Queue name (e.g., 'notifications-queue')\n * @param message - Complete message with id, timestamp, and payload\n * @throws {QueueBindingNotFoundError} If queue binding is not configured\n */\n async send<T>(queueName: string, message: QueueMessage<T>): Promise<void> {\n const queue = this.getQueue(queueName)\n await queue.send(message)\n }\n\n /**\n * Resolve queue binding from Cloudflare environment\n *\n * Converts kebab-case queue name to UPPER_SNAKE_CASE binding name.\n *\n * @param queueName - Queue name (e.g., 'notifications-queue')\n * @returns Cloudflare Queue binding\n * @throws {QueueBindingNotFoundError} If binding not found in env\n */\n private getQueue(queueName: string): Queue {\n const bindingName = queueName.toUpperCase().replace(/-/g, '_')\n const queue = (this.env as unknown as Record<string, unknown>)[bindingName] as Queue | undefined\n\n if (!queue) {\n throw new QueueBindingNotFoundError(queueName, bindingName)\n }\n\n return queue\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type ConsumerRegistry } from '../consumer-registry'\nimport type { QueueMessage } from '../queue-consumer'\nimport type { IQueueProvider } from './queue-provider.interface'\n\n/**\n * Sync Queue Provider\n *\n * Processes messages immediately by finding matching consumers and calling\n * their handle() method directly. Used for testing and development where\n * real queue infrastructure is not available.\n *\n * **Behavior:**\n * - Messages are processed synchronously when send() is called\n * - Matching consumers are found via ConsumerRegistry by message type\n * - All matching consumers are called sequentially\n * - Errors are re-thrown after onError() is called (fail-fast for testing)\n *\n * **Consumer Matching:**\n * - Consumers are matched by message type, not queue name\n * - Wildcard ('*') matches all message types\n *\n * @example Testing with sync provider\n * ```typescript\n * const provider = new SyncQueueProvider(registry)\n * await provider.send('notifications-queue', {\n * id: '123',\n * timestamp: Date.now(),\n * type: 'email.send',\n * payload: { to: 'test@example.com' }\n * })\n * // Consumer's handle() is called immediately!\n * ```\n */\n@Transient()\nexport class SyncQueueProvider implements IQueueProvider {\n constructor(\n @inject(DI_TOKENS.ConsumerRegistry) private readonly registry: ConsumerRegistry\n ) {}\n\n /**\n * Process a message synchronously\n *\n * Finds all matching consumers by message type and calls their handle() method.\n * If any consumer throws, onError() is called and the error is re-thrown.\n *\n * @param _queueName - Queue name (not used for routing, consumers match by message type)\n * @param message - Complete message with id, timestamp, and payload\n * @throws Re-throws any error from consumer.handle() after calling onError()\n */\n async send<T>(_queueName: string, message: QueueMessage<T>): Promise<void> {\n // Consumers are matched by message type, not queue name\n const consumers = this.registry.getConsumers(message.type)\n\n // Process synchronously - call each matching consumer\n for (const consumer of consumers) {\n try {\n await consumer.handle(message)\n } catch (error) {\n const errorInstance = error instanceof Error\n ? error\n : new Error(String(error))\n\n // Call onError hook if defined\n if (consumer.onError) {\n await consumer.onError(errorInstance, message)\n }\n\n // Re-throw for fail-fast behavior in tests\n throw errorInstance\n }\n }\n }\n}\n","import { inject } from 'tsyringe'\nimport { type StratalEnv } from '../../env'\nimport { Transient } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type ConsumerRegistry } from '../consumer-registry'\nimport { QueueProviderNotSupportedError } from '../errors'\nimport { CloudflareQueueProvider, SyncQueueProvider, type IQueueProvider } from '../providers'\nimport type { QueueModuleOptions } from '../queue.module'\nimport { QUEUE_TOKENS } from '../queue.tokens'\n\n/**\n * Queue Provider Factory\n *\n * Creates the appropriate queue provider based on configuration provided\n * via QueueModule.forRootAsync().\n *\n * **Provider Selection:**\n * - `cloudflare`: Production provider using Cloudflare Queue bindings\n * - `sync`: Testing provider that processes messages immediately\n *\n * @example\n * ```typescript\n * // Configuration via QueueModule.forRootAsync()\n * QueueModule.forRootAsync({\n * inject: [CONFIG_TOKENS.ConfigService],\n * useFactory: (config) => ({ provider: config.get('queue').provider })\n * })\n *\n * // Factory usage (internal)\n * const factory = container.resolve(QueueProviderFactory)\n * const provider = factory.create()\n * ```\n */\n@Transient(QUEUE_TOKENS.QueueProviderFactory)\nexport class QueueProviderFactory {\n constructor(\n @inject(DI_TOKENS.CloudflareEnv) private readonly env: StratalEnv,\n @inject(DI_TOKENS.ConsumerRegistry) private readonly registry: ConsumerRegistry,\n @inject(QUEUE_TOKENS.QueueModuleOptions, { isOptional: true }) private readonly options?: QueueModuleOptions,\n ) { }\n\n /**\n * Create a queue provider based on module configuration\n *\n * @returns Queue provider instance\n * @throws {QueueProviderNotSupportedError} If provider type is not supported\n */\n create(): IQueueProvider {\n const providerType = this.options?.provider ?? 'cloudflare'\n\n switch (providerType) {\n case 'cloudflare':\n return new CloudflareQueueProvider(this.env)\n\n case 'sync':\n return new SyncQueueProvider(this.registry)\n\n default:\n throw new QueueProviderNotSupportedError(providerType)\n }\n }\n}\n","/**\n * Queue Module\n *\n * Provides declarative queue infrastructure with provider abstraction.\n *\n * **Usage:**\n * ```typescript\n * // 1. Configure provider (once, in app root)\n * QueueModule.forRootAsync({\n * inject: [CONFIG_TOKENS.ConfigService],\n * useFactory: (config) => ({ provider: config.get('queue').provider })\n * })\n *\n * // 2. Register queues (queue name IS the injection token)\n * QueueModule.registerQueue('notifications-queue')\n * QueueModule.registerQueue('batch-notifications-queue')\n *\n * // 3. Inject and use\n * constructor(@InjectQueue('notifications-queue') private queue: IQueueSender) {}\n * await this.queue.dispatch({ type: 'email.send', payload: {...} })\n * ```\n *\n * **Providers:**\n * - `cloudflare`: Production provider using Cloudflare Queue bindings\n * - `sync`: Testing provider that processes messages immediately\n */\n\nimport { DI_TOKENS } from '../di/tokens'\nimport { Scope } from '../di/types'\nimport { Module } from '../module'\nimport type { AsyncModuleOptions, DynamicModule, InjectionToken } from '../module/types'\nimport { ConsumerRegistry } from './consumer-registry'\nimport type { QueueName } from './queue-name'\nimport { QueueRegistry } from './queue-registry'\nimport type { IQueueSender } from './queue-sender.interface'\nimport { QUEUE_TOKENS } from './queue.tokens'\nimport { QueueProviderFactory } from './services'\n\n/**\n * Queue module configuration options\n */\nexport interface QueueModuleOptions {\n /**\n * Queue provider type\n * - 'cloudflare': Production provider using Cloudflare Queue bindings\n * - 'sync': Testing provider that processes messages immediately\n */\n provider: 'cloudflare' | 'sync'\n}\n\n@Module({\n providers: [\n { provide: DI_TOKENS.ConsumerRegistry, useClass: ConsumerRegistry, scope: Scope.Singleton },\n { provide: QUEUE_TOKENS.QueueProviderFactory, useClass: QueueProviderFactory, scope: Scope.Singleton },\n { provide: QUEUE_TOKENS.QueueRegistry, useClass: QueueRegistry },\n ],\n})\nexport class QueueModule {\n /**\n * Configure queue infrastructure with async factory.\n *\n * Use when provider configuration depends on other services like ConfigService.\n *\n * @param options - Async configuration with factory and inject tokens\n * @returns Dynamic module with queue infrastructure\n *\n * @example\n * ```typescript\n * QueueModule.forRootAsync({\n * inject: [CONFIG_TOKENS.ConfigService],\n * useFactory: (config: IConfigService) => ({\n * provider: config.get('queue').provider\n * })\n * })\n * ```\n */\n static forRootAsync(options: AsyncModuleOptions<QueueModuleOptions>): DynamicModule {\n return {\n module: QueueModule,\n providers: [\n {\n provide: QUEUE_TOKENS.QueueModuleOptions,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n /**\n * Register a queue for injection.\n *\n * The queue name serves as both the identifier and the DI injection token.\n * Queue names are typed via module augmentation of QueueNames interface.\n *\n * @param name - Queue name (typed with autocomplete if QueueNames is augmented)\n * @returns Dynamic module that provides the queue sender\n *\n * @example\n * ```typescript\n * // In AppModule imports\n * QueueModule.registerQueue('notifications-queue')\n *\n * // Then inject using the queue name\n * constructor(@InjectQueue('notifications-queue') private queue: IQueueSender) {}\n * ```\n */\n static registerQueue(name: QueueName): DynamicModule {\n return {\n module: QueueModule,\n providers: [\n {\n provide: name as InjectionToken<IQueueSender>,\n useFactory: (registry: QueueRegistry) => registry.getQueue(name),\n inject: [QUEUE_TOKENS.QueueRegistry],\n },\n ],\n }\n }\n}\n"],"mappings":"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"}