@lark-apaas/devtool-kits 1.2.17-alpha.5 → 1.2.17-alpha.50

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,170 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ __name
4
+ } from "../chunk-7QVYU63E.js";
5
+
6
+ // src/bin/generate-page-routes.ts
7
+ import fs from "fs";
8
+ import path from "path";
9
+ import { parse } from "@babel/parser";
10
+ import _traverse from "@babel/traverse";
11
+ import * as t from "@babel/types";
12
+ var traverse = typeof _traverse === "function" ? _traverse : _traverse.default;
13
+ var args = process.argv.slice(2);
14
+ function getArg(name, defaultValue) {
15
+ const index = args.indexOf(name);
16
+ if (index !== -1 && args[index + 1]) {
17
+ return args[index + 1];
18
+ }
19
+ return defaultValue;
20
+ }
21
+ __name(getArg, "getArg");
22
+ var appPath = path.resolve(process.cwd(), getArg("--app-path", "./client/src/app.tsx"));
23
+ var outDir = path.resolve(process.cwd(), getArg("--out-dir", "./dist"));
24
+ var filename = getArg("--filename", "page-routes.json");
25
+ function isRouteComponent(openingElement) {
26
+ return t.isJSXIdentifier(openingElement.name) && openingElement.name.name === "Route";
27
+ }
28
+ __name(isRouteComponent, "isRouteComponent");
29
+ function evaluateTemplateLiteral(templateLiteral) {
30
+ const quasis = templateLiteral.quasis;
31
+ const expressions = templateLiteral.expressions;
32
+ if (quasis.length === 1 && expressions.length === 0) {
33
+ return quasis[0].value.raw;
34
+ }
35
+ return quasis.map((q) => q.value.raw).join("");
36
+ }
37
+ __name(evaluateTemplateLiteral, "evaluateTemplateLiteral");
38
+ function extractRouteInfo(openingElement) {
39
+ const routeInfo = {};
40
+ openingElement.attributes.forEach((attr) => {
41
+ if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
42
+ const name = attr.name.name;
43
+ let value;
44
+ if (attr.value) {
45
+ if (t.isStringLiteral(attr.value)) {
46
+ value = attr.value.value;
47
+ } else if (t.isJSXExpressionContainer(attr.value)) {
48
+ const expression = attr.value.expression;
49
+ if (t.isStringLiteral(expression)) {
50
+ value = expression.value;
51
+ } else if (t.isTemplateLiteral(expression)) {
52
+ value = evaluateTemplateLiteral(expression);
53
+ } else {
54
+ value = true;
55
+ }
56
+ }
57
+ } else {
58
+ value = true;
59
+ }
60
+ routeInfo[name] = value;
61
+ }
62
+ });
63
+ return routeInfo;
64
+ }
65
+ __name(extractRouteInfo, "extractRouteInfo");
66
+ function buildFullPath(routeStack, currentRoute) {
67
+ let fullPath = "";
68
+ for (let i = 0; i < routeStack.length; i++) {
69
+ if (routeStack[i].path) {
70
+ let parentPath = routeStack[i].path;
71
+ if (!parentPath.startsWith("/")) parentPath = `/${parentPath}`;
72
+ if (parentPath.endsWith("/") && parentPath !== "/") {
73
+ parentPath = parentPath.slice(0, -1);
74
+ }
75
+ fullPath += parentPath === "/" ? "" : parentPath;
76
+ }
77
+ }
78
+ if (currentRoute.index) {
79
+ return fullPath || "/";
80
+ } else if (currentRoute.path) {
81
+ const routePath = currentRoute.path;
82
+ if (routePath === "*") {
83
+ return null;
84
+ }
85
+ if (!routePath.startsWith("/")) {
86
+ fullPath = `${fullPath}/${routePath}`;
87
+ } else {
88
+ fullPath = routePath;
89
+ }
90
+ if (fullPath === "") fullPath = "/";
91
+ if (!fullPath.startsWith("/")) fullPath = `/${fullPath}`;
92
+ return fullPath;
93
+ }
94
+ return null;
95
+ }
96
+ __name(buildFullPath, "buildFullPath");
97
+ function parsePageRoutes(appFilePath) {
98
+ if (!fs.existsSync(appFilePath)) {
99
+ throw new Error(`App file does not exist: ${appFilePath}`);
100
+ }
101
+ const sourceCode = fs.readFileSync(appFilePath, "utf-8");
102
+ const ast = parse(sourceCode, {
103
+ sourceType: "module",
104
+ plugins: [
105
+ "jsx",
106
+ "typescript",
107
+ "decorators-legacy",
108
+ "classProperties",
109
+ "objectRestSpread",
110
+ "functionBind",
111
+ "exportDefaultFrom",
112
+ "exportNamespaceFrom",
113
+ "dynamicImport",
114
+ "nullishCoalescingOperator",
115
+ "optionalChaining"
116
+ ]
117
+ });
118
+ const routeSet = /* @__PURE__ */ new Set();
119
+ const routeStack = [];
120
+ traverse(ast, {
121
+ JSXElement: {
122
+ enter(nodePath) {
123
+ const { openingElement } = nodePath.node;
124
+ if (isRouteComponent(openingElement)) {
125
+ routeStack.push(extractRouteInfo(openingElement));
126
+ }
127
+ },
128
+ exit(nodePath) {
129
+ const { openingElement } = nodePath.node;
130
+ if (isRouteComponent(openingElement)) {
131
+ const currentRoute = routeStack.pop();
132
+ if (currentRoute && currentRoute.path === "*") return;
133
+ if (currentRoute && (currentRoute.path || currentRoute.index)) {
134
+ const fullPath = buildFullPath(routeStack, currentRoute);
135
+ if (fullPath) routeSet.add(fullPath);
136
+ }
137
+ }
138
+ }
139
+ }
140
+ });
141
+ const routes = Array.from(routeSet).map((routePath) => ({
142
+ path: routePath
143
+ }));
144
+ return routes.length > 0 ? routes : [
145
+ {
146
+ path: "/"
147
+ }
148
+ ];
149
+ }
150
+ __name(parsePageRoutes, "parsePageRoutes");
151
+ try {
152
+ const routes = parsePageRoutes(appPath);
153
+ if (!fs.existsSync(outDir)) {
154
+ fs.mkdirSync(outDir, {
155
+ recursive: true
156
+ });
157
+ }
158
+ const outPath = path.resolve(outDir, filename);
159
+ fs.writeFileSync(outPath, JSON.stringify(routes, null, 2));
160
+ console.log(`[page-routes] Generated ${outPath} (${routes.length} routes)`);
161
+ } catch (error) {
162
+ console.warn("[page-routes] Failed to generate page-routes.json, writing empty fallback:", error);
163
+ if (!fs.existsSync(outDir)) {
164
+ fs.mkdirSync(outDir, {
165
+ recursive: true
166
+ });
167
+ }
168
+ fs.writeFileSync(path.resolve(outDir, filename), JSON.stringify([], null, 2));
169
+ }
170
+ //# sourceMappingURL=generate-page-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/bin/generate-page-routes.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'fs';\nimport path from 'path';\nimport { parse } from '@babel/parser';\nimport _traverse from '@babel/traverse';\n// Handle CJS default export interop in ESM context\nconst traverse = typeof _traverse === 'function' ? _traverse : (_traverse as any).default;\nimport * as t from '@babel/types';\n\nconst args = process.argv.slice(2);\n\nfunction getArg(name: string, defaultValue: string): string {\n const index = args.indexOf(name);\n if (index !== -1 && args[index + 1]) {\n return args[index + 1];\n }\n return defaultValue;\n}\n\nconst appPath = path.resolve(process.cwd(), getArg('--app-path', './client/src/app.tsx'));\nconst outDir = path.resolve(process.cwd(), getArg('--out-dir', './dist'));\nconst filename = getArg('--filename', 'page-routes.json');\n\ninterface RouteInfo {\n path?: string;\n index?: boolean;\n [key: string]: unknown;\n}\n\nfunction isRouteComponent(openingElement: t.JSXOpeningElement): boolean {\n return (\n t.isJSXIdentifier(openingElement.name) &&\n openingElement.name.name === 'Route'\n );\n}\n\nfunction evaluateTemplateLiteral(templateLiteral: t.TemplateLiteral): string {\n const quasis = templateLiteral.quasis;\n const expressions = templateLiteral.expressions;\n\n if (quasis.length === 1 && expressions.length === 0) {\n return quasis[0].value.raw;\n }\n\n return quasis.map((q) => q.value.raw).join('');\n}\n\nfunction extractRouteInfo(openingElement: t.JSXOpeningElement): RouteInfo {\n const routeInfo: RouteInfo = {};\n\n openingElement.attributes.forEach((attr) => {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {\n const name = attr.name.name;\n let value: unknown;\n\n if (attr.value) {\n if (t.isStringLiteral(attr.value)) {\n value = attr.value.value;\n } else if (t.isJSXExpressionContainer(attr.value)) {\n const expression = attr.value.expression;\n if (t.isStringLiteral(expression)) {\n value = expression.value;\n } else if (t.isTemplateLiteral(expression)) {\n value = evaluateTemplateLiteral(expression);\n } else {\n value = true;\n }\n }\n } else {\n value = true;\n }\n\n routeInfo[name] = value;\n }\n });\n\n return routeInfo;\n}\n\nfunction buildFullPath(routeStack: RouteInfo[], currentRoute: RouteInfo): string | null {\n let fullPath = '';\n\n for (let i = 0; i < routeStack.length; i++) {\n if (routeStack[i].path) {\n let parentPath = routeStack[i].path!;\n if (!parentPath.startsWith('/')) parentPath = `/${parentPath}`;\n if (parentPath.endsWith('/') && parentPath !== '/') {\n parentPath = parentPath.slice(0, -1);\n }\n\n fullPath += parentPath === '/' ? '' : parentPath;\n }\n }\n\n if (currentRoute.index) {\n return fullPath || '/';\n } else if (currentRoute.path) {\n const routePath = currentRoute.path;\n\n if (routePath === '*') {\n return null;\n }\n\n if (!routePath.startsWith('/')) {\n fullPath = `${fullPath}/${routePath}`;\n } else {\n fullPath = routePath;\n }\n\n if (fullPath === '') fullPath = '/';\n if (!fullPath.startsWith('/')) fullPath = `/${fullPath}`;\n\n return fullPath;\n }\n\n return null;\n}\n\nfunction parsePageRoutes(appFilePath: string): Array<{ path: string }> {\n if (!fs.existsSync(appFilePath)) {\n throw new Error(`App file does not exist: ${appFilePath}`);\n }\n\n const sourceCode = fs.readFileSync(appFilePath, 'utf-8');\n\n const ast = parse(sourceCode, {\n sourceType: 'module',\n plugins: [\n 'jsx',\n 'typescript',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n });\n\n const routeSet = new Set<string>();\n const routeStack: RouteInfo[] = [];\n\n traverse(ast, {\n JSXElement: {\n enter(nodePath: any) {\n const { openingElement } = nodePath.node;\n if (isRouteComponent(openingElement)) {\n routeStack.push(extractRouteInfo(openingElement));\n }\n },\n exit(nodePath: any) {\n const { openingElement } = nodePath.node;\n if (isRouteComponent(openingElement)) {\n const currentRoute = routeStack.pop();\n if (currentRoute && currentRoute.path === '*') return;\n if (currentRoute && (currentRoute.path || currentRoute.index)) {\n const fullPath = buildFullPath(routeStack, currentRoute);\n if (fullPath) routeSet.add(fullPath);\n }\n }\n },\n },\n });\n\n // page-routes 不带 basePath 前缀,供日志服务消费\n const routes = Array.from(routeSet).map((routePath) => ({ path: routePath }));\n return routes.length > 0 ? routes : [{ path: '/' }];\n}\n\ntry {\n const routes = parsePageRoutes(appPath);\n if (!fs.existsSync(outDir)) {\n fs.mkdirSync(outDir, { recursive: true });\n }\n const outPath = path.resolve(outDir, filename);\n fs.writeFileSync(outPath, JSON.stringify(routes, null, 2));\n console.log(`[page-routes] Generated ${outPath} (${routes.length} routes)`);\n} catch (error) {\n console.warn('[page-routes] Failed to generate page-routes.json, writing empty fallback:', error);\n if (!fs.existsSync(outDir)) {\n fs.mkdirSync(outDir, { recursive: true });\n }\n fs.writeFileSync(path.resolve(outDir, filename), JSON.stringify([], null, 2));\n}\n"],"mappings":"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","names":["fs","path","parse","_traverse","t","traverse","_traverse","default","args","process","argv","slice","getArg","name","defaultValue","index","indexOf","appPath","path","resolve","cwd","outDir","filename","isRouteComponent","openingElement","isJSXIdentifier","evaluateTemplateLiteral","templateLiteral","quasis","expressions","length","value","raw","map","q","join","extractRouteInfo","routeInfo","attributes","forEach","attr","isJSXAttribute","isStringLiteral","isJSXExpressionContainer","expression","isTemplateLiteral","buildFullPath","routeStack","currentRoute","fullPath","i","parentPath","startsWith","endsWith","routePath","parsePageRoutes","appFilePath","fs","existsSync","Error","sourceCode","readFileSync","ast","parse","sourceType","plugins","routeSet","Set","JSXElement","enter","nodePath","node","push","exit","pop","add","routes","Array","from","mkdirSync","recursive","outPath","writeFileSync","JSON","stringify","console","log","error","warn"]}
@@ -0,0 +1,7 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ export {
5
+ __name
6
+ };
7
+ //# sourceMappingURL=chunk-7QVYU63E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,350 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-7QVYU63E.js";
4
+
5
+ // src/middlewares/openapi/services.ts
6
+ import { promises as fs2 } from "fs";
7
+ import * as fsSync from "fs";
8
+ import path2 from "path";
9
+ import ts from "typescript";
10
+
11
+ // src/middlewares/openapi/utils.ts
12
+ import path from "path";
13
+ import { promises as fs } from "fs";
14
+ async function findControllerFiles(dir) {
15
+ const files = [];
16
+ async function scan(currentDir) {
17
+ const entries = await fs.readdir(currentDir, {
18
+ withFileTypes: true
19
+ });
20
+ for (const entry of entries) {
21
+ const fullPath = path.join(currentDir, entry.name);
22
+ if (entry.isDirectory()) {
23
+ await scan(fullPath);
24
+ } else if (entry.isFile() && entry.name.endsWith(".controller.ts")) {
25
+ files.push(fullPath);
26
+ }
27
+ }
28
+ }
29
+ __name(scan, "scan");
30
+ await scan(dir);
31
+ return files;
32
+ }
33
+ __name(findControllerFiles, "findControllerFiles");
34
+ async function buildSourceMap(controllerFiles, processFile) {
35
+ const sourceMap = /* @__PURE__ */ new Map();
36
+ const concurrency = 10;
37
+ const results = [];
38
+ for (let i = 0; i < controllerFiles.length; i += concurrency) {
39
+ const batch = controllerFiles.slice(i, i + concurrency);
40
+ const batchResults = await Promise.all(batch.map((filePath) => processFile(filePath)));
41
+ results.push(...batchResults);
42
+ }
43
+ for (const metadata of results) {
44
+ for (const [operationId, info] of metadata.entries()) {
45
+ sourceMap.set(operationId, info);
46
+ }
47
+ }
48
+ return sourceMap;
49
+ }
50
+ __name(buildSourceMap, "buildSourceMap");
51
+ function findSourceInfo(operationId, sourceMap) {
52
+ const directMatch = sourceMap.get(operationId);
53
+ if (directMatch) {
54
+ return directMatch;
55
+ }
56
+ for (const [key, value] of sourceMap.entries()) {
57
+ const [className, methodName] = key.split("_");
58
+ if (!className || !methodName) continue;
59
+ const camelCaseId = className.charAt(0).toLowerCase() + className.slice(1) + methodName.charAt(0).toUpperCase() + methodName.slice(1);
60
+ if (operationId === camelCaseId) {
61
+ return value;
62
+ }
63
+ if (operationId === methodName) {
64
+ return value;
65
+ }
66
+ }
67
+ return void 0;
68
+ }
69
+ __name(findSourceInfo, "findSourceInfo");
70
+ function enhanceOpenApiPaths(openapi, sourceMap) {
71
+ let enhancedCount = 0;
72
+ if (!openapi.paths) {
73
+ return enhancedCount;
74
+ }
75
+ for (const pathItem of Object.values(openapi.paths)) {
76
+ if (!pathItem || typeof pathItem !== "object") continue;
77
+ for (const operation of Object.values(pathItem)) {
78
+ if (operation && typeof operation === "object" && "operationId" in operation) {
79
+ const sourceInfo = findSourceInfo(operation.operationId, sourceMap);
80
+ if (sourceInfo) {
81
+ operation["x-source"] = {
82
+ file: sourceInfo.file,
83
+ line: sourceInfo.line
84
+ };
85
+ enhancedCount++;
86
+ }
87
+ }
88
+ }
89
+ }
90
+ return enhancedCount;
91
+ }
92
+ __name(enhanceOpenApiPaths, "enhanceOpenApiPaths");
93
+ function transformOpenapiPaths(openapi, basePath) {
94
+ if (basePath === "/" || !openapi.paths) {
95
+ return openapi;
96
+ }
97
+ const newPaths = {};
98
+ Object.keys(openapi.paths).forEach((key) => {
99
+ const staticApiKey = key.startsWith(basePath) ? key.slice(basePath.length) : key;
100
+ newPaths[staticApiKey] = openapi.paths[key];
101
+ });
102
+ return {
103
+ ...openapi,
104
+ paths: newPaths,
105
+ basePath
106
+ };
107
+ }
108
+ __name(transformOpenapiPaths, "transformOpenapiPaths");
109
+
110
+ // src/middlewares/openapi/services.ts
111
+ async function enhanceOpenApiWithSourceInfo(options = {}) {
112
+ const startTime = Date.now();
113
+ const openapiPath = options.openapiPath || path2.resolve(__dirname, "../client/src/api/gen/openapi.json");
114
+ const serverDir = options.serverDir || path2.resolve(__dirname, "../server");
115
+ const writeFile = options.writeFile !== false;
116
+ let openapi;
117
+ if (options.openapiData) {
118
+ openapi = JSON.parse(JSON.stringify(options.openapiData));
119
+ } else {
120
+ const openapiContent = await fs2.readFile(openapiPath, "utf-8");
121
+ openapi = JSON.parse(openapiContent);
122
+ }
123
+ const controllerFiles = await findControllerFiles(serverDir);
124
+ const sourceMap = await buildSourceMap(controllerFiles, processControllerFile);
125
+ const enhanced = enhanceOpenApiPaths(openapi, sourceMap);
126
+ if (writeFile) {
127
+ await fs2.writeFile(openapiPath, JSON.stringify(openapi, null, 2) + "\n", "utf-8");
128
+ }
129
+ const duration = Date.now() - startTime;
130
+ return {
131
+ openapi,
132
+ stats: {
133
+ duration,
134
+ controllersFound: controllerFiles.length,
135
+ endpointsExtracted: sourceMap.size,
136
+ endpointsEnhanced: enhanced
137
+ }
138
+ };
139
+ }
140
+ __name(enhanceOpenApiWithSourceInfo, "enhanceOpenApiWithSourceInfo");
141
+ async function processControllerFile(filePath) {
142
+ const relativePath = path2.relative(process.cwd(), filePath);
143
+ const content = await fs2.readFile(filePath, "utf-8");
144
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
145
+ return extractControllerMetadata(sourceFile, relativePath);
146
+ }
147
+ __name(processControllerFile, "processControllerFile");
148
+ function extractControllerMetadata(sourceFile, filePath) {
149
+ const metadata = /* @__PURE__ */ new Map();
150
+ let controllerPath = "";
151
+ let className = "";
152
+ function getDecorators(node) {
153
+ if ("modifiers" in node && Array.isArray(node.modifiers)) {
154
+ return node.modifiers.filter((mod) => mod.kind === ts.SyntaxKind.Decorator);
155
+ }
156
+ if ("decorators" in node && Array.isArray(node.decorators)) {
157
+ return node.decorators;
158
+ }
159
+ return [];
160
+ }
161
+ __name(getDecorators, "getDecorators");
162
+ function visit(node) {
163
+ if (ts.isClassDeclaration(node)) {
164
+ const decorators = getDecorators(node);
165
+ if (node.name) {
166
+ className = node.name.getText(sourceFile);
167
+ }
168
+ for (const decorator of decorators) {
169
+ if (ts.isCallExpression(decorator.expression)) {
170
+ const expression = decorator.expression;
171
+ const decoratorName = expression.expression.getText(sourceFile);
172
+ if (decoratorName === "Controller") {
173
+ if (expression.arguments.length > 0) {
174
+ const arg = expression.arguments[0];
175
+ if (ts.isStringLiteral(arg)) {
176
+ controllerPath = arg.text;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ }
182
+ }
183
+ if (ts.isMethodDeclaration(node) && node.name) {
184
+ const methodName = node.name.getText(sourceFile);
185
+ let httpMethod = "";
186
+ let routePath = "";
187
+ const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
188
+ const decorators = getDecorators(node);
189
+ for (const decorator of decorators) {
190
+ if (ts.isCallExpression(decorator.expression)) {
191
+ const decoratorName = decorator.expression.expression.getText(sourceFile);
192
+ if ([
193
+ "Get",
194
+ "Post",
195
+ "Put",
196
+ "Delete",
197
+ "Patch",
198
+ "Options",
199
+ "Head",
200
+ "All"
201
+ ].includes(decoratorName)) {
202
+ httpMethod = decoratorName.toLowerCase();
203
+ if (decorator.expression.arguments.length > 0) {
204
+ const arg = decorator.expression.arguments[0];
205
+ if (ts.isStringLiteral(arg)) {
206
+ routePath = arg.text;
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ if (httpMethod && methodName && className) {
213
+ const operationId = `${className}_${methodName}`;
214
+ metadata.set(operationId, {
215
+ file: filePath,
216
+ line: line + 1,
217
+ method: httpMethod,
218
+ controllerPath,
219
+ routePath
220
+ });
221
+ }
222
+ }
223
+ ts.forEachChild(node, visit);
224
+ }
225
+ __name(visit, "visit");
226
+ visit(sourceFile);
227
+ return metadata;
228
+ }
229
+ __name(extractControllerMetadata, "extractControllerMetadata");
230
+ var HTTP_DECORATOR_NAMES = [
231
+ "Get",
232
+ "Post",
233
+ "Put",
234
+ "Delete",
235
+ "Patch",
236
+ "Options",
237
+ "Head",
238
+ "All"
239
+ ];
240
+ function findControllerFilesSync(dir) {
241
+ const files = [];
242
+ function scan(currentDir) {
243
+ let entries;
244
+ try {
245
+ entries = fsSync.readdirSync(currentDir, {
246
+ withFileTypes: true
247
+ });
248
+ } catch {
249
+ return;
250
+ }
251
+ for (const entry of entries) {
252
+ const fullPath = path2.join(currentDir, entry.name);
253
+ if (entry.isDirectory()) {
254
+ scan(fullPath);
255
+ } else if (entry.isFile() && entry.name.endsWith(".controller.ts")) {
256
+ files.push(fullPath);
257
+ }
258
+ }
259
+ }
260
+ __name(scan, "scan");
261
+ scan(dir);
262
+ return files;
263
+ }
264
+ __name(findControllerFilesSync, "findControllerFilesSync");
265
+ function normalizeApiPath(controllerPath, routePath) {
266
+ const combined = routePath ? `${controllerPath}/${routePath}` : controllerPath;
267
+ let normalized = combined.replace(/\/+/g, "/");
268
+ if (!normalized.startsWith("/")) normalized = `/${normalized}`;
269
+ if (normalized.length > 1 && normalized.endsWith("/")) normalized = normalized.slice(0, -1);
270
+ return normalized;
271
+ }
272
+ __name(normalizeApiPath, "normalizeApiPath");
273
+ function parseControllerRoutes(filePath) {
274
+ let content;
275
+ try {
276
+ content = fsSync.readFileSync(filePath, "utf-8");
277
+ } catch {
278
+ return [];
279
+ }
280
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
281
+ const routes = [];
282
+ function getDecoratorsCompat(node) {
283
+ if ("modifiers" in node && Array.isArray(node.modifiers)) {
284
+ return node.modifiers.filter((mod) => mod.kind === ts.SyntaxKind.Decorator);
285
+ }
286
+ if ("decorators" in node && Array.isArray(node.decorators)) {
287
+ return node.decorators;
288
+ }
289
+ return [];
290
+ }
291
+ __name(getDecoratorsCompat, "getDecoratorsCompat");
292
+ function getStringArg(expr) {
293
+ if (expr.arguments.length > 0 && ts.isStringLiteral(expr.arguments[0])) {
294
+ return expr.arguments[0].text;
295
+ }
296
+ return "";
297
+ }
298
+ __name(getStringArg, "getStringArg");
299
+ function visit(node) {
300
+ if (ts.isClassDeclaration(node)) {
301
+ let controllerPath = "";
302
+ for (const dec of getDecoratorsCompat(node)) {
303
+ if (ts.isCallExpression(dec.expression)) {
304
+ const name = dec.expression.expression.getText(sourceFile);
305
+ if (name === "Controller") {
306
+ controllerPath = getStringArg(dec.expression);
307
+ break;
308
+ }
309
+ }
310
+ }
311
+ for (const member of node.members) {
312
+ if (!ts.isMethodDeclaration(member)) continue;
313
+ for (const dec of getDecoratorsCompat(member)) {
314
+ if (!ts.isCallExpression(dec.expression)) continue;
315
+ const decoratorName = dec.expression.expression.getText(sourceFile);
316
+ if (!HTTP_DECORATOR_NAMES.includes(decoratorName)) continue;
317
+ const routePath = getStringArg(dec.expression);
318
+ const fullPath = normalizeApiPath(controllerPath, routePath);
319
+ const method = decoratorName === "All" ? "*" : decoratorName.toUpperCase();
320
+ routes.push({
321
+ method,
322
+ path: fullPath
323
+ });
324
+ }
325
+ }
326
+ }
327
+ ts.forEachChild(node, visit);
328
+ }
329
+ __name(visit, "visit");
330
+ visit(sourceFile);
331
+ return routes;
332
+ }
333
+ __name(parseControllerRoutes, "parseControllerRoutes");
334
+ function parseApiRoutes(serverDir) {
335
+ const resolvedDir = path2.resolve(serverDir);
336
+ const controllerFiles = findControllerFilesSync(resolvedDir);
337
+ const routes = [];
338
+ for (const filePath of controllerFiles) {
339
+ routes.push(...parseControllerRoutes(filePath));
340
+ }
341
+ return routes;
342
+ }
343
+ __name(parseApiRoutes, "parseApiRoutes");
344
+
345
+ export {
346
+ transformOpenapiPaths,
347
+ enhanceOpenApiWithSourceInfo,
348
+ parseApiRoutes
349
+ };
350
+ //# sourceMappingURL=chunk-LSHFHCDF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middlewares/openapi/services.ts","../src/middlewares/openapi/utils.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as fsSync from 'node:fs';\nimport path from 'node:path';\nimport ts from 'typescript';\nimport type { SourceInfo, EnhanceOptions, EnhanceResult } from './types';\nimport { findControllerFiles, buildSourceMap, enhanceOpenApiPaths } from './utils';\n\n/**\n * Enhances OpenAPI JSON with source file location metadata\n * Can be called programmatically or run as a script\n */\nexport async function enhanceOpenApiWithSourceInfo(options: EnhanceOptions = {}): Promise<EnhanceResult> {\n const startTime = Date.now();\n\n const openapiPath = options.openapiPath || path.resolve(__dirname, '../client/src/api/gen/openapi.json');\n const serverDir = options.serverDir || path.resolve(__dirname, '../server');\n const writeFile = options.writeFile !== false;\n\n let openapi: any;\n if (options.openapiData) {\n // Use provided data (for in-memory enhancement)\n openapi = JSON.parse(JSON.stringify(options.openapiData)); // Deep clone\n } else {\n // Read from file\n const openapiContent = await fs.readFile(openapiPath, 'utf-8');\n openapi = JSON.parse(openapiContent);\n }\n\n const controllerFiles = await findControllerFiles(serverDir);\n const sourceMap = await buildSourceMap(controllerFiles, processControllerFile);\n const enhanced = enhanceOpenApiPaths(openapi, sourceMap);\n\n if (writeFile) {\n await fs.writeFile(openapiPath, JSON.stringify(openapi, null, 2) + '\\n', 'utf-8');\n }\n\n const duration = Date.now() - startTime;\n\n return {\n openapi,\n stats: {\n duration,\n controllersFound: controllerFiles.length,\n endpointsExtracted: sourceMap.size,\n endpointsEnhanced: enhanced,\n },\n };\n}\n\n/**\n * Process a single controller file\n */\nasync function processControllerFile(filePath: string): Promise<Map<string, SourceInfo>> {\n const relativePath = path.relative(process.cwd(), filePath);\n\n // Parse file\n const content = await fs.readFile(filePath, 'utf-8');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n return extractControllerMetadata(sourceFile, relativePath);\n}\n\n/**\n * Extract controller metadata from TypeScript source file\n */\nfunction extractControllerMetadata(sourceFile: ts.SourceFile, filePath: string): Map<string, SourceInfo> {\n const metadata = new Map<string, SourceInfo>();\n let controllerPath = '';\n let className = '';\n\n // Helper function to get decorators from both old and new TypeScript APIs\n function getDecorators(node: ts.Node): readonly ts.Decorator[] {\n // TypeScript 5.x: decorators are in modifiers array\n if ('modifiers' in node && Array.isArray(node.modifiers)) {\n return (node.modifiers as ts.ModifierLike[]).filter(\n (mod): mod is ts.Decorator => mod.kind === ts.SyntaxKind.Decorator,\n );\n }\n // TypeScript 4.x: decorators are in decorators array\n if ('decorators' in node && Array.isArray(node.decorators)) {\n return node.decorators as readonly ts.Decorator[];\n }\n return [];\n }\n\n function visit(node: ts.Node): void {\n // Extract @Controller decorator and its path\n if (ts.isClassDeclaration(node)) {\n const decorators = getDecorators(node);\n\n // Extract class name\n if (node.name) {\n className = node.name.getText(sourceFile);\n }\n\n for (const decorator of decorators) {\n if (ts.isCallExpression(decorator.expression)) {\n const expression = decorator.expression;\n const decoratorName = expression.expression.getText(sourceFile);\n\n if (decoratorName === 'Controller') {\n if (expression.arguments.length > 0) {\n const arg = expression.arguments[0];\n if (ts.isStringLiteral(arg)) {\n controllerPath = arg.text;\n }\n }\n }\n }\n }\n }\n\n // Extract methods with HTTP decorators\n if (ts.isMethodDeclaration(node) && node.name) {\n const methodName = node.name.getText(sourceFile);\n let httpMethod = '';\n let routePath = '';\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));\n\n const decorators = getDecorators(node);\n\n for (const decorator of decorators) {\n if (ts.isCallExpression(decorator.expression)) {\n const decoratorName = decorator.expression.expression.getText(sourceFile);\n if (['Get', 'Post', 'Put', 'Delete', 'Patch', 'Options', 'Head', 'All'].includes(decoratorName)) {\n httpMethod = decoratorName.toLowerCase();\n if (decorator.expression.arguments.length > 0) {\n const arg = decorator.expression.arguments[0];\n if (ts.isStringLiteral(arg)) {\n routePath = arg.text;\n }\n }\n }\n }\n }\n\n if (httpMethod && methodName && className) {\n const operationId = `${className}_${methodName}`;\n metadata.set(operationId, {\n file: filePath,\n line: line + 1,\n method: httpMethod,\n controllerPath,\n routePath,\n });\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return metadata;\n}\n\n// --- API Route Parsing (synchronous, for build-time injection) ---\n\nconst HTTP_DECORATOR_NAMES = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Options', 'Head', 'All'];\n\nfunction findControllerFilesSync(dir: string): string[] {\n const files: string[] = [];\n function scan(currentDir: string): void {\n let entries: fsSync.Dirent[];\n try {\n entries = fsSync.readdirSync(currentDir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const fullPath = path.join(currentDir, entry.name);\n if (entry.isDirectory()) {\n scan(fullPath);\n } else if (entry.isFile() && entry.name.endsWith('.controller.ts')) {\n files.push(fullPath);\n }\n }\n }\n scan(dir);\n return files;\n}\n\nfunction normalizeApiPath(controllerPath: string, routePath: string): string {\n const combined = routePath ? `${controllerPath}/${routePath}` : controllerPath;\n let normalized = combined.replace(/\\/+/g, '/');\n if (!normalized.startsWith('/')) normalized = `/${normalized}`;\n if (normalized.length > 1 && normalized.endsWith('/')) normalized = normalized.slice(0, -1);\n return normalized;\n}\n\nfunction parseControllerRoutes(filePath: string): Array<{ method: string; path: string }> {\n let content: string;\n try {\n content = fsSync.readFileSync(filePath, 'utf-8');\n } catch {\n return [];\n }\n\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n const routes: Array<{ method: string; path: string }> = [];\n\n function getDecoratorsCompat(node: ts.Node): readonly ts.Decorator[] {\n if ('modifiers' in node && Array.isArray(node.modifiers)) {\n return (node.modifiers as ts.ModifierLike[]).filter(\n (mod): mod is ts.Decorator => mod.kind === ts.SyntaxKind.Decorator,\n );\n }\n if ('decorators' in node && Array.isArray(node.decorators)) {\n return node.decorators as readonly ts.Decorator[];\n }\n return [];\n }\n\n function getStringArg(expr: ts.CallExpression): string {\n if (expr.arguments.length > 0 && ts.isStringLiteral(expr.arguments[0])) {\n return expr.arguments[0].text;\n }\n return '';\n }\n\n function visit(node: ts.Node): void {\n if (ts.isClassDeclaration(node)) {\n let controllerPath = '';\n for (const dec of getDecoratorsCompat(node)) {\n if (ts.isCallExpression(dec.expression)) {\n const name = dec.expression.expression.getText(sourceFile);\n if (name === 'Controller') {\n controllerPath = getStringArg(dec.expression);\n break;\n }\n }\n }\n\n for (const member of node.members) {\n if (!ts.isMethodDeclaration(member)) continue;\n for (const dec of getDecoratorsCompat(member)) {\n if (!ts.isCallExpression(dec.expression)) continue;\n const decoratorName = dec.expression.expression.getText(sourceFile);\n if (!HTTP_DECORATOR_NAMES.includes(decoratorName)) continue;\n\n const routePath = getStringArg(dec.expression);\n const fullPath = normalizeApiPath(controllerPath, routePath);\n const method = decoratorName === 'All' ? '*' : decoratorName.toUpperCase();\n routes.push({ method, path: fullPath });\n }\n }\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return routes;\n}\n\n/**\n * Scan serverDir for NestJS controller files and extract all parameterized API routes.\n * Synchronous — safe to call at preset config time (before bundling).\n */\nexport function parseApiRoutes(serverDir: string): Array<{ method: string; path: string }> {\n const resolvedDir = path.resolve(serverDir);\n const controllerFiles = findControllerFilesSync(resolvedDir);\n const routes: Array<{ method: string; path: string }> = [];\n for (const filePath of controllerFiles) {\n routes.push(...parseControllerRoutes(filePath));\n }\n return routes;\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport type { SourceInfo } from './types';\n\n/**\n * Find all controller files in a directory\n */\nexport async function findControllerFiles(dir: string): Promise<string[]> {\n const files: string[] = [];\n\n async function scan(currentDir: string): Promise<void> {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n await scan(fullPath);\n } else if (entry.isFile() && entry.name.endsWith('.controller.ts')) {\n files.push(fullPath);\n }\n }\n }\n\n await scan(dir);\n return files;\n}\n\n/**\n * Build source map from controller files\n */\nexport async function buildSourceMap(\n controllerFiles: string[],\n processFile: (filePath: string) => Promise<Map<string, SourceInfo>>,\n): Promise<Map<string, SourceInfo>> {\n const sourceMap = new Map<string, SourceInfo>();\n\n // Process files in parallel with a concurrency limit\n const concurrency = 10;\n const results: Map<string, SourceInfo>[] = [];\n\n for (let i = 0; i < controllerFiles.length; i += concurrency) {\n const batch = controllerFiles.slice(i, i + concurrency);\n const batchResults = await Promise.all(batch.map((filePath) => processFile(filePath)));\n results.push(...batchResults);\n }\n\n // Merge results\n for (const metadata of results) {\n for (const [operationId, info] of metadata.entries()) {\n sourceMap.set(operationId, info);\n }\n }\n\n return sourceMap;\n}\n\n/**\n * Try to match operationId with different formats\n * Supports:\n * - Direct match: ClassName_methodName\n * - Camel case: classNameMethodName\n * - Method only: methodName\n */\nfunction findSourceInfo(operationId: string, sourceMap: Map<string, SourceInfo>): SourceInfo | undefined {\n // Try direct match first\n const directMatch = sourceMap.get(operationId);\n if (directMatch) {\n return directMatch;\n }\n\n // Try matching with different formats\n for (const [key, value] of sourceMap.entries()) {\n // key format: ClassName_methodName\n const [className, methodName] = key.split('_');\n if (!className || !methodName) continue;\n\n // Try camelCase format: classNameMethodName\n const camelCaseId = className.charAt(0).toLowerCase() + className.slice(1) + methodName.charAt(0).toUpperCase() + methodName.slice(1);\n if (operationId === camelCaseId) {\n return value;\n }\n\n // Try method name only\n if (operationId === methodName) {\n return value;\n }\n }\n\n return undefined;\n}\n\n/**\n * Enhance OpenAPI paths with source information\n */\nexport function enhanceOpenApiPaths(openapi: any, sourceMap: Map<string, SourceInfo>): number {\n let enhancedCount = 0;\n\n if (!openapi.paths) {\n return enhancedCount;\n }\n\n for (const pathItem of Object.values(openapi.paths)) {\n if (!pathItem || typeof pathItem !== 'object') continue;\n\n for (const operation of Object.values(pathItem)) {\n if (operation && typeof operation === 'object' && 'operationId' in operation) {\n const sourceInfo = findSourceInfo(operation.operationId as string, sourceMap);\n if (sourceInfo) {\n operation['x-source'] = {\n file: sourceInfo.file,\n line: sourceInfo.line,\n };\n enhancedCount++;\n }\n }\n }\n }\n\n return enhancedCount;\n}\n\n/**\n * Transform OpenAPI paths by removing basePath prefix\n */\nexport function transformOpenapiPaths(openapi: any, basePath: string): any {\n if (basePath === '/' || !openapi.paths) {\n return openapi;\n }\n\n const newPaths: any = {};\n Object.keys(openapi.paths).forEach((key) => {\n const staticApiKey = key.startsWith(basePath) ? key.slice(basePath.length) : key;\n newPaths[staticApiKey] = openapi.paths[key];\n });\n\n return {\n ...openapi,\n paths: newPaths,\n basePath,\n };\n}\n"],"mappings":"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","names":["promises","fs","fsSync","path","ts","path","promises","fs","findControllerFiles","dir","files","scan","currentDir","entries","fs","readdir","withFileTypes","entry","fullPath","path","join","name","isDirectory","isFile","endsWith","push","buildSourceMap","controllerFiles","processFile","sourceMap","Map","concurrency","results","i","length","batch","slice","batchResults","Promise","all","map","filePath","metadata","operationId","info","set","findSourceInfo","directMatch","get","key","value","className","methodName","split","camelCaseId","charAt","toLowerCase","toUpperCase","undefined","enhanceOpenApiPaths","openapi","enhancedCount","paths","pathItem","Object","values","operation","sourceInfo","file","line","transformOpenapiPaths","basePath","newPaths","keys","forEach","staticApiKey","startsWith","enhanceOpenApiWithSourceInfo","options","startTime","Date","now","openapiPath","path","resolve","__dirname","serverDir","writeFile","openapi","openapiData","JSON","parse","stringify","openapiContent","fs","readFile","controllerFiles","findControllerFiles","sourceMap","buildSourceMap","processControllerFile","enhanced","enhanceOpenApiPaths","duration","stats","controllersFound","length","endpointsExtracted","size","endpointsEnhanced","filePath","relativePath","relative","process","cwd","content","sourceFile","ts","createSourceFile","ScriptTarget","Latest","extractControllerMetadata","metadata","Map","controllerPath","className","getDecorators","node","Array","isArray","modifiers","filter","mod","kind","SyntaxKind","Decorator","decorators","visit","isClassDeclaration","name","getText","decorator","isCallExpression","expression","decoratorName","arguments","arg","isStringLiteral","text","isMethodDeclaration","methodName","httpMethod","routePath","line","getLineAndCharacterOfPosition","getStart","includes","toLowerCase","operationId","set","file","method","forEachChild","HTTP_DECORATOR_NAMES","findControllerFilesSync","dir","files","scan","currentDir","entries","readdirSync","withFileTypes","entry","fullPath","join","isDirectory","isFile","endsWith","push","normalizeApiPath","combined","normalized","replace","startsWith","slice","parseControllerRoutes","readFileSync","routes","getDecoratorsCompat","getStringArg","expr","dec","member","members","toUpperCase","parseApiRoutes","resolvedDir"]}