@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
|
@@ -1241,6 +1241,7 @@ var MiddlewareFactory = class {
|
|
|
1241
1241
|
};
|
|
1242
1242
|
|
|
1243
1243
|
// ../neko-router/dist/CompiledRoute.mjs
|
|
1244
|
+
var import_neko_helper = require("@devbro/neko-helper");
|
|
1244
1245
|
var CompiledRoute = class {
|
|
1245
1246
|
static {
|
|
1246
1247
|
__name(this, "CompiledRoute");
|
|
@@ -1261,7 +1262,7 @@ var CompiledRoute = class {
|
|
|
1261
1262
|
for (const middleware of [...this.globalMiddlewares, ...this.route.getMiddlewares()]) {
|
|
1262
1263
|
if (middleware instanceof Middleware) {
|
|
1263
1264
|
this.middlewares.push(middleware);
|
|
1264
|
-
} else if (
|
|
1265
|
+
} else if ((0, import_neko_helper.isClass)(middleware)) {
|
|
1265
1266
|
this.middlewares.push(middleware.getInstance({}));
|
|
1266
1267
|
} else if (typeof middleware === "function") {
|
|
1267
1268
|
this.middlewares.push(MiddlewareFactory.create(middleware));
|
|
@@ -1270,9 +1271,6 @@ var CompiledRoute = class {
|
|
|
1270
1271
|
}
|
|
1271
1272
|
}
|
|
1272
1273
|
}
|
|
1273
|
-
isClass(func) {
|
|
1274
|
-
return typeof func === "function" && /^class\s/.test(Function.prototype.toString.call(func));
|
|
1275
|
-
}
|
|
1276
1274
|
async run() {
|
|
1277
1275
|
return await this.runMiddlewares(this.middlewares, this.request, this.response);
|
|
1278
1276
|
}
|
|
@@ -1408,7 +1406,7 @@ var Route = class {
|
|
|
1408
1406
|
i = start;
|
|
1409
1407
|
} else if (char === "*") {
|
|
1410
1408
|
let start = i + 1;
|
|
1411
|
-
while (start < path10.length && /[a-zA-Z0-9_
|
|
1409
|
+
while (start < path10.length && /[a-zA-Z0-9_]/.test(path10[start])) {
|
|
1412
1410
|
start++;
|
|
1413
1411
|
}
|
|
1414
1412
|
tokens.push({ type: "WILDCARD", value: path10.slice(i + 1, start) });
|
|
@@ -1619,7 +1617,7 @@ var Router = class {
|
|
|
1619
1617
|
|
|
1620
1618
|
// src/facades.mts
|
|
1621
1619
|
var import_neko_scheduler = require("@devbro/neko-scheduler");
|
|
1622
|
-
var
|
|
1620
|
+
var import_neko_helper3 = require("@devbro/neko-helper");
|
|
1623
1621
|
var import_neko_context3 = require("@devbro/neko-context");
|
|
1624
1622
|
var import_neko_storage2 = require("@devbro/neko-storage");
|
|
1625
1623
|
var import_neko_mailer2 = require("@devbro/neko-mailer");
|
|
@@ -1660,7 +1658,7 @@ __export(queue_exports, {
|
|
|
1660
1658
|
DatabaseTransport: () => DatabaseTransport
|
|
1661
1659
|
});
|
|
1662
1660
|
__reExport(queue_exports, require("@devbro/neko-queue"));
|
|
1663
|
-
var
|
|
1661
|
+
var import_neko_helper2 = require("@devbro/neko-helper");
|
|
1664
1662
|
var import_neko_context2 = require("@devbro/neko-context");
|
|
1665
1663
|
var DatabaseTransport = class {
|
|
1666
1664
|
static {
|
|
@@ -1721,7 +1719,7 @@ var DatabaseTransport = class {
|
|
|
1721
1719
|
}, "processMessage");
|
|
1722
1720
|
constructor(config9 = {}) {
|
|
1723
1721
|
this.config = { ...this.config, ...config9 };
|
|
1724
|
-
this.repeater = (0,
|
|
1722
|
+
this.repeater = (0, import_neko_helper2.createRepeater)(
|
|
1725
1723
|
this.processMessage,
|
|
1726
1724
|
this.config.listen_interval * 1e3
|
|
1727
1725
|
);
|
|
@@ -1789,6 +1787,24 @@ import_neko_queue.QueueTransportFactory.register("database", (opt) => {
|
|
|
1789
1787
|
import_neko_queue.QueueTransportFactory.register("memory", (opt) => {
|
|
1790
1788
|
return new import_neko_queue.MemoryTransport(opt);
|
|
1791
1789
|
});
|
|
1790
|
+
import_neko_queue.QueueTransportFactory.register("sqs", (opt) => {
|
|
1791
|
+
return new import_neko_queue.AwsSqsTransport(opt);
|
|
1792
|
+
});
|
|
1793
|
+
import_neko_queue.QueueTransportFactory.register("amqp", (opt) => {
|
|
1794
|
+
return new import_neko_queue.AmqpTransport(opt);
|
|
1795
|
+
});
|
|
1796
|
+
import_neko_queue.QueueTransportFactory.register("redis", (opt) => {
|
|
1797
|
+
return new import_neko_queue.RedisTransport(opt);
|
|
1798
|
+
});
|
|
1799
|
+
import_neko_queue.QueueTransportFactory.register("async", (opt) => {
|
|
1800
|
+
return new import_neko_queue.AsyncTransport();
|
|
1801
|
+
});
|
|
1802
|
+
import_neko_queue.QueueTransportFactory.register("azure_service_bus", (opt) => {
|
|
1803
|
+
return new import_neko_queue.AzureServiceBusTransport(opt);
|
|
1804
|
+
});
|
|
1805
|
+
import_neko_queue.QueueTransportFactory.register("google_pubsub", (opt) => {
|
|
1806
|
+
return new import_neko_queue.GooglePubSubTransport(opt);
|
|
1807
|
+
});
|
|
1792
1808
|
var CacheProviderFactory = class _CacheProviderFactory {
|
|
1793
1809
|
static {
|
|
1794
1810
|
__name(this, "CacheProviderFactory");
|
|
@@ -1819,12 +1835,24 @@ import_neko_storage.StorageProviderFactory.register("local", (opt) => {
|
|
|
1819
1835
|
import_neko_storage.StorageProviderFactory.register("s3", (opt) => {
|
|
1820
1836
|
return new import_neko_storage.AWSS3StorageProvider(opt);
|
|
1821
1837
|
});
|
|
1838
|
+
import_neko_storage.StorageProviderFactory.register("gcp", (opt) => {
|
|
1839
|
+
return new import_neko_storage.GCPStorageProvider(opt);
|
|
1840
|
+
});
|
|
1841
|
+
import_neko_storage.StorageProviderFactory.register("azure", (opt) => {
|
|
1842
|
+
return new import_neko_storage.AzureBlobStorageProvider(opt);
|
|
1843
|
+
});
|
|
1844
|
+
import_neko_storage.StorageProviderFactory.register("ftp", (opt) => {
|
|
1845
|
+
return new import_neko_storage.FTPStorageProvider(opt);
|
|
1846
|
+
});
|
|
1847
|
+
import_neko_storage.StorageProviderFactory.register("sftp", (opt) => {
|
|
1848
|
+
return new import_neko_storage.SFTPStorageProvider(opt);
|
|
1849
|
+
});
|
|
1822
1850
|
|
|
1823
1851
|
// src/facades.mts
|
|
1824
1852
|
var import_neko_cache2 = require("@devbro/neko-cache");
|
|
1825
1853
|
var import_neko_queue2 = require("@devbro/neko-queue");
|
|
1826
|
-
var router = (0,
|
|
1827
|
-
var scheduler = (0,
|
|
1854
|
+
var router = (0, import_neko_helper3.createSingleton)(() => new Router());
|
|
1855
|
+
var scheduler = (0, import_neko_helper3.createSingleton)(() => {
|
|
1828
1856
|
const rc = new import_neko_scheduler.Scheduler();
|
|
1829
1857
|
rc.setErrorHandler((err, job) => {
|
|
1830
1858
|
logger().error({
|
|
@@ -1836,7 +1864,7 @@ var scheduler = (0, import_neko_helper2.createSingleton)(() => {
|
|
|
1836
1864
|
return rc;
|
|
1837
1865
|
});
|
|
1838
1866
|
var db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context3.ctx)().getOrThrow(["database", label]), "db");
|
|
1839
|
-
var storage = (0,
|
|
1867
|
+
var storage = (0, import_neko_helper3.createSingleton)((label = "default") => {
|
|
1840
1868
|
let storage_config = import_neko_config.config.get(["storages", label].join("."));
|
|
1841
1869
|
const provider = import_neko_storage2.StorageProviderFactory.create(
|
|
1842
1870
|
storage_config.provider,
|
|
@@ -1844,7 +1872,7 @@ var storage = (0, import_neko_helper2.createSingleton)((label = "default") => {
|
|
|
1844
1872
|
);
|
|
1845
1873
|
return new import_neko_storage2.Storage(provider);
|
|
1846
1874
|
});
|
|
1847
|
-
var cli = (0,
|
|
1875
|
+
var cli = (0, import_neko_helper3.createSingleton)(() => {
|
|
1848
1876
|
const [node, app, ...args] = process.argv;
|
|
1849
1877
|
return new import_clipanion.Cli({
|
|
1850
1878
|
binaryLabel: `My Application`,
|
|
@@ -1852,13 +1880,13 @@ var cli = (0, import_neko_helper2.createSingleton)(() => {
|
|
|
1852
1880
|
binaryVersion: `1.0.0`
|
|
1853
1881
|
});
|
|
1854
1882
|
});
|
|
1855
|
-
var httpServer = (0,
|
|
1883
|
+
var httpServer = (0, import_neko_helper3.createSingleton)(() => {
|
|
1856
1884
|
const server = new http_exports.HttpServer();
|
|
1857
1885
|
server.setErrorHandler(handleHttpErrors);
|
|
1858
1886
|
server.setRouter(router());
|
|
1859
1887
|
return server;
|
|
1860
1888
|
});
|
|
1861
|
-
var logger = (0,
|
|
1889
|
+
var logger = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1862
1890
|
const logger_config = import_neko_config.config.get(["loggers", label].join("."));
|
|
1863
1891
|
const rc = new import_neko_logger.Logger(logger_config);
|
|
1864
1892
|
rc.setExtrasFunction((message) => {
|
|
@@ -1867,7 +1895,7 @@ var logger = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
1867
1895
|
});
|
|
1868
1896
|
return rc;
|
|
1869
1897
|
});
|
|
1870
|
-
var mailer = (0,
|
|
1898
|
+
var mailer = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1871
1899
|
const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
|
|
1872
1900
|
const provider = import_neko_mailer2.MailerProviderFactory.create(
|
|
1873
1901
|
mailer_config.provider,
|
|
@@ -1876,7 +1904,7 @@ var mailer = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
1876
1904
|
const rc = new import_neko_mailer2.Mailer(provider);
|
|
1877
1905
|
return rc;
|
|
1878
1906
|
});
|
|
1879
|
-
var queue = (0,
|
|
1907
|
+
var queue = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1880
1908
|
const queue_config = import_neko_config.config.get(["queues", label].join("."));
|
|
1881
1909
|
if (!queue_config) {
|
|
1882
1910
|
throw new Error(`Queue configuration for '${label}' not found`);
|
|
@@ -1887,7 +1915,7 @@ var queue = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
1887
1915
|
);
|
|
1888
1916
|
return new import_neko_queue2.QueueConnection(provider);
|
|
1889
1917
|
});
|
|
1890
|
-
var cache = (0,
|
|
1918
|
+
var cache = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1891
1919
|
const cache_config = import_neko_config.config.get(["caches", label].join("."));
|
|
1892
1920
|
if (!cache_config) {
|
|
1893
1921
|
throw new Error(`Cache configuration for '${label}' not found`);
|
|
@@ -2112,12 +2140,15 @@ var StartCommand = class extends import_clipanion5.Command {
|
|
|
2112
2140
|
__name(this, "StartCommand");
|
|
2113
2141
|
}
|
|
2114
2142
|
scheduler = import_clipanion5.Option.Boolean(`--scheduler`, false);
|
|
2143
|
+
cron = import_clipanion5.Option.Boolean(`--cron`, false);
|
|
2115
2144
|
http = import_clipanion5.Option.Boolean(`--http`, false);
|
|
2116
2145
|
queue = import_clipanion5.Option.Boolean(`--queue`, false);
|
|
2117
2146
|
all = import_clipanion5.Option.Boolean("--all", false);
|
|
2118
2147
|
static paths = [[`start`]];
|
|
2119
2148
|
async execute() {
|
|
2120
|
-
if ([this.all, this.http, this.scheduler, this.queue].filter(
|
|
2149
|
+
if ([this.all, this.http, this.scheduler || this.cron, this.queue].filter(
|
|
2150
|
+
(x) => x
|
|
2151
|
+
).length == 0) {
|
|
2121
2152
|
this.context.stdout.write(
|
|
2122
2153
|
`No service was selected. please check -h for details
|
|
2123
2154
|
`
|
|
@@ -2127,7 +2158,7 @@ var StartCommand = class extends import_clipanion5.Command {
|
|
|
2127
2158
|
logger().info(`Starting Server
|
|
2128
2159
|
`);
|
|
2129
2160
|
import_neko_sql.PostgresqlConnection.defaults.idleTimeoutMillis = 1e4;
|
|
2130
|
-
if (this.scheduler || this.all) {
|
|
2161
|
+
if (this.scheduler || this.cron || this.all) {
|
|
2131
2162
|
logger().info(`starting scheduler
|
|
2132
2163
|
`);
|
|
2133
2164
|
scheduler().start();
|
|
@@ -2325,144 +2356,155 @@ var config_exports = {};
|
|
|
2325
2356
|
__reExport(config_exports, require("@devbro/neko-config"));
|
|
2326
2357
|
|
|
2327
2358
|
// src/app/console/generate/GenerateApiDocsCommand.mts
|
|
2328
|
-
var
|
|
2359
|
+
var import_neko_helper4 = require("@devbro/neko-helper");
|
|
2329
2360
|
var GenerateApiDocsCommand = class extends import_clipanion9.Command {
|
|
2330
2361
|
static {
|
|
2331
2362
|
__name(this, "GenerateApiDocsCommand");
|
|
2332
2363
|
}
|
|
2333
|
-
static paths = [
|
|
2334
|
-
[`make`, `apidocs`],
|
|
2335
|
-
[`generate`, `apidocs`]
|
|
2336
|
-
];
|
|
2364
|
+
static paths = [[`generate`, `apidocsv2`]];
|
|
2337
2365
|
static usage = import_clipanion9.Command.Usage({
|
|
2338
2366
|
category: `Generate`,
|
|
2339
2367
|
description: `Generate OpenAPI documentation from routes`,
|
|
2340
2368
|
details: `
|
|
2341
|
-
This command generates OpenAPI 3.0 specification documentation by analyzing
|
|
2369
|
+
This command utility generates OpenAPI 3.0 specification documentation by analyzing
|
|
2342
2370
|
your application's routes and merging with example files.
|
|
2343
2371
|
|
|
2344
|
-
|
|
2345
|
-
-
|
|
2346
|
-
-
|
|
2347
|
-
-
|
|
2348
|
-
- Response schemas
|
|
2349
|
-
|
|
2350
|
-
The command will merge files specified in config.api_docs.merge_files
|
|
2351
|
-
and output the final documentation to config.api_docs.output.
|
|
2372
|
+
Subcommands:
|
|
2373
|
+
- generate-from-routes: Generate OpenAPI spec from registered routes
|
|
2374
|
+
- generate-base: Generate base OpenAPI specification structure
|
|
2375
|
+
- merge-files: Merge multiple OpenAPI files into final documentation
|
|
2352
2376
|
|
|
2377
|
+
|
|
2353
2378
|
This command depends on config data. make sure your default config contains the following:
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2379
|
+
|
|
2380
|
+
\`\`\`
|
|
2381
|
+
api_docs: {
|
|
2382
|
+
|
|
2383
|
+
merge_files: [
|
|
2384
|
+
|
|
2385
|
+
path.join(__dirname, '../..', 'private', 'openapi_base.json'),
|
|
2386
|
+
|
|
2387
|
+
path.join(__dirname, '../..', 'private', 'openapi_from_routes.json'),
|
|
2388
|
+
|
|
2389
|
+
path.join(__dirname, '../..', 'private', 'openapi_from_tests.json'),
|
|
2390
|
+
|
|
2391
|
+
path.join(__dirname, '../..', 'private', 'openapi_other_user_changes.json'),
|
|
2392
|
+
|
|
2393
|
+
],
|
|
2394
|
+
|
|
2395
|
+
output: path.join(__dirname, '../..', 'public', 'openapi.json'),
|
|
2396
|
+
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
\`\`\`
|
|
2362
2400
|
`,
|
|
2363
|
-
examples: [
|
|
2401
|
+
examples: [
|
|
2402
|
+
[
|
|
2403
|
+
`Generate from routes`,
|
|
2404
|
+
`$0 generate apidocsv2 generate-from-routes --output path/to/output.json`
|
|
2405
|
+
],
|
|
2406
|
+
[
|
|
2407
|
+
`Generate base spec`,
|
|
2408
|
+
`$0 generate apidocsv2 generate-base --output path/to/output.json`
|
|
2409
|
+
],
|
|
2410
|
+
[`Merge files`, `$0 generate apidocsv2 merge-files`],
|
|
2411
|
+
[`Show help`, `$0 generate apidocsv2 --help`]
|
|
2412
|
+
]
|
|
2364
2413
|
});
|
|
2365
|
-
|
|
2366
|
-
|
|
2414
|
+
subcommand = import_clipanion9.Option.String({ required: false });
|
|
2415
|
+
output = import_clipanion9.Option.String(`--output,-o`, {
|
|
2416
|
+
description: `Output file path for generated documentation`
|
|
2417
|
+
});
|
|
2418
|
+
config = import_clipanion9.Option.String(`--config,-c`, {
|
|
2419
|
+
description: `Path in config to get details from (default: api_docs)`,
|
|
2420
|
+
required: false
|
|
2367
2421
|
});
|
|
2368
2422
|
async execute() {
|
|
2369
|
-
if (this.
|
|
2423
|
+
if (!this.subcommand) {
|
|
2370
2424
|
this.context.stdout.write(
|
|
2371
2425
|
this.constructor.usage?.toString() || "No help available\n"
|
|
2372
2426
|
);
|
|
2373
2427
|
return 0;
|
|
2374
2428
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2429
|
+
switch (this.subcommand) {
|
|
2430
|
+
case "generate-from-routes":
|
|
2431
|
+
return await this.executeGenerateFromRoutes();
|
|
2432
|
+
case "generate-base":
|
|
2433
|
+
return await this.executeGenerateBase();
|
|
2434
|
+
case "merge-files":
|
|
2435
|
+
return await this.executeMergeFiles();
|
|
2436
|
+
default:
|
|
2437
|
+
this.context.stderr.write(`Unknown subcommand: ${this.subcommand}
|
|
2377
2438
|
`);
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
title: "API Documentation",
|
|
2383
|
-
version: "1.0.0",
|
|
2384
|
-
description: "Auto-generated API documentation"
|
|
2385
|
-
},
|
|
2386
|
-
servers: [
|
|
2387
|
-
{
|
|
2388
|
-
url: "/",
|
|
2389
|
-
description: "Local server"
|
|
2390
|
-
}
|
|
2391
|
-
],
|
|
2392
|
-
paths: {}
|
|
2393
|
-
};
|
|
2394
|
-
for (const route of routes) {
|
|
2395
|
-
const routePath = route.path;
|
|
2396
|
-
const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
|
|
2397
|
-
if (!openApiSpec.paths[openApiPath]) {
|
|
2398
|
-
openApiSpec.paths[openApiPath] = {};
|
|
2399
|
-
}
|
|
2400
|
-
for (const method of route.methods) {
|
|
2401
|
-
const lowerMethod = method.toLowerCase();
|
|
2402
|
-
if (lowerMethod === "head") {
|
|
2403
|
-
continue;
|
|
2404
|
-
}
|
|
2405
|
-
openApiSpec.paths[openApiPath][lowerMethod] = {
|
|
2406
|
-
summary: `${method} ${routePath}`,
|
|
2407
|
-
description: `Endpoint for ${method} ${routePath}`,
|
|
2408
|
-
parameters: this.extractParameters(routePath),
|
|
2409
|
-
responses: {
|
|
2410
|
-
"200": {
|
|
2411
|
-
description: "Successful response",
|
|
2412
|
-
content: {
|
|
2413
|
-
"application/json": {
|
|
2414
|
-
schema: {
|
|
2415
|
-
type: "object"
|
|
2416
|
-
}
|
|
2417
|
-
}
|
|
2418
|
-
}
|
|
2419
|
-
},
|
|
2420
|
-
"500": {
|
|
2421
|
-
description: "Internal server error"
|
|
2422
|
-
}
|
|
2423
|
-
}
|
|
2424
|
-
};
|
|
2425
|
-
if (["post", "put", "patch"].includes(lowerMethod)) {
|
|
2426
|
-
openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
|
|
2427
|
-
required: true,
|
|
2428
|
-
content: {
|
|
2429
|
-
"application/json": {
|
|
2430
|
-
schema: {
|
|
2431
|
-
type: "object"
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
};
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2439
|
+
this.context.stdout.write(
|
|
2440
|
+
this.constructor.usage?.toString() || "No help available\n"
|
|
2441
|
+
);
|
|
2442
|
+
return 1;
|
|
2438
2443
|
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2444
|
+
}
|
|
2445
|
+
async executeGenerateFromRoutes() {
|
|
2446
|
+
this.context.stdout.write(
|
|
2447
|
+
`Generating OpenAPI documentation from routes...
|
|
2448
|
+
`
|
|
2449
|
+
);
|
|
2450
|
+
const openApiSpec = this.generateFromRoutes();
|
|
2451
|
+
const outputPath = this.output || import_path7.default.join(config_exports.config.get("private_path"), "openapi_from_routes.json");
|
|
2452
|
+
await fs6.mkdir(import_path7.default.dirname(outputPath), { recursive: true });
|
|
2441
2453
|
await fs6.writeFile(
|
|
2442
2454
|
outputPath,
|
|
2443
2455
|
JSON.stringify(openApiSpec, null, 2),
|
|
2444
2456
|
"utf-8"
|
|
2445
2457
|
);
|
|
2446
2458
|
this.context.stdout.write(
|
|
2447
|
-
`OpenAPI documentation generated at: ${outputPath}
|
|
2459
|
+
`OpenAPI routes documentation generated at: ${outputPath}
|
|
2460
|
+
`
|
|
2461
|
+
);
|
|
2462
|
+
this.context.stdout.write(
|
|
2463
|
+
`Total routes documented: ${Object.keys(openApiSpec.paths).length}
|
|
2464
|
+
`
|
|
2465
|
+
);
|
|
2466
|
+
return 0;
|
|
2467
|
+
}
|
|
2468
|
+
async executeGenerateBase() {
|
|
2469
|
+
this.context.stdout.write(`Generating base OpenAPI specification...
|
|
2470
|
+
`);
|
|
2471
|
+
const baseSpec = this.getBaseOpenApiSpec();
|
|
2472
|
+
const outputPath = this.output || import_path7.default.join(config_exports.config.get("private_path"), "openapi_base.json");
|
|
2473
|
+
await fs6.mkdir(import_path7.default.dirname(outputPath), { recursive: true });
|
|
2474
|
+
await fs6.writeFile(outputPath, JSON.stringify(baseSpec, null, 2), "utf-8");
|
|
2475
|
+
this.context.stdout.write(
|
|
2476
|
+
`Base OpenAPI specification generated at: ${outputPath}
|
|
2448
2477
|
`
|
|
2449
2478
|
);
|
|
2450
|
-
|
|
2479
|
+
return 0;
|
|
2480
|
+
}
|
|
2481
|
+
async executeMergeFiles() {
|
|
2482
|
+
this.context.stdout.write(`Merging OpenAPI files...
|
|
2451
2483
|
`);
|
|
2452
|
-
let
|
|
2484
|
+
let configPath = this.config || "api_docs";
|
|
2485
|
+
const files_to_merge = config_exports.config.get(`${configPath}.merge_files`);
|
|
2453
2486
|
let final_api_docs = {};
|
|
2454
|
-
for (
|
|
2455
|
-
|
|
2456
|
-
|
|
2487
|
+
for (const file_path of files_to_merge) {
|
|
2488
|
+
try {
|
|
2489
|
+
const file_json = JSON.parse(await fs6.readFile(file_path, "utf8"));
|
|
2490
|
+
final_api_docs = import_neko_helper4.Arr.deepMerge(final_api_docs, file_json);
|
|
2491
|
+
this.context.stdout.write(` Merged: ${file_path}
|
|
2492
|
+
`);
|
|
2493
|
+
} catch (error) {
|
|
2494
|
+
this.context.stderr.write(
|
|
2495
|
+
` Warning: Could not read ${file_path}: ${error.message}
|
|
2496
|
+
`
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2457
2499
|
}
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
);
|
|
2500
|
+
const outputPath = this.output || config_exports.config.get(`${configPath}.output`);
|
|
2501
|
+
await fs6.mkdir(import_path7.default.dirname(outputPath), { recursive: true });
|
|
2502
|
+
await fs6.writeFile(outputPath, JSON.stringify(final_api_docs, null, 2));
|
|
2462
2503
|
this.context.stdout.write(
|
|
2463
|
-
`
|
|
2504
|
+
`Final OpenAPI document written to: ${outputPath}
|
|
2464
2505
|
`
|
|
2465
2506
|
);
|
|
2507
|
+
return 0;
|
|
2466
2508
|
}
|
|
2467
2509
|
extractParameters(routePath) {
|
|
2468
2510
|
const paramRegex = /:([a-zA-Z0-9_]+)/g;
|
|
@@ -2481,6 +2523,78 @@ var GenerateApiDocsCommand = class extends import_clipanion9.Command {
|
|
|
2481
2523
|
}
|
|
2482
2524
|
return parameters;
|
|
2483
2525
|
}
|
|
2526
|
+
generateFromRoutes() {
|
|
2527
|
+
const openApiSpec = {
|
|
2528
|
+
paths: {}
|
|
2529
|
+
};
|
|
2530
|
+
const routes = router().routes;
|
|
2531
|
+
for (const route of routes) {
|
|
2532
|
+
const routePath = route.path;
|
|
2533
|
+
const openApiPath = routePath.replace(/\/$/g, "");
|
|
2534
|
+
if (!openApiSpec.paths[openApiPath]) {
|
|
2535
|
+
openApiSpec.paths[openApiPath] = {};
|
|
2536
|
+
}
|
|
2537
|
+
for (const method of route.methods) {
|
|
2538
|
+
const lowerMethod = method.toLowerCase();
|
|
2539
|
+
if (lowerMethod === "head") {
|
|
2540
|
+
continue;
|
|
2541
|
+
}
|
|
2542
|
+
openApiSpec.paths[openApiPath][lowerMethod] = {
|
|
2543
|
+
summary: `${routePath}`,
|
|
2544
|
+
description: `Endpoint for ${method} ${routePath}`,
|
|
2545
|
+
security: [],
|
|
2546
|
+
parameters: this.extractParameters(routePath),
|
|
2547
|
+
responses: {}
|
|
2548
|
+
};
|
|
2549
|
+
if (["post", "put", "patch"].includes(lowerMethod)) {
|
|
2550
|
+
openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
|
|
2551
|
+
required: true,
|
|
2552
|
+
content: {
|
|
2553
|
+
"application/json": {
|
|
2554
|
+
schema: {
|
|
2555
|
+
type: "object"
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
};
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
return openApiSpec;
|
|
2564
|
+
}
|
|
2565
|
+
getBaseOpenApiSpec() {
|
|
2566
|
+
const openApiSpec = {
|
|
2567
|
+
openapi: "3.0.0",
|
|
2568
|
+
info: {
|
|
2569
|
+
title: "API Documentation",
|
|
2570
|
+
version: "1.0.0",
|
|
2571
|
+
description: "Auto-generated API documentation"
|
|
2572
|
+
},
|
|
2573
|
+
servers: [
|
|
2574
|
+
{
|
|
2575
|
+
url: "/",
|
|
2576
|
+
description: "Local server"
|
|
2577
|
+
}
|
|
2578
|
+
],
|
|
2579
|
+
components: {
|
|
2580
|
+
securitySchemes: {
|
|
2581
|
+
bearerAuth: {
|
|
2582
|
+
type: "http",
|
|
2583
|
+
scheme: "bearer",
|
|
2584
|
+
bearerFormat: "JWT",
|
|
2585
|
+
description: "JWT token authentication"
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
},
|
|
2589
|
+
security: [
|
|
2590
|
+
{
|
|
2591
|
+
bearerAuth: []
|
|
2592
|
+
}
|
|
2593
|
+
],
|
|
2594
|
+
paths: {}
|
|
2595
|
+
};
|
|
2596
|
+
return openApiSpec;
|
|
2597
|
+
}
|
|
2484
2598
|
};
|
|
2485
2599
|
cli().register(GenerateApiDocsCommand);
|
|
2486
2600
|
|