@dudousxd/nestjs-inertia-codegen 1.0.7 → 1.3.0
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/CHANGELOG.md +42 -0
- package/dist/cli/main.cjs +280 -33
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +279 -32
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +266 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +267 -28
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -243,7 +243,7 @@ async function emitApi(routes, outDir) {
|
|
|
243
243
|
await (0, import_promises3.mkdir)(outDir, {
|
|
244
244
|
recursive: true
|
|
245
245
|
});
|
|
246
|
-
const content = buildApiFile(routes);
|
|
246
|
+
const content = buildApiFile(routes, outDir);
|
|
247
247
|
await (0, import_promises3.writeFile)((0, import_node_path3.join)(outDir, "api.ts"), content, "utf8");
|
|
248
248
|
}
|
|
249
249
|
__name(emitApi, "emitApi");
|
|
@@ -308,7 +308,20 @@ function insertIntoTree(tree, segments, leaf, fullName) {
|
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
__name(insertIntoTree, "insertIntoTree");
|
|
311
|
-
function
|
|
311
|
+
function buildResponseType(c, outDir) {
|
|
312
|
+
if (c.controllerRef) {
|
|
313
|
+
let relPath = (0, import_node_path3.relative)(outDir, c.controllerRef.filePath).replace(/\.ts$/, "");
|
|
314
|
+
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
315
|
+
return `Awaited<ReturnType<import('${relPath}').${c.controllerRef.className}['${c.controllerRef.methodName}']>>`;
|
|
316
|
+
}
|
|
317
|
+
const respRef = c.contractSource.responseRef;
|
|
318
|
+
if (respRef) {
|
|
319
|
+
return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;
|
|
320
|
+
}
|
|
321
|
+
return c.contractSource.response;
|
|
322
|
+
}
|
|
323
|
+
__name(buildResponseType, "buildResponseType");
|
|
324
|
+
function emitRouterTypeBlock(tree, indent, outDir) {
|
|
312
325
|
const pad = " ".repeat(indent);
|
|
313
326
|
const lines = [];
|
|
314
327
|
for (const [key, node] of tree) {
|
|
@@ -316,15 +329,17 @@ function emitRouterTypeBlock(tree, indent) {
|
|
|
316
329
|
if (node.kind === "leaf") {
|
|
317
330
|
const c = node;
|
|
318
331
|
const method = c.method.toUpperCase();
|
|
319
|
-
const
|
|
320
|
-
const
|
|
321
|
-
const
|
|
332
|
+
const queryRef = c.contractSource.queryRef;
|
|
333
|
+
const query = queryRef ? queryRef.isArray ? `Array<${queryRef.name}>` : queryRef.name : c.contractSource.query ?? "never";
|
|
334
|
+
const bodyRef = c.contractSource.bodyRef;
|
|
335
|
+
const body = method === "GET" ? "never" : bodyRef ? bodyRef.isArray ? `Array<${bodyRef.name}>` : bodyRef.name : c.contractSource.body ?? "never";
|
|
336
|
+
const response = buildResponseType(c, outDir);
|
|
322
337
|
const safeMethod = JSON.stringify(method);
|
|
323
338
|
const safeUrl = JSON.stringify(c.path);
|
|
324
339
|
lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
|
|
325
340
|
} else {
|
|
326
341
|
lines.push(`${pad}${objKey}: {`);
|
|
327
|
-
lines.push(...emitRouterTypeBlock(node.children, indent + 2));
|
|
342
|
+
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));
|
|
328
343
|
lines.push(`${pad}};`);
|
|
329
344
|
}
|
|
330
345
|
}
|
|
@@ -345,18 +360,21 @@ function emitApiObjectBlock(tree, indent) {
|
|
|
345
360
|
if (method === "GET") {
|
|
346
361
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
347
362
|
lines.push(`${pad}${objKey}: {`);
|
|
363
|
+
lines.push(`${pad} queryKey: (query?: ${typeAccess}['query']) => query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
348
364
|
lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query']) =>`);
|
|
349
|
-
lines.push(`${pad}
|
|
350
|
-
lines.push(`${pad} queryKey: [${flatName}, query],`);
|
|
365
|
+
lines.push(`${pad} _queryOptions({`);
|
|
366
|
+
lines.push(`${pad} queryKey: query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
351
367
|
lines.push(`${pad} queryFn: () => fetcher.get<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { query }),`);
|
|
352
368
|
lines.push(`${pad} }),`);
|
|
353
369
|
lines.push(`${pad}},`);
|
|
354
370
|
} else {
|
|
355
371
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
356
372
|
lines.push(`${pad}${objKey}: {`);
|
|
357
|
-
lines.push(`${pad}
|
|
358
|
-
lines.push(`${pad}
|
|
359
|
-
lines.push(`${pad}
|
|
373
|
+
lines.push(`${pad} queryKey: () => [${flatName}] as const,`);
|
|
374
|
+
lines.push(`${pad} mutationOptions: () =>`);
|
|
375
|
+
lines.push(`${pad} _mutationOptions({`);
|
|
376
|
+
lines.push(`${pad} mutationFn: (body: ${typeAccess}['body']) => fetcher.${fetcherMethod}<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { body }),`);
|
|
377
|
+
lines.push(`${pad} }),`);
|
|
360
378
|
lines.push(`${pad}},`);
|
|
361
379
|
}
|
|
362
380
|
} else {
|
|
@@ -373,18 +391,55 @@ function buildRouterTypeAccess(name) {
|
|
|
373
391
|
return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
|
|
374
392
|
}
|
|
375
393
|
__name(buildRouterTypeAccess, "buildRouterTypeAccess");
|
|
376
|
-
function buildApiFile(routes) {
|
|
394
|
+
function buildApiFile(routes, outDir) {
|
|
377
395
|
const contracted = routes.filter((r) => r.contract);
|
|
396
|
+
const importsByFile = /* @__PURE__ */ new Map();
|
|
397
|
+
for (const r of contracted) {
|
|
398
|
+
const cs = r.contract?.contractSource;
|
|
399
|
+
if (!cs) continue;
|
|
400
|
+
const refs = r.controllerRef ? [
|
|
401
|
+
cs.queryRef,
|
|
402
|
+
cs.bodyRef
|
|
403
|
+
] : [
|
|
404
|
+
cs.queryRef,
|
|
405
|
+
cs.bodyRef,
|
|
406
|
+
cs.responseRef
|
|
407
|
+
];
|
|
408
|
+
for (const ref of refs) {
|
|
409
|
+
if (!ref) continue;
|
|
410
|
+
let names = importsByFile.get(ref.filePath);
|
|
411
|
+
if (!names) {
|
|
412
|
+
names = /* @__PURE__ */ new Set();
|
|
413
|
+
importsByFile.set(ref.filePath, names);
|
|
414
|
+
}
|
|
415
|
+
names.add(ref.name);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
378
418
|
const hasGetRoutes = contracted.some((r) => r.method === "GET");
|
|
419
|
+
const hasMutationRoutes = contracted.some((r) => r.method !== "GET");
|
|
379
420
|
const lines = [
|
|
380
421
|
"// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
|
|
381
422
|
""
|
|
382
423
|
];
|
|
383
|
-
|
|
384
|
-
|
|
424
|
+
const tqImports = [];
|
|
425
|
+
if (hasGetRoutes) tqImports.push("queryOptions as _queryOptions");
|
|
426
|
+
if (hasMutationRoutes) tqImports.push("mutationOptions as _mutationOptions");
|
|
427
|
+
if (tqImports.length > 0) {
|
|
428
|
+
lines.push(`import { ${tqImports.join(", ")} } from '@tanstack/react-query';`);
|
|
385
429
|
}
|
|
386
430
|
lines.push("import { route } from './routes.js';");
|
|
387
431
|
lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
|
|
432
|
+
if (importsByFile.size > 0 && outDir) {
|
|
433
|
+
lines.push("");
|
|
434
|
+
for (const [filePath, names] of importsByFile) {
|
|
435
|
+
let relPath = (0, import_node_path3.relative)(outDir, filePath).replace(/\.ts$/, "");
|
|
436
|
+
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
437
|
+
const sortedNames = [
|
|
438
|
+
...names
|
|
439
|
+
].sort();
|
|
440
|
+
lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
388
443
|
lines.push("");
|
|
389
444
|
lines.push("export const fetcher = createFetcher();");
|
|
390
445
|
lines.push("");
|
|
@@ -425,13 +480,14 @@ function buildApiFile(routes) {
|
|
|
425
480
|
method: r.method,
|
|
426
481
|
name,
|
|
427
482
|
path: r.path,
|
|
483
|
+
controllerRef: r.controllerRef,
|
|
428
484
|
contractSource: c.contractSource
|
|
429
485
|
};
|
|
430
486
|
insertIntoTree(tree, segments, leaf, name);
|
|
431
487
|
}
|
|
432
488
|
void detectCollisions;
|
|
433
489
|
lines.push("export type ApiRouter = {");
|
|
434
|
-
lines.push(...emitRouterTypeBlock(tree, 2));
|
|
490
|
+
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ""));
|
|
435
491
|
lines.push("};");
|
|
436
492
|
lines.push("");
|
|
437
493
|
lines.push("export const api = {");
|
|
@@ -701,9 +757,28 @@ var import_node_path10 = require("path");
|
|
|
701
757
|
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
702
758
|
|
|
703
759
|
// src/discovery/contracts-fast.ts
|
|
760
|
+
var import_node_fs = require("fs");
|
|
704
761
|
var import_node_path8 = require("path");
|
|
705
762
|
var import_fast_glob2 = __toESM(require("fast-glob"), 1);
|
|
706
763
|
var import_ts_morph = require("ts-morph");
|
|
764
|
+
var _projectRoot = "";
|
|
765
|
+
var _tsconfigPaths = null;
|
|
766
|
+
var _debug = process.env.NESTJS_INERTIA_DEBUG === "1";
|
|
767
|
+
function dbg(...args) {
|
|
768
|
+
if (_debug) console.log("[codegen:debug]", ...args);
|
|
769
|
+
}
|
|
770
|
+
__name(dbg, "dbg");
|
|
771
|
+
function loadTsconfigPaths(tsconfigPath) {
|
|
772
|
+
try {
|
|
773
|
+
const raw = (0, import_node_fs.readFileSync)(tsconfigPath, "utf8");
|
|
774
|
+
const stripped = raw.replace(/\/\/.*$/gm, "");
|
|
775
|
+
const parsed = JSON.parse(stripped);
|
|
776
|
+
return parsed.compilerOptions?.paths ?? null;
|
|
777
|
+
} catch {
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
__name(loadTsconfigPaths, "loadTsconfigPaths");
|
|
707
782
|
async function discoverContractsFast(opts) {
|
|
708
783
|
const { cwd, glob, tsconfig } = opts;
|
|
709
784
|
const tsconfigPath = tsconfig ? (0, import_node_path8.resolve)(tsconfig) : (0, import_node_path8.join)(cwd, "tsconfig.json");
|
|
@@ -736,6 +811,8 @@ async function discoverContractsFast(opts) {
|
|
|
736
811
|
project.addSourceFileAtPath(f);
|
|
737
812
|
}
|
|
738
813
|
const routes = [];
|
|
814
|
+
_projectRoot = cwd;
|
|
815
|
+
_tsconfigPaths = loadTsconfigPaths(tsconfigPath);
|
|
739
816
|
for (const sourceFile of project.getSourceFiles()) {
|
|
740
817
|
routes.push(...extractFromSourceFile(sourceFile, project));
|
|
741
818
|
}
|
|
@@ -937,17 +1014,41 @@ function findTypeInFile(name, file) {
|
|
|
937
1014
|
return null;
|
|
938
1015
|
}
|
|
939
1016
|
__name(findTypeInFile, "findTypeInFile");
|
|
1017
|
+
function resolveModuleSpecifier(moduleSpecifier, sourceFile, project) {
|
|
1018
|
+
if (moduleSpecifier.startsWith(".")) {
|
|
1019
|
+
const dir = (0, import_node_path8.dirname)(sourceFile.getFilePath());
|
|
1020
|
+
return [
|
|
1021
|
+
(0, import_node_path8.resolve)(dir, `${moduleSpecifier}.ts`),
|
|
1022
|
+
(0, import_node_path8.resolve)(dir, moduleSpecifier, "index.ts")
|
|
1023
|
+
];
|
|
1024
|
+
}
|
|
1025
|
+
const baseUrl = _projectRoot;
|
|
1026
|
+
dbg("resolveModuleSpecifier", moduleSpecifier, "paths:", JSON.stringify(_tsconfigPaths), "baseUrl:", baseUrl);
|
|
1027
|
+
if (_tsconfigPaths) {
|
|
1028
|
+
for (const [pattern, mappings] of Object.entries(_tsconfigPaths)) {
|
|
1029
|
+
const prefix = pattern.replace("*", "");
|
|
1030
|
+
if (moduleSpecifier.startsWith(prefix)) {
|
|
1031
|
+
const rest = moduleSpecifier.slice(prefix.length);
|
|
1032
|
+
const candidates = [];
|
|
1033
|
+
for (const mapping of mappings) {
|
|
1034
|
+
const resolved = (0, import_node_path8.resolve)(baseUrl, mapping.replace("*", rest));
|
|
1035
|
+
candidates.push(`${resolved}.ts`, (0, import_node_path8.resolve)(resolved, "index.ts"));
|
|
1036
|
+
}
|
|
1037
|
+
dbg(" resolved candidates:", candidates);
|
|
1038
|
+
return candidates;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
return [];
|
|
1043
|
+
}
|
|
1044
|
+
__name(resolveModuleSpecifier, "resolveModuleSpecifier");
|
|
940
1045
|
function resolveImportedType(name, sourceFile, project) {
|
|
941
1046
|
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
942
1047
|
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
943
1048
|
if (!namedImport) continue;
|
|
944
1049
|
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
const candidates = [
|
|
948
|
-
(0, import_node_path8.resolve)(dir, `${moduleSpecifier}.ts`),
|
|
949
|
-
(0, import_node_path8.resolve)(dir, moduleSpecifier, "index.ts")
|
|
950
|
-
];
|
|
1050
|
+
const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);
|
|
1051
|
+
if (candidates.length === 0) continue;
|
|
951
1052
|
for (const candidate of candidates) {
|
|
952
1053
|
let importedFile = project.getSourceFile(candidate);
|
|
953
1054
|
if (!importedFile) {
|
|
@@ -981,7 +1082,8 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
|
981
1082
|
const name = import_ts_morph.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
|
|
982
1083
|
if (name === "string" || name === "number" || name === "boolean") return name;
|
|
983
1084
|
if (name === "Date") return "string";
|
|
984
|
-
if (name === "unknown" || name === "any") return "unknown";
|
|
1085
|
+
if (name === "unknown" || name === "any" || name === "void") return "unknown";
|
|
1086
|
+
if (name === "StreamableFile" || name === "Observable" || name === "ReadableStream") return "unknown";
|
|
985
1087
|
if (name === "Array") {
|
|
986
1088
|
const typeArgs = typeNode.getTypeArguments();
|
|
987
1089
|
const firstTypeArg = typeArgs[0];
|
|
@@ -990,6 +1092,18 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
|
990
1092
|
}
|
|
991
1093
|
return "Array<unknown>";
|
|
992
1094
|
}
|
|
1095
|
+
if ([
|
|
1096
|
+
"Record",
|
|
1097
|
+
"Omit",
|
|
1098
|
+
"Pick",
|
|
1099
|
+
"Partial",
|
|
1100
|
+
"Required",
|
|
1101
|
+
"Readonly",
|
|
1102
|
+
"Map",
|
|
1103
|
+
"Set"
|
|
1104
|
+
].includes(name)) {
|
|
1105
|
+
return typeNode.getText();
|
|
1106
|
+
}
|
|
993
1107
|
if (name === "Promise") {
|
|
994
1108
|
const typeArgs = typeNode.getTypeArguments();
|
|
995
1109
|
const firstTypeArg = typeArgs[0];
|
|
@@ -1002,7 +1116,8 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
|
1002
1116
|
if (resolved) {
|
|
1003
1117
|
return expandTypeDecl(resolved, project, depth - 1);
|
|
1004
1118
|
}
|
|
1005
|
-
|
|
1119
|
+
dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
|
|
1120
|
+
return "unknown";
|
|
1006
1121
|
}
|
|
1007
1122
|
const kind = typeNode.getKind();
|
|
1008
1123
|
if (kind === import_ts_morph.SyntaxKind.StringKeyword) return "string";
|
|
@@ -1129,6 +1244,68 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
|
1129
1244
|
return name;
|
|
1130
1245
|
}
|
|
1131
1246
|
__name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
|
|
1247
|
+
function tryResolveTypeRef(typeNode, sourceFile, project) {
|
|
1248
|
+
if (import_ts_morph.Node.isTypeReference(typeNode)) {
|
|
1249
|
+
const typeName = typeNode.getTypeName();
|
|
1250
|
+
const name = import_ts_morph.Node.isIdentifier(typeName) ? typeName.getText() : null;
|
|
1251
|
+
if (!name) return null;
|
|
1252
|
+
if (name === "Promise") {
|
|
1253
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
1254
|
+
const first = typeArgs[0];
|
|
1255
|
+
if (first) return tryResolveTypeRef(first, sourceFile, project);
|
|
1256
|
+
return null;
|
|
1257
|
+
}
|
|
1258
|
+
if (name === "Array") {
|
|
1259
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
1260
|
+
const first = typeArgs[0];
|
|
1261
|
+
if (first) {
|
|
1262
|
+
const inner = tryResolveTypeRef(first, sourceFile, project);
|
|
1263
|
+
if (inner) return {
|
|
1264
|
+
...inner,
|
|
1265
|
+
isArray: true
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
return null;
|
|
1269
|
+
}
|
|
1270
|
+
if ([
|
|
1271
|
+
"string",
|
|
1272
|
+
"number",
|
|
1273
|
+
"boolean",
|
|
1274
|
+
"void",
|
|
1275
|
+
"unknown",
|
|
1276
|
+
"any",
|
|
1277
|
+
"Date"
|
|
1278
|
+
].includes(name)) {
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1282
|
+
if (localDecl?.isExported()) {
|
|
1283
|
+
return {
|
|
1284
|
+
name,
|
|
1285
|
+
filePath: sourceFile.getFilePath()
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1289
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
|
|
1290
|
+
const decl = resolved.decl;
|
|
1291
|
+
if (decl.isExported()) {
|
|
1292
|
+
return {
|
|
1293
|
+
name,
|
|
1294
|
+
filePath: resolved.file.getFilePath()
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
if (import_ts_morph.Node.isArrayTypeNode(typeNode)) {
|
|
1300
|
+
const inner = tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
|
|
1301
|
+
if (inner) return {
|
|
1302
|
+
...inner,
|
|
1303
|
+
isArray: true
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
return null;
|
|
1307
|
+
}
|
|
1308
|
+
__name(tryResolveTypeRef, "tryResolveTypeRef");
|
|
1132
1309
|
function extractDtoContract(method, sourceFile, project) {
|
|
1133
1310
|
const body = extractBodyType(method, sourceFile, project);
|
|
1134
1311
|
const query = extractQueryType(method, sourceFile, project);
|
|
@@ -1137,11 +1314,61 @@ function extractDtoContract(method, sourceFile, project) {
|
|
|
1137
1314
|
if (body === null && query === null && paramsType === null && response === "unknown") {
|
|
1138
1315
|
return null;
|
|
1139
1316
|
}
|
|
1317
|
+
let bodyRef = null;
|
|
1318
|
+
let queryRef = null;
|
|
1319
|
+
let responseRef = null;
|
|
1320
|
+
for (const param of method.getParameters()) {
|
|
1321
|
+
if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
|
|
1322
|
+
bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1323
|
+
}
|
|
1324
|
+
if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
|
|
1325
|
+
queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
const returnTypeNode = method.getReturnTypeNode();
|
|
1329
|
+
if (returnTypeNode) {
|
|
1330
|
+
responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
|
|
1331
|
+
}
|
|
1332
|
+
if (!responseRef) {
|
|
1333
|
+
const apiResp = method.getDecorator("ApiResponse");
|
|
1334
|
+
if (apiResp) {
|
|
1335
|
+
const args = apiResp.getArguments();
|
|
1336
|
+
const optsArg = args[0];
|
|
1337
|
+
if (optsArg && import_ts_morph.Node.isObjectLiteralExpression(optsArg)) {
|
|
1338
|
+
for (const prop of optsArg.getProperties()) {
|
|
1339
|
+
if (import_ts_morph.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
|
|
1340
|
+
const val = prop.getInitializer();
|
|
1341
|
+
if (val && import_ts_morph.Node.isIdentifier(val)) {
|
|
1342
|
+
const name = val.getText();
|
|
1343
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1344
|
+
if (localDecl?.isExported()) {
|
|
1345
|
+
responseRef = {
|
|
1346
|
+
name,
|
|
1347
|
+
filePath: sourceFile.getFilePath()
|
|
1348
|
+
};
|
|
1349
|
+
} else {
|
|
1350
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1351
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
|
|
1352
|
+
responseRef = {
|
|
1353
|
+
name,
|
|
1354
|
+
filePath: resolved.file.getFilePath()
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1140
1364
|
return {
|
|
1141
1365
|
query,
|
|
1142
1366
|
body,
|
|
1143
1367
|
response,
|
|
1144
|
-
params: paramsType
|
|
1368
|
+
params: paramsType,
|
|
1369
|
+
queryRef,
|
|
1370
|
+
bodyRef,
|
|
1371
|
+
responseRef
|
|
1145
1372
|
};
|
|
1146
1373
|
}
|
|
1147
1374
|
__name(extractDtoContract, "extractDtoContract");
|
|
@@ -1240,6 +1467,11 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1240
1467
|
path: combined,
|
|
1241
1468
|
name: routeName,
|
|
1242
1469
|
params,
|
|
1470
|
+
controllerRef: {
|
|
1471
|
+
className,
|
|
1472
|
+
methodName,
|
|
1473
|
+
filePath: sourceFile.getFilePath()
|
|
1474
|
+
},
|
|
1243
1475
|
contract: {
|
|
1244
1476
|
contractSource: {
|
|
1245
1477
|
query: contractDef.query,
|
|
@@ -1274,13 +1506,20 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1274
1506
|
path: combined,
|
|
1275
1507
|
name: routeName,
|
|
1276
1508
|
params,
|
|
1277
|
-
|
|
1509
|
+
controllerRef: {
|
|
1510
|
+
className,
|
|
1511
|
+
methodName,
|
|
1512
|
+
filePath: sourceFile.getFilePath()
|
|
1513
|
+
},
|
|
1278
1514
|
...dtoContract ? {
|
|
1279
1515
|
contract: {
|
|
1280
1516
|
contractSource: {
|
|
1281
1517
|
query: dtoContract.query,
|
|
1282
1518
|
body: dtoContract.body,
|
|
1283
|
-
response: dtoContract.response
|
|
1519
|
+
response: dtoContract.response,
|
|
1520
|
+
queryRef: dtoContract.queryRef,
|
|
1521
|
+
bodyRef: dtoContract.bodyRef,
|
|
1522
|
+
responseRef: dtoContract.responseRef
|
|
1284
1523
|
}
|
|
1285
1524
|
}
|
|
1286
1525
|
} : {}
|
|
@@ -1453,7 +1692,7 @@ async function watch(config, onChange) {
|
|
|
1453
1692
|
__name(watch, "watch");
|
|
1454
1693
|
|
|
1455
1694
|
// src/index.ts
|
|
1456
|
-
var VERSION = "1.0
|
|
1695
|
+
var VERSION = "1.3.0";
|
|
1457
1696
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1458
1697
|
0 && (module.exports = {
|
|
1459
1698
|
CodegenError,
|