@devbro/pashmak 0.1.47 → 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 +64 -32
- package/dist/bin/app/console/KeyGenerateCommand.cjs +64 -32
- package/dist/bin/app/console/StartCommand.cjs +69 -34
- package/dist/bin/app/console/generate/GenerateApiDocsCommand.cjs +248 -133
- package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +64 -32
- package/dist/bin/app/console/generate/index.cjs +248 -133
- package/dist/bin/app/console/index.cjs +253 -135
- package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +64 -32
- package/dist/bin/app/console/migrate/MigrateCommand.cjs +64 -32
- package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +64 -32
- package/dist/bin/app/console/migrate/index.cjs +64 -32
- package/dist/bin/app/console/queue/GenerateQueueMigrateCommand.cjs +64 -32
- package/dist/bin/cache.cjs +64 -32
- package/dist/bin/facades.cjs +64 -32
- package/dist/bin/factories.cjs +64 -32
- package/dist/bin/http.cjs +739 -0
- package/dist/bin/index.cjs +264 -141
- package/dist/bin/middlewares.cjs +66 -34
- package/dist/bin/queue.cjs +64 -32
- package/dist/bin/router.cjs +4 -8
- package/dist/config.d.mts +0 -1
- package/dist/facades.mjs +2 -13
- package/dist/facades.mjs.map +1 -1
- package/dist/factories.mjs +45 -2
- package/dist/factories.mjs.map +1 -1
- package/dist/http.d.mts +4 -0
- package/dist/http.mjs +20 -0
- 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,13 +1271,8 @@ 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
|
-
|
|
1278
|
-
this.response.end();
|
|
1279
|
-
return rc;
|
|
1275
|
+
return await this.runMiddlewares(this.middlewares, this.request, this.response);
|
|
1280
1276
|
}
|
|
1281
1277
|
prepareOutputJsonFormat(obj) {
|
|
1282
1278
|
function traverse(value) {
|
|
@@ -1410,7 +1406,7 @@ var Route = class {
|
|
|
1410
1406
|
i = start;
|
|
1411
1407
|
} else if (char === "*") {
|
|
1412
1408
|
let start = i + 1;
|
|
1413
|
-
while (start < path10.length && /[a-zA-Z0-9_
|
|
1409
|
+
while (start < path10.length && /[a-zA-Z0-9_]/.test(path10[start])) {
|
|
1414
1410
|
start++;
|
|
1415
1411
|
}
|
|
1416
1412
|
tokens.push({ type: "WILDCARD", value: path10.slice(i + 1, start) });
|
|
@@ -1621,7 +1617,7 @@ var Router = class {
|
|
|
1621
1617
|
|
|
1622
1618
|
// src/facades.mts
|
|
1623
1619
|
var import_neko_scheduler = require("@devbro/neko-scheduler");
|
|
1624
|
-
var
|
|
1620
|
+
var import_neko_helper3 = require("@devbro/neko-helper");
|
|
1625
1621
|
var import_neko_context3 = require("@devbro/neko-context");
|
|
1626
1622
|
var import_neko_storage2 = require("@devbro/neko-storage");
|
|
1627
1623
|
var import_neko_mailer2 = require("@devbro/neko-mailer");
|
|
@@ -1630,7 +1626,24 @@ var import_clipanion = require("clipanion");
|
|
|
1630
1626
|
|
|
1631
1627
|
// src/http.mts
|
|
1632
1628
|
var http_exports = {};
|
|
1629
|
+
__export(http_exports, {
|
|
1630
|
+
handleHttpErrors: () => handleHttpErrors
|
|
1631
|
+
});
|
|
1632
|
+
var import_neko_http = require("@devbro/neko-http");
|
|
1633
1633
|
__reExport(http_exports, require("@devbro/neko-http"));
|
|
1634
|
+
async function handleHttpErrors(err, req, res) {
|
|
1635
|
+
if (err instanceof import_neko_http.HttpError) {
|
|
1636
|
+
res.writeHead(err.statusCode, { "Content-Type": "application/json" });
|
|
1637
|
+
res.write(JSON.stringify({ message: err.message, error: err.code }));
|
|
1638
|
+
logger().warn({ msg: "HttpError: " + err.message, err });
|
|
1639
|
+
return;
|
|
1640
|
+
} else {
|
|
1641
|
+
logger().error({ msg: "Error: " + err.message, err });
|
|
1642
|
+
}
|
|
1643
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1644
|
+
res.write(JSON.stringify({ error: "Internal Server Error" }));
|
|
1645
|
+
}
|
|
1646
|
+
__name(handleHttpErrors, "handleHttpErrors");
|
|
1634
1647
|
|
|
1635
1648
|
// src/facades.mts
|
|
1636
1649
|
var import_neko_logger = require("@devbro/neko-logger");
|
|
@@ -1645,7 +1658,7 @@ __export(queue_exports, {
|
|
|
1645
1658
|
DatabaseTransport: () => DatabaseTransport
|
|
1646
1659
|
});
|
|
1647
1660
|
__reExport(queue_exports, require("@devbro/neko-queue"));
|
|
1648
|
-
var
|
|
1661
|
+
var import_neko_helper2 = require("@devbro/neko-helper");
|
|
1649
1662
|
var import_neko_context2 = require("@devbro/neko-context");
|
|
1650
1663
|
var DatabaseTransport = class {
|
|
1651
1664
|
static {
|
|
@@ -1706,7 +1719,7 @@ var DatabaseTransport = class {
|
|
|
1706
1719
|
}, "processMessage");
|
|
1707
1720
|
constructor(config9 = {}) {
|
|
1708
1721
|
this.config = { ...this.config, ...config9 };
|
|
1709
|
-
this.repeater = (0,
|
|
1722
|
+
this.repeater = (0, import_neko_helper2.createRepeater)(
|
|
1710
1723
|
this.processMessage,
|
|
1711
1724
|
this.config.listen_interval * 1e3
|
|
1712
1725
|
);
|
|
@@ -1774,6 +1787,24 @@ import_neko_queue.QueueTransportFactory.register("database", (opt) => {
|
|
|
1774
1787
|
import_neko_queue.QueueTransportFactory.register("memory", (opt) => {
|
|
1775
1788
|
return new import_neko_queue.MemoryTransport(opt);
|
|
1776
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
|
+
});
|
|
1777
1808
|
var CacheProviderFactory = class _CacheProviderFactory {
|
|
1778
1809
|
static {
|
|
1779
1810
|
__name(this, "CacheProviderFactory");
|
|
@@ -1804,12 +1835,24 @@ import_neko_storage.StorageProviderFactory.register("local", (opt) => {
|
|
|
1804
1835
|
import_neko_storage.StorageProviderFactory.register("s3", (opt) => {
|
|
1805
1836
|
return new import_neko_storage.AWSS3StorageProvider(opt);
|
|
1806
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
|
+
});
|
|
1807
1850
|
|
|
1808
1851
|
// src/facades.mts
|
|
1809
1852
|
var import_neko_cache2 = require("@devbro/neko-cache");
|
|
1810
1853
|
var import_neko_queue2 = require("@devbro/neko-queue");
|
|
1811
|
-
var router = (0,
|
|
1812
|
-
var scheduler = (0,
|
|
1854
|
+
var router = (0, import_neko_helper3.createSingleton)(() => new Router());
|
|
1855
|
+
var scheduler = (0, import_neko_helper3.createSingleton)(() => {
|
|
1813
1856
|
const rc = new import_neko_scheduler.Scheduler();
|
|
1814
1857
|
rc.setErrorHandler((err, job) => {
|
|
1815
1858
|
logger().error({
|
|
@@ -1821,7 +1864,7 @@ var scheduler = (0, import_neko_helper2.createSingleton)(() => {
|
|
|
1821
1864
|
return rc;
|
|
1822
1865
|
});
|
|
1823
1866
|
var db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context3.ctx)().getOrThrow(["database", label]), "db");
|
|
1824
|
-
var storage = (0,
|
|
1867
|
+
var storage = (0, import_neko_helper3.createSingleton)((label = "default") => {
|
|
1825
1868
|
let storage_config = import_neko_config.config.get(["storages", label].join("."));
|
|
1826
1869
|
const provider = import_neko_storage2.StorageProviderFactory.create(
|
|
1827
1870
|
storage_config.provider,
|
|
@@ -1829,7 +1872,7 @@ var storage = (0, import_neko_helper2.createSingleton)((label = "default") => {
|
|
|
1829
1872
|
);
|
|
1830
1873
|
return new import_neko_storage2.Storage(provider);
|
|
1831
1874
|
});
|
|
1832
|
-
var cli = (0,
|
|
1875
|
+
var cli = (0, import_neko_helper3.createSingleton)(() => {
|
|
1833
1876
|
const [node, app, ...args] = process.argv;
|
|
1834
1877
|
return new import_clipanion.Cli({
|
|
1835
1878
|
binaryLabel: `My Application`,
|
|
@@ -1837,24 +1880,13 @@ var cli = (0, import_neko_helper2.createSingleton)(() => {
|
|
|
1837
1880
|
binaryVersion: `1.0.0`
|
|
1838
1881
|
});
|
|
1839
1882
|
});
|
|
1840
|
-
var httpServer = (0,
|
|
1883
|
+
var httpServer = (0, import_neko_helper3.createSingleton)(() => {
|
|
1841
1884
|
const server = new http_exports.HttpServer();
|
|
1842
|
-
server.setErrorHandler(
|
|
1843
|
-
if (err instanceof http_exports.HttpError) {
|
|
1844
|
-
res.writeHead(err.statusCode, { "Content-Type": "application/json" });
|
|
1845
|
-
res.end(JSON.stringify({ message: err.message, error: err.code }));
|
|
1846
|
-
logger().warn({ msg: "HttpError: " + err.message, err });
|
|
1847
|
-
return;
|
|
1848
|
-
} else {
|
|
1849
|
-
logger().error({ msg: "Error: " + err.message, err });
|
|
1850
|
-
}
|
|
1851
|
-
res.writeHead(500, { "Content-Type": "" });
|
|
1852
|
-
res.end(JSON.stringify({ error: "Internal Server Error" }));
|
|
1853
|
-
});
|
|
1885
|
+
server.setErrorHandler(handleHttpErrors);
|
|
1854
1886
|
server.setRouter(router());
|
|
1855
1887
|
return server;
|
|
1856
1888
|
});
|
|
1857
|
-
var logger = (0,
|
|
1889
|
+
var logger = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1858
1890
|
const logger_config = import_neko_config.config.get(["loggers", label].join("."));
|
|
1859
1891
|
const rc = new import_neko_logger.Logger(logger_config);
|
|
1860
1892
|
rc.setExtrasFunction((message) => {
|
|
@@ -1863,7 +1895,7 @@ var logger = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
1863
1895
|
});
|
|
1864
1896
|
return rc;
|
|
1865
1897
|
});
|
|
1866
|
-
var mailer = (0,
|
|
1898
|
+
var mailer = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1867
1899
|
const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
|
|
1868
1900
|
const provider = import_neko_mailer2.MailerProviderFactory.create(
|
|
1869
1901
|
mailer_config.provider,
|
|
@@ -1872,7 +1904,7 @@ var mailer = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
1872
1904
|
const rc = new import_neko_mailer2.Mailer(provider);
|
|
1873
1905
|
return rc;
|
|
1874
1906
|
});
|
|
1875
|
-
var queue = (0,
|
|
1907
|
+
var queue = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1876
1908
|
const queue_config = import_neko_config.config.get(["queues", label].join("."));
|
|
1877
1909
|
if (!queue_config) {
|
|
1878
1910
|
throw new Error(`Queue configuration for '${label}' not found`);
|
|
@@ -1883,7 +1915,7 @@ var queue = (0, import_neko_helper2.createSingleton)((label) => {
|
|
|
1883
1915
|
);
|
|
1884
1916
|
return new import_neko_queue2.QueueConnection(provider);
|
|
1885
1917
|
});
|
|
1886
|
-
var cache = (0,
|
|
1918
|
+
var cache = (0, import_neko_helper3.createSingleton)((label) => {
|
|
1887
1919
|
const cache_config = import_neko_config.config.get(["caches", label].join("."));
|
|
1888
1920
|
if (!cache_config) {
|
|
1889
1921
|
throw new Error(`Cache configuration for '${label}' not found`);
|
|
@@ -2108,12 +2140,15 @@ var StartCommand = class extends import_clipanion5.Command {
|
|
|
2108
2140
|
__name(this, "StartCommand");
|
|
2109
2141
|
}
|
|
2110
2142
|
scheduler = import_clipanion5.Option.Boolean(`--scheduler`, false);
|
|
2143
|
+
cron = import_clipanion5.Option.Boolean(`--cron`, false);
|
|
2111
2144
|
http = import_clipanion5.Option.Boolean(`--http`, false);
|
|
2112
2145
|
queue = import_clipanion5.Option.Boolean(`--queue`, false);
|
|
2113
2146
|
all = import_clipanion5.Option.Boolean("--all", false);
|
|
2114
2147
|
static paths = [[`start`]];
|
|
2115
2148
|
async execute() {
|
|
2116
|
-
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) {
|
|
2117
2152
|
this.context.stdout.write(
|
|
2118
2153
|
`No service was selected. please check -h for details
|
|
2119
2154
|
`
|
|
@@ -2123,7 +2158,7 @@ var StartCommand = class extends import_clipanion5.Command {
|
|
|
2123
2158
|
logger().info(`Starting Server
|
|
2124
2159
|
`);
|
|
2125
2160
|
import_neko_sql.PostgresqlConnection.defaults.idleTimeoutMillis = 1e4;
|
|
2126
|
-
if (this.scheduler || this.all) {
|
|
2161
|
+
if (this.scheduler || this.cron || this.all) {
|
|
2127
2162
|
logger().info(`starting scheduler
|
|
2128
2163
|
`);
|
|
2129
2164
|
scheduler().start();
|
|
@@ -2321,144 +2356,155 @@ var config_exports = {};
|
|
|
2321
2356
|
__reExport(config_exports, require("@devbro/neko-config"));
|
|
2322
2357
|
|
|
2323
2358
|
// src/app/console/generate/GenerateApiDocsCommand.mts
|
|
2324
|
-
var
|
|
2359
|
+
var import_neko_helper4 = require("@devbro/neko-helper");
|
|
2325
2360
|
var GenerateApiDocsCommand = class extends import_clipanion9.Command {
|
|
2326
2361
|
static {
|
|
2327
2362
|
__name(this, "GenerateApiDocsCommand");
|
|
2328
2363
|
}
|
|
2329
|
-
static paths = [
|
|
2330
|
-
[`make`, `apidocs`],
|
|
2331
|
-
[`generate`, `apidocs`]
|
|
2332
|
-
];
|
|
2364
|
+
static paths = [[`generate`, `apidocsv2`]];
|
|
2333
2365
|
static usage = import_clipanion9.Command.Usage({
|
|
2334
2366
|
category: `Generate`,
|
|
2335
2367
|
description: `Generate OpenAPI documentation from routes`,
|
|
2336
2368
|
details: `
|
|
2337
|
-
This command generates OpenAPI 3.0 specification documentation by analyzing
|
|
2369
|
+
This command utility generates OpenAPI 3.0 specification documentation by analyzing
|
|
2338
2370
|
your application's routes and merging with example files.
|
|
2339
2371
|
|
|
2340
|
-
|
|
2341
|
-
-
|
|
2342
|
-
-
|
|
2343
|
-
-
|
|
2344
|
-
- Response schemas
|
|
2345
|
-
|
|
2346
|
-
The command will merge files specified in config.api_docs.merge_files
|
|
2347
|
-
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
|
|
2348
2376
|
|
|
2377
|
+
|
|
2349
2378
|
This command depends on config data. make sure your default config contains the following:
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
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
|
+
\`\`\`
|
|
2358
2400
|
`,
|
|
2359
|
-
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
|
+
]
|
|
2413
|
+
});
|
|
2414
|
+
subcommand = import_clipanion9.Option.String({ required: false });
|
|
2415
|
+
output = import_clipanion9.Option.String(`--output,-o`, {
|
|
2416
|
+
description: `Output file path for generated documentation`
|
|
2360
2417
|
});
|
|
2361
|
-
|
|
2362
|
-
description: `
|
|
2418
|
+
config = import_clipanion9.Option.String(`--config,-c`, {
|
|
2419
|
+
description: `Path in config to get details from (default: api_docs)`,
|
|
2420
|
+
required: false
|
|
2363
2421
|
});
|
|
2364
2422
|
async execute() {
|
|
2365
|
-
if (this.
|
|
2423
|
+
if (!this.subcommand) {
|
|
2366
2424
|
this.context.stdout.write(
|
|
2367
2425
|
this.constructor.usage?.toString() || "No help available\n"
|
|
2368
2426
|
);
|
|
2369
2427
|
return 0;
|
|
2370
2428
|
}
|
|
2371
|
-
|
|
2372
|
-
|
|
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}
|
|
2373
2438
|
`);
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
title: "API Documentation",
|
|
2379
|
-
version: "1.0.0",
|
|
2380
|
-
description: "Auto-generated API documentation"
|
|
2381
|
-
},
|
|
2382
|
-
servers: [
|
|
2383
|
-
{
|
|
2384
|
-
url: "/",
|
|
2385
|
-
description: "Local server"
|
|
2386
|
-
}
|
|
2387
|
-
],
|
|
2388
|
-
paths: {}
|
|
2389
|
-
};
|
|
2390
|
-
for (const route of routes) {
|
|
2391
|
-
const routePath = route.path;
|
|
2392
|
-
const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
|
|
2393
|
-
if (!openApiSpec.paths[openApiPath]) {
|
|
2394
|
-
openApiSpec.paths[openApiPath] = {};
|
|
2395
|
-
}
|
|
2396
|
-
for (const method of route.methods) {
|
|
2397
|
-
const lowerMethod = method.toLowerCase();
|
|
2398
|
-
if (lowerMethod === "head") {
|
|
2399
|
-
continue;
|
|
2400
|
-
}
|
|
2401
|
-
openApiSpec.paths[openApiPath][lowerMethod] = {
|
|
2402
|
-
summary: `${method} ${routePath}`,
|
|
2403
|
-
description: `Endpoint for ${method} ${routePath}`,
|
|
2404
|
-
parameters: this.extractParameters(routePath),
|
|
2405
|
-
responses: {
|
|
2406
|
-
"200": {
|
|
2407
|
-
description: "Successful response",
|
|
2408
|
-
content: {
|
|
2409
|
-
"application/json": {
|
|
2410
|
-
schema: {
|
|
2411
|
-
type: "object"
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
},
|
|
2416
|
-
"500": {
|
|
2417
|
-
description: "Internal server error"
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
|
-
};
|
|
2421
|
-
if (["post", "put", "patch"].includes(lowerMethod)) {
|
|
2422
|
-
openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
|
|
2423
|
-
required: true,
|
|
2424
|
-
content: {
|
|
2425
|
-
"application/json": {
|
|
2426
|
-
schema: {
|
|
2427
|
-
type: "object"
|
|
2428
|
-
}
|
|
2429
|
-
}
|
|
2430
|
-
}
|
|
2431
|
-
};
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2439
|
+
this.context.stdout.write(
|
|
2440
|
+
this.constructor.usage?.toString() || "No help available\n"
|
|
2441
|
+
);
|
|
2442
|
+
return 1;
|
|
2434
2443
|
}
|
|
2435
|
-
|
|
2436
|
-
|
|
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 });
|
|
2437
2453
|
await fs6.writeFile(
|
|
2438
2454
|
outputPath,
|
|
2439
2455
|
JSON.stringify(openApiSpec, null, 2),
|
|
2440
2456
|
"utf-8"
|
|
2441
2457
|
);
|
|
2442
2458
|
this.context.stdout.write(
|
|
2443
|
-
`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}
|
|
2444
2477
|
`
|
|
2445
2478
|
);
|
|
2446
|
-
|
|
2479
|
+
return 0;
|
|
2480
|
+
}
|
|
2481
|
+
async executeMergeFiles() {
|
|
2482
|
+
this.context.stdout.write(`Merging OpenAPI files...
|
|
2447
2483
|
`);
|
|
2448
|
-
let
|
|
2484
|
+
let configPath = this.config || "api_docs";
|
|
2485
|
+
const files_to_merge = config_exports.config.get(`${configPath}.merge_files`);
|
|
2449
2486
|
let final_api_docs = {};
|
|
2450
|
-
for (
|
|
2451
|
-
|
|
2452
|
-
|
|
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
|
+
}
|
|
2453
2499
|
}
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
);
|
|
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));
|
|
2458
2503
|
this.context.stdout.write(
|
|
2459
|
-
`
|
|
2504
|
+
`Final OpenAPI document written to: ${outputPath}
|
|
2460
2505
|
`
|
|
2461
2506
|
);
|
|
2507
|
+
return 0;
|
|
2462
2508
|
}
|
|
2463
2509
|
extractParameters(routePath) {
|
|
2464
2510
|
const paramRegex = /:([a-zA-Z0-9_]+)/g;
|
|
@@ -2477,6 +2523,78 @@ var GenerateApiDocsCommand = class extends import_clipanion9.Command {
|
|
|
2477
2523
|
}
|
|
2478
2524
|
return parameters;
|
|
2479
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
|
+
}
|
|
2480
2598
|
};
|
|
2481
2599
|
cli().register(GenerateApiDocsCommand);
|
|
2482
2600
|
|