@devbro/pashmak 0.1.27 → 0.1.28

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.
@@ -0,0 +1,9 @@
1
+ import { Command } from 'clipanion';
2
+
3
+ declare class GenerateApiDocsCommand extends Command {
4
+ static paths: string[][];
5
+ execute(): Promise<void>;
6
+ private extractParameters;
7
+ }
8
+
9
+ export { GenerateApiDocsCommand };
@@ -0,0 +1,117 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { cli, router } from "../../../facades.mjs";
4
+ import { Command } from "clipanion";
5
+ import path from "path";
6
+ import * as fs from "fs/promises";
7
+ class GenerateApiDocsCommand extends Command {
8
+ static {
9
+ __name(this, "GenerateApiDocsCommand");
10
+ }
11
+ static paths = [
12
+ [`make`, `apidocs`],
13
+ [`generate`, `apidocs`]
14
+ ];
15
+ async execute() {
16
+ const rootDir = process.cwd();
17
+ this.context.stdout.write(`Generating OpenAPI documentation...
18
+ `);
19
+ const routes = router().routes;
20
+ const openApiSpec = {
21
+ openapi: "3.0.0",
22
+ info: {
23
+ title: "API Documentation",
24
+ version: "1.0.0",
25
+ description: "Auto-generated API documentation"
26
+ },
27
+ servers: [
28
+ {
29
+ url: "/",
30
+ description: "Local server"
31
+ }
32
+ ],
33
+ paths: {}
34
+ };
35
+ for (const route of routes) {
36
+ const routePath = route.path;
37
+ const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
38
+ if (!openApiSpec.paths[openApiPath]) {
39
+ openApiSpec.paths[openApiPath] = {};
40
+ }
41
+ for (const method of route.methods) {
42
+ const lowerMethod = method.toLowerCase();
43
+ if (lowerMethod === "head") {
44
+ continue;
45
+ }
46
+ openApiSpec.paths[openApiPath][lowerMethod] = {
47
+ summary: `${method} ${routePath}`,
48
+ description: `Endpoint for ${method} ${routePath}`,
49
+ parameters: this.extractParameters(routePath),
50
+ responses: {
51
+ "200": {
52
+ description: "Successful response",
53
+ content: {
54
+ "application/json": {
55
+ schema: {
56
+ type: "object"
57
+ }
58
+ }
59
+ }
60
+ },
61
+ "500": {
62
+ description: "Internal server error"
63
+ }
64
+ }
65
+ };
66
+ if (["post", "put", "patch"].includes(lowerMethod)) {
67
+ openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
68
+ required: true,
69
+ content: {
70
+ "application/json": {
71
+ schema: {
72
+ type: "object"
73
+ }
74
+ }
75
+ }
76
+ };
77
+ }
78
+ }
79
+ }
80
+ const publicDir = path.join(rootDir, "public");
81
+ await fs.mkdir(publicDir, { recursive: true });
82
+ const outputPath = path.join(publicDir, "openapi.json");
83
+ await fs.writeFile(
84
+ outputPath,
85
+ JSON.stringify(openApiSpec, null, 2),
86
+ "utf-8"
87
+ );
88
+ this.context.stdout.write(
89
+ `OpenAPI documentation generated at: ${outputPath}
90
+ `
91
+ );
92
+ this.context.stdout.write(`Total routes documented: ${routes.length}
93
+ `);
94
+ }
95
+ extractParameters(routePath) {
96
+ const paramRegex = /:([a-zA-Z0-9_]+)/g;
97
+ const parameters = [];
98
+ let match;
99
+ while ((match = paramRegex.exec(routePath)) !== null) {
100
+ parameters.push({
101
+ name: match[1],
102
+ in: "path",
103
+ required: true,
104
+ schema: {
105
+ type: "string"
106
+ },
107
+ description: `Path parameter ${match[1]}`
108
+ });
109
+ }
110
+ return parameters;
111
+ }
112
+ }
113
+ cli().register(GenerateApiDocsCommand);
114
+ export {
115
+ GenerateApiDocsCommand
116
+ };
117
+ //# sourceMappingURL=GenerateApiDocsCommand.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app/console/generate/GenerateApiDocsCommand.mts"],"sourcesContent":["import { cli, router } from \"../../../facades.mjs\";\nimport { Command } from \"clipanion\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\n\nexport class GenerateApiDocsCommand extends Command {\n static paths = [\n [`make`, `apidocs`],\n [`generate`, `apidocs`],\n ];\n\n async execute() {\n const rootDir = process.cwd();\n\n this.context.stdout.write(`Generating OpenAPI documentation...\\n`);\n\n // Get all routes from the router\n const routes = router().routes;\n\n // Generate OpenAPI 3.0 specification\n const openApiSpec = {\n openapi: \"3.0.0\",\n info: {\n title: \"API Documentation\",\n version: \"1.0.0\",\n description: \"Auto-generated API documentation\",\n },\n servers: [\n {\n url: \"/\",\n description: \"Local server\",\n },\n ],\n paths: {} as Record<string, any>,\n };\n\n // Process each route\n for (const route of routes) {\n const routePath = route.path;\n // Convert route path to OpenAPI format (e.g., /api/:id -> /api/{id})\n const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, \"{$1}\");\n\n if (!openApiSpec.paths[openApiPath]) {\n openApiSpec.paths[openApiPath] = {};\n }\n\n // Add each HTTP method for this route\n for (const method of route.methods) {\n const lowerMethod = method.toLowerCase();\n\n // Skip HEAD as it's usually auto-generated\n if (lowerMethod === \"head\") {\n continue;\n }\n\n openApiSpec.paths[openApiPath][lowerMethod] = {\n summary: `${method} ${routePath}`,\n description: `Endpoint for ${method} ${routePath}`,\n parameters: this.extractParameters(routePath),\n responses: {\n \"200\": {\n description: \"Successful response\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n },\n },\n },\n },\n \"500\": {\n description: \"Internal server error\",\n },\n },\n };\n\n // Add request body for POST, PUT, PATCH\n if ([\"post\", \"put\", \"patch\"].includes(lowerMethod)) {\n openApiSpec.paths[openApiPath][lowerMethod].requestBody = {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n },\n },\n },\n };\n }\n }\n }\n\n // Ensure public directory exists\n const publicDir = path.join(rootDir, \"public\");\n await fs.mkdir(publicDir, { recursive: true });\n\n // Write the OpenAPI spec to public/openapi.json\n const outputPath = path.join(publicDir, \"openapi.json\");\n await fs.writeFile(\n outputPath,\n JSON.stringify(openApiSpec, null, 2),\n \"utf-8\",\n );\n\n this.context.stdout.write(\n `OpenAPI documentation generated at: ${outputPath}\\n`,\n );\n this.context.stdout.write(`Total routes documented: ${routes.length}\\n`);\n }\n\n private extractParameters(routePath: string): any[] {\n const paramRegex = /:([a-zA-Z0-9_]+)/g;\n const parameters: any[] = [];\n let match;\n\n while ((match = paramRegex.exec(routePath)) !== null) {\n parameters.push({\n name: match[1],\n in: \"path\",\n required: true,\n schema: {\n type: \"string\",\n },\n description: `Path parameter ${match[1]}`,\n });\n }\n\n return parameters;\n }\n}\n\ncli().register(GenerateApiDocsCommand);\n"],"mappings":"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","names":[]}
@@ -1,2 +1,3 @@
1
1
  export { GenerateControllerCommand } from './GenerateControllerCommand.mjs';
2
+ export { GenerateApiDocsCommand } from './GenerateApiDocsCommand.mjs';
2
3
  import 'clipanion';
@@ -1,2 +1,3 @@
1
1
  export * from "./GenerateControllerCommand.mjs";
2
+ export * from "./GenerateApiDocsCommand.mjs";
2
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app/console/generate/index.mts"],"sourcesContent":["export * from \"./GenerateControllerCommand.mjs\";\n"],"mappings":"AAAA,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app/console/generate/index.mts"],"sourcesContent":["export * from \"./GenerateControllerCommand.mjs\";\nexport * from \"./GenerateApiDocsCommand.mjs\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;","names":[]}
@@ -5,6 +5,7 @@ export { StartCommand } from './StartCommand.mjs';
5
5
  export { DefaultCommand } from './DefaultCommand.mjs';
6
6
  export { KeyGenerateCommand } from './KeyGenerateCommand.mjs';
7
7
  export { GenerateControllerCommand } from './generate/GenerateControllerCommand.mjs';
8
+ export { GenerateApiDocsCommand } from './generate/GenerateApiDocsCommand.mjs';
8
9
  export { CreateProjectCommand } from './project/CreateProjectCommand.mjs';
9
10
  export { GenerateQueueMigrateCommand } from './queue/GenerateQueueMigrateCommand.mjs';
10
11
  import 'clipanion';