@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 +11 -0
- package/dist/cli/main.cjs +137 -8
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +138 -9
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +137 -8
- 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 +138 -9
- 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");
|
|
@@ -263,9 +263,9 @@ function emitRouterTypeBlock(tree, indent) {
|
|
|
263
263
|
if (node.kind === "leaf") {
|
|
264
264
|
const c = node;
|
|
265
265
|
const method = c.method.toUpperCase();
|
|
266
|
-
const query = c.contractSource.query ?? "never";
|
|
267
|
-
const body = method === "GET" ? "never" : c.contractSource.body ?? "never";
|
|
268
|
-
const response = c.contractSource.response;
|
|
266
|
+
const query = c.contractSource.queryRef ? c.contractSource.queryRef.name : c.contractSource.query ?? "never";
|
|
267
|
+
const body = method === "GET" ? "never" : c.contractSource.bodyRef ? c.contractSource.bodyRef.name : c.contractSource.body ?? "never";
|
|
268
|
+
const response = c.contractSource.responseRef ? c.contractSource.responseRef.name : c.contractSource.response;
|
|
269
269
|
const safeMethod = JSON.stringify(method);
|
|
270
270
|
const safeUrl = JSON.stringify(c.path);
|
|
271
271
|
lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
|
|
@@ -321,14 +321,43 @@ function buildRouterTypeAccess(name) {
|
|
|
321
321
|
return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
|
|
322
322
|
}
|
|
323
323
|
__name(buildRouterTypeAccess, "buildRouterTypeAccess");
|
|
324
|
-
function buildApiFile(routes) {
|
|
324
|
+
function buildApiFile(routes, outDir) {
|
|
325
325
|
const contracted = routes.filter((r) => r.contract);
|
|
326
|
+
const importsByFile = /* @__PURE__ */ new Map();
|
|
327
|
+
for (const r of contracted) {
|
|
328
|
+
const cs = r.contract?.contractSource;
|
|
329
|
+
if (!cs) continue;
|
|
330
|
+
for (const ref of [
|
|
331
|
+
cs.queryRef,
|
|
332
|
+
cs.bodyRef,
|
|
333
|
+
cs.responseRef
|
|
334
|
+
]) {
|
|
335
|
+
if (!ref) continue;
|
|
336
|
+
let names = importsByFile.get(ref.filePath);
|
|
337
|
+
if (!names) {
|
|
338
|
+
names = /* @__PURE__ */ new Set();
|
|
339
|
+
importsByFile.set(ref.filePath, names);
|
|
340
|
+
}
|
|
341
|
+
names.add(ref.name);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
326
344
|
const lines = [
|
|
327
345
|
"// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
|
|
328
346
|
""
|
|
329
347
|
];
|
|
330
348
|
lines.push("import { route } from './routes.js';");
|
|
331
349
|
lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
|
|
350
|
+
if (importsByFile.size > 0 && outDir) {
|
|
351
|
+
lines.push("");
|
|
352
|
+
for (const [filePath, names] of importsByFile) {
|
|
353
|
+
let relPath = relative3(outDir, filePath).replace(/\.ts$/, "");
|
|
354
|
+
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
355
|
+
const sortedNames = [
|
|
356
|
+
...names
|
|
357
|
+
].sort();
|
|
358
|
+
lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
332
361
|
lines.push("");
|
|
333
362
|
lines.push("export const fetcher = createFetcher();");
|
|
334
363
|
lines.push("");
|
|
@@ -1073,6 +1102,53 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
|
1073
1102
|
return name;
|
|
1074
1103
|
}
|
|
1075
1104
|
__name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
|
|
1105
|
+
function tryResolveTypeRef(typeNode, sourceFile, project) {
|
|
1106
|
+
if (Node.isTypeReference(typeNode)) {
|
|
1107
|
+
const typeName = typeNode.getTypeName();
|
|
1108
|
+
const name = Node.isIdentifier(typeName) ? typeName.getText() : null;
|
|
1109
|
+
if (!name) return null;
|
|
1110
|
+
if (name === "Promise") {
|
|
1111
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
1112
|
+
const first = typeArgs[0];
|
|
1113
|
+
if (first) return tryResolveTypeRef(first, sourceFile, project);
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1116
|
+
if ([
|
|
1117
|
+
"string",
|
|
1118
|
+
"number",
|
|
1119
|
+
"boolean",
|
|
1120
|
+
"void",
|
|
1121
|
+
"unknown",
|
|
1122
|
+
"any",
|
|
1123
|
+
"Date",
|
|
1124
|
+
"Array"
|
|
1125
|
+
].includes(name)) {
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1129
|
+
if (localDecl && localDecl.isExported()) {
|
|
1130
|
+
return {
|
|
1131
|
+
name,
|
|
1132
|
+
filePath: sourceFile.getFilePath()
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1136
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
|
|
1137
|
+
const decl = resolved.decl;
|
|
1138
|
+
if (decl.isExported()) {
|
|
1139
|
+
return {
|
|
1140
|
+
name,
|
|
1141
|
+
filePath: resolved.file.getFilePath()
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
if (Node.isArrayTypeNode(typeNode)) {
|
|
1147
|
+
return tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
|
|
1148
|
+
}
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1151
|
+
__name(tryResolveTypeRef, "tryResolveTypeRef");
|
|
1076
1152
|
function extractDtoContract(method, sourceFile, project) {
|
|
1077
1153
|
const body = extractBodyType(method, sourceFile, project);
|
|
1078
1154
|
const query = extractQueryType(method, sourceFile, project);
|
|
@@ -1081,11 +1157,61 @@ function extractDtoContract(method, sourceFile, project) {
|
|
|
1081
1157
|
if (body === null && query === null && paramsType === null && response === "unknown") {
|
|
1082
1158
|
return null;
|
|
1083
1159
|
}
|
|
1160
|
+
let bodyRef = null;
|
|
1161
|
+
let queryRef = null;
|
|
1162
|
+
let responseRef = null;
|
|
1163
|
+
for (const param of method.getParameters()) {
|
|
1164
|
+
if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
|
|
1165
|
+
bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1166
|
+
}
|
|
1167
|
+
if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
|
|
1168
|
+
queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
const returnTypeNode = method.getReturnTypeNode();
|
|
1172
|
+
if (returnTypeNode) {
|
|
1173
|
+
responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
|
|
1174
|
+
}
|
|
1175
|
+
if (!responseRef) {
|
|
1176
|
+
const apiResp = method.getDecorator("ApiResponse");
|
|
1177
|
+
if (apiResp) {
|
|
1178
|
+
const args = apiResp.getArguments();
|
|
1179
|
+
const optsArg = args[0];
|
|
1180
|
+
if (optsArg && Node.isObjectLiteralExpression(optsArg)) {
|
|
1181
|
+
for (const prop of optsArg.getProperties()) {
|
|
1182
|
+
if (Node.isPropertyAssignment(prop) && prop.getName() === "type") {
|
|
1183
|
+
const val = prop.getInitializer();
|
|
1184
|
+
if (val && Node.isIdentifier(val)) {
|
|
1185
|
+
const name = val.getText();
|
|
1186
|
+
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
1187
|
+
if (localDecl && localDecl.isExported()) {
|
|
1188
|
+
responseRef = {
|
|
1189
|
+
name,
|
|
1190
|
+
filePath: sourceFile.getFilePath()
|
|
1191
|
+
};
|
|
1192
|
+
} else {
|
|
1193
|
+
const resolved = resolveImportedType(name, sourceFile, project);
|
|
1194
|
+
if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
|
|
1195
|
+
responseRef = {
|
|
1196
|
+
name,
|
|
1197
|
+
filePath: resolved.file.getFilePath()
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1084
1207
|
return {
|
|
1085
1208
|
query,
|
|
1086
1209
|
body,
|
|
1087
1210
|
response,
|
|
1088
|
-
params: paramsType
|
|
1211
|
+
params: paramsType,
|
|
1212
|
+
queryRef,
|
|
1213
|
+
bodyRef,
|
|
1214
|
+
responseRef
|
|
1089
1215
|
};
|
|
1090
1216
|
}
|
|
1091
1217
|
__name(extractDtoContract, "extractDtoContract");
|
|
@@ -1224,7 +1350,10 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1224
1350
|
contractSource: {
|
|
1225
1351
|
query: dtoContract.query,
|
|
1226
1352
|
body: dtoContract.body,
|
|
1227
|
-
response: dtoContract.response
|
|
1353
|
+
response: dtoContract.response,
|
|
1354
|
+
queryRef: dtoContract.queryRef,
|
|
1355
|
+
bodyRef: dtoContract.bodyRef,
|
|
1356
|
+
responseRef: dtoContract.responseRef
|
|
1228
1357
|
}
|
|
1229
1358
|
}
|
|
1230
1359
|
} : {}
|
|
@@ -1397,7 +1526,7 @@ async function watch(config, onChange) {
|
|
|
1397
1526
|
__name(watch, "watch");
|
|
1398
1527
|
|
|
1399
1528
|
// src/index.ts
|
|
1400
|
-
var VERSION = "
|
|
1529
|
+
var VERSION = "3.0.0";
|
|
1401
1530
|
|
|
1402
1531
|
// src/cli/codegen.ts
|
|
1403
1532
|
async function runCodegen(opts = {}) {
|