@devbro/pashmak 0.1.48 → 0.1.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/DatabaseServiceProvider.d.mts +4 -1
  2. package/dist/DatabaseServiceProvider.mjs +5 -2
  3. package/dist/DatabaseServiceProvider.mjs.map +1 -1
  4. package/dist/app/console/StartCommand.d.mts +1 -0
  5. package/dist/app/console/StartCommand.mjs +5 -2
  6. package/dist/app/console/StartCommand.mjs.map +1 -1
  7. package/dist/app/console/generate/GenerateApiDocsCommand.d.mts +34 -2
  8. package/dist/app/console/generate/GenerateApiDocsCommand.mjs +183 -100
  9. package/dist/app/console/generate/GenerateApiDocsCommand.mjs.map +1 -1
  10. package/dist/app/console/project/base_project/src/config/storages.ts.tpl +2 -2
  11. package/dist/bin/DatabaseServiceProvider.cjs +8 -2
  12. package/dist/bin/app/console/DefaultCommand.cjs +45 -17
  13. package/dist/bin/app/console/KeyGenerateCommand.cjs +45 -17
  14. package/dist/bin/app/console/StartCommand.cjs +50 -19
  15. package/dist/bin/app/console/generate/GenerateApiDocsCommand.cjs +229 -118
  16. package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +45 -17
  17. package/dist/bin/app/console/generate/index.cjs +229 -118
  18. package/dist/bin/app/console/index.cjs +234 -120
  19. package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +45 -17
  20. package/dist/bin/app/console/migrate/MigrateCommand.cjs +45 -17
  21. package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +45 -17
  22. package/dist/bin/app/console/migrate/index.cjs +45 -17
  23. package/dist/bin/app/console/queue/GenerateQueueMigrateCommand.cjs +45 -17
  24. package/dist/bin/cache.cjs +45 -17
  25. package/dist/bin/facades.cjs +45 -17
  26. package/dist/bin/factories.cjs +45 -17
  27. package/dist/bin/http.cjs +45 -17
  28. package/dist/bin/index.cjs +243 -126
  29. package/dist/bin/middlewares.cjs +45 -17
  30. package/dist/bin/queue.cjs +45 -17
  31. package/dist/bin/router.cjs +3 -5
  32. package/dist/factories.mjs +45 -2
  33. package/dist/factories.mjs.map +1 -1
  34. package/dist/http.mjs +1 -1
  35. package/dist/http.mjs.map +1 -1
  36. package/dist/queue.d.mts +1 -1
  37. package/dist/queue.mjs.map +1 -1
  38. package/package.json +1 -1
@@ -89,13 +89,14 @@ var init_MiddlewareFactory = __esm({
89
89
  });
90
90
 
91
91
  // ../neko-router/dist/CompiledRoute.mjs
92
- var import_stream, CompiledRoute;
92
+ var import_stream, import_neko_helper, CompiledRoute;
93
93
  var init_CompiledRoute = __esm({
94
94
  "../neko-router/dist/CompiledRoute.mjs"() {
95
95
  "use strict";
96
96
  import_stream = require("stream");
97
97
  init_Middleware();
98
98
  init_MiddlewareFactory();
99
+ import_neko_helper = require("@devbro/neko-helper");
99
100
  CompiledRoute = class {
100
101
  static {
101
102
  __name(this, "CompiledRoute");
@@ -116,7 +117,7 @@ var init_CompiledRoute = __esm({
116
117
  for (const middleware of [...this.globalMiddlewares, ...this.route.getMiddlewares()]) {
117
118
  if (middleware instanceof Middleware) {
118
119
  this.middlewares.push(middleware);
119
- } else if (this.isClass(middleware)) {
120
+ } else if ((0, import_neko_helper.isClass)(middleware)) {
120
121
  this.middlewares.push(middleware.getInstance({}));
121
122
  } else if (typeof middleware === "function") {
122
123
  this.middlewares.push(MiddlewareFactory.create(middleware));
@@ -125,9 +126,6 @@ var init_CompiledRoute = __esm({
125
126
  }
126
127
  }
127
128
  }
128
- isClass(func) {
129
- return typeof func === "function" && /^class\s/.test(Function.prototype.toString.call(func));
130
- }
131
129
  async run() {
132
130
  return await this.runMiddlewares(this.middlewares, this.request, this.response);
133
131
  }
@@ -276,7 +274,7 @@ var init_Route = __esm({
276
274
  i = start;
277
275
  } else if (char === "*") {
278
276
  let start = i + 1;
279
- while (start < path10.length && /[a-zA-Z0-9_\.]/.test(path10[start])) {
277
+ while (start < path10.length && /[a-zA-Z0-9_]/.test(path10[start])) {
280
278
  start++;
281
279
  }
282
280
  tokens.push({ type: "WILDCARD", value: path10.slice(i + 1, start) });
@@ -586,13 +584,13 @@ var queue_exports = {};
586
584
  __export(queue_exports, {
587
585
  DatabaseTransport: () => DatabaseTransport
588
586
  });
589
- var import_neko_helper, import_neko_context2, DatabaseTransport;
587
+ var import_neko_helper2, import_neko_context2, DatabaseTransport;
590
588
  var init_queue = __esm({
591
589
  "src/queue.mts"() {
592
590
  "use strict";
593
591
  __reExport(queue_exports, require("@devbro/neko-queue"));
594
592
  init_facades();
595
- import_neko_helper = require("@devbro/neko-helper");
593
+ import_neko_helper2 = require("@devbro/neko-helper");
596
594
  import_neko_context2 = require("@devbro/neko-context");
597
595
  DatabaseTransport = class {
598
596
  static {
@@ -653,7 +651,7 @@ var init_queue = __esm({
653
651
  }, "processMessage");
654
652
  constructor(config11 = {}) {
655
653
  this.config = { ...this.config, ...config11 };
656
- this.repeater = (0, import_neko_helper.createRepeater)(
654
+ this.repeater = (0, import_neko_helper2.createRepeater)(
657
655
  this.processMessage,
658
656
  this.config.listen_interval * 1e3
659
657
  );
@@ -730,6 +728,24 @@ var init_factories = __esm({
730
728
  import_neko_queue.QueueTransportFactory.register("memory", (opt) => {
731
729
  return new import_neko_queue.MemoryTransport(opt);
732
730
  });
731
+ import_neko_queue.QueueTransportFactory.register("sqs", (opt) => {
732
+ return new import_neko_queue.AwsSqsTransport(opt);
733
+ });
734
+ import_neko_queue.QueueTransportFactory.register("amqp", (opt) => {
735
+ return new import_neko_queue.AmqpTransport(opt);
736
+ });
737
+ import_neko_queue.QueueTransportFactory.register("redis", (opt) => {
738
+ return new import_neko_queue.RedisTransport(opt);
739
+ });
740
+ import_neko_queue.QueueTransportFactory.register("async", (opt) => {
741
+ return new import_neko_queue.AsyncTransport();
742
+ });
743
+ import_neko_queue.QueueTransportFactory.register("azure_service_bus", (opt) => {
744
+ return new import_neko_queue.AzureServiceBusTransport(opt);
745
+ });
746
+ import_neko_queue.QueueTransportFactory.register("google_pubsub", (opt) => {
747
+ return new import_neko_queue.GooglePubSubTransport(opt);
748
+ });
733
749
  CacheProviderFactory = class _CacheProviderFactory {
734
750
  static {
735
751
  __name(this, "CacheProviderFactory");
@@ -760,17 +776,29 @@ var init_factories = __esm({
760
776
  import_neko_storage.StorageProviderFactory.register("s3", (opt) => {
761
777
  return new import_neko_storage.AWSS3StorageProvider(opt);
762
778
  });
779
+ import_neko_storage.StorageProviderFactory.register("gcp", (opt) => {
780
+ return new import_neko_storage.GCPStorageProvider(opt);
781
+ });
782
+ import_neko_storage.StorageProviderFactory.register("azure", (opt) => {
783
+ return new import_neko_storage.AzureBlobStorageProvider(opt);
784
+ });
785
+ import_neko_storage.StorageProviderFactory.register("ftp", (opt) => {
786
+ return new import_neko_storage.FTPStorageProvider(opt);
787
+ });
788
+ import_neko_storage.StorageProviderFactory.register("sftp", (opt) => {
789
+ return new import_neko_storage.SFTPStorageProvider(opt);
790
+ });
763
791
  }
764
792
  });
765
793
 
766
794
  // src/facades.mts
767
- var import_neko_scheduler, import_neko_helper2, import_neko_context3, import_neko_storage2, import_neko_mailer2, import_neko_config, import_clipanion, import_neko_logger, import_neko_cache2, import_neko_queue2, router, scheduler, db, storage, cli, httpServer, logger, mailer, queue, cache;
795
+ var import_neko_scheduler, import_neko_helper3, import_neko_context3, import_neko_storage2, import_neko_mailer2, import_neko_config, import_clipanion, import_neko_logger, import_neko_cache2, import_neko_queue2, router, scheduler, db, storage, cli, httpServer, logger, mailer, queue, cache;
768
796
  var init_facades = __esm({
769
797
  "src/facades.mts"() {
770
798
  "use strict";
771
799
  init_router();
772
800
  import_neko_scheduler = require("@devbro/neko-scheduler");
773
- import_neko_helper2 = require("@devbro/neko-helper");
801
+ import_neko_helper3 = require("@devbro/neko-helper");
774
802
  import_neko_context3 = require("@devbro/neko-context");
775
803
  import_neko_storage2 = require("@devbro/neko-storage");
776
804
  import_neko_mailer2 = require("@devbro/neko-mailer");
@@ -781,8 +809,8 @@ var init_facades = __esm({
781
809
  init_factories();
782
810
  import_neko_cache2 = require("@devbro/neko-cache");
783
811
  import_neko_queue2 = require("@devbro/neko-queue");
784
- router = (0, import_neko_helper2.createSingleton)(() => new Router());
785
- scheduler = (0, import_neko_helper2.createSingleton)(() => {
812
+ router = (0, import_neko_helper3.createSingleton)(() => new Router());
813
+ scheduler = (0, import_neko_helper3.createSingleton)(() => {
786
814
  const rc = new import_neko_scheduler.Scheduler();
787
815
  rc.setErrorHandler((err, job) => {
788
816
  logger().error({
@@ -794,7 +822,7 @@ var init_facades = __esm({
794
822
  return rc;
795
823
  });
796
824
  db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context3.ctx)().getOrThrow(["database", label]), "db");
797
- storage = (0, import_neko_helper2.createSingleton)((label = "default") => {
825
+ storage = (0, import_neko_helper3.createSingleton)((label = "default") => {
798
826
  let storage_config = import_neko_config.config.get(["storages", label].join("."));
799
827
  const provider = import_neko_storage2.StorageProviderFactory.create(
800
828
  storage_config.provider,
@@ -802,7 +830,7 @@ var init_facades = __esm({
802
830
  );
803
831
  return new import_neko_storage2.Storage(provider);
804
832
  });
805
- cli = (0, import_neko_helper2.createSingleton)(() => {
833
+ cli = (0, import_neko_helper3.createSingleton)(() => {
806
834
  const [node, app, ...args] = process.argv;
807
835
  return new import_clipanion.Cli({
808
836
  binaryLabel: `My Application`,
@@ -810,13 +838,13 @@ var init_facades = __esm({
810
838
  binaryVersion: `1.0.0`
811
839
  });
812
840
  });
813
- httpServer = (0, import_neko_helper2.createSingleton)(() => {
841
+ httpServer = (0, import_neko_helper3.createSingleton)(() => {
814
842
  const server = new http_exports.HttpServer();
815
843
  server.setErrorHandler(handleHttpErrors);
816
844
  server.setRouter(router());
817
845
  return server;
818
846
  });
819
- logger = (0, import_neko_helper2.createSingleton)((label) => {
847
+ logger = (0, import_neko_helper3.createSingleton)((label) => {
820
848
  const logger_config = import_neko_config.config.get(["loggers", label].join("."));
821
849
  const rc = new import_neko_logger.Logger(logger_config);
822
850
  rc.setExtrasFunction((message) => {
@@ -825,7 +853,7 @@ var init_facades = __esm({
825
853
  });
826
854
  return rc;
827
855
  });
828
- mailer = (0, import_neko_helper2.createSingleton)((label) => {
856
+ mailer = (0, import_neko_helper3.createSingleton)((label) => {
829
857
  const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
830
858
  const provider = import_neko_mailer2.MailerProviderFactory.create(
831
859
  mailer_config.provider,
@@ -834,7 +862,7 @@ var init_facades = __esm({
834
862
  const rc = new import_neko_mailer2.Mailer(provider);
835
863
  return rc;
836
864
  });
837
- queue = (0, import_neko_helper2.createSingleton)((label) => {
865
+ queue = (0, import_neko_helper3.createSingleton)((label) => {
838
866
  const queue_config = import_neko_config.config.get(["queues", label].join("."));
839
867
  if (!queue_config) {
840
868
  throw new Error(`Queue configuration for '${label}' not found`);
@@ -845,7 +873,7 @@ var init_facades = __esm({
845
873
  );
846
874
  return new import_neko_queue2.QueueConnection(provider);
847
875
  });
848
- cache = (0, import_neko_helper2.createSingleton)((label) => {
876
+ cache = (0, import_neko_helper3.createSingleton)((label) => {
849
877
  const cache_config = import_neko_config.config.get(["caches", label].join("."));
850
878
  if (!cache_config) {
851
879
  throw new Error(`Cache configuration for '${label}' not found`);
@@ -2260,12 +2288,15 @@ var init_StartCommand = __esm({
2260
2288
  __name(this, "StartCommand");
2261
2289
  }
2262
2290
  scheduler = import_clipanion5.Option.Boolean(`--scheduler`, false);
2291
+ cron = import_clipanion5.Option.Boolean(`--cron`, false);
2263
2292
  http = import_clipanion5.Option.Boolean(`--http`, false);
2264
2293
  queue = import_clipanion5.Option.Boolean(`--queue`, false);
2265
2294
  all = import_clipanion5.Option.Boolean("--all", false);
2266
2295
  static paths = [[`start`]];
2267
2296
  async execute() {
2268
- if ([this.all, this.http, this.scheduler, this.queue].filter((x) => x).length == 0) {
2297
+ if ([this.all, this.http, this.scheduler || this.cron, this.queue].filter(
2298
+ (x) => x
2299
+ ).length == 0) {
2269
2300
  this.context.stdout.write(
2270
2301
  `No service was selected. please check -h for details
2271
2302
  `
@@ -2275,7 +2306,7 @@ var init_StartCommand = __esm({
2275
2306
  logger().info(`Starting Server
2276
2307
  `);
2277
2308
  import_neko_sql.PostgresqlConnection.defaults.idleTimeoutMillis = 1e4;
2278
- if (this.scheduler || this.all) {
2309
+ if (this.scheduler || this.cron || this.all) {
2279
2310
  logger().info(`starting scheduler
2280
2311
  `);
2281
2312
  scheduler().start();
@@ -2496,7 +2527,7 @@ var init_config = __esm({
2496
2527
  });
2497
2528
 
2498
2529
  // src/app/console/generate/GenerateApiDocsCommand.mts
2499
- var import_clipanion9, import_path7, fs6, import_neko_helper3, GenerateApiDocsCommand;
2530
+ var import_clipanion9, import_path7, fs6, import_neko_helper4, GenerateApiDocsCommand;
2500
2531
  var init_GenerateApiDocsCommand = __esm({
2501
2532
  "src/app/console/generate/GenerateApiDocsCommand.mts"() {
2502
2533
  "use strict";
@@ -2505,144 +2536,155 @@ var init_GenerateApiDocsCommand = __esm({
2505
2536
  import_path7 = __toESM(require("path"), 1);
2506
2537
  fs6 = __toESM(require("fs/promises"), 1);
2507
2538
  init_config();
2508
- import_neko_helper3 = require("@devbro/neko-helper");
2539
+ import_neko_helper4 = require("@devbro/neko-helper");
2509
2540
  GenerateApiDocsCommand = class extends import_clipanion9.Command {
2510
2541
  static {
2511
2542
  __name(this, "GenerateApiDocsCommand");
2512
2543
  }
2513
- static paths = [
2514
- [`make`, `apidocs`],
2515
- [`generate`, `apidocs`]
2516
- ];
2544
+ static paths = [[`generate`, `apidocsv2`]];
2517
2545
  static usage = import_clipanion9.Command.Usage({
2518
2546
  category: `Generate`,
2519
2547
  description: `Generate OpenAPI documentation from routes`,
2520
2548
  details: `
2521
- This command generates OpenAPI 3.0 specification documentation by analyzing
2549
+ This command utility generates OpenAPI 3.0 specification documentation by analyzing
2522
2550
  your application's routes and merging with example files.
2523
2551
 
2524
- The generated documentation includes:
2525
- - All registered routes with their HTTP methods
2526
- - Path parameters extracted from route definitions
2527
- - Request body schemas for POST, PUT, and PATCH methods
2528
- - Response schemas
2529
-
2530
- The command will merge files specified in config.api_docs.merge_files
2531
- and output the final documentation to config.api_docs.output.
2552
+ Subcommands:
2553
+ - generate-from-routes: Generate OpenAPI spec from registered routes
2554
+ - generate-base: Generate base OpenAPI specification structure
2555
+ - merge-files: Merge multiple OpenAPI files into final documentation
2532
2556
 
2557
+
2533
2558
  This command depends on config data. make sure your default config contains the following:
2534
- api_docs: {
2535
- merge_files: [
2536
- path.join(__dirname, '../..', 'private', 'openapi_examples.json'),
2537
- path.join(__dirname, '../..', 'private', 'openapi_base.json'),
2538
- path.join(__dirname, '../..', 'private', 'openapi_user_changes.json'),
2539
- ],
2540
- output: path.join(__dirname, '../..', 'private', 'openapi.json'),
2541
- }
2559
+
2560
+ \`\`\`
2561
+ api_docs: {
2562
+
2563
+ merge_files: [
2564
+
2565
+ path.join(__dirname, '../..', 'private', 'openapi_base.json'),
2566
+
2567
+ path.join(__dirname, '../..', 'private', 'openapi_from_routes.json'),
2568
+
2569
+ path.join(__dirname, '../..', 'private', 'openapi_from_tests.json'),
2570
+
2571
+ path.join(__dirname, '../..', 'private', 'openapi_other_user_changes.json'),
2572
+
2573
+ ],
2574
+
2575
+ output: path.join(__dirname, '../..', 'public', 'openapi.json'),
2576
+
2577
+ }
2578
+
2579
+ \`\`\`
2542
2580
  `,
2543
- examples: [[`Generate API documentation`, `$0 generate apidocs`]]
2581
+ examples: [
2582
+ [
2583
+ `Generate from routes`,
2584
+ `$0 generate apidocsv2 generate-from-routes --output path/to/output.json`
2585
+ ],
2586
+ [
2587
+ `Generate base spec`,
2588
+ `$0 generate apidocsv2 generate-base --output path/to/output.json`
2589
+ ],
2590
+ [`Merge files`, `$0 generate apidocsv2 merge-files`],
2591
+ [`Show help`, `$0 generate apidocsv2 --help`]
2592
+ ]
2544
2593
  });
2545
- help = import_clipanion9.Option.Boolean(`--help,-h`, false, {
2546
- description: `Show help message for this command`
2594
+ subcommand = import_clipanion9.Option.String({ required: false });
2595
+ output = import_clipanion9.Option.String(`--output,-o`, {
2596
+ description: `Output file path for generated documentation`
2597
+ });
2598
+ config = import_clipanion9.Option.String(`--config,-c`, {
2599
+ description: `Path in config to get details from (default: api_docs)`,
2600
+ required: false
2547
2601
  });
2548
2602
  async execute() {
2549
- if (this.help) {
2603
+ if (!this.subcommand) {
2550
2604
  this.context.stdout.write(
2551
2605
  this.constructor.usage?.toString() || "No help available\n"
2552
2606
  );
2553
2607
  return 0;
2554
2608
  }
2555
- const rootDir = process.cwd();
2556
- this.context.stdout.write(`Generating OpenAPI documentation...
2609
+ switch (this.subcommand) {
2610
+ case "generate-from-routes":
2611
+ return await this.executeGenerateFromRoutes();
2612
+ case "generate-base":
2613
+ return await this.executeGenerateBase();
2614
+ case "merge-files":
2615
+ return await this.executeMergeFiles();
2616
+ default:
2617
+ this.context.stderr.write(`Unknown subcommand: ${this.subcommand}
2557
2618
  `);
2558
- const routes = router().routes;
2559
- const openApiSpec = {
2560
- openapi: "3.0.0",
2561
- info: {
2562
- title: "API Documentation",
2563
- version: "1.0.0",
2564
- description: "Auto-generated API documentation"
2565
- },
2566
- servers: [
2567
- {
2568
- url: "/",
2569
- description: "Local server"
2570
- }
2571
- ],
2572
- paths: {}
2573
- };
2574
- for (const route of routes) {
2575
- const routePath = route.path;
2576
- const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
2577
- if (!openApiSpec.paths[openApiPath]) {
2578
- openApiSpec.paths[openApiPath] = {};
2579
- }
2580
- for (const method of route.methods) {
2581
- const lowerMethod = method.toLowerCase();
2582
- if (lowerMethod === "head") {
2583
- continue;
2584
- }
2585
- openApiSpec.paths[openApiPath][lowerMethod] = {
2586
- summary: `${method} ${routePath}`,
2587
- description: `Endpoint for ${method} ${routePath}`,
2588
- parameters: this.extractParameters(routePath),
2589
- responses: {
2590
- "200": {
2591
- description: "Successful response",
2592
- content: {
2593
- "application/json": {
2594
- schema: {
2595
- type: "object"
2596
- }
2597
- }
2598
- }
2599
- },
2600
- "500": {
2601
- description: "Internal server error"
2602
- }
2603
- }
2604
- };
2605
- if (["post", "put", "patch"].includes(lowerMethod)) {
2606
- openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
2607
- required: true,
2608
- content: {
2609
- "application/json": {
2610
- schema: {
2611
- type: "object"
2612
- }
2613
- }
2614
- }
2615
- };
2616
- }
2617
- }
2619
+ this.context.stdout.write(
2620
+ this.constructor.usage?.toString() || "No help available\n"
2621
+ );
2622
+ return 1;
2618
2623
  }
2619
- await fs6.mkdir(config_exports.config.get("private_path"), { recursive: true });
2620
- const outputPath = import_path7.default.join(config_exports.config.get("private_path"), "openapi.json");
2624
+ }
2625
+ async executeGenerateFromRoutes() {
2626
+ this.context.stdout.write(
2627
+ `Generating OpenAPI documentation from routes...
2628
+ `
2629
+ );
2630
+ const openApiSpec = this.generateFromRoutes();
2631
+ const outputPath = this.output || import_path7.default.join(config_exports.config.get("private_path"), "openapi_from_routes.json");
2632
+ await fs6.mkdir(import_path7.default.dirname(outputPath), { recursive: true });
2621
2633
  await fs6.writeFile(
2622
2634
  outputPath,
2623
2635
  JSON.stringify(openApiSpec, null, 2),
2624
2636
  "utf-8"
2625
2637
  );
2626
2638
  this.context.stdout.write(
2627
- `OpenAPI documentation generated at: ${outputPath}
2639
+ `OpenAPI routes documentation generated at: ${outputPath}
2628
2640
  `
2629
2641
  );
2630
- this.context.stdout.write(`Total routes documented: ${routes.length}
2642
+ this.context.stdout.write(
2643
+ `Total routes documented: ${Object.keys(openApiSpec.paths).length}
2644
+ `
2645
+ );
2646
+ return 0;
2647
+ }
2648
+ async executeGenerateBase() {
2649
+ this.context.stdout.write(`Generating base OpenAPI specification...
2650
+ `);
2651
+ const baseSpec = this.getBaseOpenApiSpec();
2652
+ const outputPath = this.output || import_path7.default.join(config_exports.config.get("private_path"), "openapi_base.json");
2653
+ await fs6.mkdir(import_path7.default.dirname(outputPath), { recursive: true });
2654
+ await fs6.writeFile(outputPath, JSON.stringify(baseSpec, null, 2), "utf-8");
2655
+ this.context.stdout.write(
2656
+ `Base OpenAPI specification generated at: ${outputPath}
2657
+ `
2658
+ );
2659
+ return 0;
2660
+ }
2661
+ async executeMergeFiles() {
2662
+ this.context.stdout.write(`Merging OpenAPI files...
2631
2663
  `);
2632
- let files_to_merge = config_exports.config.get("api_docs.merge_files");
2664
+ let configPath = this.config || "api_docs";
2665
+ const files_to_merge = config_exports.config.get(`${configPath}.merge_files`);
2633
2666
  let final_api_docs = {};
2634
- for (let file_path of files_to_merge) {
2635
- let file_json = JSON.parse(await fs6.readFile(file_path, "utf8"));
2636
- final_api_docs = import_neko_helper3.Arr.deepMerge(final_api_docs, file_json);
2667
+ for (const file_path of files_to_merge) {
2668
+ try {
2669
+ const file_json = JSON.parse(await fs6.readFile(file_path, "utf8"));
2670
+ final_api_docs = import_neko_helper4.Arr.deepMerge(final_api_docs, file_json);
2671
+ this.context.stdout.write(` Merged: ${file_path}
2672
+ `);
2673
+ } catch (error) {
2674
+ this.context.stderr.write(
2675
+ ` Warning: Could not read ${file_path}: ${error.message}
2676
+ `
2677
+ );
2678
+ }
2637
2679
  }
2638
- await fs6.writeFile(
2639
- config_exports.config.get("api_docs.output"),
2640
- JSON.stringify(final_api_docs, null, 2)
2641
- );
2680
+ const outputPath = this.output || config_exports.config.get(`${configPath}.output`);
2681
+ await fs6.mkdir(import_path7.default.dirname(outputPath), { recursive: true });
2682
+ await fs6.writeFile(outputPath, JSON.stringify(final_api_docs, null, 2));
2642
2683
  this.context.stdout.write(
2643
- `wrote final open api document to : ${config_exports.config.get("api_docs.output")}
2684
+ `Final OpenAPI document written to: ${outputPath}
2644
2685
  `
2645
2686
  );
2687
+ return 0;
2646
2688
  }
2647
2689
  extractParameters(routePath) {
2648
2690
  const paramRegex = /:([a-zA-Z0-9_]+)/g;
@@ -2661,6 +2703,78 @@ var init_GenerateApiDocsCommand = __esm({
2661
2703
  }
2662
2704
  return parameters;
2663
2705
  }
2706
+ generateFromRoutes() {
2707
+ const openApiSpec = {
2708
+ paths: {}
2709
+ };
2710
+ const routes = router().routes;
2711
+ for (const route of routes) {
2712
+ const routePath = route.path;
2713
+ const openApiPath = routePath.replace(/\/$/g, "");
2714
+ if (!openApiSpec.paths[openApiPath]) {
2715
+ openApiSpec.paths[openApiPath] = {};
2716
+ }
2717
+ for (const method of route.methods) {
2718
+ const lowerMethod = method.toLowerCase();
2719
+ if (lowerMethod === "head") {
2720
+ continue;
2721
+ }
2722
+ openApiSpec.paths[openApiPath][lowerMethod] = {
2723
+ summary: `${routePath}`,
2724
+ description: `Endpoint for ${method} ${routePath}`,
2725
+ security: [],
2726
+ parameters: this.extractParameters(routePath),
2727
+ responses: {}
2728
+ };
2729
+ if (["post", "put", "patch"].includes(lowerMethod)) {
2730
+ openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
2731
+ required: true,
2732
+ content: {
2733
+ "application/json": {
2734
+ schema: {
2735
+ type: "object"
2736
+ }
2737
+ }
2738
+ }
2739
+ };
2740
+ }
2741
+ }
2742
+ }
2743
+ return openApiSpec;
2744
+ }
2745
+ getBaseOpenApiSpec() {
2746
+ const openApiSpec = {
2747
+ openapi: "3.0.0",
2748
+ info: {
2749
+ title: "API Documentation",
2750
+ version: "1.0.0",
2751
+ description: "Auto-generated API documentation"
2752
+ },
2753
+ servers: [
2754
+ {
2755
+ url: "/",
2756
+ description: "Local server"
2757
+ }
2758
+ ],
2759
+ components: {
2760
+ securitySchemes: {
2761
+ bearerAuth: {
2762
+ type: "http",
2763
+ scheme: "bearer",
2764
+ bearerFormat: "JWT",
2765
+ description: "JWT token authentication"
2766
+ }
2767
+ }
2768
+ },
2769
+ security: [
2770
+ {
2771
+ bearerAuth: []
2772
+ }
2773
+ ],
2774
+ paths: {}
2775
+ };
2776
+ return openApiSpec;
2777
+ }
2664
2778
  };
2665
2779
  cli().register(GenerateApiDocsCommand);
2666
2780
  }
@@ -3006,8 +3120,11 @@ var init_DatabaseServiceProvider = __esm({
3006
3120
  return _DatabaseServiceProvider.instance;
3007
3121
  }
3008
3122
  getConnection(db_config) {
3009
- const conn = new import_neko_sql2.PostgresqlConnection(db_config);
3010
- return conn;
3123
+ if (db_config.provider === "postgresql") {
3124
+ const conn = new import_neko_sql2.PostgresqlConnection(db_config.config);
3125
+ return conn;
3126
+ }
3127
+ throw new Error(`Unsupported database provider: ${db_config.provider}`);
3011
3128
  }
3012
3129
  };
3013
3130
  }