@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.
- package/dist/DatabaseServiceProvider.d.mts +4 -1
- package/dist/DatabaseServiceProvider.mjs +5 -2
- package/dist/DatabaseServiceProvider.mjs.map +1 -1
- package/dist/app/console/StartCommand.d.mts +1 -0
- package/dist/app/console/StartCommand.mjs +5 -2
- package/dist/app/console/StartCommand.mjs.map +1 -1
- package/dist/app/console/generate/GenerateApiDocsCommand.d.mts +34 -2
- package/dist/app/console/generate/GenerateApiDocsCommand.mjs +183 -100
- package/dist/app/console/generate/GenerateApiDocsCommand.mjs.map +1 -1
- package/dist/app/console/project/base_project/src/config/storages.ts.tpl +2 -2
- package/dist/bin/DatabaseServiceProvider.cjs +8 -2
- package/dist/bin/app/console/DefaultCommand.cjs +45 -17
- package/dist/bin/app/console/KeyGenerateCommand.cjs +45 -17
- package/dist/bin/app/console/StartCommand.cjs +50 -19
- package/dist/bin/app/console/generate/GenerateApiDocsCommand.cjs +229 -118
- package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +45 -17
- package/dist/bin/app/console/generate/index.cjs +229 -118
- package/dist/bin/app/console/index.cjs +234 -120
- package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +45 -17
- package/dist/bin/app/console/migrate/MigrateCommand.cjs +45 -17
- package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +45 -17
- package/dist/bin/app/console/migrate/index.cjs +45 -17
- package/dist/bin/app/console/queue/GenerateQueueMigrateCommand.cjs +45 -17
- package/dist/bin/cache.cjs +45 -17
- package/dist/bin/facades.cjs +45 -17
- package/dist/bin/factories.cjs +45 -17
- package/dist/bin/http.cjs +45 -17
- package/dist/bin/index.cjs +243 -126
- package/dist/bin/middlewares.cjs +45 -17
- package/dist/bin/queue.cjs +45 -17
- package/dist/bin/router.cjs +3 -5
- package/dist/factories.mjs +45 -2
- package/dist/factories.mjs.map +1 -1
- package/dist/http.mjs +1 -1
- package/dist/http.mjs.map +1 -1
- package/dist/queue.d.mts +1 -1
- package/dist/queue.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -78,6 +78,7 @@ var MiddlewareFactory = class {
|
|
|
78
78
|
};
|
|
79
79
|
|
|
80
80
|
// ../neko-router/dist/CompiledRoute.mjs
|
|
81
|
+
var import_neko_helper = require("@devbro/neko-helper");
|
|
81
82
|
var CompiledRoute = class {
|
|
82
83
|
static {
|
|
83
84
|
__name(this, "CompiledRoute");
|
|
@@ -98,7 +99,7 @@ var CompiledRoute = class {
|
|
|
98
99
|
for (const middleware of [...this.globalMiddlewares, ...this.route.getMiddlewares()]) {
|
|
99
100
|
if (middleware instanceof Middleware) {
|
|
100
101
|
this.middlewares.push(middleware);
|
|
101
|
-
} else if (
|
|
102
|
+
} else if ((0, import_neko_helper.isClass)(middleware)) {
|
|
102
103
|
this.middlewares.push(middleware.getInstance({}));
|
|
103
104
|
} else if (typeof middleware === "function") {
|
|
104
105
|
this.middlewares.push(MiddlewareFactory.create(middleware));
|
|
@@ -107,9 +108,6 @@ var CompiledRoute = class {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
|
-
isClass(func) {
|
|
111
|
-
return typeof func === "function" && /^class\s/.test(Function.prototype.toString.call(func));
|
|
112
|
-
}
|
|
113
111
|
async run() {
|
|
114
112
|
return await this.runMiddlewares(this.middlewares, this.request, this.response);
|
|
115
113
|
}
|
|
@@ -245,7 +243,7 @@ var Route = class {
|
|
|
245
243
|
i = start;
|
|
246
244
|
} else if (char === "*") {
|
|
247
245
|
let start = i + 1;
|
|
248
|
-
while (start < path4.length && /[a-zA-Z0-9_
|
|
246
|
+
while (start < path4.length && /[a-zA-Z0-9_]/.test(path4[start])) {
|
|
249
247
|
start++;
|
|
250
248
|
}
|
|
251
249
|
tokens.push({ type: "WILDCARD", value: path4.slice(i + 1, start) });
|
|
@@ -456,7 +454,7 @@ var Router = class {
|
|
|
456
454
|
|
|
457
455
|
// src/facades.mts
|
|
458
456
|
var import_neko_scheduler = require("@devbro/neko-scheduler");
|
|
459
|
-
var
|
|
457
|
+
var import_neko_helper3 = require("@devbro/neko-helper");
|
|
460
458
|
var import_neko_context3 = require("@devbro/neko-context");
|
|
461
459
|
var import_neko_storage2 = require("@devbro/neko-storage");
|
|
462
460
|
var import_neko_mailer2 = require("@devbro/neko-mailer");
|
|
@@ -497,7 +495,7 @@ __export(queue_exports, {
|
|
|
497
495
|
DatabaseTransport: () => DatabaseTransport
|
|
498
496
|
});
|
|
499
497
|
__reExport(queue_exports, require("@devbro/neko-queue"));
|
|
500
|
-
var
|
|
498
|
+
var import_neko_helper2 = require("@devbro/neko-helper");
|
|
501
499
|
var import_neko_context2 = require("@devbro/neko-context");
|
|
502
500
|
var DatabaseTransport = class {
|
|
503
501
|
static {
|
|
@@ -558,7 +556,7 @@ var DatabaseTransport = class {
|
|
|
558
556
|
}, "processMessage");
|
|
559
557
|
constructor(config4 = {}) {
|
|
560
558
|
this.config = { ...this.config, ...config4 };
|
|
561
|
-
this.repeater = (0,
|
|
559
|
+
this.repeater = (0, import_neko_helper2.createRepeater)(
|
|
562
560
|
this.processMessage,
|
|
563
561
|
this.config.listen_interval * 1e3
|
|
564
562
|
);
|
|
@@ -626,6 +624,24 @@ import_neko_queue.QueueTransportFactory.register("database", (opt) => {
|
|
|
626
624
|
import_neko_queue.QueueTransportFactory.register("memory", (opt) => {
|
|
627
625
|
return new import_neko_queue.MemoryTransport(opt);
|
|
628
626
|
});
|
|
627
|
+
import_neko_queue.QueueTransportFactory.register("sqs", (opt) => {
|
|
628
|
+
return new import_neko_queue.AwsSqsTransport(opt);
|
|
629
|
+
});
|
|
630
|
+
import_neko_queue.QueueTransportFactory.register("amqp", (opt) => {
|
|
631
|
+
return new import_neko_queue.AmqpTransport(opt);
|
|
632
|
+
});
|
|
633
|
+
import_neko_queue.QueueTransportFactory.register("redis", (opt) => {
|
|
634
|
+
return new import_neko_queue.RedisTransport(opt);
|
|
635
|
+
});
|
|
636
|
+
import_neko_queue.QueueTransportFactory.register("async", (opt) => {
|
|
637
|
+
return new import_neko_queue.AsyncTransport();
|
|
638
|
+
});
|
|
639
|
+
import_neko_queue.QueueTransportFactory.register("azure_service_bus", (opt) => {
|
|
640
|
+
return new import_neko_queue.AzureServiceBusTransport(opt);
|
|
641
|
+
});
|
|
642
|
+
import_neko_queue.QueueTransportFactory.register("google_pubsub", (opt) => {
|
|
643
|
+
return new import_neko_queue.GooglePubSubTransport(opt);
|
|
644
|
+
});
|
|
629
645
|
var CacheProviderFactory = class _CacheProviderFactory {
|
|
630
646
|
static {
|
|
631
647
|
__name(this, "CacheProviderFactory");
|
|
@@ -656,12 +672,24 @@ import_neko_storage.StorageProviderFactory.register("local", (opt) => {
|
|
|
656
672
|
import_neko_storage.StorageProviderFactory.register("s3", (opt) => {
|
|
657
673
|
return new import_neko_storage.AWSS3StorageProvider(opt);
|
|
658
674
|
});
|
|
675
|
+
import_neko_storage.StorageProviderFactory.register("gcp", (opt) => {
|
|
676
|
+
return new import_neko_storage.GCPStorageProvider(opt);
|
|
677
|
+
});
|
|
678
|
+
import_neko_storage.StorageProviderFactory.register("azure", (opt) => {
|
|
679
|
+
return new import_neko_storage.AzureBlobStorageProvider(opt);
|
|
680
|
+
});
|
|
681
|
+
import_neko_storage.StorageProviderFactory.register("ftp", (opt) => {
|
|
682
|
+
return new import_neko_storage.FTPStorageProvider(opt);
|
|
683
|
+
});
|
|
684
|
+
import_neko_storage.StorageProviderFactory.register("sftp", (opt) => {
|
|
685
|
+
return new import_neko_storage.SFTPStorageProvider(opt);
|
|
686
|
+
});
|
|
659
687
|
|
|
660
688
|
// src/facades.mts
|
|
661
689
|
var import_neko_cache2 = require("@devbro/neko-cache");
|
|
662
690
|
var import_neko_queue2 = require("@devbro/neko-queue");
|
|
663
|
-
var router = (0,
|
|
664
|
-
var scheduler = (0,
|
|
691
|
+
var router = (0, import_neko_helper3.createSingleton)(() => new Router());
|
|
692
|
+
var scheduler = (0, import_neko_helper3.createSingleton)(() => {
|
|
665
693
|
const rc = new import_neko_scheduler.Scheduler();
|
|
666
694
|
rc.setErrorHandler((err, job) => {
|
|
667
695
|
logger().error({
|
|
@@ -673,7 +701,7 @@ var scheduler = (0, import_neko_helper2.createSingleton)(() => {
|
|
|
673
701
|
return rc;
|
|
674
702
|
});
|
|
675
703
|
var db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context3.ctx)().getOrThrow(["database", label]), "db");
|
|
676
|
-
var storage = (0,
|
|
704
|
+
var storage = (0, import_neko_helper3.createSingleton)((label = "default") => {
|
|
677
705
|
let storage_config = import_neko_config.config.get(["storages", label].join("."));
|
|
678
706
|
const provider = import_neko_storage2.StorageProviderFactory.create(
|
|
679
707
|
storage_config.provider,
|
|
@@ -681,7 +709,7 @@ var storage = (0, import_neko_helper2.createSingleton)((label = "default") => {
|
|
|
681
709
|
);
|
|
682
710
|
return new import_neko_storage2.Storage(provider);
|
|
683
711
|
});
|
|
684
|
-
var cli = (0,
|
|
712
|
+
var cli = (0, import_neko_helper3.createSingleton)(() => {
|
|
685
713
|
const [node, app, ...args] = process.argv;
|
|
686
714
|
return new import_clipanion.Cli({
|
|
687
715
|
binaryLabel: `My Application`,
|
|
@@ -689,13 +717,13 @@ var cli = (0, import_neko_helper2.createSingleton)(() => {
|
|
|
689
717
|
binaryVersion: `1.0.0`
|
|
690
718
|
});
|
|
691
719
|
});
|
|
692
|
-
var httpServer = (0,
|
|
720
|
+
var httpServer = (0, import_neko_helper3.createSingleton)(() => {
|
|
693
721
|
const server = new http_exports.HttpServer();
|
|
694
722
|
server.setErrorHandler(handleHttpErrors);
|
|
695
723
|
server.setRouter(router());
|
|
696
724
|
return server;
|
|
697
725
|
});
|
|
698
|
-
var logger = (0,
|
|
726
|
+
var logger = (0, import_neko_helper3.createSingleton)((label) => {
|
|
699
727
|
const logger_config = import_neko_config.config.get(["loggers", label].join("."));
|
|
700
728
|
const rc = new import_neko_logger.Logger(logger_config);
|
|
701
729
|
rc.setExtrasFunction((message) => {
|
|
@@ -704,7 +732,7 @@ var logger = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
704
732
|
});
|
|
705
733
|
return rc;
|
|
706
734
|
});
|
|
707
|
-
var mailer = (0,
|
|
735
|
+
var mailer = (0, import_neko_helper3.createSingleton)((label) => {
|
|
708
736
|
const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
|
|
709
737
|
const provider = import_neko_mailer2.MailerProviderFactory.create(
|
|
710
738
|
mailer_config.provider,
|
|
@@ -713,7 +741,7 @@ var mailer = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
713
741
|
const rc = new import_neko_mailer2.Mailer(provider);
|
|
714
742
|
return rc;
|
|
715
743
|
});
|
|
716
|
-
var queue = (0,
|
|
744
|
+
var queue = (0, import_neko_helper3.createSingleton)((label) => {
|
|
717
745
|
const queue_config = import_neko_config.config.get(["queues", label].join("."));
|
|
718
746
|
if (!queue_config) {
|
|
719
747
|
throw new Error(`Queue configuration for '${label}' not found`);
|
|
@@ -724,7 +752,7 @@ var queue = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
724
752
|
);
|
|
725
753
|
return new import_neko_queue2.QueueConnection(provider);
|
|
726
754
|
});
|
|
727
|
-
var cache = (0,
|
|
755
|
+
var cache = (0, import_neko_helper3.createSingleton)((label) => {
|
|
728
756
|
const cache_config = import_neko_config.config.get(["caches", label].join("."));
|
|
729
757
|
if (!cache_config) {
|
|
730
758
|
throw new Error(`Cache configuration for '${label}' not found`);
|
|
@@ -799,144 +827,155 @@ var config_exports = {};
|
|
|
799
827
|
__reExport(config_exports, require("@devbro/neko-config"));
|
|
800
828
|
|
|
801
829
|
// src/app/console/generate/GenerateApiDocsCommand.mts
|
|
802
|
-
var
|
|
830
|
+
var import_neko_helper4 = require("@devbro/neko-helper");
|
|
803
831
|
var GenerateApiDocsCommand = class extends import_clipanion3.Command {
|
|
804
832
|
static {
|
|
805
833
|
__name(this, "GenerateApiDocsCommand");
|
|
806
834
|
}
|
|
807
|
-
static paths = [
|
|
808
|
-
[`make`, `apidocs`],
|
|
809
|
-
[`generate`, `apidocs`]
|
|
810
|
-
];
|
|
835
|
+
static paths = [[`generate`, `apidocsv2`]];
|
|
811
836
|
static usage = import_clipanion3.Command.Usage({
|
|
812
837
|
category: `Generate`,
|
|
813
838
|
description: `Generate OpenAPI documentation from routes`,
|
|
814
839
|
details: `
|
|
815
|
-
This command generates OpenAPI 3.0 specification documentation by analyzing
|
|
840
|
+
This command utility generates OpenAPI 3.0 specification documentation by analyzing
|
|
816
841
|
your application's routes and merging with example files.
|
|
817
842
|
|
|
818
|
-
|
|
819
|
-
-
|
|
820
|
-
-
|
|
821
|
-
-
|
|
822
|
-
- Response schemas
|
|
823
|
-
|
|
824
|
-
The command will merge files specified in config.api_docs.merge_files
|
|
825
|
-
and output the final documentation to config.api_docs.output.
|
|
843
|
+
Subcommands:
|
|
844
|
+
- generate-from-routes: Generate OpenAPI spec from registered routes
|
|
845
|
+
- generate-base: Generate base OpenAPI specification structure
|
|
846
|
+
- merge-files: Merge multiple OpenAPI files into final documentation
|
|
826
847
|
|
|
848
|
+
|
|
827
849
|
This command depends on config data. make sure your default config contains the following:
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
850
|
+
|
|
851
|
+
\`\`\`
|
|
852
|
+
api_docs: {
|
|
853
|
+
|
|
854
|
+
merge_files: [
|
|
855
|
+
|
|
856
|
+
path.join(__dirname, '../..', 'private', 'openapi_base.json'),
|
|
857
|
+
|
|
858
|
+
path.join(__dirname, '../..', 'private', 'openapi_from_routes.json'),
|
|
859
|
+
|
|
860
|
+
path.join(__dirname, '../..', 'private', 'openapi_from_tests.json'),
|
|
861
|
+
|
|
862
|
+
path.join(__dirname, '../..', 'private', 'openapi_other_user_changes.json'),
|
|
863
|
+
|
|
864
|
+
],
|
|
865
|
+
|
|
866
|
+
output: path.join(__dirname, '../..', 'public', 'openapi.json'),
|
|
867
|
+
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
\`\`\`
|
|
836
871
|
`,
|
|
837
|
-
examples: [
|
|
872
|
+
examples: [
|
|
873
|
+
[
|
|
874
|
+
`Generate from routes`,
|
|
875
|
+
`$0 generate apidocsv2 generate-from-routes --output path/to/output.json`
|
|
876
|
+
],
|
|
877
|
+
[
|
|
878
|
+
`Generate base spec`,
|
|
879
|
+
`$0 generate apidocsv2 generate-base --output path/to/output.json`
|
|
880
|
+
],
|
|
881
|
+
[`Merge files`, `$0 generate apidocsv2 merge-files`],
|
|
882
|
+
[`Show help`, `$0 generate apidocsv2 --help`]
|
|
883
|
+
]
|
|
884
|
+
});
|
|
885
|
+
subcommand = import_clipanion3.Option.String({ required: false });
|
|
886
|
+
output = import_clipanion3.Option.String(`--output,-o`, {
|
|
887
|
+
description: `Output file path for generated documentation`
|
|
838
888
|
});
|
|
839
|
-
|
|
840
|
-
description: `
|
|
889
|
+
config = import_clipanion3.Option.String(`--config,-c`, {
|
|
890
|
+
description: `Path in config to get details from (default: api_docs)`,
|
|
891
|
+
required: false
|
|
841
892
|
});
|
|
842
893
|
async execute() {
|
|
843
|
-
if (this.
|
|
894
|
+
if (!this.subcommand) {
|
|
844
895
|
this.context.stdout.write(
|
|
845
896
|
this.constructor.usage?.toString() || "No help available\n"
|
|
846
897
|
);
|
|
847
898
|
return 0;
|
|
848
899
|
}
|
|
849
|
-
|
|
850
|
-
|
|
900
|
+
switch (this.subcommand) {
|
|
901
|
+
case "generate-from-routes":
|
|
902
|
+
return await this.executeGenerateFromRoutes();
|
|
903
|
+
case "generate-base":
|
|
904
|
+
return await this.executeGenerateBase();
|
|
905
|
+
case "merge-files":
|
|
906
|
+
return await this.executeMergeFiles();
|
|
907
|
+
default:
|
|
908
|
+
this.context.stderr.write(`Unknown subcommand: ${this.subcommand}
|
|
851
909
|
`);
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
title: "API Documentation",
|
|
857
|
-
version: "1.0.0",
|
|
858
|
-
description: "Auto-generated API documentation"
|
|
859
|
-
},
|
|
860
|
-
servers: [
|
|
861
|
-
{
|
|
862
|
-
url: "/",
|
|
863
|
-
description: "Local server"
|
|
864
|
-
}
|
|
865
|
-
],
|
|
866
|
-
paths: {}
|
|
867
|
-
};
|
|
868
|
-
for (const route of routes) {
|
|
869
|
-
const routePath = route.path;
|
|
870
|
-
const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
|
|
871
|
-
if (!openApiSpec.paths[openApiPath]) {
|
|
872
|
-
openApiSpec.paths[openApiPath] = {};
|
|
873
|
-
}
|
|
874
|
-
for (const method of route.methods) {
|
|
875
|
-
const lowerMethod = method.toLowerCase();
|
|
876
|
-
if (lowerMethod === "head") {
|
|
877
|
-
continue;
|
|
878
|
-
}
|
|
879
|
-
openApiSpec.paths[openApiPath][lowerMethod] = {
|
|
880
|
-
summary: `${method} ${routePath}`,
|
|
881
|
-
description: `Endpoint for ${method} ${routePath}`,
|
|
882
|
-
parameters: this.extractParameters(routePath),
|
|
883
|
-
responses: {
|
|
884
|
-
"200": {
|
|
885
|
-
description: "Successful response",
|
|
886
|
-
content: {
|
|
887
|
-
"application/json": {
|
|
888
|
-
schema: {
|
|
889
|
-
type: "object"
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
},
|
|
894
|
-
"500": {
|
|
895
|
-
description: "Internal server error"
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
};
|
|
899
|
-
if (["post", "put", "patch"].includes(lowerMethod)) {
|
|
900
|
-
openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
|
|
901
|
-
required: true,
|
|
902
|
-
content: {
|
|
903
|
-
"application/json": {
|
|
904
|
-
schema: {
|
|
905
|
-
type: "object"
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
}
|
|
910
|
+
this.context.stdout.write(
|
|
911
|
+
this.constructor.usage?.toString() || "No help available\n"
|
|
912
|
+
);
|
|
913
|
+
return 1;
|
|
912
914
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
+
}
|
|
916
|
+
async executeGenerateFromRoutes() {
|
|
917
|
+
this.context.stdout.write(
|
|
918
|
+
`Generating OpenAPI documentation from routes...
|
|
919
|
+
`
|
|
920
|
+
);
|
|
921
|
+
const openApiSpec = this.generateFromRoutes();
|
|
922
|
+
const outputPath = this.output || import_path3.default.join(config_exports.config.get("private_path"), "openapi_from_routes.json");
|
|
923
|
+
await fs2.mkdir(import_path3.default.dirname(outputPath), { recursive: true });
|
|
915
924
|
await fs2.writeFile(
|
|
916
925
|
outputPath,
|
|
917
926
|
JSON.stringify(openApiSpec, null, 2),
|
|
918
927
|
"utf-8"
|
|
919
928
|
);
|
|
920
929
|
this.context.stdout.write(
|
|
921
|
-
`OpenAPI documentation generated at: ${outputPath}
|
|
930
|
+
`OpenAPI routes documentation generated at: ${outputPath}
|
|
931
|
+
`
|
|
932
|
+
);
|
|
933
|
+
this.context.stdout.write(
|
|
934
|
+
`Total routes documented: ${Object.keys(openApiSpec.paths).length}
|
|
935
|
+
`
|
|
936
|
+
);
|
|
937
|
+
return 0;
|
|
938
|
+
}
|
|
939
|
+
async executeGenerateBase() {
|
|
940
|
+
this.context.stdout.write(`Generating base OpenAPI specification...
|
|
941
|
+
`);
|
|
942
|
+
const baseSpec = this.getBaseOpenApiSpec();
|
|
943
|
+
const outputPath = this.output || import_path3.default.join(config_exports.config.get("private_path"), "openapi_base.json");
|
|
944
|
+
await fs2.mkdir(import_path3.default.dirname(outputPath), { recursive: true });
|
|
945
|
+
await fs2.writeFile(outputPath, JSON.stringify(baseSpec, null, 2), "utf-8");
|
|
946
|
+
this.context.stdout.write(
|
|
947
|
+
`Base OpenAPI specification generated at: ${outputPath}
|
|
922
948
|
`
|
|
923
949
|
);
|
|
924
|
-
|
|
950
|
+
return 0;
|
|
951
|
+
}
|
|
952
|
+
async executeMergeFiles() {
|
|
953
|
+
this.context.stdout.write(`Merging OpenAPI files...
|
|
925
954
|
`);
|
|
926
|
-
let
|
|
955
|
+
let configPath = this.config || "api_docs";
|
|
956
|
+
const files_to_merge = config_exports.config.get(`${configPath}.merge_files`);
|
|
927
957
|
let final_api_docs = {};
|
|
928
|
-
for (
|
|
929
|
-
|
|
930
|
-
|
|
958
|
+
for (const file_path of files_to_merge) {
|
|
959
|
+
try {
|
|
960
|
+
const file_json = JSON.parse(await fs2.readFile(file_path, "utf8"));
|
|
961
|
+
final_api_docs = import_neko_helper4.Arr.deepMerge(final_api_docs, file_json);
|
|
962
|
+
this.context.stdout.write(` Merged: ${file_path}
|
|
963
|
+
`);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
this.context.stderr.write(
|
|
966
|
+
` Warning: Could not read ${file_path}: ${error.message}
|
|
967
|
+
`
|
|
968
|
+
);
|
|
969
|
+
}
|
|
931
970
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
);
|
|
971
|
+
const outputPath = this.output || config_exports.config.get(`${configPath}.output`);
|
|
972
|
+
await fs2.mkdir(import_path3.default.dirname(outputPath), { recursive: true });
|
|
973
|
+
await fs2.writeFile(outputPath, JSON.stringify(final_api_docs, null, 2));
|
|
936
974
|
this.context.stdout.write(
|
|
937
|
-
`
|
|
975
|
+
`Final OpenAPI document written to: ${outputPath}
|
|
938
976
|
`
|
|
939
977
|
);
|
|
978
|
+
return 0;
|
|
940
979
|
}
|
|
941
980
|
extractParameters(routePath) {
|
|
942
981
|
const paramRegex = /:([a-zA-Z0-9_]+)/g;
|
|
@@ -955,6 +994,78 @@ var GenerateApiDocsCommand = class extends import_clipanion3.Command {
|
|
|
955
994
|
}
|
|
956
995
|
return parameters;
|
|
957
996
|
}
|
|
997
|
+
generateFromRoutes() {
|
|
998
|
+
const openApiSpec = {
|
|
999
|
+
paths: {}
|
|
1000
|
+
};
|
|
1001
|
+
const routes = router().routes;
|
|
1002
|
+
for (const route of routes) {
|
|
1003
|
+
const routePath = route.path;
|
|
1004
|
+
const openApiPath = routePath.replace(/\/$/g, "");
|
|
1005
|
+
if (!openApiSpec.paths[openApiPath]) {
|
|
1006
|
+
openApiSpec.paths[openApiPath] = {};
|
|
1007
|
+
}
|
|
1008
|
+
for (const method of route.methods) {
|
|
1009
|
+
const lowerMethod = method.toLowerCase();
|
|
1010
|
+
if (lowerMethod === "head") {
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
openApiSpec.paths[openApiPath][lowerMethod] = {
|
|
1014
|
+
summary: `${routePath}`,
|
|
1015
|
+
description: `Endpoint for ${method} ${routePath}`,
|
|
1016
|
+
security: [],
|
|
1017
|
+
parameters: this.extractParameters(routePath),
|
|
1018
|
+
responses: {}
|
|
1019
|
+
};
|
|
1020
|
+
if (["post", "put", "patch"].includes(lowerMethod)) {
|
|
1021
|
+
openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
|
|
1022
|
+
required: true,
|
|
1023
|
+
content: {
|
|
1024
|
+
"application/json": {
|
|
1025
|
+
schema: {
|
|
1026
|
+
type: "object"
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
return openApiSpec;
|
|
1035
|
+
}
|
|
1036
|
+
getBaseOpenApiSpec() {
|
|
1037
|
+
const openApiSpec = {
|
|
1038
|
+
openapi: "3.0.0",
|
|
1039
|
+
info: {
|
|
1040
|
+
title: "API Documentation",
|
|
1041
|
+
version: "1.0.0",
|
|
1042
|
+
description: "Auto-generated API documentation"
|
|
1043
|
+
},
|
|
1044
|
+
servers: [
|
|
1045
|
+
{
|
|
1046
|
+
url: "/",
|
|
1047
|
+
description: "Local server"
|
|
1048
|
+
}
|
|
1049
|
+
],
|
|
1050
|
+
components: {
|
|
1051
|
+
securitySchemes: {
|
|
1052
|
+
bearerAuth: {
|
|
1053
|
+
type: "http",
|
|
1054
|
+
scheme: "bearer",
|
|
1055
|
+
bearerFormat: "JWT",
|
|
1056
|
+
description: "JWT token authentication"
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
security: [
|
|
1061
|
+
{
|
|
1062
|
+
bearerAuth: []
|
|
1063
|
+
}
|
|
1064
|
+
],
|
|
1065
|
+
paths: {}
|
|
1066
|
+
};
|
|
1067
|
+
return openApiSpec;
|
|
1068
|
+
}
|
|
958
1069
|
};
|
|
959
1070
|
cli().register(GenerateApiDocsCommand);
|
|
960
1071
|
// Annotate the CommonJS export names for ESM import in node:
|