@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/cli/main.js
CHANGED
|
@@ -185,12 +185,12 @@ __name(extractPropsSource, "extractPropsSource");
|
|
|
185
185
|
|
|
186
186
|
// src/emit/emit-api.ts
|
|
187
187
|
import { mkdir, writeFile } from "fs/promises";
|
|
188
|
-
import { join as join2 } from "path";
|
|
188
|
+
import { join as join2, relative as relative3 } from "path";
|
|
189
189
|
async function emitApi(routes, outDir) {
|
|
190
190
|
await mkdir(outDir, {
|
|
191
191
|
recursive: true
|
|
192
192
|
});
|
|
193
|
-
const content = buildApiFile(routes);
|
|
193
|
+
const content = buildApiFile(routes, outDir);
|
|
194
194
|
await writeFile(join2(outDir, "api.ts"), content, "utf8");
|
|
195
195
|
}
|
|
196
196
|
__name(emitApi, "emitApi");
|
|
@@ -255,7 +255,20 @@ function insertIntoTree(tree, segments, leaf, fullName) {
|
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
__name(insertIntoTree, "insertIntoTree");
|
|
258
|
-
function
|
|
258
|
+
function buildResponseType(c, outDir) {
|
|
259
|
+
if (c.controllerRef) {
|
|
260
|
+
let relPath = relative3(outDir, c.controllerRef.filePath).replace(/\.ts$/, "");
|
|
261
|
+
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
262
|
+
return `Awaited<ReturnType<import('${relPath}').${c.controllerRef.className}['${c.controllerRef.methodName}']>>`;
|
|
263
|
+
}
|
|
264
|
+
const respRef = c.contractSource.responseRef;
|
|
265
|
+
if (respRef) {
|
|
266
|
+
return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;
|
|
267
|
+
}
|
|
268
|
+
return c.contractSource.response;
|
|
269
|
+
}
|
|
270
|
+
__name(buildResponseType, "buildResponseType");
|
|
271
|
+
function emitRouterTypeBlock(tree, indent, outDir) {
|
|
259
272
|
const pad = " ".repeat(indent);
|
|
260
273
|
const lines = [];
|
|
261
274
|
for (const [key, node] of tree) {
|
|
@@ -263,15 +276,17 @@ function emitRouterTypeBlock(tree, indent) {
|
|
|
263
276
|
if (node.kind === "leaf") {
|
|
264
277
|
const c = node;
|
|
265
278
|
const method = c.method.toUpperCase();
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
const
|
|
279
|
+
const queryRef = c.contractSource.queryRef;
|
|
280
|
+
const query = queryRef ? queryRef.isArray ? `Array<${queryRef.name}>` : queryRef.name : c.contractSource.query ?? "never";
|
|
281
|
+
const bodyRef = c.contractSource.bodyRef;
|
|
282
|
+
const body = method === "GET" ? "never" : bodyRef ? bodyRef.isArray ? `Array<${bodyRef.name}>` : bodyRef.name : c.contractSource.body ?? "never";
|
|
283
|
+
const response = buildResponseType(c, outDir);
|
|
269
284
|
const safeMethod = JSON.stringify(method);
|
|
270
285
|
const safeUrl = JSON.stringify(c.path);
|
|
271
286
|
lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
|
|
272
287
|
} else {
|
|
273
288
|
lines.push(`${pad}${objKey}: {`);
|
|
274
|
-
lines.push(...emitRouterTypeBlock(node.children, indent + 2));
|
|
289
|
+
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));
|
|
275
290
|
lines.push(`${pad}};`);
|
|
276
291
|
}
|
|
277
292
|
}
|
|
@@ -292,18 +307,21 @@ function emitApiObjectBlock(tree, indent) {
|
|
|
292
307
|
if (method === "GET") {
|
|
293
308
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
294
309
|
lines.push(`${pad}${objKey}: {`);
|
|
310
|
+
lines.push(`${pad} queryKey: (query?: ${typeAccess}['query']) => query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
295
311
|
lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query']) =>`);
|
|
296
|
-
lines.push(`${pad}
|
|
297
|
-
lines.push(`${pad} queryKey: [${flatName}, query],`);
|
|
312
|
+
lines.push(`${pad} _queryOptions({`);
|
|
313
|
+
lines.push(`${pad} queryKey: query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
298
314
|
lines.push(`${pad} queryFn: () => fetcher.get<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { query }),`);
|
|
299
315
|
lines.push(`${pad} }),`);
|
|
300
316
|
lines.push(`${pad}},`);
|
|
301
317
|
} else {
|
|
302
318
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
303
319
|
lines.push(`${pad}${objKey}: {`);
|
|
304
|
-
lines.push(`${pad}
|
|
305
|
-
lines.push(`${pad}
|
|
306
|
-
lines.push(`${pad}
|
|
320
|
+
lines.push(`${pad} queryKey: () => [${flatName}] as const,`);
|
|
321
|
+
lines.push(`${pad} mutationOptions: () =>`);
|
|
322
|
+
lines.push(`${pad} _mutationOptions({`);
|
|
323
|
+
lines.push(`${pad} mutationFn: (body: ${typeAccess}['body']) => fetcher.${fetcherMethod}<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { body }),`);
|
|
324
|
+
lines.push(`${pad} }),`);
|
|
307
325
|
lines.push(`${pad}},`);
|
|
308
326
|
}
|
|
309
327
|
} else {
|
|
@@ -320,18 +338,55 @@ function buildRouterTypeAccess(name) {
|
|
|
320
338
|
return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
|
|
321
339
|
}
|
|
322
340
|
__name(buildRouterTypeAccess, "buildRouterTypeAccess");
|
|
323
|
-
function buildApiFile(routes) {
|
|
341
|
+
function buildApiFile(routes, outDir) {
|
|
324
342
|
const contracted = routes.filter((r) => r.contract);
|
|
343
|
+
const importsByFile = /* @__PURE__ */ new Map();
|
|
344
|
+
for (const r of contracted) {
|
|
345
|
+
const cs = r.contract?.contractSource;
|
|
346
|
+
if (!cs) continue;
|
|
347
|
+
const refs = r.controllerRef ? [
|
|
348
|
+
cs.queryRef,
|
|
349
|
+
cs.bodyRef
|
|
350
|
+
] : [
|
|
351
|
+
cs.queryRef,
|
|
352
|
+
cs.bodyRef,
|
|
353
|
+
cs.responseRef
|
|
354
|
+
];
|
|
355
|
+
for (const ref of refs) {
|
|
356
|
+
if (!ref) continue;
|
|
357
|
+
let names = importsByFile.get(ref.filePath);
|
|
358
|
+
if (!names) {
|
|
359
|
+
names = /* @__PURE__ */ new Set();
|
|
360
|
+
importsByFile.set(ref.filePath, names);
|
|
361
|
+
}
|
|
362
|
+
names.add(ref.name);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
325
365
|
const hasGetRoutes = contracted.some((r) => r.method === "GET");
|
|
366
|
+
const hasMutationRoutes = contracted.some((r) => r.method !== "GET");
|
|
326
367
|
const lines = [
|
|
327
368
|
"// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
|
|
328
369
|
""
|
|
329
370
|
];
|
|
330
|
-
|
|
331
|
-
|
|
371
|
+
const tqImports = [];
|
|
372
|
+
if (hasGetRoutes) tqImports.push("queryOptions as _queryOptions");
|
|
373
|
+
if (hasMutationRoutes) tqImports.push("mutationOptions as _mutationOptions");
|
|
374
|
+
if (tqImports.length > 0) {
|
|
375
|
+
lines.push(`import { ${tqImports.join(", ")} } from '@tanstack/react-query';`);
|
|
332
376
|
}
|
|
333
377
|
lines.push("import { route } from './routes.js';");
|
|
334
378
|
lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
|
|
379
|
+
if (importsByFile.size > 0 && outDir) {
|
|
380
|
+
lines.push("");
|
|
381
|
+
for (const [filePath, names] of importsByFile) {
|
|
382
|
+
let relPath = relative3(outDir, filePath).replace(/\.ts$/, "");
|
|
383
|
+
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
384
|
+
const sortedNames = [
|
|
385
|
+
...names
|
|
386
|
+
].sort();
|
|
387
|
+
lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
335
390
|
lines.push("");
|
|
336
391
|
lines.push("export const fetcher = createFetcher();");
|
|
337
392
|
lines.push("");
|
|
@@ -372,13 +427,14 @@ function buildApiFile(routes) {
|
|
|
372
427
|
method: r.method,
|
|
373
428
|
name,
|
|
374
429
|
path: r.path,
|
|
430
|
+
controllerRef: r.controllerRef,
|
|
375
431
|
contractSource: c.contractSource
|
|
376
432
|
};
|
|
377
433
|
insertIntoTree(tree, segments, leaf, name);
|
|
378
434
|
}
|
|
379
435
|
void detectCollisions;
|
|
380
436
|
lines.push("export type ApiRouter = {");
|
|
381
|
-
lines.push(...emitRouterTypeBlock(tree, 2));
|
|
437
|
+
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ""));
|
|
382
438
|
lines.push("};");
|
|
383
439
|
lines.push("");
|
|
384
440
|
lines.push("export const api = {");
|
|
@@ -648,9 +704,28 @@ import { join as join9 } from "path";
|
|
|
648
704
|
import chokidar from "chokidar";
|
|
649
705
|
|
|
650
706
|
// src/discovery/contracts-fast.ts
|
|
707
|
+
import { readFileSync } from "fs";
|
|
651
708
|
import { dirname, join as join7, resolve as resolve2 } from "path";
|
|
652
709
|
import fg2 from "fast-glob";
|
|
653
710
|
import { Node, Project, SyntaxKind } from "ts-morph";
|
|
711
|
+
var _projectRoot = "";
|
|
712
|
+
var _tsconfigPaths = null;
|
|
713
|
+
var _debug = process.env.NESTJS_INERTIA_DEBUG === "1";
|
|
714
|
+
function dbg(...args) {
|
|
715
|
+
if (_debug) console.log("[codegen:debug]", ...args);
|
|
716
|
+
}
|
|
717
|
+
__name(dbg, "dbg");
|
|
718
|
+
function loadTsconfigPaths(tsconfigPath) {
|
|
719
|
+
try {
|
|
720
|
+
const raw = readFileSync(tsconfigPath, "utf8");
|
|
721
|
+
const stripped = raw.replace(/\/\/.*$/gm, "");
|
|
722
|
+
const parsed = JSON.parse(stripped);
|
|
723
|
+
return parsed.compilerOptions?.paths ?? null;
|
|
724
|
+
} catch {
|
|
725
|
+
return null;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
__name(loadTsconfigPaths, "loadTsconfigPaths");
|
|
654
729
|
async function discoverContractsFast(opts) {
|
|
655
730
|
const { cwd, glob, tsconfig } = opts;
|
|
656
731
|
const tsconfigPath = tsconfig ? resolve2(tsconfig) : join7(cwd, "tsconfig.json");
|
|
@@ -683,6 +758,8 @@ async function discoverContractsFast(opts) {
|
|
|
683
758
|
project.addSourceFileAtPath(f);
|
|
684
759
|
}
|
|
685
760
|
const routes = [];
|
|
761
|
+
_projectRoot = cwd;
|
|
762
|
+
_tsconfigPaths = loadTsconfigPaths(tsconfigPath);
|
|
686
763
|
for (const sourceFile of project.getSourceFiles()) {
|
|
687
764
|
routes.push(...extractFromSourceFile(sourceFile, project));
|
|
688
765
|
}
|
|
@@ -884,17 +961,41 @@ function findTypeInFile(name, file) {
|
|
|
884
961
|
return null;
|
|
885
962
|
}
|
|
886
963
|
__name(findTypeInFile, "findTypeInFile");
|
|
964
|
+
function resolveModuleSpecifier(moduleSpecifier, sourceFile, project) {
|
|
965
|
+
if (moduleSpecifier.startsWith(".")) {
|
|
966
|
+
const dir = dirname(sourceFile.getFilePath());
|
|
967
|
+
return [
|
|
968
|
+
resolve2(dir, `${moduleSpecifier}.ts`),
|
|
969
|
+
resolve2(dir, moduleSpecifier, "index.ts")
|
|
970
|
+
];
|
|
971
|
+
}
|
|
972
|
+
const baseUrl = _projectRoot;
|
|
973
|
+
dbg("resolveModuleSpecifier", moduleSpecifier, "paths:", JSON.stringify(_tsconfigPaths), "baseUrl:", baseUrl);
|
|
974
|
+
if (_tsconfigPaths) {
|
|
975
|
+
for (const [pattern, mappings] of Object.entries(_tsconfigPaths)) {
|
|
976
|
+
const prefix = pattern.replace("*", "");
|
|
977
|
+
if (moduleSpecifier.startsWith(prefix)) {
|
|
978
|
+
const rest = moduleSpecifier.slice(prefix.length);
|
|
979
|
+
const candidates = [];
|
|
980
|
+
for (const mapping of mappings) {
|
|
981
|
+
const resolved = resolve2(baseUrl, mapping.replace("*", rest));
|
|
982
|
+
candidates.push(`${resolved}.ts`, resolve2(resolved, "index.ts"));
|
|
983
|
+
}
|
|
984
|
+
dbg(" resolved candidates:", candidates);
|
|
985
|
+
return candidates;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
return [];
|
|
990
|
+
}
|
|
991
|
+
__name(resolveModuleSpecifier, "resolveModuleSpecifier");
|
|
887
992
|
function resolveImportedType(name, sourceFile, project) {
|
|
888
993
|
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
889
994
|
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
890
995
|
if (!namedImport) continue;
|
|
891
996
|
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
const candidates = [
|
|
895
|
-
resolve2(dir, `${moduleSpecifier}.ts`),
|
|
896
|
-
resolve2(dir, moduleSpecifier, "index.ts")
|
|
897
|
-
];
|
|
997
|
+
const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);
|
|
998
|
+
if (candidates.length === 0) continue;
|
|
898
999
|
for (const candidate of candidates) {
|
|
899
1000
|
let importedFile = project.getSourceFile(candidate);
|
|
900
1001
|
if (!importedFile) {
|
|
@@ -928,7 +1029,8 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
|
928
1029
|
const name = Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
|
|
929
1030
|
if (name === "string" || name === "number" || name === "boolean") return name;
|
|
930
1031
|
if (name === "Date") return "string";
|
|
931
|
-
if (name === "unknown" || name === "any") return "unknown";
|
|
1032
|
+
if (name === "unknown" || name === "any" || name === "void") return "unknown";
|
|
1033
|
+
if (name === "StreamableFile" || name === "Observable" || name === "ReadableStream") return "unknown";
|
|
932
1034
|
if (name === "Array") {
|
|
933
1035
|
const typeArgs = typeNode.getTypeArguments();
|
|
934
1036
|
const firstTypeArg = typeArgs[0];
|
|
@@ -937,6 +1039,18 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
|
937
1039
|
}
|
|
938
1040
|
return "Array<unknown>";
|
|
939
1041
|
}
|
|
1042
|
+
if ([
|
|
1043
|
+
"Record",
|
|
1044
|
+
"Omit",
|
|
1045
|
+
"Pick",
|
|
1046
|
+
"Partial",
|
|
1047
|
+
"Required",
|
|
1048
|
+
"Readonly",
|
|
1049
|
+
"Map",
|
|
1050
|
+
"Set"
|
|
1051
|
+
].includes(name)) {
|
|
1052
|
+
return typeNode.getText();
|
|
1053
|
+
}
|
|
940
1054
|
if (name === "Promise") {
|
|
941
1055
|
const typeArgs = typeNode.getTypeArguments();
|
|
942
1056
|
const firstTypeArg = typeArgs[0];
|
|
@@ -949,7 +1063,8 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
|
949
1063
|
if (resolved) {
|
|
950
1064
|
return expandTypeDecl(resolved, project, depth - 1);
|
|
951
1065
|
}
|
|
952
|
-
|
|
1066
|
+
dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
|
|
1067
|
+
return "unknown";
|
|
953
1068
|
}
|
|
954
1069
|
const kind = typeNode.getKind();
|
|
955
1070
|
if (kind === SyntaxKind.StringKeyword) return "string";
|
|
@@ -1076,6 +1191,68 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
|
1076
1191
|
return name;
|
|
1077
1192
|
}
|
|
1078
1193
|
__name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
|
|
1194
|
+
function tryResolveTypeRef(typeNode, sourceFile, project) {
|
|
1195
|
+
if (Node.isTypeReference(typeNode)) {
|
|
1196
|
+
const typeName = typeNode.getTypeName();
|
|
1197
|
+
const name = Node.isIdentifier(typeName) ? typeName.getText() : null;
|
|
1198
|
+
if (!name) return null;
|
|
1199
|
+
if (name === "Promise") {
|
|
1200
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
1201
|
+
const first = typeArgs[0];
|
|
1202
|
+
if (first) return tryResolveTypeRef(first, sourceFile, project);
|
|
1203
|
+
return null;
|
|
1204
|
+
}
|
|
1205
|
+
if (name === "Array") {
|
|
1206
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
1207
|
+
const first = typeArgs[0];
|
|
1208
|
+
if (first) {
|
|
1209
|
+
const inner = tryResolveTypeRef(first, sourceFile, project);
|
|
1210
|
+
if (inner) return {
|
|
1211
|
+
...inner,
|
|
1212
|
+
isArray: true
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
if ([
|
|
1218
|
+
"string",
|
|
1219
|
+
"number",
|
|
1220
|
+
"boolean",
|
|
1221
|
+
"void",
|
|
1222
|
+
"unknown",
|
|
1223
|
+
"any",
|
|
1224
|
+
"Date"
|
|
1225
|
+
].includes(name)) {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1229
|
+
if (localDecl?.isExported()) {
|
|
1230
|
+
return {
|
|
1231
|
+
name,
|
|
1232
|
+
filePath: sourceFile.getFilePath()
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1236
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
|
|
1237
|
+
const decl = resolved.decl;
|
|
1238
|
+
if (decl.isExported()) {
|
|
1239
|
+
return {
|
|
1240
|
+
name,
|
|
1241
|
+
filePath: resolved.file.getFilePath()
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
if (Node.isArrayTypeNode(typeNode)) {
|
|
1247
|
+
const inner = tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
|
|
1248
|
+
if (inner) return {
|
|
1249
|
+
...inner,
|
|
1250
|
+
isArray: true
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
__name(tryResolveTypeRef, "tryResolveTypeRef");
|
|
1079
1256
|
function extractDtoContract(method, sourceFile, project) {
|
|
1080
1257
|
const body = extractBodyType(method, sourceFile, project);
|
|
1081
1258
|
const query = extractQueryType(method, sourceFile, project);
|
|
@@ -1084,11 +1261,61 @@ function extractDtoContract(method, sourceFile, project) {
|
|
|
1084
1261
|
if (body === null && query === null && paramsType === null && response === "unknown") {
|
|
1085
1262
|
return null;
|
|
1086
1263
|
}
|
|
1264
|
+
let bodyRef = null;
|
|
1265
|
+
let queryRef = null;
|
|
1266
|
+
let responseRef = null;
|
|
1267
|
+
for (const param of method.getParameters()) {
|
|
1268
|
+
if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
|
|
1269
|
+
bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1270
|
+
}
|
|
1271
|
+
if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
|
|
1272
|
+
queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
const returnTypeNode = method.getReturnTypeNode();
|
|
1276
|
+
if (returnTypeNode) {
|
|
1277
|
+
responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
|
|
1278
|
+
}
|
|
1279
|
+
if (!responseRef) {
|
|
1280
|
+
const apiResp = method.getDecorator("ApiResponse");
|
|
1281
|
+
if (apiResp) {
|
|
1282
|
+
const args = apiResp.getArguments();
|
|
1283
|
+
const optsArg = args[0];
|
|
1284
|
+
if (optsArg && Node.isObjectLiteralExpression(optsArg)) {
|
|
1285
|
+
for (const prop of optsArg.getProperties()) {
|
|
1286
|
+
if (Node.isPropertyAssignment(prop) && prop.getName() === "type") {
|
|
1287
|
+
const val = prop.getInitializer();
|
|
1288
|
+
if (val && Node.isIdentifier(val)) {
|
|
1289
|
+
const name = val.getText();
|
|
1290
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1291
|
+
if (localDecl?.isExported()) {
|
|
1292
|
+
responseRef = {
|
|
1293
|
+
name,
|
|
1294
|
+
filePath: sourceFile.getFilePath()
|
|
1295
|
+
};
|
|
1296
|
+
} else {
|
|
1297
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1298
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
|
|
1299
|
+
responseRef = {
|
|
1300
|
+
name,
|
|
1301
|
+
filePath: resolved.file.getFilePath()
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1087
1311
|
return {
|
|
1088
1312
|
query,
|
|
1089
1313
|
body,
|
|
1090
1314
|
response,
|
|
1091
|
-
params: paramsType
|
|
1315
|
+
params: paramsType,
|
|
1316
|
+
queryRef,
|
|
1317
|
+
bodyRef,
|
|
1318
|
+
responseRef
|
|
1092
1319
|
};
|
|
1093
1320
|
}
|
|
1094
1321
|
__name(extractDtoContract, "extractDtoContract");
|
|
@@ -1187,6 +1414,11 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1187
1414
|
path: combined,
|
|
1188
1415
|
name: routeName,
|
|
1189
1416
|
params,
|
|
1417
|
+
controllerRef: {
|
|
1418
|
+
className,
|
|
1419
|
+
methodName,
|
|
1420
|
+
filePath: sourceFile.getFilePath()
|
|
1421
|
+
},
|
|
1190
1422
|
contract: {
|
|
1191
1423
|
contractSource: {
|
|
1192
1424
|
query: contractDef.query,
|
|
@@ -1221,13 +1453,20 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1221
1453
|
path: combined,
|
|
1222
1454
|
name: routeName,
|
|
1223
1455
|
params,
|
|
1224
|
-
|
|
1456
|
+
controllerRef: {
|
|
1457
|
+
className,
|
|
1458
|
+
methodName,
|
|
1459
|
+
filePath: sourceFile.getFilePath()
|
|
1460
|
+
},
|
|
1225
1461
|
...dtoContract ? {
|
|
1226
1462
|
contract: {
|
|
1227
1463
|
contractSource: {
|
|
1228
1464
|
query: dtoContract.query,
|
|
1229
1465
|
body: dtoContract.body,
|
|
1230
|
-
response: dtoContract.response
|
|
1466
|
+
response: dtoContract.response,
|
|
1467
|
+
queryRef: dtoContract.queryRef,
|
|
1468
|
+
bodyRef: dtoContract.bodyRef,
|
|
1469
|
+
responseRef: dtoContract.responseRef
|
|
1231
1470
|
}
|
|
1232
1471
|
}
|
|
1233
1472
|
} : {}
|
|
@@ -1400,7 +1639,7 @@ async function watch(config, onChange) {
|
|
|
1400
1639
|
__name(watch, "watch");
|
|
1401
1640
|
|
|
1402
1641
|
// src/index.ts
|
|
1403
|
-
var VERSION = "1.0
|
|
1642
|
+
var VERSION = "1.3.0";
|
|
1404
1643
|
|
|
1405
1644
|
// src/cli/codegen.ts
|
|
1406
1645
|
async function runCodegen(opts = {}) {
|
|
@@ -1432,7 +1671,7 @@ __name(runCodegen, "runCodegen");
|
|
|
1432
1671
|
|
|
1433
1672
|
// src/cli/init.ts
|
|
1434
1673
|
import { execSync } from "child_process";
|
|
1435
|
-
import { readFileSync, writeFileSync } from "fs";
|
|
1674
|
+
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
1436
1675
|
import { access as access2, mkdir as mkdir7, readFile as readFile4, writeFile as writeFile7 } from "fs/promises";
|
|
1437
1676
|
import { join as join10 } from "path";
|
|
1438
1677
|
import { createInterface } from "readline";
|
|
@@ -1656,7 +1895,7 @@ __name(findAfterLastImport, "findAfterLastImport");
|
|
|
1656
1895
|
function patchAppModule(filePath, rootView) {
|
|
1657
1896
|
let content;
|
|
1658
1897
|
try {
|
|
1659
|
-
content =
|
|
1898
|
+
content = readFileSync2(filePath, "utf8");
|
|
1660
1899
|
} catch {
|
|
1661
1900
|
return "skipped";
|
|
1662
1901
|
}
|
|
@@ -1701,7 +1940,7 @@ __name(patchAppModule, "patchAppModule");
|
|
|
1701
1940
|
function patchMainTs(filePath) {
|
|
1702
1941
|
let content;
|
|
1703
1942
|
try {
|
|
1704
|
-
content =
|
|
1943
|
+
content = readFileSync2(filePath, "utf8");
|
|
1705
1944
|
} catch {
|
|
1706
1945
|
return "skipped";
|
|
1707
1946
|
}
|
|
@@ -1774,11 +2013,19 @@ function htmlShellTemplate(framework, _engine) {
|
|
|
1774
2013
|
__name(htmlShellTemplate, "htmlShellTemplate");
|
|
1775
2014
|
function viteConfigTemplate(framework) {
|
|
1776
2015
|
const pluginOption = `{ ${framework}: true }`;
|
|
1777
|
-
return `import {
|
|
2016
|
+
return `import { resolve } from 'node:path';
|
|
2017
|
+
import { defineConfig } from 'vite';
|
|
1778
2018
|
import nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';
|
|
1779
2019
|
|
|
1780
2020
|
export default defineConfig({
|
|
1781
2021
|
plugins: [nestInertia(${pluginOption})],
|
|
2022
|
+
resolve: {
|
|
2023
|
+
alias: {
|
|
2024
|
+
'@': resolve(__dirname, 'src'),
|
|
2025
|
+
'~': resolve(__dirname, 'inertia'),
|
|
2026
|
+
'~codegen': resolve(__dirname, '.nestjs-inertia'),
|
|
2027
|
+
},
|
|
2028
|
+
},
|
|
1782
2029
|
});
|
|
1783
2030
|
`;
|
|
1784
2031
|
}
|