@dudousxd/nestjs-inertia-codegen 2.0.1 → 3.0.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 CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog — @dudousxd/nestjs-inertia-codegen
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat(codegen): import type references from source instead of inline expansion — eliminates unknown fields from depth limits
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies []:
12
+ - @dudousxd/nestjs-inertia@3.0.0
13
+
3
14
  ## 2.0.1
4
15
 
5
16
  ### Patch Changes
package/dist/cli/main.cjs CHANGED
@@ -222,7 +222,7 @@ async function emitApi(routes, outDir) {
222
222
  await (0, import_promises3.mkdir)(outDir, {
223
223
  recursive: true
224
224
  });
225
- const content = buildApiFile(routes);
225
+ const content = buildApiFile(routes, outDir);
226
226
  await (0, import_promises3.writeFile)((0, import_node_path3.join)(outDir, "api.ts"), content, "utf8");
227
227
  }
228
228
  __name(emitApi, "emitApi");
@@ -295,9 +295,9 @@ function emitRouterTypeBlock(tree, indent) {
295
295
  if (node.kind === "leaf") {
296
296
  const c = node;
297
297
  const method = c.method.toUpperCase();
298
- const query = c.contractSource.query ?? "never";
299
- const body = method === "GET" ? "never" : c.contractSource.body ?? "never";
300
- const response = c.contractSource.response;
298
+ const query = c.contractSource.queryRef ? c.contractSource.queryRef.name : c.contractSource.query ?? "never";
299
+ const body = method === "GET" ? "never" : c.contractSource.bodyRef ? c.contractSource.bodyRef.name : c.contractSource.body ?? "never";
300
+ const response = c.contractSource.responseRef ? c.contractSource.responseRef.name : c.contractSource.response;
301
301
  const safeMethod = JSON.stringify(method);
302
302
  const safeUrl = JSON.stringify(c.path);
303
303
  lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
@@ -353,14 +353,43 @@ function buildRouterTypeAccess(name) {
353
353
  return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
354
354
  }
355
355
  __name(buildRouterTypeAccess, "buildRouterTypeAccess");
356
- function buildApiFile(routes) {
356
+ function buildApiFile(routes, outDir) {
357
357
  const contracted = routes.filter((r) => r.contract);
358
+ const importsByFile = /* @__PURE__ */ new Map();
359
+ for (const r of contracted) {
360
+ const cs = r.contract?.contractSource;
361
+ if (!cs) continue;
362
+ for (const ref of [
363
+ cs.queryRef,
364
+ cs.bodyRef,
365
+ cs.responseRef
366
+ ]) {
367
+ if (!ref) continue;
368
+ let names = importsByFile.get(ref.filePath);
369
+ if (!names) {
370
+ names = /* @__PURE__ */ new Set();
371
+ importsByFile.set(ref.filePath, names);
372
+ }
373
+ names.add(ref.name);
374
+ }
375
+ }
358
376
  const lines = [
359
377
  "// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
360
378
  ""
361
379
  ];
362
380
  lines.push("import { route } from './routes.js';");
363
381
  lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
382
+ if (importsByFile.size > 0 && outDir) {
383
+ lines.push("");
384
+ for (const [filePath, names] of importsByFile) {
385
+ let relPath = (0, import_node_path3.relative)(outDir, filePath).replace(/\.ts$/, "");
386
+ if (!relPath.startsWith(".")) relPath = `./${relPath}`;
387
+ const sortedNames = [
388
+ ...names
389
+ ].sort();
390
+ lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
391
+ }
392
+ }
364
393
  lines.push("");
365
394
  lines.push("export const fetcher = createFetcher();");
366
395
  lines.push("");
@@ -1105,6 +1134,53 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
1105
1134
  return name;
1106
1135
  }
1107
1136
  __name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
1137
+ function tryResolveTypeRef(typeNode, sourceFile, project) {
1138
+ if (import_ts_morph.Node.isTypeReference(typeNode)) {
1139
+ const typeName = typeNode.getTypeName();
1140
+ const name = import_ts_morph.Node.isIdentifier(typeName) ? typeName.getText() : null;
1141
+ if (!name) return null;
1142
+ if (name === "Promise") {
1143
+ const typeArgs = typeNode.getTypeArguments();
1144
+ const first = typeArgs[0];
1145
+ if (first) return tryResolveTypeRef(first, sourceFile, project);
1146
+ return null;
1147
+ }
1148
+ if ([
1149
+ "string",
1150
+ "number",
1151
+ "boolean",
1152
+ "void",
1153
+ "unknown",
1154
+ "any",
1155
+ "Date",
1156
+ "Array"
1157
+ ].includes(name)) {
1158
+ return null;
1159
+ }
1160
+ const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
1161
+ if (localDecl && localDecl.isExported()) {
1162
+ return {
1163
+ name,
1164
+ filePath: sourceFile.getFilePath()
1165
+ };
1166
+ }
1167
+ const resolved = resolveImportedType(name, sourceFile, project);
1168
+ if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
1169
+ const decl = resolved.decl;
1170
+ if (decl.isExported()) {
1171
+ return {
1172
+ name,
1173
+ filePath: resolved.file.getFilePath()
1174
+ };
1175
+ }
1176
+ }
1177
+ }
1178
+ if (import_ts_morph.Node.isArrayTypeNode(typeNode)) {
1179
+ return tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
1180
+ }
1181
+ return null;
1182
+ }
1183
+ __name(tryResolveTypeRef, "tryResolveTypeRef");
1108
1184
  function extractDtoContract(method, sourceFile, project) {
1109
1185
  const body = extractBodyType(method, sourceFile, project);
1110
1186
  const query = extractQueryType(method, sourceFile, project);
@@ -1113,11 +1189,61 @@ function extractDtoContract(method, sourceFile, project) {
1113
1189
  if (body === null && query === null && paramsType === null && response === "unknown") {
1114
1190
  return null;
1115
1191
  }
1192
+ let bodyRef = null;
1193
+ let queryRef = null;
1194
+ let responseRef = null;
1195
+ for (const param of method.getParameters()) {
1196
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
1197
+ bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
1198
+ }
1199
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
1200
+ queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
1201
+ }
1202
+ }
1203
+ const returnTypeNode = method.getReturnTypeNode();
1204
+ if (returnTypeNode) {
1205
+ responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
1206
+ }
1207
+ if (!responseRef) {
1208
+ const apiResp = method.getDecorator("ApiResponse");
1209
+ if (apiResp) {
1210
+ const args = apiResp.getArguments();
1211
+ const optsArg = args[0];
1212
+ if (optsArg && import_ts_morph.Node.isObjectLiteralExpression(optsArg)) {
1213
+ for (const prop of optsArg.getProperties()) {
1214
+ if (import_ts_morph.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
1215
+ const val = prop.getInitializer();
1216
+ if (val && import_ts_morph.Node.isIdentifier(val)) {
1217
+ const name = val.getText();
1218
+ const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
1219
+ if (localDecl && localDecl.isExported()) {
1220
+ responseRef = {
1221
+ name,
1222
+ filePath: sourceFile.getFilePath()
1223
+ };
1224
+ } else {
1225
+ const resolved = resolveImportedType(name, sourceFile, project);
1226
+ if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
1227
+ responseRef = {
1228
+ name,
1229
+ filePath: resolved.file.getFilePath()
1230
+ };
1231
+ }
1232
+ }
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+ }
1238
+ }
1116
1239
  return {
1117
1240
  query,
1118
1241
  body,
1119
1242
  response,
1120
- params: paramsType
1243
+ params: paramsType,
1244
+ queryRef,
1245
+ bodyRef,
1246
+ responseRef
1121
1247
  };
1122
1248
  }
1123
1249
  __name(extractDtoContract, "extractDtoContract");
@@ -1256,7 +1382,10 @@ function extractFromSourceFile(sourceFile, project) {
1256
1382
  contractSource: {
1257
1383
  query: dtoContract.query,
1258
1384
  body: dtoContract.body,
1259
- response: dtoContract.response
1385
+ response: dtoContract.response,
1386
+ queryRef: dtoContract.queryRef,
1387
+ bodyRef: dtoContract.bodyRef,
1388
+ responseRef: dtoContract.responseRef
1260
1389
  }
1261
1390
  }
1262
1391
  } : {}
@@ -1429,7 +1558,7 @@ async function watch(config, onChange) {
1429
1558
  __name(watch, "watch");
1430
1559
 
1431
1560
  // src/index.ts
1432
- var VERSION = "2.0.1";
1561
+ var VERSION = "3.0.0";
1433
1562
 
1434
1563
  // src/cli/codegen.ts
1435
1564
  async function runCodegen(opts = {}) {