@geekmidas/cli 0.2.0 → 0.2.2

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.
@@ -13,12 +13,12 @@ var SubscriberGenerator = class extends require_Generator.ConstructGenerator {
13
13
  const provider = options?.provider || "aws-lambda";
14
14
  const logger = console;
15
15
  const subscriberInfos = [];
16
- if (constructs.length === 0) return subscriberInfos;
17
16
  if (provider === "server") {
18
17
  await this.generateServerSubscribersFile(outputDir, constructs);
19
18
  logger.log(`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`);
20
19
  return subscriberInfos;
21
20
  }
21
+ if (constructs.length === 0) return subscriberInfos;
22
22
  if (provider !== "aws-lambda") return subscriberInfos;
23
23
  const subscribersDir = (0, node_path.join)(outputDir, "subscribers");
24
24
  await (0, node_fs_promises.mkdir)(subscribersDir, { recursive: true });
@@ -53,6 +53,7 @@ export const handler = adapter.handler;
53
53
  return handlerPath;
54
54
  }
55
55
  async generateServerSubscribersFile(outputDir, subscribers) {
56
+ await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
56
57
  const subscribersFileName = "subscribers.ts";
57
58
  const subscribersPath = (0, node_path.join)(outputDir, subscribersFileName);
58
59
  const importsByFile = /* @__PURE__ */ new Map();
@@ -201,4 +202,4 @@ Object.defineProperty(exports, 'SubscriberGenerator', {
201
202
  return SubscriberGenerator;
202
203
  }
203
204
  });
204
- //# sourceMappingURL=SubscriberGenerator-BfMZCVNy.cjs.map
205
+ //# sourceMappingURL=SubscriberGenerator-CB-NHtZW.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriberGenerator-CB-NHtZW.cjs","names":["ConstructGenerator","value: any","context: BuildContext","constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","subscriberInfos: SubscriberInfo[]","sourceFile: string","exportName: string","_subscriber: Subscriber<any, any, any, any, any, any>","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","exports"],"sources":["../src/generators/SubscriberGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Subscriber } from '@geekmidas/constructs/subscribers';\nimport type { BuildContext } from '../build/types';\nimport type { SubscriberInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class SubscriberGenerator extends ConstructGenerator<\n Subscriber<any, any, any, any, any, any>,\n SubscriberInfo[]\n> {\n isConstruct(value: any): value is Subscriber<any, any, any, any, any, any> {\n return Subscriber.isSubscriber(value);\n }\n\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<SubscriberInfo[]> {\n const provider = options?.provider || 'aws-lambda';\n const logger = console;\n const subscriberInfos: SubscriberInfo[] = [];\n\n if (provider === 'server') {\n // Generate subscribers.ts for server-based polling (even if empty)\n await this.generateServerSubscribersFile(outputDir, constructs);\n\n logger.log(\n `Generated server subscribers file with ${constructs.length} subscribers (polling mode)`,\n );\n\n // Return empty array as server subscribers don't have individual handlers\n return subscriberInfos;\n }\n\n if (constructs.length === 0) {\n return subscriberInfos;\n }\n\n if (provider !== 'aws-lambda') {\n return subscriberInfos;\n }\n\n // Create subscribers subdirectory\n const subscribersDir = join(outputDir, 'subscribers');\n await mkdir(subscribersDir, { recursive: true });\n\n // Generate subscriber handlers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateSubscriberHandler(\n subscribersDir,\n path.relative,\n key,\n construct,\n context,\n );\n\n subscriberInfos.push({\n name: key,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n subscribedEvents: construct.subscribedEvents || [],\n timeout: construct.timeout,\n environment: await construct.getEnvironment(),\n });\n\n logger.log(`Generated subscriber handler: ${key}`);\n }\n\n return subscriberInfos;\n }\n\n private async generateSubscriberHandler(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n _subscriber: Subscriber<any, any, any, any, any, any>,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n\n const content = `import { AWSLambdaSubscriber } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\n\nconst adapter = new AWSLambdaSubscriber(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n\n private async generateServerSubscribersFile(\n outputDir: string,\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n ): Promise<string> {\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n const subscribersFileName = 'subscribers.ts';\n const subscribersPath = join(outputDir, subscribersFileName);\n\n // Group imports by file\n const importsByFile = new Map<string, string[]>();\n\n for (const { path, key } of subscribers) {\n const relativePath = relative(dirname(subscribersPath), path.relative);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n if (!importsByFile.has(importPath)) {\n importsByFile.set(importPath, []);\n }\n importsByFile.get(importPath)!.push(key);\n }\n\n // Generate import statements\n const imports = Array.from(importsByFile.entries())\n .map(\n ([importPath, exports]) =>\n `import { ${exports.join(', ')} } from '${importPath}';`,\n )\n .join('\\n');\n\n const allExportNames = subscribers.map(({ key }) => key);\n\n const content = `/**\n * Generated subscribers setup\n *\n * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY\n * This uses event polling which is not suitable for production.\n *\n * For production, use AWS Lambda with SQS/SNS event source mappings.\n * Lambda automatically:\n * - Scales based on queue depth\n * - Handles batch processing and retries\n * - Manages dead letter queues\n * - Provides better cost optimization\n *\n * This polling implementation is useful for:\n * - Local development and testing\n * - Understanding event flow without Lambda deployment\n *\n * Supported connection strings:\n * - sqs://region/account-id/queue-name (SQS queue)\n * - sns://region/account-id/topic-name (SNS topic)\n * - rabbitmq://host:port/queue-name (RabbitMQ)\n * - basic://in-memory (In-memory for testing)\n */\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { EventConnectionFactory, Subscriber } from '@geekmidas/events';\nimport type { EventConnection, EventSubscriber } from '@geekmidas/events';\nimport { ServiceDiscovery } from '@geekmidas/services';\n${imports}\n\nconst subscribers = [\n ${allExportNames.join(',\\n ')}\n];\n\nconst activeSubscribers: EventSubscriber<any>[] = [];\n\nexport async function setupSubscribers(\n envParser: EnvironmentParser<any>,\n logger: Logger,\n): Promise<void> {\n logger.info('Setting up subscribers in polling mode (local development)');\n\n const config = envParser.create((get) => ({\n connectionString: get('EVENT_SUBSCRIBER_CONNECTION_STRING').string().optional(),\n })).parse();\n\n if (!config.connectionString) {\n logger.warn('EVENT_SUBSCRIBER_CONNECTION_STRING not configured, skipping subscriber setup');\n return;\n }\n\n const serviceDiscovery = ServiceDiscovery.getInstance(logger, envParser);\n\n // Create connection once, outside the loop (more efficient)\n // EventConnectionFactory automatically determines the right connection type\n let connection: EventConnection;\n try {\n connection = await EventConnectionFactory.fromConnectionString(config.connectionString);\n\n const connectionType = new URL(config.connectionString).protocol.replace(':', '');\n logger.info({ connectionType }, 'Created shared event connection');\n } catch (error) {\n logger.error({ error }, 'Failed to create event connection');\n return;\n }\n\n for (const subscriber of subscribers) {\n try {\n // Create subscriber from shared connection\n const eventSubscriber = await Subscriber.fromConnection(connection);\n\n // Register services\n const services = subscriber.services.length > 0\n ? await serviceDiscovery.register(subscriber.services)\n : {};\n\n // Subscribe to events\n const subscribedEvents = subscriber.subscribedEvents || [];\n\n if (subscribedEvents.length === 0) {\n logger.warn({ subscriber: subscriber.constructor.name }, 'Subscriber has no subscribed events, skipping');\n continue;\n }\n\n await eventSubscriber.subscribe(subscribedEvents, async (event) => {\n try {\n // Process single event (batch of 1)\n await subscriber.handler({\n events: [event],\n services: services as any,\n logger: subscriber.logger,\n });\n\n logger.debug({ eventType: event.type }, 'Successfully processed event');\n } catch (error) {\n logger.error({ error, event }, 'Failed to process event');\n // Event will become visible again for retry\n }\n });\n\n activeSubscribers.push(eventSubscriber);\n\n logger.info(\n {\n events: subscribedEvents,\n },\n 'Subscriber started polling'\n );\n } catch (error) {\n logger.error({ error, subscriber: subscriber.constructor.name }, 'Failed to setup subscriber');\n }\n }\n\n // Setup graceful shutdown\n const shutdown = () => {\n logger.info('Stopping all subscribers');\n for (const eventSubscriber of activeSubscribers) {\n connection.stop();\n }\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n`;\n\n await writeFile(subscribersPath, content);\n return subscribersPath;\n }\n}\n"],"mappings":";;;;;;;AAWA,IAAa,sBAAb,cAAyCA,qCAGvC;CACA,YAAYC,OAA+D;AACzE,SAAO,8CAAW,aAAa,MAAM;CACtC;CAED,MAAM,MACJC,SACAC,YACAC,WACAC,SAC2B;EAC3B,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,SAAS;EACf,MAAMC,kBAAoC,CAAE;AAE5C,MAAI,aAAa,UAAU;AAEzB,SAAM,KAAK,8BAA8B,WAAW,WAAW;AAE/D,UAAO,KACJ,yCAAyC,WAAW,OAAO,6BAC7D;AAGD,UAAO;EACR;AAED,MAAI,WAAW,WAAW,EACxB,QAAO;AAGT,MAAI,aAAa,aACf,QAAO;EAIT,MAAM,iBAAiB,oBAAK,WAAW,cAAc;AACrD,QAAM,4BAAM,gBAAgB,EAAE,WAAW,KAAM,EAAC;AAGhD,OAAK,MAAM,EAAE,KAAK,WAAW,MAAM,IAAI,YAAY;GACjD,MAAM,cAAc,MAAM,KAAK,0BAC7B,gBACA,KAAK,UACL,KACA,WACA,QACD;AAED,mBAAgB,KAAK;IACnB,MAAM;IACN,SAAS,wBAAS,QAAQ,KAAK,EAAE,YAAY,CAAC,QAC5C,SACA,WACD;IACD,kBAAkB,UAAU,oBAAoB,CAAE;IAClD,SAAS,UAAU;IACnB,aAAa,MAAM,UAAU,gBAAgB;GAC9C,EAAC;AAEF,UAAO,KAAK,gCAAgC,IAAI,EAAE;EACnD;AAED,SAAO;CACR;CAED,MAAc,0BACZF,WACAG,YACAC,YACAC,aACAP,SACiB;EACjB,MAAM,mBAAmB,EAAE,WAAW;EACtC,MAAM,cAAc,oBAAK,WAAW,gBAAgB;EAEpD,MAAM,eAAe,wBAAS,uBAAQ,YAAY,EAAE,WAAW;EAC/D,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;EAEvD,MAAM,wBAAwB,wBAC5B,uBAAQ,YAAY,EACpB,QAAQ,cACT;EAED,MAAM,WAAW;WACV,WAAW,WAAW,WAAW;SACnC,QAAQ,uBAAuB,SAAS,sBAAsB;;qDAElB,WAAW;;;;AAK5D,QAAM,gCAAU,aAAa,QAAQ;AACrC,SAAO;CACR;CAED,MAAc,8BACZE,WACAM,aACiB;AAEjB,QAAM,4BAAM,WAAW,EAAE,WAAW,KAAM,EAAC;EAE3C,MAAM,sBAAsB;EAC5B,MAAM,kBAAkB,oBAAK,WAAW,oBAAoB;EAG5D,MAAM,gCAAgB,IAAI;AAE1B,OAAK,MAAM,EAAE,MAAM,KAAK,IAAI,aAAa;GACvC,MAAM,eAAe,wBAAS,uBAAQ,gBAAgB,EAAE,KAAK,SAAS;GACtE,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;AAEvD,QAAK,cAAc,IAAI,WAAW,CAChC,eAAc,IAAI,YAAY,CAAE,EAAC;AAEnC,iBAAc,IAAI,WAAW,CAAE,KAAK,IAAI;EACzC;EAGD,MAAM,UAAU,MAAM,KAAK,cAAc,SAAS,CAAC,CAChD,IACC,CAAC,CAAC,YAAYC,UAAQ,MACnB,WAAW,UAAQ,KAAK,KAAK,CAAC,WAAW,WAAW,IACxD,CACA,KAAK,KAAK;EAEb,MAAM,iBAAiB,YAAY,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI;EAExD,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BnB,QAAQ;;;IAGN,eAAe,KAAK,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+F7B,QAAM,gCAAU,iBAAiB,QAAQ;AACzC,SAAO;CACR;AACF"}
@@ -12,12 +12,12 @@ var SubscriberGenerator = class extends ConstructGenerator {
12
12
  const provider = options?.provider || "aws-lambda";
13
13
  const logger = console;
14
14
  const subscriberInfos = [];
15
- if (constructs.length === 0) return subscriberInfos;
16
15
  if (provider === "server") {
17
16
  await this.generateServerSubscribersFile(outputDir, constructs);
18
17
  logger.log(`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`);
19
18
  return subscriberInfos;
20
19
  }
20
+ if (constructs.length === 0) return subscriberInfos;
21
21
  if (provider !== "aws-lambda") return subscriberInfos;
22
22
  const subscribersDir = join(outputDir, "subscribers");
23
23
  await mkdir(subscribersDir, { recursive: true });
@@ -52,6 +52,7 @@ export const handler = adapter.handler;
52
52
  return handlerPath;
53
53
  }
54
54
  async generateServerSubscribersFile(outputDir, subscribers) {
55
+ await mkdir(outputDir, { recursive: true });
55
56
  const subscribersFileName = "subscribers.ts";
56
57
  const subscribersPath = join(outputDir, subscribersFileName);
57
58
  const importsByFile = /* @__PURE__ */ new Map();
@@ -195,4 +196,4 @@ export async function setupSubscribers(
195
196
 
196
197
  //#endregion
197
198
  export { SubscriberGenerator };
198
- //# sourceMappingURL=SubscriberGenerator-D2u00NI3.mjs.map
199
+ //# sourceMappingURL=SubscriberGenerator-Cuu4co3-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriberGenerator-Cuu4co3-.mjs","names":["value: any","context: BuildContext","constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","subscriberInfos: SubscriberInfo[]","sourceFile: string","exportName: string","_subscriber: Subscriber<any, any, any, any, any, any>","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]"],"sources":["../src/generators/SubscriberGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Subscriber } from '@geekmidas/constructs/subscribers';\nimport type { BuildContext } from '../build/types';\nimport type { SubscriberInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class SubscriberGenerator extends ConstructGenerator<\n Subscriber<any, any, any, any, any, any>,\n SubscriberInfo[]\n> {\n isConstruct(value: any): value is Subscriber<any, any, any, any, any, any> {\n return Subscriber.isSubscriber(value);\n }\n\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<SubscriberInfo[]> {\n const provider = options?.provider || 'aws-lambda';\n const logger = console;\n const subscriberInfos: SubscriberInfo[] = [];\n\n if (provider === 'server') {\n // Generate subscribers.ts for server-based polling (even if empty)\n await this.generateServerSubscribersFile(outputDir, constructs);\n\n logger.log(\n `Generated server subscribers file with ${constructs.length} subscribers (polling mode)`,\n );\n\n // Return empty array as server subscribers don't have individual handlers\n return subscriberInfos;\n }\n\n if (constructs.length === 0) {\n return subscriberInfos;\n }\n\n if (provider !== 'aws-lambda') {\n return subscriberInfos;\n }\n\n // Create subscribers subdirectory\n const subscribersDir = join(outputDir, 'subscribers');\n await mkdir(subscribersDir, { recursive: true });\n\n // Generate subscriber handlers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateSubscriberHandler(\n subscribersDir,\n path.relative,\n key,\n construct,\n context,\n );\n\n subscriberInfos.push({\n name: key,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n subscribedEvents: construct.subscribedEvents || [],\n timeout: construct.timeout,\n environment: await construct.getEnvironment(),\n });\n\n logger.log(`Generated subscriber handler: ${key}`);\n }\n\n return subscriberInfos;\n }\n\n private async generateSubscriberHandler(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n _subscriber: Subscriber<any, any, any, any, any, any>,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n\n const content = `import { AWSLambdaSubscriber } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\n\nconst adapter = new AWSLambdaSubscriber(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n\n private async generateServerSubscribersFile(\n outputDir: string,\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n ): Promise<string> {\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n const subscribersFileName = 'subscribers.ts';\n const subscribersPath = join(outputDir, subscribersFileName);\n\n // Group imports by file\n const importsByFile = new Map<string, string[]>();\n\n for (const { path, key } of subscribers) {\n const relativePath = relative(dirname(subscribersPath), path.relative);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n if (!importsByFile.has(importPath)) {\n importsByFile.set(importPath, []);\n }\n importsByFile.get(importPath)!.push(key);\n }\n\n // Generate import statements\n const imports = Array.from(importsByFile.entries())\n .map(\n ([importPath, exports]) =>\n `import { ${exports.join(', ')} } from '${importPath}';`,\n )\n .join('\\n');\n\n const allExportNames = subscribers.map(({ key }) => key);\n\n const content = `/**\n * Generated subscribers setup\n *\n * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY\n * This uses event polling which is not suitable for production.\n *\n * For production, use AWS Lambda with SQS/SNS event source mappings.\n * Lambda automatically:\n * - Scales based on queue depth\n * - Handles batch processing and retries\n * - Manages dead letter queues\n * - Provides better cost optimization\n *\n * This polling implementation is useful for:\n * - Local development and testing\n * - Understanding event flow without Lambda deployment\n *\n * Supported connection strings:\n * - sqs://region/account-id/queue-name (SQS queue)\n * - sns://region/account-id/topic-name (SNS topic)\n * - rabbitmq://host:port/queue-name (RabbitMQ)\n * - basic://in-memory (In-memory for testing)\n */\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { EventConnectionFactory, Subscriber } from '@geekmidas/events';\nimport type { EventConnection, EventSubscriber } from '@geekmidas/events';\nimport { ServiceDiscovery } from '@geekmidas/services';\n${imports}\n\nconst subscribers = [\n ${allExportNames.join(',\\n ')}\n];\n\nconst activeSubscribers: EventSubscriber<any>[] = [];\n\nexport async function setupSubscribers(\n envParser: EnvironmentParser<any>,\n logger: Logger,\n): Promise<void> {\n logger.info('Setting up subscribers in polling mode (local development)');\n\n const config = envParser.create((get) => ({\n connectionString: get('EVENT_SUBSCRIBER_CONNECTION_STRING').string().optional(),\n })).parse();\n\n if (!config.connectionString) {\n logger.warn('EVENT_SUBSCRIBER_CONNECTION_STRING not configured, skipping subscriber setup');\n return;\n }\n\n const serviceDiscovery = ServiceDiscovery.getInstance(logger, envParser);\n\n // Create connection once, outside the loop (more efficient)\n // EventConnectionFactory automatically determines the right connection type\n let connection: EventConnection;\n try {\n connection = await EventConnectionFactory.fromConnectionString(config.connectionString);\n\n const connectionType = new URL(config.connectionString).protocol.replace(':', '');\n logger.info({ connectionType }, 'Created shared event connection');\n } catch (error) {\n logger.error({ error }, 'Failed to create event connection');\n return;\n }\n\n for (const subscriber of subscribers) {\n try {\n // Create subscriber from shared connection\n const eventSubscriber = await Subscriber.fromConnection(connection);\n\n // Register services\n const services = subscriber.services.length > 0\n ? await serviceDiscovery.register(subscriber.services)\n : {};\n\n // Subscribe to events\n const subscribedEvents = subscriber.subscribedEvents || [];\n\n if (subscribedEvents.length === 0) {\n logger.warn({ subscriber: subscriber.constructor.name }, 'Subscriber has no subscribed events, skipping');\n continue;\n }\n\n await eventSubscriber.subscribe(subscribedEvents, async (event) => {\n try {\n // Process single event (batch of 1)\n await subscriber.handler({\n events: [event],\n services: services as any,\n logger: subscriber.logger,\n });\n\n logger.debug({ eventType: event.type }, 'Successfully processed event');\n } catch (error) {\n logger.error({ error, event }, 'Failed to process event');\n // Event will become visible again for retry\n }\n });\n\n activeSubscribers.push(eventSubscriber);\n\n logger.info(\n {\n events: subscribedEvents,\n },\n 'Subscriber started polling'\n );\n } catch (error) {\n logger.error({ error, subscriber: subscriber.constructor.name }, 'Failed to setup subscriber');\n }\n }\n\n // Setup graceful shutdown\n const shutdown = () => {\n logger.info('Stopping all subscribers');\n for (const eventSubscriber of activeSubscribers) {\n connection.stop();\n }\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n`;\n\n await writeFile(subscribersPath, content);\n return subscribersPath;\n }\n}\n"],"mappings":";;;;;;AAWA,IAAa,sBAAb,cAAyC,mBAGvC;CACA,YAAYA,OAA+D;AACzE,SAAO,WAAW,aAAa,MAAM;CACtC;CAED,MAAM,MACJC,SACAC,YACAC,WACAC,SAC2B;EAC3B,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,SAAS;EACf,MAAMC,kBAAoC,CAAE;AAE5C,MAAI,aAAa,UAAU;AAEzB,SAAM,KAAK,8BAA8B,WAAW,WAAW;AAE/D,UAAO,KACJ,yCAAyC,WAAW,OAAO,6BAC7D;AAGD,UAAO;EACR;AAED,MAAI,WAAW,WAAW,EACxB,QAAO;AAGT,MAAI,aAAa,aACf,QAAO;EAIT,MAAM,iBAAiB,KAAK,WAAW,cAAc;AACrD,QAAM,MAAM,gBAAgB,EAAE,WAAW,KAAM,EAAC;AAGhD,OAAK,MAAM,EAAE,KAAK,WAAW,MAAM,IAAI,YAAY;GACjD,MAAM,cAAc,MAAM,KAAK,0BAC7B,gBACA,KAAK,UACL,KACA,WACA,QACD;AAED,mBAAgB,KAAK;IACnB,MAAM;IACN,SAAS,SAAS,QAAQ,KAAK,EAAE,YAAY,CAAC,QAC5C,SACA,WACD;IACD,kBAAkB,UAAU,oBAAoB,CAAE;IAClD,SAAS,UAAU;IACnB,aAAa,MAAM,UAAU,gBAAgB;GAC9C,EAAC;AAEF,UAAO,KAAK,gCAAgC,IAAI,EAAE;EACnD;AAED,SAAO;CACR;CAED,MAAc,0BACZF,WACAG,YACAC,YACAC,aACAP,SACiB;EACjB,MAAM,mBAAmB,EAAE,WAAW;EACtC,MAAM,cAAc,KAAK,WAAW,gBAAgB;EAEpD,MAAM,eAAe,SAAS,QAAQ,YAAY,EAAE,WAAW;EAC/D,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;EAEvD,MAAM,wBAAwB,SAC5B,QAAQ,YAAY,EACpB,QAAQ,cACT;EAED,MAAM,WAAW;WACV,WAAW,WAAW,WAAW;SACnC,QAAQ,uBAAuB,SAAS,sBAAsB;;qDAElB,WAAW;;;;AAK5D,QAAM,UAAU,aAAa,QAAQ;AACrC,SAAO;CACR;CAED,MAAc,8BACZE,WACAM,aACiB;AAEjB,QAAM,MAAM,WAAW,EAAE,WAAW,KAAM,EAAC;EAE3C,MAAM,sBAAsB;EAC5B,MAAM,kBAAkB,KAAK,WAAW,oBAAoB;EAG5D,MAAM,gCAAgB,IAAI;AAE1B,OAAK,MAAM,EAAE,MAAM,KAAK,IAAI,aAAa;GACvC,MAAM,eAAe,SAAS,QAAQ,gBAAgB,EAAE,KAAK,SAAS;GACtE,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;AAEvD,QAAK,cAAc,IAAI,WAAW,CAChC,eAAc,IAAI,YAAY,CAAE,EAAC;AAEnC,iBAAc,IAAI,WAAW,CAAE,KAAK,IAAI;EACzC;EAGD,MAAM,UAAU,MAAM,KAAK,cAAc,SAAS,CAAC,CAChD,IACC,CAAC,CAAC,YAAY,QAAQ,MACnB,WAAW,QAAQ,KAAK,KAAK,CAAC,WAAW,WAAW,IACxD,CACA,KAAK,KAAK;EAEb,MAAM,iBAAiB,YAAY,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI;EAExD,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BnB,QAAQ;;;IAGN,eAAe,KAAK,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+F7B,QAAM,UAAU,iBAAiB,QAAQ;AACzC,SAAO;CACR;AACF"}
@@ -3,10 +3,10 @@ require('../Generator-CDoEXCDg.cjs');
3
3
  require('../CronGenerator-1PflEYe2.cjs');
4
4
  require('../EndpointGenerator-BbGrDiCP.cjs');
5
5
  require('../FunctionGenerator-Clw64SwQ.cjs');
6
- require('../SubscriberGenerator-BfMZCVNy.cjs');
6
+ require('../SubscriberGenerator-CB-NHtZW.cjs');
7
7
  require('../generators-CEKtVh81.cjs');
8
8
  require('../manifests-D0saShvH.cjs');
9
9
  require('../providerResolver-DgvzNfP4.cjs');
10
- const require_build = require('../build-BBhlEjf5.cjs');
10
+ const require_build = require('../build-Ajg356_5.cjs');
11
11
 
12
12
  exports.buildCommand = require_build.buildCommand;
@@ -3,10 +3,10 @@ import "../Generator-UanJW0_V.mjs";
3
3
  import "../CronGenerator-DXRfHQcV.mjs";
4
4
  import "../EndpointGenerator-BmZ9BxbO.mjs";
5
5
  import "../FunctionGenerator-DOEB_yPh.mjs";
6
- import "../SubscriberGenerator-D2u00NI3.mjs";
6
+ import "../SubscriberGenerator-Cuu4co3-.mjs";
7
7
  import "../generators-CsLujGXs.mjs";
8
8
  import "../manifests-BrJXpHrf.mjs";
9
9
  import "../providerResolver-B_TjNF0_.mjs";
10
- import { buildCommand } from "../build-kY-lG30Q.mjs";
10
+ import { buildCommand } from "../build-zpABVsc0.mjs";
11
11
 
12
12
  export { buildCommand };
@@ -3,7 +3,7 @@ const require_config = require('./config-D1EpSGk6.cjs');
3
3
  const require_CronGenerator = require('./CronGenerator-1PflEYe2.cjs');
4
4
  const require_EndpointGenerator = require('./EndpointGenerator-BbGrDiCP.cjs');
5
5
  const require_FunctionGenerator = require('./FunctionGenerator-Clw64SwQ.cjs');
6
- const require_SubscriberGenerator = require('./SubscriberGenerator-BfMZCVNy.cjs');
6
+ const require_SubscriberGenerator = require('./SubscriberGenerator-CB-NHtZW.cjs');
7
7
  const require_manifests = require('./manifests-D0saShvH.cjs');
8
8
  const require_providerResolver = require('./providerResolver-DgvzNfP4.cjs');
9
9
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
@@ -86,4 +86,4 @@ Object.defineProperty(exports, 'buildCommand', {
86
86
  return buildCommand;
87
87
  }
88
88
  });
89
- //# sourceMappingURL=build-BBhlEjf5.cjs.map
89
+ //# sourceMappingURL=build-Ajg356_5.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-BBhlEjf5.cjs","names":["options: BuildOptions","buildContext: BuildContext","EndpointGenerator","FunctionGenerator","CronGenerator","SubscriberGenerator","provider: LegacyProvider","context: BuildContext","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type {\n BuildOptions,\n CronInfo,\n FunctionInfo,\n LegacyProvider,\n RouteInfo,\n SubscriberInfo,\n} from '../types';\nimport { generateManifests } from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser configuration\n const [envParserPath, envParserName] = config.envParser.split('#');\n const envParserImportPattern = !envParserName\n ? 'envParser'\n : envParserName === 'envParser'\n ? '{ envParser }'\n : `{ ${envParserName} as envParser }`;\n\n // Parse logger configuration\n const [loggerPath, loggerName] = config.logger.split('#');\n const loggerImportPattern = !loggerName\n ? 'logger'\n : loggerName === 'logger'\n ? '{ logger }'\n : `{ ${loggerName} as logger }`;\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n };\n\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs in parallel\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Collect all build results from each provider\n const allBuildResults = await Promise.all(\n resolved.providers.map((provider) =>\n buildForProvider(\n provider,\n buildContext,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n ),\n ),\n );\n\n // Aggregate all routes, functions, crons, and subscribers from all providers\n const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);\n const aggregatedFunctions = allBuildResults.flatMap(\n (result) => result.functions,\n );\n const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);\n const aggregatedSubscribers = allBuildResults.flatMap(\n (result) => result.subscribers,\n );\n\n // Generate single manifest at root .gkm directory\n await generateManifests(\n rootOutputDir,\n aggregatedRoutes,\n aggregatedFunctions,\n aggregatedCrons,\n aggregatedSubscribers,\n );\n}\n\ninterface BuildResult {\n routes: RouteInfo[];\n functions: FunctionInfo[];\n crons: CronInfo[];\n subscribers: SubscriberInfo[];\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<BuildResult> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Return build results instead of generating manifest here\n return {\n routes,\n functions: functionInfos,\n crons: cronInfos,\n subscribers: subscriberInfos,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"build-Ajg356_5.cjs","names":["options: BuildOptions","buildContext: BuildContext","EndpointGenerator","FunctionGenerator","CronGenerator","SubscriberGenerator","provider: LegacyProvider","context: BuildContext","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type {\n BuildOptions,\n CronInfo,\n FunctionInfo,\n LegacyProvider,\n RouteInfo,\n SubscriberInfo,\n} from '../types';\nimport { generateManifests } from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser configuration\n const [envParserPath, envParserName] = config.envParser.split('#');\n const envParserImportPattern = !envParserName\n ? 'envParser'\n : envParserName === 'envParser'\n ? '{ envParser }'\n : `{ ${envParserName} as envParser }`;\n\n // Parse logger configuration\n const [loggerPath, loggerName] = config.logger.split('#');\n const loggerImportPattern = !loggerName\n ? 'logger'\n : loggerName === 'logger'\n ? '{ logger }'\n : `{ ${loggerName} as logger }`;\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n };\n\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs in parallel\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Collect all build results from each provider\n const allBuildResults = await Promise.all(\n resolved.providers.map((provider) =>\n buildForProvider(\n provider,\n buildContext,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n ),\n ),\n );\n\n // Aggregate all routes, functions, crons, and subscribers from all providers\n const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);\n const aggregatedFunctions = allBuildResults.flatMap(\n (result) => result.functions,\n );\n const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);\n const aggregatedSubscribers = allBuildResults.flatMap(\n (result) => result.subscribers,\n );\n\n // Generate single manifest at root .gkm directory\n await generateManifests(\n rootOutputDir,\n aggregatedRoutes,\n aggregatedFunctions,\n aggregatedCrons,\n aggregatedSubscribers,\n );\n}\n\ninterface BuildResult {\n routes: RouteInfo[];\n functions: FunctionInfo[];\n crons: CronInfo[];\n subscribers: SubscriberInfo[];\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<BuildResult> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Return build results instead of generating manifest here\n return {\n routes,\n functions: functionInfos,\n crons: cronInfos,\n subscribers: subscriberInfos,\n };\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { loadConfig } from "./config-U-mdW-7Y.mjs";
2
2
  import { CronGenerator } from "./CronGenerator-DXRfHQcV.mjs";
3
3
  import { EndpointGenerator } from "./EndpointGenerator-BmZ9BxbO.mjs";
4
4
  import { FunctionGenerator } from "./FunctionGenerator-DOEB_yPh.mjs";
5
- import { SubscriberGenerator } from "./SubscriberGenerator-D2u00NI3.mjs";
5
+ import { SubscriberGenerator } from "./SubscriberGenerator-Cuu4co3-.mjs";
6
6
  import { generateManifests } from "./manifests-BrJXpHrf.mjs";
7
7
  import { resolveProviders } from "./providerResolver-B_TjNF0_.mjs";
8
8
  import { mkdir } from "node:fs/promises";
@@ -80,4 +80,4 @@ async function buildForProvider(provider, context, endpointGenerator, functionGe
80
80
 
81
81
  //#endregion
82
82
  export { buildCommand };
83
- //# sourceMappingURL=build-kY-lG30Q.mjs.map
83
+ //# sourceMappingURL=build-zpABVsc0.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-kY-lG30Q.mjs","names":["options: BuildOptions","buildContext: BuildContext","provider: LegacyProvider","context: BuildContext","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type {\n BuildOptions,\n CronInfo,\n FunctionInfo,\n LegacyProvider,\n RouteInfo,\n SubscriberInfo,\n} from '../types';\nimport { generateManifests } from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser configuration\n const [envParserPath, envParserName] = config.envParser.split('#');\n const envParserImportPattern = !envParserName\n ? 'envParser'\n : envParserName === 'envParser'\n ? '{ envParser }'\n : `{ ${envParserName} as envParser }`;\n\n // Parse logger configuration\n const [loggerPath, loggerName] = config.logger.split('#');\n const loggerImportPattern = !loggerName\n ? 'logger'\n : loggerName === 'logger'\n ? '{ logger }'\n : `{ ${loggerName} as logger }`;\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n };\n\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs in parallel\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Collect all build results from each provider\n const allBuildResults = await Promise.all(\n resolved.providers.map((provider) =>\n buildForProvider(\n provider,\n buildContext,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n ),\n ),\n );\n\n // Aggregate all routes, functions, crons, and subscribers from all providers\n const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);\n const aggregatedFunctions = allBuildResults.flatMap(\n (result) => result.functions,\n );\n const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);\n const aggregatedSubscribers = allBuildResults.flatMap(\n (result) => result.subscribers,\n );\n\n // Generate single manifest at root .gkm directory\n await generateManifests(\n rootOutputDir,\n aggregatedRoutes,\n aggregatedFunctions,\n aggregatedCrons,\n aggregatedSubscribers,\n );\n}\n\ninterface BuildResult {\n routes: RouteInfo[];\n functions: FunctionInfo[];\n crons: CronInfo[];\n subscribers: SubscriberInfo[];\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<BuildResult> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Return build results instead of generating manifest here\n return {\n routes,\n functions: functionInfos,\n crons: cronInfos,\n subscribers: subscriberInfos,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"build-zpABVsc0.mjs","names":["options: BuildOptions","buildContext: BuildContext","provider: LegacyProvider","context: BuildContext","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type {\n BuildOptions,\n CronInfo,\n FunctionInfo,\n LegacyProvider,\n RouteInfo,\n SubscriberInfo,\n} from '../types';\nimport { generateManifests } from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser configuration\n const [envParserPath, envParserName] = config.envParser.split('#');\n const envParserImportPattern = !envParserName\n ? 'envParser'\n : envParserName === 'envParser'\n ? '{ envParser }'\n : `{ ${envParserName} as envParser }`;\n\n // Parse logger configuration\n const [loggerPath, loggerName] = config.logger.split('#');\n const loggerImportPattern = !loggerName\n ? 'logger'\n : loggerName === 'logger'\n ? '{ logger }'\n : `{ ${loggerName} as logger }`;\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n };\n\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs in parallel\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Collect all build results from each provider\n const allBuildResults = await Promise.all(\n resolved.providers.map((provider) =>\n buildForProvider(\n provider,\n buildContext,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n ),\n ),\n );\n\n // Aggregate all routes, functions, crons, and subscribers from all providers\n const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);\n const aggregatedFunctions = allBuildResults.flatMap(\n (result) => result.functions,\n );\n const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);\n const aggregatedSubscribers = allBuildResults.flatMap(\n (result) => result.subscribers,\n );\n\n // Generate single manifest at root .gkm directory\n await generateManifests(\n rootOutputDir,\n aggregatedRoutes,\n aggregatedFunctions,\n aggregatedCrons,\n aggregatedSubscribers,\n );\n}\n\ninterface BuildResult {\n routes: RouteInfo[];\n functions: FunctionInfo[];\n crons: CronInfo[];\n subscribers: SubscriberInfo[];\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<BuildResult> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Return build results instead of generating manifest here\n return {\n routes,\n functions: functionInfos,\n crons: cronInfos,\n subscribers: subscriberInfos,\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  require('../Generator-CDoEXCDg.cjs');
2
- const require_SubscriberGenerator = require('../SubscriberGenerator-BfMZCVNy.cjs');
2
+ const require_SubscriberGenerator = require('../SubscriberGenerator-CB-NHtZW.cjs');
3
3
 
4
4
  exports.SubscriberGenerator = require_SubscriberGenerator.SubscriberGenerator;
@@ -1,4 +1,4 @@
1
1
  import "../Generator-UanJW0_V.mjs";
2
- import { SubscriberGenerator } from "../SubscriberGenerator-D2u00NI3.mjs";
2
+ import { SubscriberGenerator } from "../SubscriberGenerator-Cuu4co3-.mjs";
3
3
 
4
4
  export { SubscriberGenerator };
@@ -2,7 +2,7 @@ const require_Generator = require('../Generator-CDoEXCDg.cjs');
2
2
  const require_CronGenerator = require('../CronGenerator-1PflEYe2.cjs');
3
3
  const require_EndpointGenerator = require('../EndpointGenerator-BbGrDiCP.cjs');
4
4
  const require_FunctionGenerator = require('../FunctionGenerator-Clw64SwQ.cjs');
5
- const require_SubscriberGenerator = require('../SubscriberGenerator-BfMZCVNy.cjs');
5
+ const require_SubscriberGenerator = require('../SubscriberGenerator-CB-NHtZW.cjs');
6
6
  require('../generators-CEKtVh81.cjs');
7
7
 
8
8
  exports.ConstructGenerator = require_Generator.ConstructGenerator;
@@ -2,7 +2,7 @@ import { ConstructGenerator } from "../Generator-UanJW0_V.mjs";
2
2
  import { CronGenerator } from "../CronGenerator-DXRfHQcV.mjs";
3
3
  import { EndpointGenerator } from "../EndpointGenerator-BmZ9BxbO.mjs";
4
4
  import { FunctionGenerator } from "../FunctionGenerator-DOEB_yPh.mjs";
5
- import { SubscriberGenerator } from "../SubscriberGenerator-D2u00NI3.mjs";
5
+ import { SubscriberGenerator } from "../SubscriberGenerator-Cuu4co3-.mjs";
6
6
  import "../generators-CsLujGXs.mjs";
7
7
 
8
8
  export { ConstructGenerator, CronGenerator, EndpointGenerator, FunctionGenerator, SubscriberGenerator };
package/dist/index.cjs CHANGED
@@ -5,18 +5,18 @@ require('./Generator-CDoEXCDg.cjs');
5
5
  require('./CronGenerator-1PflEYe2.cjs');
6
6
  require('./EndpointGenerator-BbGrDiCP.cjs');
7
7
  require('./FunctionGenerator-Clw64SwQ.cjs');
8
- require('./SubscriberGenerator-BfMZCVNy.cjs');
8
+ require('./SubscriberGenerator-CB-NHtZW.cjs');
9
9
  require('./generators-CEKtVh81.cjs');
10
10
  require('./manifests-D0saShvH.cjs');
11
11
  require('./providerResolver-DgvzNfP4.cjs');
12
- const require_build = require('./build-BBhlEjf5.cjs');
12
+ const require_build = require('./build-Ajg356_5.cjs');
13
13
  const require_openapi_react_query = require('./openapi-react-query-Dvjqx_Eo.cjs');
14
14
  const require_openapi = require('./openapi-CMLr04cz.cjs');
15
15
  const commander = require_chunk.__toESM(require("commander"));
16
16
 
17
17
  //#region package.json
18
18
  var name = "@geekmidas/cli";
19
- var version = "0.2.0";
19
+ var version = "0.2.2";
20
20
  var private$1 = false;
21
21
  var type = "module";
22
22
  var exports$1 = {
@@ -45,9 +45,6 @@ var scripts = {
45
45
  };
46
46
  var dependencies = {
47
47
  "@apidevtools/swagger-parser": "^10.1.0",
48
- "@geekmidas/constructs": "workspace:*",
49
- "@geekmidas/schema": "workspace:*",
50
- "@geekmidas/envkit": "workspace:*",
51
48
  "commander": "^12.1.0",
52
49
  "fast-glob": "^3.3.2",
53
50
  "lodash.kebabcase": "^4.1.1",
@@ -58,9 +55,14 @@ var devDependencies = {
58
55
  "@geekmidas/testkit": "workspace:*",
59
56
  "typescript": "^5.8.2",
60
57
  "vitest": "^3.2.4",
61
- "@geekmidas/logger": "workspace:*",
62
58
  "zod": "^3.23.8"
63
59
  };
60
+ var peerDependencies = {
61
+ "@geekmidas/constructs": "workspace:~",
62
+ "@geekmidas/schema": "workspace:~",
63
+ "@geekmidas/envkit": "workspace:~",
64
+ "@geekmidas/logger": "workspace:~"
65
+ };
64
66
  var package_default = {
65
67
  name,
66
68
  version,
@@ -70,7 +72,8 @@ var package_default = {
70
72
  bin,
71
73
  scripts,
72
74
  dependencies,
73
- devDependencies
75
+ devDependencies,
76
+ peerDependencies
74
77
  };
75
78
 
76
79
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Command","pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { output?: string }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.2.0\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"@geekmidas/constructs\": \"workspace:*\",\n \"@geekmidas/schema\": \"workspace:*\",\n \"@geekmidas/envkit\": \"workspace:*\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@geekmidas/testkit\": \"workspace:*\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"@geekmidas/logger\": \"workspace:*\",\n \"zod\": \"^3.23.8\"\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description('Generate OpenAPI 3.0 specification from endpoints')\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.json',\n )\n .action(async (options: { output?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["Command","pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { output?: string }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.2.2\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@geekmidas/testkit\": \"workspace:*\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"zod\": \"^3.23.8\"\n },\n \"peerDependencies\": {\n \"@geekmidas/constructs\": \"workspace:~\",\n \"@geekmidas/schema\": \"workspace:~\",\n \"@geekmidas/envkit\": \"workspace:~\",\n \"@geekmidas/logger\": \"workspace:~\"\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description('Generate OpenAPI 3.0 specification from endpoints')\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.json',\n )\n .action(async (options: { output?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -4,18 +4,18 @@ import "./Generator-UanJW0_V.mjs";
4
4
  import "./CronGenerator-DXRfHQcV.mjs";
5
5
  import "./EndpointGenerator-BmZ9BxbO.mjs";
6
6
  import "./FunctionGenerator-DOEB_yPh.mjs";
7
- import "./SubscriberGenerator-D2u00NI3.mjs";
7
+ import "./SubscriberGenerator-Cuu4co3-.mjs";
8
8
  import "./generators-CsLujGXs.mjs";
9
9
  import "./manifests-BrJXpHrf.mjs";
10
10
  import "./providerResolver-B_TjNF0_.mjs";
11
- import { buildCommand } from "./build-kY-lG30Q.mjs";
11
+ import { buildCommand } from "./build-zpABVsc0.mjs";
12
12
  import { generateReactQueryCommand } from "./openapi-react-query-DbrWwQzb.mjs";
13
13
  import { openapiCommand } from "./openapi-BQx3_JbM.mjs";
14
14
  import { Command } from "commander";
15
15
 
16
16
  //#region package.json
17
17
  var name = "@geekmidas/cli";
18
- var version = "0.2.0";
18
+ var version = "0.2.2";
19
19
  var private$1 = false;
20
20
  var type = "module";
21
21
  var exports = {
@@ -44,9 +44,6 @@ var scripts = {
44
44
  };
45
45
  var dependencies = {
46
46
  "@apidevtools/swagger-parser": "^10.1.0",
47
- "@geekmidas/constructs": "workspace:*",
48
- "@geekmidas/schema": "workspace:*",
49
- "@geekmidas/envkit": "workspace:*",
50
47
  "commander": "^12.1.0",
51
48
  "fast-glob": "^3.3.2",
52
49
  "lodash.kebabcase": "^4.1.1",
@@ -57,9 +54,14 @@ var devDependencies = {
57
54
  "@geekmidas/testkit": "workspace:*",
58
55
  "typescript": "^5.8.2",
59
56
  "vitest": "^3.2.4",
60
- "@geekmidas/logger": "workspace:*",
61
57
  "zod": "^3.23.8"
62
58
  };
59
+ var peerDependencies = {
60
+ "@geekmidas/constructs": "workspace:~",
61
+ "@geekmidas/schema": "workspace:~",
62
+ "@geekmidas/envkit": "workspace:~",
63
+ "@geekmidas/logger": "workspace:~"
64
+ };
63
65
  var package_default = {
64
66
  name,
65
67
  version,
@@ -69,7 +71,8 @@ var package_default = {
69
71
  bin,
70
72
  scripts,
71
73
  dependencies,
72
- devDependencies
74
+ devDependencies,
75
+ peerDependencies
73
76
  };
74
77
 
75
78
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { output?: string }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.2.0\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"@geekmidas/constructs\": \"workspace:*\",\n \"@geekmidas/schema\": \"workspace:*\",\n \"@geekmidas/envkit\": \"workspace:*\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@geekmidas/testkit\": \"workspace:*\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"@geekmidas/logger\": \"workspace:*\",\n \"zod\": \"^3.23.8\"\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description('Generate OpenAPI 3.0 specification from endpoints')\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.json',\n )\n .action(async (options: { output?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":";;;;;;;;;;;;;;;;WACU;cACG;gBACA;WACH;cACG;CACT,KAAK;EACH,SAAS;EACT,UAAU;EACV,WAAW;CACZ;CACD,aAAa;EACX,SAAS;EACT,UAAU;EACV,WAAW;CACZ;CACD,yBAAyB;EACvB,SAAS;EACT,UAAU;EACV,WAAW;CACZ;AACF;UACM,EACL,OAAO,mBACR;cACU;CACT,MAAM;CACN,QAAQ;CACR,aAAa;CACb,iBAAiB;AAClB;mBACe;CACd,+BAA+B;CAC/B,yBAAyB;CACzB,qBAAqB;CACrB,qBAAqB;CACrB,aAAa;CACb,aAAa;CACb,oBAAoB;CACpB,sBAAsB;AACvB;sBACkB;CACjB,2BAA2B;CAC3B,sBAAsB;CACtB,cAAc;CACd,UAAU;CACV,qBAAqB;CACrB,OAAO;AACR;sBAhDH;;;;;;;;;;AAiDC;;;;ACxCD,MAAM,UAAU,IAAI;AAEpB,QACG,KAAK,MAAM,CACX,YAAY,kCAAkC,CAC9C,QAAQA,gBAAI,QAAQ,CACpB,OAAO,gBAAgB,2BAA2B;AAErD,QACG,QAAQ,QAAQ,CAChB,YAAY,sDAAsD,CAClE,OACC,yBACA,uDACD,CACA,OACC,2BACA,iGACD,CACA,OACC,oBACA,4DACD,CACA,OACC,OAAOC,YAID;AACJ,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAIlC,MAAI,QAAQ,UAAU;AACpB,QAAK,CAAC,OAAO,QAAS,EAAC,SAAS,QAAQ,SAAS,EAAE;AACjD,YAAQ,OACL,oBAAoB,QAAQ,SAAS,8BACvC;AACD,YAAQ,KAAK,EAAE;GAChB;AACD,SAAM,aAAa;IACjB,UAAU,QAAQ;IAClB,eAAe,QAAQ,iBAAiB;GACzC,EAAC;EACH,WAEQ,QAAQ,WAAW;AAC1B,WAAQ,KACN,8DACD;GACD,MAAM,eAAe,CACnB,GAAG,IAAI,IAAI,QAAQ,UAAU,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAC7D;AACD,SAAM,aAAa;IACjB,WAAW;IACX,eAAe,QAAQ,iBAAiB;GACzC,EAAC;EACH,MAGC,OAAM,aAAa,EACjB,eAAe,QAAQ,iBAAiB,MACzC,EAAC;CAEL,SAAQ,OAAO;AACd,UAAQ,MAAM,iBAAkB,MAAgB,QAAQ;AACxD,UAAQ,KAAK,EAAE;CAChB;AACF,EACF;AAEH,QACG,QAAQ,OAAO,CACf,YAAY,mBAAmB,CAC/B,OAAO,MAAM;CACZ,MAAM,gBAAgB,QAAQ,MAAM;AACpC,KAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,SAAQ,OAAO,MAAM,kCAAkC;AACxD,EAAC;AAEJ,QACG,QAAQ,WAAW,CACnB,YAAY,8BAA8B,CAC1C,OAAO,MAAM;CACZ,MAAM,gBAAgB,QAAQ,MAAM;AACpC,KAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,SAAQ,OAAO,MAAM,iDAAiD;AACvE,EAAC;AAEJ,QACG,QAAQ,MAAM,CACd,YAAY,4BAA4B,CACxC,OAAO,MAAM;CACZ,MAAM,gBAAgB,QAAQ,MAAM;AACpC,KAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,SAAQ,OAAO,MAAM,sCAAsC;AAC5D,EAAC;AAEJ,QACG,QAAQ,UAAU,CAClB,YAAY,oDAAoD,CAChE,OACC,mBACA,yCACA,eACD,CACA,OAAO,OAAOC,YAAiC;AAC9C,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,QAAM,eAAe,QAAQ;CAC9B,SAAQ,OAAO;AACd,UAAQ,MAAM,8BAA+B,MAAgB,QAAQ;AACrE,UAAQ,KAAK,EAAE;CAChB;AACF,EAAC;AAEJ,QACG,QAAQ,uBAAuB,CAC/B,YAAY,wDAAwD,CACpE,OAAO,kBAAkB,gCAAgC,eAAe,CACxE,OACC,mBACA,wCACA,mBACD,CACA,OAAO,iBAAiB,sCAAsC,MAAM,CACpE,OACC,OAAOC,YAAgE;AACrE,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,QAAM,0BAA0B,QAAQ;CACzC,SAAQ,OAAO;AACd,UAAQ,MACN,kCACC,MAAgB,QAClB;AACD,UAAQ,KAAK,EAAE;CAChB;AACF,EACF;AAEH,QAAQ,OAAO"}
1
+ {"version":3,"file":"index.mjs","names":["pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { output?: string }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.2.2\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@geekmidas/testkit\": \"workspace:*\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"zod\": \"^3.23.8\"\n },\n \"peerDependencies\": {\n \"@geekmidas/constructs\": \"workspace:~\",\n \"@geekmidas/schema\": \"workspace:~\",\n \"@geekmidas/envkit\": \"workspace:~\",\n \"@geekmidas/logger\": \"workspace:~\"\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description('Generate OpenAPI 3.0 specification from endpoints')\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.json',\n )\n .action(async (options: { output?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -28,18 +28,20 @@
28
28
  "commander": "^12.1.0",
29
29
  "fast-glob": "^3.3.2",
30
30
  "lodash.kebabcase": "^4.1.1",
31
- "openapi-typescript": "^7.4.2",
32
- "@geekmidas/constructs": "0.0.1",
33
- "@geekmidas/schema": "0.0.1",
34
- "@geekmidas/envkit": "0.0.7"
31
+ "openapi-typescript": "^7.4.2"
35
32
  },
36
33
  "devDependencies": {
37
34
  "@types/lodash.kebabcase": "^4.1.9",
38
35
  "typescript": "^5.8.2",
39
36
  "vitest": "^3.2.4",
40
37
  "zod": "^3.23.8",
41
- "@geekmidas/testkit": "0.0.16",
42
- "@geekmidas/logger": "0.0.1"
38
+ "@geekmidas/testkit": "0.0.16"
39
+ },
40
+ "peerDependencies": {
41
+ "@geekmidas/constructs": "~0.0.5",
42
+ "@geekmidas/schema": "~0.0.1",
43
+ "@geekmidas/logger": "~0.0.1",
44
+ "@geekmidas/envkit": "~0.0.7"
43
45
  },
44
46
  "scripts": {
45
47
  "ts": "tsc --noEmit --skipLibCheck src/**/*.ts",
@@ -27,12 +27,8 @@ export class SubscriberGenerator extends ConstructGenerator<
27
27
  const logger = console;
28
28
  const subscriberInfos: SubscriberInfo[] = [];
29
29
 
30
- if (constructs.length === 0) {
31
- return subscriberInfos;
32
- }
33
-
34
30
  if (provider === 'server') {
35
- // Generate subscribers.ts for server-based polling
31
+ // Generate subscribers.ts for server-based polling (even if empty)
36
32
  await this.generateServerSubscribersFile(outputDir, constructs);
37
33
 
38
34
  logger.log(
@@ -43,6 +39,10 @@ export class SubscriberGenerator extends ConstructGenerator<
43
39
  return subscriberInfos;
44
40
  }
45
41
 
42
+ if (constructs.length === 0) {
43
+ return subscriberInfos;
44
+ }
45
+
46
46
  if (provider !== 'aws-lambda') {
47
47
  return subscriberInfos;
48
48
  }
@@ -113,6 +113,9 @@ export const handler = adapter.handler;
113
113
  outputDir: string,
114
114
  subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],
115
115
  ): Promise<string> {
116
+ // Ensure output directory exists
117
+ await mkdir(outputDir, { recursive: true });
118
+
116
119
  const subscribersFileName = 'subscribers.ts';
117
120
  const subscribersPath = join(outputDir, subscribersFileName);
118
121
 
@@ -249,6 +249,57 @@ describe('SubscriberGenerator', () => {
249
249
  expect(subscriberInfos).toEqual([]);
250
250
  });
251
251
 
252
+ it('should generate subscribers.ts file for server provider even with no subscribers', async () => {
253
+ const subscriberInfos = await generator.build(
254
+ context,
255
+ [],
256
+ outputDir,
257
+ { provider: 'server' },
258
+ );
259
+
260
+ expect(subscriberInfos).toEqual([]);
261
+
262
+ // Check that subscribers.ts was generated
263
+ const subscribersPath = join(outputDir, 'subscribers.ts');
264
+ const subscribersContent = await readFile(subscribersPath, 'utf-8');
265
+
266
+ expect(subscribersContent).toContain('export async function setupSubscribers');
267
+ expect(subscribersContent).toContain('const subscribers = [');
268
+ expect(subscribersContent).toContain('import type { EnvironmentParser }');
269
+ expect(subscribersContent).toContain('import type { Logger }');
270
+ });
271
+
272
+ it('should generate subscribers.ts file for server provider with subscribers', async () => {
273
+ const constructs = [
274
+ createSubscriberConstruct('userEventSubscriber', [
275
+ 'user.created',
276
+ 'user.updated',
277
+ ]),
278
+ createSubscriberConstruct('orderEventSubscriber', ['order.placed']),
279
+ ];
280
+
281
+ const subscriberInfos = await generator.build(
282
+ context,
283
+ constructs,
284
+ outputDir,
285
+ { provider: 'server' },
286
+ );
287
+
288
+ expect(subscriberInfos).toEqual([]);
289
+
290
+ // Check that subscribers.ts was generated
291
+ const subscribersPath = join(outputDir, 'subscribers.ts');
292
+ const subscribersContent = await readFile(subscribersPath, 'utf-8');
293
+
294
+ expect(subscribersContent).toContain('export async function setupSubscribers');
295
+ expect(subscribersContent).toContain('import { userEventSubscriber }');
296
+ expect(subscribersContent).toContain('import { orderEventSubscriber }');
297
+ expect(subscribersContent).toContain('const subscribers = [');
298
+ expect(subscribersContent).toContain('userEventSubscriber');
299
+ expect(subscribersContent).toContain('orderEventSubscriber');
300
+ expect(subscribersContent).toContain('Setting up subscribers in polling mode');
301
+ });
302
+
252
303
  it('should handle subscribers with custom environment parser patterns', async () => {
253
304
  const customContext = {
254
305
  ...context,
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubscriberGenerator-BfMZCVNy.cjs","names":["ConstructGenerator","value: any","context: BuildContext","constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","subscriberInfos: SubscriberInfo[]","sourceFile: string","exportName: string","_subscriber: Subscriber<any, any, any, any, any, any>","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","exports"],"sources":["../src/generators/SubscriberGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Subscriber } from '@geekmidas/constructs/subscribers';\nimport type { BuildContext } from '../build/types';\nimport type { SubscriberInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class SubscriberGenerator extends ConstructGenerator<\n Subscriber<any, any, any, any, any, any>,\n SubscriberInfo[]\n> {\n isConstruct(value: any): value is Subscriber<any, any, any, any, any, any> {\n return Subscriber.isSubscriber(value);\n }\n\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<SubscriberInfo[]> {\n const provider = options?.provider || 'aws-lambda';\n const logger = console;\n const subscriberInfos: SubscriberInfo[] = [];\n\n if (constructs.length === 0) {\n return subscriberInfos;\n }\n\n if (provider === 'server') {\n // Generate subscribers.ts for server-based polling\n await this.generateServerSubscribersFile(outputDir, constructs);\n\n logger.log(\n `Generated server subscribers file with ${constructs.length} subscribers (polling mode)`,\n );\n\n // Return empty array as server subscribers don't have individual handlers\n return subscriberInfos;\n }\n\n if (provider !== 'aws-lambda') {\n return subscriberInfos;\n }\n\n // Create subscribers subdirectory\n const subscribersDir = join(outputDir, 'subscribers');\n await mkdir(subscribersDir, { recursive: true });\n\n // Generate subscriber handlers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateSubscriberHandler(\n subscribersDir,\n path.relative,\n key,\n construct,\n context,\n );\n\n subscriberInfos.push({\n name: key,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n subscribedEvents: construct.subscribedEvents || [],\n timeout: construct.timeout,\n environment: await construct.getEnvironment(),\n });\n\n logger.log(`Generated subscriber handler: ${key}`);\n }\n\n return subscriberInfos;\n }\n\n private async generateSubscriberHandler(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n _subscriber: Subscriber<any, any, any, any, any, any>,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n\n const content = `import { AWSLambdaSubscriber } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\n\nconst adapter = new AWSLambdaSubscriber(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n\n private async generateServerSubscribersFile(\n outputDir: string,\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n ): Promise<string> {\n const subscribersFileName = 'subscribers.ts';\n const subscribersPath = join(outputDir, subscribersFileName);\n\n // Group imports by file\n const importsByFile = new Map<string, string[]>();\n\n for (const { path, key } of subscribers) {\n const relativePath = relative(dirname(subscribersPath), path.relative);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n if (!importsByFile.has(importPath)) {\n importsByFile.set(importPath, []);\n }\n importsByFile.get(importPath)!.push(key);\n }\n\n // Generate import statements\n const imports = Array.from(importsByFile.entries())\n .map(\n ([importPath, exports]) =>\n `import { ${exports.join(', ')} } from '${importPath}';`,\n )\n .join('\\n');\n\n const allExportNames = subscribers.map(({ key }) => key);\n\n const content = `/**\n * Generated subscribers setup\n *\n * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY\n * This uses event polling which is not suitable for production.\n *\n * For production, use AWS Lambda with SQS/SNS event source mappings.\n * Lambda automatically:\n * - Scales based on queue depth\n * - Handles batch processing and retries\n * - Manages dead letter queues\n * - Provides better cost optimization\n *\n * This polling implementation is useful for:\n * - Local development and testing\n * - Understanding event flow without Lambda deployment\n *\n * Supported connection strings:\n * - sqs://region/account-id/queue-name (SQS queue)\n * - sns://region/account-id/topic-name (SNS topic)\n * - rabbitmq://host:port/queue-name (RabbitMQ)\n * - basic://in-memory (In-memory for testing)\n */\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { EventConnectionFactory, Subscriber } from '@geekmidas/events';\nimport type { EventConnection, EventSubscriber } from '@geekmidas/events';\nimport { ServiceDiscovery } from '@geekmidas/services';\n${imports}\n\nconst subscribers = [\n ${allExportNames.join(',\\n ')}\n];\n\nconst activeSubscribers: EventSubscriber<any>[] = [];\n\nexport async function setupSubscribers(\n envParser: EnvironmentParser<any>,\n logger: Logger,\n): Promise<void> {\n logger.info('Setting up subscribers in polling mode (local development)');\n\n const config = envParser.create((get) => ({\n connectionString: get('EVENT_SUBSCRIBER_CONNECTION_STRING').string().optional(),\n })).parse();\n\n if (!config.connectionString) {\n logger.warn('EVENT_SUBSCRIBER_CONNECTION_STRING not configured, skipping subscriber setup');\n return;\n }\n\n const serviceDiscovery = ServiceDiscovery.getInstance(logger, envParser);\n\n // Create connection once, outside the loop (more efficient)\n // EventConnectionFactory automatically determines the right connection type\n let connection: EventConnection;\n try {\n connection = await EventConnectionFactory.fromConnectionString(config.connectionString);\n\n const connectionType = new URL(config.connectionString).protocol.replace(':', '');\n logger.info({ connectionType }, 'Created shared event connection');\n } catch (error) {\n logger.error({ error }, 'Failed to create event connection');\n return;\n }\n\n for (const subscriber of subscribers) {\n try {\n // Create subscriber from shared connection\n const eventSubscriber = await Subscriber.fromConnection(connection);\n\n // Register services\n const services = subscriber.services.length > 0\n ? await serviceDiscovery.register(subscriber.services)\n : {};\n\n // Subscribe to events\n const subscribedEvents = subscriber.subscribedEvents || [];\n\n if (subscribedEvents.length === 0) {\n logger.warn({ subscriber: subscriber.constructor.name }, 'Subscriber has no subscribed events, skipping');\n continue;\n }\n\n await eventSubscriber.subscribe(subscribedEvents, async (event) => {\n try {\n // Process single event (batch of 1)\n await subscriber.handler({\n events: [event],\n services: services as any,\n logger: subscriber.logger,\n });\n\n logger.debug({ eventType: event.type }, 'Successfully processed event');\n } catch (error) {\n logger.error({ error, event }, 'Failed to process event');\n // Event will become visible again for retry\n }\n });\n\n activeSubscribers.push(eventSubscriber);\n\n logger.info(\n {\n events: subscribedEvents,\n },\n 'Subscriber started polling'\n );\n } catch (error) {\n logger.error({ error, subscriber: subscriber.constructor.name }, 'Failed to setup subscriber');\n }\n }\n\n // Setup graceful shutdown\n const shutdown = () => {\n logger.info('Stopping all subscribers');\n for (const eventSubscriber of activeSubscribers) {\n connection.stop();\n }\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n`;\n\n await writeFile(subscribersPath, content);\n return subscribersPath;\n }\n}\n"],"mappings":";;;;;;;AAWA,IAAa,sBAAb,cAAyCA,qCAGvC;CACA,YAAYC,OAA+D;AACzE,SAAO,8CAAW,aAAa,MAAM;CACtC;CAED,MAAM,MACJC,SACAC,YACAC,WACAC,SAC2B;EAC3B,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,SAAS;EACf,MAAMC,kBAAoC,CAAE;AAE5C,MAAI,WAAW,WAAW,EACxB,QAAO;AAGT,MAAI,aAAa,UAAU;AAEzB,SAAM,KAAK,8BAA8B,WAAW,WAAW;AAE/D,UAAO,KACJ,yCAAyC,WAAW,OAAO,6BAC7D;AAGD,UAAO;EACR;AAED,MAAI,aAAa,aACf,QAAO;EAIT,MAAM,iBAAiB,oBAAK,WAAW,cAAc;AACrD,QAAM,4BAAM,gBAAgB,EAAE,WAAW,KAAM,EAAC;AAGhD,OAAK,MAAM,EAAE,KAAK,WAAW,MAAM,IAAI,YAAY;GACjD,MAAM,cAAc,MAAM,KAAK,0BAC7B,gBACA,KAAK,UACL,KACA,WACA,QACD;AAED,mBAAgB,KAAK;IACnB,MAAM;IACN,SAAS,wBAAS,QAAQ,KAAK,EAAE,YAAY,CAAC,QAC5C,SACA,WACD;IACD,kBAAkB,UAAU,oBAAoB,CAAE;IAClD,SAAS,UAAU;IACnB,aAAa,MAAM,UAAU,gBAAgB;GAC9C,EAAC;AAEF,UAAO,KAAK,gCAAgC,IAAI,EAAE;EACnD;AAED,SAAO;CACR;CAED,MAAc,0BACZF,WACAG,YACAC,YACAC,aACAP,SACiB;EACjB,MAAM,mBAAmB,EAAE,WAAW;EACtC,MAAM,cAAc,oBAAK,WAAW,gBAAgB;EAEpD,MAAM,eAAe,wBAAS,uBAAQ,YAAY,EAAE,WAAW;EAC/D,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;EAEvD,MAAM,wBAAwB,wBAC5B,uBAAQ,YAAY,EACpB,QAAQ,cACT;EAED,MAAM,WAAW;WACV,WAAW,WAAW,WAAW;SACnC,QAAQ,uBAAuB,SAAS,sBAAsB;;qDAElB,WAAW;;;;AAK5D,QAAM,gCAAU,aAAa,QAAQ;AACrC,SAAO;CACR;CAED,MAAc,8BACZE,WACAM,aACiB;EACjB,MAAM,sBAAsB;EAC5B,MAAM,kBAAkB,oBAAK,WAAW,oBAAoB;EAG5D,MAAM,gCAAgB,IAAI;AAE1B,OAAK,MAAM,EAAE,MAAM,KAAK,IAAI,aAAa;GACvC,MAAM,eAAe,wBAAS,uBAAQ,gBAAgB,EAAE,KAAK,SAAS;GACtE,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;AAEvD,QAAK,cAAc,IAAI,WAAW,CAChC,eAAc,IAAI,YAAY,CAAE,EAAC;AAEnC,iBAAc,IAAI,WAAW,CAAE,KAAK,IAAI;EACzC;EAGD,MAAM,UAAU,MAAM,KAAK,cAAc,SAAS,CAAC,CAChD,IACC,CAAC,CAAC,YAAYC,UAAQ,MACnB,WAAW,UAAQ,KAAK,KAAK,CAAC,WAAW,WAAW,IACxD,CACA,KAAK,KAAK;EAEb,MAAM,iBAAiB,YAAY,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI;EAExD,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BnB,QAAQ;;;IAGN,eAAe,KAAK,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+F7B,QAAM,gCAAU,iBAAiB,QAAQ;AACzC,SAAO;CACR;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubscriberGenerator-D2u00NI3.mjs","names":["value: any","context: BuildContext","constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","subscriberInfos: SubscriberInfo[]","sourceFile: string","exportName: string","_subscriber: Subscriber<any, any, any, any, any, any>","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]"],"sources":["../src/generators/SubscriberGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Subscriber } from '@geekmidas/constructs/subscribers';\nimport type { BuildContext } from '../build/types';\nimport type { SubscriberInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class SubscriberGenerator extends ConstructGenerator<\n Subscriber<any, any, any, any, any, any>,\n SubscriberInfo[]\n> {\n isConstruct(value: any): value is Subscriber<any, any, any, any, any, any> {\n return Subscriber.isSubscriber(value);\n }\n\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<SubscriberInfo[]> {\n const provider = options?.provider || 'aws-lambda';\n const logger = console;\n const subscriberInfos: SubscriberInfo[] = [];\n\n if (constructs.length === 0) {\n return subscriberInfos;\n }\n\n if (provider === 'server') {\n // Generate subscribers.ts for server-based polling\n await this.generateServerSubscribersFile(outputDir, constructs);\n\n logger.log(\n `Generated server subscribers file with ${constructs.length} subscribers (polling mode)`,\n );\n\n // Return empty array as server subscribers don't have individual handlers\n return subscriberInfos;\n }\n\n if (provider !== 'aws-lambda') {\n return subscriberInfos;\n }\n\n // Create subscribers subdirectory\n const subscribersDir = join(outputDir, 'subscribers');\n await mkdir(subscribersDir, { recursive: true });\n\n // Generate subscriber handlers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateSubscriberHandler(\n subscribersDir,\n path.relative,\n key,\n construct,\n context,\n );\n\n subscriberInfos.push({\n name: key,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n subscribedEvents: construct.subscribedEvents || [],\n timeout: construct.timeout,\n environment: await construct.getEnvironment(),\n });\n\n logger.log(`Generated subscriber handler: ${key}`);\n }\n\n return subscriberInfos;\n }\n\n private async generateSubscriberHandler(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n _subscriber: Subscriber<any, any, any, any, any, any>,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n\n const content = `import { AWSLambdaSubscriber } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\n\nconst adapter = new AWSLambdaSubscriber(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n\n private async generateServerSubscribersFile(\n outputDir: string,\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n ): Promise<string> {\n const subscribersFileName = 'subscribers.ts';\n const subscribersPath = join(outputDir, subscribersFileName);\n\n // Group imports by file\n const importsByFile = new Map<string, string[]>();\n\n for (const { path, key } of subscribers) {\n const relativePath = relative(dirname(subscribersPath), path.relative);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n if (!importsByFile.has(importPath)) {\n importsByFile.set(importPath, []);\n }\n importsByFile.get(importPath)!.push(key);\n }\n\n // Generate import statements\n const imports = Array.from(importsByFile.entries())\n .map(\n ([importPath, exports]) =>\n `import { ${exports.join(', ')} } from '${importPath}';`,\n )\n .join('\\n');\n\n const allExportNames = subscribers.map(({ key }) => key);\n\n const content = `/**\n * Generated subscribers setup\n *\n * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY\n * This uses event polling which is not suitable for production.\n *\n * For production, use AWS Lambda with SQS/SNS event source mappings.\n * Lambda automatically:\n * - Scales based on queue depth\n * - Handles batch processing and retries\n * - Manages dead letter queues\n * - Provides better cost optimization\n *\n * This polling implementation is useful for:\n * - Local development and testing\n * - Understanding event flow without Lambda deployment\n *\n * Supported connection strings:\n * - sqs://region/account-id/queue-name (SQS queue)\n * - sns://region/account-id/topic-name (SNS topic)\n * - rabbitmq://host:port/queue-name (RabbitMQ)\n * - basic://in-memory (In-memory for testing)\n */\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { EventConnectionFactory, Subscriber } from '@geekmidas/events';\nimport type { EventConnection, EventSubscriber } from '@geekmidas/events';\nimport { ServiceDiscovery } from '@geekmidas/services';\n${imports}\n\nconst subscribers = [\n ${allExportNames.join(',\\n ')}\n];\n\nconst activeSubscribers: EventSubscriber<any>[] = [];\n\nexport async function setupSubscribers(\n envParser: EnvironmentParser<any>,\n logger: Logger,\n): Promise<void> {\n logger.info('Setting up subscribers in polling mode (local development)');\n\n const config = envParser.create((get) => ({\n connectionString: get('EVENT_SUBSCRIBER_CONNECTION_STRING').string().optional(),\n })).parse();\n\n if (!config.connectionString) {\n logger.warn('EVENT_SUBSCRIBER_CONNECTION_STRING not configured, skipping subscriber setup');\n return;\n }\n\n const serviceDiscovery = ServiceDiscovery.getInstance(logger, envParser);\n\n // Create connection once, outside the loop (more efficient)\n // EventConnectionFactory automatically determines the right connection type\n let connection: EventConnection;\n try {\n connection = await EventConnectionFactory.fromConnectionString(config.connectionString);\n\n const connectionType = new URL(config.connectionString).protocol.replace(':', '');\n logger.info({ connectionType }, 'Created shared event connection');\n } catch (error) {\n logger.error({ error }, 'Failed to create event connection');\n return;\n }\n\n for (const subscriber of subscribers) {\n try {\n // Create subscriber from shared connection\n const eventSubscriber = await Subscriber.fromConnection(connection);\n\n // Register services\n const services = subscriber.services.length > 0\n ? await serviceDiscovery.register(subscriber.services)\n : {};\n\n // Subscribe to events\n const subscribedEvents = subscriber.subscribedEvents || [];\n\n if (subscribedEvents.length === 0) {\n logger.warn({ subscriber: subscriber.constructor.name }, 'Subscriber has no subscribed events, skipping');\n continue;\n }\n\n await eventSubscriber.subscribe(subscribedEvents, async (event) => {\n try {\n // Process single event (batch of 1)\n await subscriber.handler({\n events: [event],\n services: services as any,\n logger: subscriber.logger,\n });\n\n logger.debug({ eventType: event.type }, 'Successfully processed event');\n } catch (error) {\n logger.error({ error, event }, 'Failed to process event');\n // Event will become visible again for retry\n }\n });\n\n activeSubscribers.push(eventSubscriber);\n\n logger.info(\n {\n events: subscribedEvents,\n },\n 'Subscriber started polling'\n );\n } catch (error) {\n logger.error({ error, subscriber: subscriber.constructor.name }, 'Failed to setup subscriber');\n }\n }\n\n // Setup graceful shutdown\n const shutdown = () => {\n logger.info('Stopping all subscribers');\n for (const eventSubscriber of activeSubscribers) {\n connection.stop();\n }\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n`;\n\n await writeFile(subscribersPath, content);\n return subscribersPath;\n }\n}\n"],"mappings":";;;;;;AAWA,IAAa,sBAAb,cAAyC,mBAGvC;CACA,YAAYA,OAA+D;AACzE,SAAO,WAAW,aAAa,MAAM;CACtC;CAED,MAAM,MACJC,SACAC,YACAC,WACAC,SAC2B;EAC3B,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,SAAS;EACf,MAAMC,kBAAoC,CAAE;AAE5C,MAAI,WAAW,WAAW,EACxB,QAAO;AAGT,MAAI,aAAa,UAAU;AAEzB,SAAM,KAAK,8BAA8B,WAAW,WAAW;AAE/D,UAAO,KACJ,yCAAyC,WAAW,OAAO,6BAC7D;AAGD,UAAO;EACR;AAED,MAAI,aAAa,aACf,QAAO;EAIT,MAAM,iBAAiB,KAAK,WAAW,cAAc;AACrD,QAAM,MAAM,gBAAgB,EAAE,WAAW,KAAM,EAAC;AAGhD,OAAK,MAAM,EAAE,KAAK,WAAW,MAAM,IAAI,YAAY;GACjD,MAAM,cAAc,MAAM,KAAK,0BAC7B,gBACA,KAAK,UACL,KACA,WACA,QACD;AAED,mBAAgB,KAAK;IACnB,MAAM;IACN,SAAS,SAAS,QAAQ,KAAK,EAAE,YAAY,CAAC,QAC5C,SACA,WACD;IACD,kBAAkB,UAAU,oBAAoB,CAAE;IAClD,SAAS,UAAU;IACnB,aAAa,MAAM,UAAU,gBAAgB;GAC9C,EAAC;AAEF,UAAO,KAAK,gCAAgC,IAAI,EAAE;EACnD;AAED,SAAO;CACR;CAED,MAAc,0BACZF,WACAG,YACAC,YACAC,aACAP,SACiB;EACjB,MAAM,mBAAmB,EAAE,WAAW;EACtC,MAAM,cAAc,KAAK,WAAW,gBAAgB;EAEpD,MAAM,eAAe,SAAS,QAAQ,YAAY,EAAE,WAAW;EAC/D,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;EAEvD,MAAM,wBAAwB,SAC5B,QAAQ,YAAY,EACpB,QAAQ,cACT;EAED,MAAM,WAAW;WACV,WAAW,WAAW,WAAW;SACnC,QAAQ,uBAAuB,SAAS,sBAAsB;;qDAElB,WAAW;;;;AAK5D,QAAM,UAAU,aAAa,QAAQ;AACrC,SAAO;CACR;CAED,MAAc,8BACZE,WACAM,aACiB;EACjB,MAAM,sBAAsB;EAC5B,MAAM,kBAAkB,KAAK,WAAW,oBAAoB;EAG5D,MAAM,gCAAgB,IAAI;AAE1B,OAAK,MAAM,EAAE,MAAM,KAAK,IAAI,aAAa;GACvC,MAAM,eAAe,SAAS,QAAQ,gBAAgB,EAAE,KAAK,SAAS;GACtE,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;AAEvD,QAAK,cAAc,IAAI,WAAW,CAChC,eAAc,IAAI,YAAY,CAAE,EAAC;AAEnC,iBAAc,IAAI,WAAW,CAAE,KAAK,IAAI;EACzC;EAGD,MAAM,UAAU,MAAM,KAAK,cAAc,SAAS,CAAC,CAChD,IACC,CAAC,CAAC,YAAY,QAAQ,MACnB,WAAW,QAAQ,KAAK,KAAK,CAAC,WAAW,WAAW,IACxD,CACA,KAAK,KAAK;EAEb,MAAM,iBAAiB,YAAY,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI;EAExD,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BnB,QAAQ;;;IAGN,eAAe,KAAK,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+F7B,QAAM,UAAU,iBAAiB,QAAQ;AACzC,SAAO;CACR;AACF"}