@dudousxd/nestjs-inertia-codegen 2.0.0 → 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 +20 -0
- package/dist/cli/main.cjs +141 -17
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +142 -18
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +141 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +142 -18
- 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");
|
|
@@ -316,9 +316,9 @@ function emitRouterTypeBlock(tree, indent) {
|
|
|
316
316
|
if (node.kind === "leaf") {
|
|
317
317
|
const c = node;
|
|
318
318
|
const method = c.method.toUpperCase();
|
|
319
|
-
const query = c.contractSource.query ?? "never";
|
|
320
|
-
const body = method === "GET" ? "never" : c.contractSource.body ?? "never";
|
|
321
|
-
const response = c.contractSource.response;
|
|
319
|
+
const query = c.contractSource.queryRef ? c.contractSource.queryRef.name : c.contractSource.query ?? "never";
|
|
320
|
+
const body = method === "GET" ? "never" : c.contractSource.bodyRef ? c.contractSource.bodyRef.name : c.contractSource.body ?? "never";
|
|
321
|
+
const response = c.contractSource.responseRef ? c.contractSource.responseRef.name : c.contractSource.response;
|
|
322
322
|
const safeMethod = JSON.stringify(method);
|
|
323
323
|
const safeUrl = JSON.stringify(c.path);
|
|
324
324
|
lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
|
|
@@ -346,11 +346,10 @@ function emitApiObjectBlock(tree, indent) {
|
|
|
346
346
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
347
347
|
lines.push(`${pad}${objKey}: {`);
|
|
348
348
|
lines.push(`${pad} queryKey: (query?: ${typeAccess}['query']) => query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
349
|
-
lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query'])
|
|
350
|
-
lines.push(`${pad}
|
|
351
|
-
lines.push(`${pad}
|
|
352
|
-
lines.push(`${pad}
|
|
353
|
-
lines.push(`${pad} }),`);
|
|
349
|
+
lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query']) => ({`);
|
|
350
|
+
lines.push(`${pad} queryKey: query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
351
|
+
lines.push(`${pad} queryFn: () => fetcher.get<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { query }),`);
|
|
352
|
+
lines.push(`${pad} }),`);
|
|
354
353
|
lines.push(`${pad}},`);
|
|
355
354
|
} else {
|
|
356
355
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
@@ -375,18 +374,43 @@ function buildRouterTypeAccess(name) {
|
|
|
375
374
|
return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
|
|
376
375
|
}
|
|
377
376
|
__name(buildRouterTypeAccess, "buildRouterTypeAccess");
|
|
378
|
-
function buildApiFile(routes) {
|
|
377
|
+
function buildApiFile(routes, outDir) {
|
|
379
378
|
const contracted = routes.filter((r) => r.contract);
|
|
380
|
-
const
|
|
379
|
+
const importsByFile = /* @__PURE__ */ new Map();
|
|
380
|
+
for (const r of contracted) {
|
|
381
|
+
const cs = r.contract?.contractSource;
|
|
382
|
+
if (!cs) continue;
|
|
383
|
+
for (const ref of [
|
|
384
|
+
cs.queryRef,
|
|
385
|
+
cs.bodyRef,
|
|
386
|
+
cs.responseRef
|
|
387
|
+
]) {
|
|
388
|
+
if (!ref) continue;
|
|
389
|
+
let names = importsByFile.get(ref.filePath);
|
|
390
|
+
if (!names) {
|
|
391
|
+
names = /* @__PURE__ */ new Set();
|
|
392
|
+
importsByFile.set(ref.filePath, names);
|
|
393
|
+
}
|
|
394
|
+
names.add(ref.name);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
381
397
|
const lines = [
|
|
382
398
|
"// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
|
|
383
399
|
""
|
|
384
400
|
];
|
|
385
|
-
if (hasGetRoutes) {
|
|
386
|
-
lines.push("import { queryOptions } from '@tanstack/query-core';");
|
|
387
|
-
}
|
|
388
401
|
lines.push("import { route } from './routes.js';");
|
|
389
402
|
lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
|
|
403
|
+
if (importsByFile.size > 0 && outDir) {
|
|
404
|
+
lines.push("");
|
|
405
|
+
for (const [filePath, names] of importsByFile) {
|
|
406
|
+
let relPath = (0, import_node_path3.relative)(outDir, filePath).replace(/\.ts$/, "");
|
|
407
|
+
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
408
|
+
const sortedNames = [
|
|
409
|
+
...names
|
|
410
|
+
].sort();
|
|
411
|
+
lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
390
414
|
lines.push("");
|
|
391
415
|
lines.push("export const fetcher = createFetcher();");
|
|
392
416
|
lines.push("");
|
|
@@ -1131,6 +1155,53 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
|
1131
1155
|
return name;
|
|
1132
1156
|
}
|
|
1133
1157
|
__name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
|
|
1158
|
+
function tryResolveTypeRef(typeNode, sourceFile, project) {
|
|
1159
|
+
if (import_ts_morph.Node.isTypeReference(typeNode)) {
|
|
1160
|
+
const typeName = typeNode.getTypeName();
|
|
1161
|
+
const name = import_ts_morph.Node.isIdentifier(typeName) ? typeName.getText() : null;
|
|
1162
|
+
if (!name) return null;
|
|
1163
|
+
if (name === "Promise") {
|
|
1164
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
1165
|
+
const first = typeArgs[0];
|
|
1166
|
+
if (first) return tryResolveTypeRef(first, sourceFile, project);
|
|
1167
|
+
return null;
|
|
1168
|
+
}
|
|
1169
|
+
if ([
|
|
1170
|
+
"string",
|
|
1171
|
+
"number",
|
|
1172
|
+
"boolean",
|
|
1173
|
+
"void",
|
|
1174
|
+
"unknown",
|
|
1175
|
+
"any",
|
|
1176
|
+
"Date",
|
|
1177
|
+
"Array"
|
|
1178
|
+
].includes(name)) {
|
|
1179
|
+
return null;
|
|
1180
|
+
}
|
|
1181
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1182
|
+
if (localDecl && localDecl.isExported()) {
|
|
1183
|
+
return {
|
|
1184
|
+
name,
|
|
1185
|
+
filePath: sourceFile.getFilePath()
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1189
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
|
|
1190
|
+
const decl = resolved.decl;
|
|
1191
|
+
if (decl.isExported()) {
|
|
1192
|
+
return {
|
|
1193
|
+
name,
|
|
1194
|
+
filePath: resolved.file.getFilePath()
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
if (import_ts_morph.Node.isArrayTypeNode(typeNode)) {
|
|
1200
|
+
return tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
|
|
1201
|
+
}
|
|
1202
|
+
return null;
|
|
1203
|
+
}
|
|
1204
|
+
__name(tryResolveTypeRef, "tryResolveTypeRef");
|
|
1134
1205
|
function extractDtoContract(method, sourceFile, project) {
|
|
1135
1206
|
const body = extractBodyType(method, sourceFile, project);
|
|
1136
1207
|
const query = extractQueryType(method, sourceFile, project);
|
|
@@ -1139,11 +1210,61 @@ function extractDtoContract(method, sourceFile, project) {
|
|
|
1139
1210
|
if (body === null && query === null && paramsType === null && response === "unknown") {
|
|
1140
1211
|
return null;
|
|
1141
1212
|
}
|
|
1213
|
+
let bodyRef = null;
|
|
1214
|
+
let queryRef = null;
|
|
1215
|
+
let responseRef = null;
|
|
1216
|
+
for (const param of method.getParameters()) {
|
|
1217
|
+
if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
|
|
1218
|
+
bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1219
|
+
}
|
|
1220
|
+
if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
|
|
1221
|
+
queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
const returnTypeNode = method.getReturnTypeNode();
|
|
1225
|
+
if (returnTypeNode) {
|
|
1226
|
+
responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
|
|
1227
|
+
}
|
|
1228
|
+
if (!responseRef) {
|
|
1229
|
+
const apiResp = method.getDecorator("ApiResponse");
|
|
1230
|
+
if (apiResp) {
|
|
1231
|
+
const args = apiResp.getArguments();
|
|
1232
|
+
const optsArg = args[0];
|
|
1233
|
+
if (optsArg && import_ts_morph.Node.isObjectLiteralExpression(optsArg)) {
|
|
1234
|
+
for (const prop of optsArg.getProperties()) {
|
|
1235
|
+
if (import_ts_morph.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
|
|
1236
|
+
const val = prop.getInitializer();
|
|
1237
|
+
if (val && import_ts_morph.Node.isIdentifier(val)) {
|
|
1238
|
+
const name = val.getText();
|
|
1239
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1240
|
+
if (localDecl && localDecl.isExported()) {
|
|
1241
|
+
responseRef = {
|
|
1242
|
+
name,
|
|
1243
|
+
filePath: sourceFile.getFilePath()
|
|
1244
|
+
};
|
|
1245
|
+
} else {
|
|
1246
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1247
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
|
|
1248
|
+
responseRef = {
|
|
1249
|
+
name,
|
|
1250
|
+
filePath: resolved.file.getFilePath()
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1142
1260
|
return {
|
|
1143
1261
|
query,
|
|
1144
1262
|
body,
|
|
1145
1263
|
response,
|
|
1146
|
-
params: paramsType
|
|
1264
|
+
params: paramsType,
|
|
1265
|
+
queryRef,
|
|
1266
|
+
bodyRef,
|
|
1267
|
+
responseRef
|
|
1147
1268
|
};
|
|
1148
1269
|
}
|
|
1149
1270
|
__name(extractDtoContract, "extractDtoContract");
|
|
@@ -1282,7 +1403,10 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1282
1403
|
contractSource: {
|
|
1283
1404
|
query: dtoContract.query,
|
|
1284
1405
|
body: dtoContract.body,
|
|
1285
|
-
response: dtoContract.response
|
|
1406
|
+
response: dtoContract.response,
|
|
1407
|
+
queryRef: dtoContract.queryRef,
|
|
1408
|
+
bodyRef: dtoContract.bodyRef,
|
|
1409
|
+
responseRef: dtoContract.responseRef
|
|
1286
1410
|
}
|
|
1287
1411
|
}
|
|
1288
1412
|
} : {}
|
|
@@ -1455,7 +1579,7 @@ async function watch(config, onChange) {
|
|
|
1455
1579
|
__name(watch, "watch");
|
|
1456
1580
|
|
|
1457
1581
|
// src/index.ts
|
|
1458
|
-
var VERSION = "
|
|
1582
|
+
var VERSION = "3.0.0";
|
|
1459
1583
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1460
1584
|
0 && (module.exports = {
|
|
1461
1585
|
CodegenError,
|