@dudousxd/nestjs-codegen 0.29.0 → 0.30.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 +24 -0
- package/dist/cli/main.cjs +711 -436
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +862 -582
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/{index-Dc4s883u.d.cts → index-D4Blt-RT.d.cts} +1 -13
- package/dist/{index-Dc4s883u.d.ts → index-D4Blt-RT.d.ts} +1 -13
- package/dist/index.cjs +696 -434
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +854 -587
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +559 -284
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +369 -89
- package/dist/nest/index.js.map +1 -1
- package/package.json +9 -9
- package/skills/codegen-setup/SKILL.md +5 -1
package/dist/nest/index.cjs
CHANGED
|
@@ -126,11 +126,6 @@ function validateUserConfig(userConfig) {
|
|
|
126
126
|
);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
if (userConfig.scopes && Object.keys(userConfig.scopes).length > 0) {
|
|
130
|
-
console.warn(
|
|
131
|
-
"[nestjs-codegen] The top-level `scopes` option has no effect and is deprecated. For several Inertia apps use `pages.scopes` (one entry per InertiaModule.forFeature scope); for several controller sets use one `contracts.glob` (e.g. a brace glob)."
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
129
|
}
|
|
135
130
|
function isGlobInput(value) {
|
|
136
131
|
if (typeof value === "string") return true;
|
|
@@ -178,7 +173,6 @@ function applyDefaults(userConfig, cwd) {
|
|
|
178
173
|
glob: userConfig.contracts?.glob ?? "src/**/*.controller.ts",
|
|
179
174
|
debounceMs: userConfig.contracts?.debounceMs ?? 500
|
|
180
175
|
},
|
|
181
|
-
scopes: userConfig.scopes ?? {},
|
|
182
176
|
codegen: {
|
|
183
177
|
outDir,
|
|
184
178
|
cwd: resolvedCwd
|
|
@@ -215,13 +209,52 @@ var import_node_path18 = require("path");
|
|
|
215
209
|
var import_fast_glob3 = __toESM(require("fast-glob"), 1);
|
|
216
210
|
|
|
217
211
|
// src/discovery/contracts-fast.ts
|
|
218
|
-
var
|
|
212
|
+
var import_node_fs2 = require("fs");
|
|
219
213
|
var import_node_path3 = require("path");
|
|
220
214
|
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
221
|
-
var
|
|
215
|
+
var import_ts_morph12 = require("ts-morph");
|
|
216
|
+
|
|
217
|
+
// src/discovery/disk-fingerprints.ts
|
|
218
|
+
var import_node_fs = require("fs");
|
|
219
|
+
var DiskFingerprints = class {
|
|
220
|
+
stats = /* @__PURE__ */ new Map();
|
|
221
|
+
/** The paths whose disk content differs from `text`, or that no longer exist. */
|
|
222
|
+
changed(files) {
|
|
223
|
+
const changed = [];
|
|
224
|
+
for (const { path, text } of files) {
|
|
225
|
+
let key;
|
|
226
|
+
try {
|
|
227
|
+
const stat2 = (0, import_node_fs.statSync)(path);
|
|
228
|
+
key = `${stat2.mtimeMs}:${stat2.size}`;
|
|
229
|
+
} catch {
|
|
230
|
+
this.stats.delete(path);
|
|
231
|
+
changed.push(path);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (this.stats.get(path) === key) continue;
|
|
235
|
+
let disk;
|
|
236
|
+
try {
|
|
237
|
+
disk = (0, import_node_fs.readFileSync)(path, "utf-8");
|
|
238
|
+
} catch {
|
|
239
|
+
disk = void 0;
|
|
240
|
+
}
|
|
241
|
+
if (disk === text) {
|
|
242
|
+
this.stats.set(path, key);
|
|
243
|
+
} else {
|
|
244
|
+
this.stats.delete(path);
|
|
245
|
+
changed.push(path);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return changed;
|
|
249
|
+
}
|
|
250
|
+
/** Forget `path`, so its next check compares content again. */
|
|
251
|
+
forget(path) {
|
|
252
|
+
this.stats.delete(path);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
222
255
|
|
|
223
256
|
// src/discovery/dto-type-resolver.ts
|
|
224
|
-
var
|
|
257
|
+
var import_ts_morph11 = require("ts-morph");
|
|
225
258
|
|
|
226
259
|
// src/discovery/dto-to-ir.ts
|
|
227
260
|
var import_ts_morph2 = require("ts-morph");
|
|
@@ -982,7 +1015,7 @@ function inSchemaFromDecorator(decorator) {
|
|
|
982
1015
|
}
|
|
983
1016
|
|
|
984
1017
|
// src/discovery/filter-for.ts
|
|
985
|
-
var
|
|
1018
|
+
var import_ts_morph6 = require("ts-morph");
|
|
986
1019
|
|
|
987
1020
|
// src/discovery/filter-field-types.ts
|
|
988
1021
|
var import_ts_morph3 = require("ts-morph");
|
|
@@ -1222,23 +1255,66 @@ function toFilterFieldType(name, r) {
|
|
|
1222
1255
|
}
|
|
1223
1256
|
|
|
1224
1257
|
// src/discovery/heritage.ts
|
|
1258
|
+
var import_ts_morph5 = require("ts-morph");
|
|
1259
|
+
|
|
1260
|
+
// src/discovery/unresolved-imports.ts
|
|
1225
1261
|
var import_ts_morph4 = require("ts-morph");
|
|
1262
|
+
var UnresolvedImports = class {
|
|
1263
|
+
read;
|
|
1264
|
+
/**
|
|
1265
|
+
* The files with an import that failed to resolve in `program` and now resolves
|
|
1266
|
+
* to a TypeScript file the program does not hold.
|
|
1267
|
+
*/
|
|
1268
|
+
nowResolving(program) {
|
|
1269
|
+
if (this.read?.program !== program) {
|
|
1270
|
+
this.read = { program, imports: failedImports(program) };
|
|
1271
|
+
}
|
|
1272
|
+
const options = program.getCompilerOptions();
|
|
1273
|
+
const files = /* @__PURE__ */ new Set();
|
|
1274
|
+
for (const { specifier, from } of this.read.imports) {
|
|
1275
|
+
const file = import_ts_morph4.ts.resolveModuleName(specifier, from, options, import_ts_morph4.ts.sys).resolvedModule?.resolvedFileName;
|
|
1276
|
+
if (file !== void 0 && /\.(m|c)?tsx?$/.test(file) && !program.getSourceFile(file)) {
|
|
1277
|
+
files.add(from);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
return [...files];
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
function failedImports(program) {
|
|
1284
|
+
const checker = program.getTypeChecker();
|
|
1285
|
+
const imports = [];
|
|
1286
|
+
for (const file of program.getSourceFiles()) {
|
|
1287
|
+
if (program.isSourceFileDefaultLibrary(file) || file.isDeclarationFile) continue;
|
|
1288
|
+
if (program.isSourceFileFromExternalLibrary(file)) continue;
|
|
1289
|
+
for (const statement of file.statements) {
|
|
1290
|
+
if (!import_ts_morph4.ts.isImportDeclaration(statement) && !import_ts_morph4.ts.isExportDeclaration(statement)) continue;
|
|
1291
|
+
const specifier = statement.moduleSpecifier;
|
|
1292
|
+
if (!specifier || !import_ts_morph4.ts.isStringLiteral(specifier)) continue;
|
|
1293
|
+
if (!checker.getSymbolAtLocation(specifier)) {
|
|
1294
|
+
imports.push({ specifier: specifier.text, from: file.fileName });
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return imports;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// src/discovery/heritage.ts
|
|
1226
1302
|
function resolveHeritageCall(node) {
|
|
1227
1303
|
if (!node) return void 0;
|
|
1228
1304
|
const expr = unwrapExpression(node);
|
|
1229
|
-
if (
|
|
1230
|
-
if (!
|
|
1305
|
+
if (import_ts_morph5.Node.isCallExpression(expr)) return expr;
|
|
1306
|
+
if (!import_ts_morph5.Node.isIdentifier(expr)) return void 0;
|
|
1231
1307
|
const decl = expr.getDefinitions().map((d) => d.getDeclarationNode()).find(
|
|
1232
|
-
(n) => n !== void 0 &&
|
|
1308
|
+
(n) => n !== void 0 && import_ts_morph5.Node.isVariableDeclaration(n)
|
|
1233
1309
|
);
|
|
1234
1310
|
const init = decl?.getInitializer();
|
|
1235
1311
|
if (!init) return void 0;
|
|
1236
1312
|
const unwrapped = unwrapExpression(init);
|
|
1237
|
-
return
|
|
1313
|
+
return import_ts_morph5.Node.isCallExpression(unwrapped) ? unwrapped : void 0;
|
|
1238
1314
|
}
|
|
1239
1315
|
function unwrapExpression(node) {
|
|
1240
1316
|
let current = node;
|
|
1241
|
-
while (
|
|
1317
|
+
while (import_ts_morph5.Node.isAsExpression(current) || import_ts_morph5.Node.isSatisfiesExpression(current) || import_ts_morph5.Node.isParenthesizedExpression(current) || import_ts_morph5.Node.isTypeAssertion(current)) {
|
|
1242
1318
|
current = current.getExpression();
|
|
1243
1319
|
}
|
|
1244
1320
|
return current;
|
|
@@ -1246,17 +1322,17 @@ function unwrapExpression(node) {
|
|
|
1246
1322
|
function resolveReturnedClass(factoryDecl) {
|
|
1247
1323
|
const body = factoryDecl.getBody();
|
|
1248
1324
|
if (!body) return void 0;
|
|
1249
|
-
const returns = body.getDescendants().filter((n) =>
|
|
1325
|
+
const returns = body.getDescendants().filter((n) => import_ts_morph5.Node.isReturnStatement(n));
|
|
1250
1326
|
for (const ret of returns) {
|
|
1251
1327
|
const expr = ret.getExpression();
|
|
1252
1328
|
if (!expr) continue;
|
|
1253
1329
|
const inner = unwrapExpression(expr);
|
|
1254
|
-
if (
|
|
1330
|
+
if (import_ts_morph5.Node.isClassExpression(inner)) {
|
|
1255
1331
|
return inner;
|
|
1256
1332
|
}
|
|
1257
|
-
if (
|
|
1333
|
+
if (import_ts_morph5.Node.isIdentifier(inner)) {
|
|
1258
1334
|
const name = inner.getText();
|
|
1259
|
-
const decl = body.getDescendants().find((n) =>
|
|
1335
|
+
const decl = body.getDescendants().find((n) => import_ts_morph5.Node.isClassDeclaration(n) && n.getName() === name);
|
|
1260
1336
|
if (decl) return decl;
|
|
1261
1337
|
}
|
|
1262
1338
|
}
|
|
@@ -1264,10 +1340,10 @@ function resolveReturnedClass(factoryDecl) {
|
|
|
1264
1340
|
}
|
|
1265
1341
|
function factoryCalleeName(call) {
|
|
1266
1342
|
const callee = unwrapExpression(call.getExpression());
|
|
1267
|
-
if (
|
|
1268
|
-
if (
|
|
1343
|
+
if (import_ts_morph5.Node.isIdentifier(callee)) return callee;
|
|
1344
|
+
if (import_ts_morph5.Node.isPropertyAccessExpression(callee)) {
|
|
1269
1345
|
const name = callee.getNameNode();
|
|
1270
|
-
return
|
|
1346
|
+
return import_ts_morph5.Node.isIdentifier(name) ? name : void 0;
|
|
1271
1347
|
}
|
|
1272
1348
|
return void 0;
|
|
1273
1349
|
}
|
|
@@ -1280,19 +1356,19 @@ function resolveFactoryFromName(name, seen) {
|
|
|
1280
1356
|
seen.add(name);
|
|
1281
1357
|
const decls = name.getDefinitions().map((d) => d.getDeclarationNode()).filter((n) => n !== void 0);
|
|
1282
1358
|
for (const decl of decls) {
|
|
1283
|
-
if (
|
|
1284
|
-
if (
|
|
1359
|
+
if (import_ts_morph5.Node.isFunctionDeclaration(decl) || import_ts_morph5.Node.isMethodDeclaration(decl)) return decl;
|
|
1360
|
+
if (import_ts_morph5.Node.isPropertyAssignment(decl)) {
|
|
1285
1361
|
const init = decl.getInitializer();
|
|
1286
1362
|
const inner = init ? unwrapExpression(init) : void 0;
|
|
1287
|
-
if (inner &&
|
|
1363
|
+
if (inner && import_ts_morph5.Node.isIdentifier(inner)) {
|
|
1288
1364
|
const resolved = resolveFactoryFromName(inner, seen);
|
|
1289
1365
|
if (resolved) return resolved;
|
|
1290
1366
|
}
|
|
1291
1367
|
continue;
|
|
1292
1368
|
}
|
|
1293
|
-
if (
|
|
1369
|
+
if (import_ts_morph5.Node.isShorthandPropertyAssignment(decl)) {
|
|
1294
1370
|
const nameNode = decl.getNameNode();
|
|
1295
|
-
const resolved =
|
|
1371
|
+
const resolved = import_ts_morph5.Node.isIdentifier(nameNode) ? resolveFactoryFromName(nameNode, seen) : void 0;
|
|
1296
1372
|
if (resolved) return resolved;
|
|
1297
1373
|
}
|
|
1298
1374
|
}
|
|
@@ -1304,7 +1380,7 @@ function warnUnresolvedFactory(cls, calleeText, reason) {
|
|
|
1304
1380
|
);
|
|
1305
1381
|
}
|
|
1306
1382
|
function resolveFactoryStaticClass(node) {
|
|
1307
|
-
if (!
|
|
1383
|
+
if (!import_ts_morph5.Node.isPropertyAccessExpression(node)) return void 0;
|
|
1308
1384
|
const call = resolveHeritageCall(node.getExpression());
|
|
1309
1385
|
if (!call) return void 0;
|
|
1310
1386
|
const factoryDecl = resolveFactoryDeclaration(call);
|
|
@@ -1312,13 +1388,13 @@ function resolveFactoryStaticClass(node) {
|
|
|
1312
1388
|
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
1313
1389
|
if (!returnedClass) return void 0;
|
|
1314
1390
|
const staticProp = returnedClass.getStaticProperties().find((p) => p.getName() === node.getName());
|
|
1315
|
-
if (!staticProp || !
|
|
1391
|
+
if (!staticProp || !import_ts_morph5.Node.isPropertyDeclaration(staticProp)) return void 0;
|
|
1316
1392
|
const init = staticProp.getInitializer();
|
|
1317
1393
|
if (!init) return void 0;
|
|
1318
1394
|
const inner = unwrapExpression(init);
|
|
1319
|
-
if (
|
|
1320
|
-
if (!
|
|
1321
|
-
return inner.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 &&
|
|
1395
|
+
if (import_ts_morph5.Node.isClassExpression(inner)) return inner;
|
|
1396
|
+
if (!import_ts_morph5.Node.isIdentifier(inner)) return void 0;
|
|
1397
|
+
return inner.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph5.Node.isClassDeclaration(n));
|
|
1322
1398
|
}
|
|
1323
1399
|
function resolveBaseClass(cls) {
|
|
1324
1400
|
const heritage = cls.getExtends()?.getExpression();
|
|
@@ -1329,8 +1405,8 @@ function resolveBaseClass(cls) {
|
|
|
1329
1405
|
return factoryDecl ? resolveReturnedClass(factoryDecl) : void 0;
|
|
1330
1406
|
}
|
|
1331
1407
|
const expr = unwrapExpression(heritage);
|
|
1332
|
-
if (!
|
|
1333
|
-
return expr.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 &&
|
|
1408
|
+
if (!import_ts_morph5.Node.isIdentifier(expr)) return void 0;
|
|
1409
|
+
return expr.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph5.Node.isClassDeclaration(n));
|
|
1334
1410
|
}
|
|
1335
1411
|
function collectMethodsThroughChain(returnedClass) {
|
|
1336
1412
|
const byName = /* @__PURE__ */ new Map();
|
|
@@ -1377,7 +1453,7 @@ function resolveInheritedMethods(cls) {
|
|
|
1377
1453
|
classArgs.push(positional);
|
|
1378
1454
|
continue;
|
|
1379
1455
|
}
|
|
1380
|
-
if (!
|
|
1456
|
+
if (!import_ts_morph5.Node.isObjectLiteralExpression(arg)) continue;
|
|
1381
1457
|
for (const prop of arg.getProperties()) {
|
|
1382
1458
|
const named = resolvePropertyClassReference(prop);
|
|
1383
1459
|
if (!named) continue;
|
|
@@ -1399,8 +1475,8 @@ function resolveInheritedMethods(cls) {
|
|
|
1399
1475
|
}
|
|
1400
1476
|
function resolveClassReference(node) {
|
|
1401
1477
|
const expr = unwrapExpression(node);
|
|
1402
|
-
if (!
|
|
1403
|
-
const decl = expr.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 &&
|
|
1478
|
+
if (!import_ts_morph5.Node.isIdentifier(expr)) return void 0;
|
|
1479
|
+
const decl = expr.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph5.Node.isClassDeclaration(n));
|
|
1404
1480
|
if (!decl) return void 0;
|
|
1405
1481
|
return {
|
|
1406
1482
|
name: decl.getName() ?? expr.getText(),
|
|
@@ -1408,29 +1484,56 @@ function resolveClassReference(node) {
|
|
|
1408
1484
|
};
|
|
1409
1485
|
}
|
|
1410
1486
|
function resolvePropertyClassReference(prop) {
|
|
1411
|
-
if (
|
|
1487
|
+
if (import_ts_morph5.Node.isShorthandPropertyAssignment(prop)) {
|
|
1412
1488
|
const ref2 = resolveClassReference(prop.getNameNode());
|
|
1413
1489
|
return ref2 ? { key: prop.getName(), ref: ref2 } : void 0;
|
|
1414
1490
|
}
|
|
1415
|
-
if (!
|
|
1491
|
+
if (!import_ts_morph5.Node.isPropertyAssignment(prop)) return void 0;
|
|
1416
1492
|
const init = prop.getInitializer();
|
|
1417
1493
|
if (!init) return void 0;
|
|
1418
1494
|
const ref = resolveClassReference(init);
|
|
1419
1495
|
if (!ref) return void 0;
|
|
1420
1496
|
const nameNode = prop.getNameNode();
|
|
1421
|
-
const key =
|
|
1497
|
+
const key = import_ts_morph5.Node.isStringLiteral(nameNode) ? nameNode.getLiteralValue() : prop.getName();
|
|
1422
1498
|
return { key, ref };
|
|
1423
1499
|
}
|
|
1424
1500
|
var mixinTypeProject;
|
|
1501
|
+
var mixinFiles = new DiskFingerprints();
|
|
1502
|
+
var mixinStale = false;
|
|
1503
|
+
var mixinUnresolved = new UnresolvedImports();
|
|
1425
1504
|
function getMixinTypeProject() {
|
|
1426
|
-
mixinTypeProject
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1505
|
+
if (mixinTypeProject && mixinStale && !refreshMixinTypeProject(mixinTypeProject)) {
|
|
1506
|
+
mixinTypeProject = void 0;
|
|
1507
|
+
}
|
|
1508
|
+
mixinStale = false;
|
|
1509
|
+
if (!mixinTypeProject) {
|
|
1510
|
+
mixinTypeProject = new import_ts_morph5.Project({
|
|
1511
|
+
skipAddingFilesFromTsConfig: true,
|
|
1512
|
+
compilerOptions: { strict: true }
|
|
1513
|
+
});
|
|
1514
|
+
mixinFiles = new DiskFingerprints();
|
|
1515
|
+
mixinUnresolved = new UnresolvedImports();
|
|
1516
|
+
}
|
|
1430
1517
|
return mixinTypeProject;
|
|
1431
1518
|
}
|
|
1432
1519
|
function clearMixinTypeProject() {
|
|
1433
1520
|
mixinTypeProject = void 0;
|
|
1521
|
+
mixinStale = false;
|
|
1522
|
+
}
|
|
1523
|
+
function invalidateMixinTypeProject() {
|
|
1524
|
+
mixinStale = true;
|
|
1525
|
+
}
|
|
1526
|
+
function refreshMixinTypeProject(project) {
|
|
1527
|
+
const program = project.getProgram().compilerObject;
|
|
1528
|
+
const files = program.getSourceFiles().filter((file) => !program.isSourceFileDefaultLibrary(file)).map((file) => ({ path: file.fileName, text: file.text }));
|
|
1529
|
+
const changed = mixinFiles.changed(files);
|
|
1530
|
+
if (changed.length === 0) return mixinUnresolved.nowResolving(program).length === 0;
|
|
1531
|
+
for (const path of changed) {
|
|
1532
|
+
const sf = project.getSourceFile(path);
|
|
1533
|
+
if (sf?.refreshFromFileSystemSync() !== import_ts_morph5.FileSystemRefreshResult.Updated) return false;
|
|
1534
|
+
}
|
|
1535
|
+
project.resolveSourceFileDependencies();
|
|
1536
|
+
return true;
|
|
1434
1537
|
}
|
|
1435
1538
|
function resolveInstantiatedReturnType(cls, methodName) {
|
|
1436
1539
|
const filePath = cls.getSourceFile().getFilePath();
|
|
@@ -1461,7 +1564,7 @@ function resolveClassRef(ref, project) {
|
|
|
1461
1564
|
return file?.getClass(ref.name);
|
|
1462
1565
|
}
|
|
1463
1566
|
function classifyFilterForHint(typeInit) {
|
|
1464
|
-
if (
|
|
1567
|
+
if (import_ts_morph6.Node.isStringLiteral(typeInit)) {
|
|
1465
1568
|
switch (typeInit.getLiteralValue()) {
|
|
1466
1569
|
case "string":
|
|
1467
1570
|
return { kind: "string" };
|
|
@@ -1475,10 +1578,10 @@ function classifyFilterForHint(typeInit) {
|
|
|
1475
1578
|
return null;
|
|
1476
1579
|
}
|
|
1477
1580
|
}
|
|
1478
|
-
if (
|
|
1581
|
+
if (import_ts_morph6.Node.isArrayLiteralExpression(typeInit)) {
|
|
1479
1582
|
const values = [];
|
|
1480
1583
|
for (const el of typeInit.getElements()) {
|
|
1481
|
-
if (!
|
|
1584
|
+
if (!import_ts_morph6.Node.isStringLiteral(el)) return null;
|
|
1482
1585
|
values.push(el.getLiteralValue());
|
|
1483
1586
|
}
|
|
1484
1587
|
if (values.length === 0) return null;
|
|
@@ -1513,11 +1616,11 @@ function extractFilterForHints(classDecl, project) {
|
|
|
1513
1616
|
if (!filterForDec) continue;
|
|
1514
1617
|
const args = filterForDec.getArguments();
|
|
1515
1618
|
const keyArg = args[0];
|
|
1516
|
-
const inputKey = keyArg &&
|
|
1619
|
+
const inputKey = keyArg && import_ts_morph6.Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();
|
|
1517
1620
|
const optsArg = args[1];
|
|
1518
|
-
if (optsArg &&
|
|
1621
|
+
if (optsArg && import_ts_morph6.Node.isObjectLiteralExpression(optsArg)) {
|
|
1519
1622
|
const typeProp = optsArg.getProperty("type");
|
|
1520
|
-
if (typeProp &&
|
|
1623
|
+
if (typeProp && import_ts_morph6.Node.isPropertyAssignment(typeProp)) {
|
|
1521
1624
|
const typeInit = typeProp.getInitializer();
|
|
1522
1625
|
if (typeInit) {
|
|
1523
1626
|
const classified = classifyFilterForHint(typeInit);
|
|
@@ -1544,14 +1647,14 @@ function extractApplyFilterInfo(method, sourceFile, project, mixin, controllerCl
|
|
|
1544
1647
|
const filterClassArg = args[0];
|
|
1545
1648
|
if (!filterClassArg) continue;
|
|
1546
1649
|
const factoryStaticClass = resolveFactoryStaticClass(filterClassArg);
|
|
1547
|
-
if (!factoryStaticClass && !
|
|
1650
|
+
if (!factoryStaticClass && !import_ts_morph6.Node.isIdentifier(filterClassArg)) continue;
|
|
1548
1651
|
let source = "query";
|
|
1549
1652
|
const optionsArg = args[1];
|
|
1550
|
-
if (optionsArg &&
|
|
1653
|
+
if (optionsArg && import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) {
|
|
1551
1654
|
const sourceProp = optionsArg.getProperty("source");
|
|
1552
|
-
if (sourceProp &&
|
|
1655
|
+
if (sourceProp && import_ts_morph6.Node.isPropertyAssignment(sourceProp)) {
|
|
1553
1656
|
const init = sourceProp.getInitializer();
|
|
1554
|
-
if (init &&
|
|
1657
|
+
if (init && import_ts_morph6.Node.isStringLiteral(init) && init.getLiteralValue() === "body") {
|
|
1555
1658
|
source = "body";
|
|
1556
1659
|
}
|
|
1557
1660
|
}
|
|
@@ -1560,7 +1663,7 @@ function extractApplyFilterInfo(method, sourceFile, project, mixin, controllerCl
|
|
|
1560
1663
|
const resolved = factoryStaticClass ? void 0 : findType(filterClassName, declFile, project);
|
|
1561
1664
|
const declaredClass = factoryStaticClass ?? (resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg));
|
|
1562
1665
|
const ownRoute = !mixin || (controllerClass ? method.getParent() === controllerClass : declFile.getFilePath() !== mixin.factoryFilePath);
|
|
1563
|
-
const namedByRoute = ownRoute &&
|
|
1666
|
+
const namedByRoute = ownRoute && import_ts_morph6.Node.isIdentifier(filterClassArg) ? declaredClass : void 0;
|
|
1564
1667
|
for (const candidate of orderFilterCandidates({
|
|
1565
1668
|
namedByRoute,
|
|
1566
1669
|
supplied: resolveMixinFilterClass(mixin, project),
|
|
@@ -1638,22 +1741,22 @@ function resolveRelationEntity(prop, sourceFile, project) {
|
|
|
1638
1741
|
const args = dec.getArguments();
|
|
1639
1742
|
if (args.length === 0) continue;
|
|
1640
1743
|
const arg = args[0];
|
|
1641
|
-
if (
|
|
1744
|
+
if (import_ts_morph6.Node.isObjectLiteralExpression(arg)) {
|
|
1642
1745
|
const entityProp = arg.getProperty("entity");
|
|
1643
|
-
if (entityProp &&
|
|
1746
|
+
if (entityProp && import_ts_morph6.Node.isPropertyAssignment(entityProp)) {
|
|
1644
1747
|
const init = entityProp.getInitializer();
|
|
1645
|
-
if (init &&
|
|
1748
|
+
if (init && import_ts_morph6.Node.isArrowFunction(init)) {
|
|
1646
1749
|
const body = init.getBody();
|
|
1647
|
-
if (
|
|
1750
|
+
if (import_ts_morph6.Node.isIdentifier(body)) {
|
|
1648
1751
|
const resolved = findType(body.getText(), prop.getSourceFile(), project);
|
|
1649
1752
|
if (resolved?.kind === "class") return resolved.decl;
|
|
1650
1753
|
}
|
|
1651
1754
|
}
|
|
1652
1755
|
}
|
|
1653
1756
|
}
|
|
1654
|
-
if (
|
|
1757
|
+
if (import_ts_morph6.Node.isArrowFunction(arg)) {
|
|
1655
1758
|
const body = arg.getBody();
|
|
1656
|
-
if (
|
|
1759
|
+
if (import_ts_morph6.Node.isIdentifier(body)) {
|
|
1657
1760
|
const resolved = findType(body.getText(), prop.getSourceFile(), project);
|
|
1658
1761
|
if (resolved?.kind === "class") return resolved.decl;
|
|
1659
1762
|
}
|
|
@@ -1672,36 +1775,36 @@ function extractClassPropertyTypes(classDecl, project) {
|
|
|
1672
1775
|
return fields;
|
|
1673
1776
|
}
|
|
1674
1777
|
function resolveLocalClassDeclaration(identifier) {
|
|
1675
|
-
if (!
|
|
1676
|
-
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 &&
|
|
1778
|
+
if (!import_ts_morph6.Node.isIdentifier(identifier)) return void 0;
|
|
1779
|
+
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph6.Node.isClassDeclaration(n));
|
|
1677
1780
|
}
|
|
1678
1781
|
function resolveDeclaredEntity(optionsArg, filterClass, project) {
|
|
1679
|
-
if (!
|
|
1782
|
+
if (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return void 0;
|
|
1680
1783
|
const entityProp = optionsArg.getProperty("entity");
|
|
1681
|
-
if (!entityProp || !
|
|
1784
|
+
if (!entityProp || !import_ts_morph6.Node.isPropertyAssignment(entityProp)) return void 0;
|
|
1682
1785
|
const entityInit = entityProp.getInitializer();
|
|
1683
|
-
if (!entityInit || !
|
|
1786
|
+
if (!entityInit || !import_ts_morph6.Node.isIdentifier(entityInit)) return void 0;
|
|
1684
1787
|
const resolved = findType(entityInit.getText(), filterClass.getSourceFile(), project);
|
|
1685
1788
|
if (!resolved || resolved.kind !== "class") return void 0;
|
|
1686
1789
|
return resolved.decl;
|
|
1687
1790
|
}
|
|
1688
1791
|
function readFieldNameList(optionsArg, key) {
|
|
1689
|
-
if (!
|
|
1792
|
+
if (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return void 0;
|
|
1690
1793
|
const prop = optionsArg.getProperty(key);
|
|
1691
|
-
if (!prop || !
|
|
1794
|
+
if (!prop || !import_ts_morph6.Node.isPropertyAssignment(prop)) return void 0;
|
|
1692
1795
|
const init = prop.getInitializer();
|
|
1693
|
-
if (!init || !
|
|
1796
|
+
if (!init || !import_ts_morph6.Node.isArrayLiteralExpression(init)) return void 0;
|
|
1694
1797
|
const names = /* @__PURE__ */ new Set();
|
|
1695
1798
|
for (const el of init.getElements()) {
|
|
1696
|
-
if (
|
|
1799
|
+
if (import_ts_morph6.Node.isStringLiteral(el)) {
|
|
1697
1800
|
names.add(el.getLiteralValue());
|
|
1698
1801
|
continue;
|
|
1699
1802
|
}
|
|
1700
|
-
if (
|
|
1803
|
+
if (import_ts_morph6.Node.isObjectLiteralExpression(el)) {
|
|
1701
1804
|
const fieldProp = el.getProperty("field");
|
|
1702
|
-
if (fieldProp &&
|
|
1805
|
+
if (fieldProp && import_ts_morph6.Node.isPropertyAssignment(fieldProp)) {
|
|
1703
1806
|
const fieldInit = fieldProp.getInitializer();
|
|
1704
|
-
if (fieldInit &&
|
|
1807
|
+
if (fieldInit && import_ts_morph6.Node.isStringLiteral(fieldInit)) {
|
|
1705
1808
|
names.add(fieldInit.getLiteralValue());
|
|
1706
1809
|
continue;
|
|
1707
1810
|
}
|
|
@@ -1725,7 +1828,7 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
|
|
|
1725
1828
|
const args = filterableDecorator.getArguments();
|
|
1726
1829
|
if (args.length === 0) return [];
|
|
1727
1830
|
const optionsArg = args[0];
|
|
1728
|
-
if (!
|
|
1831
|
+
if (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return [];
|
|
1729
1832
|
const declaredEntity = resolveDeclaredEntity(optionsArg, filterClass, project);
|
|
1730
1833
|
const entityDecl = preferDeclaredEntity ? declaredEntity ?? entityOverride : entityOverride ?? declaredEntity;
|
|
1731
1834
|
if (!entityDecl) return [];
|
|
@@ -1736,17 +1839,17 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
|
|
|
1736
1839
|
const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === "Relations");
|
|
1737
1840
|
if (relationsDecorator) {
|
|
1738
1841
|
const relArgs = relationsDecorator.getArguments();
|
|
1739
|
-
if (relArgs.length > 0 &&
|
|
1842
|
+
if (relArgs.length > 0 && import_ts_morph6.Node.isObjectLiteralExpression(relArgs[0])) {
|
|
1740
1843
|
for (const relProp of relArgs[0].getProperties()) {
|
|
1741
|
-
if (!
|
|
1844
|
+
if (!import_ts_morph6.Node.isPropertyAssignment(relProp)) continue;
|
|
1742
1845
|
const relInit = relProp.getInitializer();
|
|
1743
|
-
if (!relInit || !
|
|
1846
|
+
if (!relInit || !import_ts_morph6.Node.isObjectLiteralExpression(relInit)) continue;
|
|
1744
1847
|
const keysProp = relInit.getProperty("keys");
|
|
1745
|
-
if (!keysProp || !
|
|
1848
|
+
if (!keysProp || !import_ts_morph6.Node.isPropertyAssignment(keysProp)) continue;
|
|
1746
1849
|
const keysInit = keysProp.getInitializer();
|
|
1747
|
-
if (!keysInit || !
|
|
1850
|
+
if (!keysInit || !import_ts_morph6.Node.isArrayLiteralExpression(keysInit)) continue;
|
|
1748
1851
|
for (const el of keysInit.getElements()) {
|
|
1749
|
-
if (
|
|
1852
|
+
if (import_ts_morph6.Node.isStringLiteral(el)) {
|
|
1750
1853
|
fields.push(toFilterFieldType(el.getLiteralValue(), { kind: "unknown" }));
|
|
1751
1854
|
}
|
|
1752
1855
|
}
|
|
@@ -1757,13 +1860,13 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
|
|
|
1757
1860
|
}
|
|
1758
1861
|
|
|
1759
1862
|
// src/discovery/pipe-schema.ts
|
|
1760
|
-
var
|
|
1863
|
+
var import_ts_morph10 = require("ts-morph");
|
|
1761
1864
|
|
|
1762
1865
|
// src/discovery/schema-type-inference.ts
|
|
1763
|
-
var
|
|
1866
|
+
var import_ts_morph8 = require("ts-morph");
|
|
1764
1867
|
|
|
1765
1868
|
// src/discovery/schema-type-program.ts
|
|
1766
|
-
var
|
|
1869
|
+
var import_ts_morph7 = require("ts-morph");
|
|
1767
1870
|
var PARAM_DECORATORS = /* @__PURE__ */ new Set(["Body", "Query", "Param"]);
|
|
1768
1871
|
var SchemaTypeProgram = class {
|
|
1769
1872
|
constructor(discovery) {
|
|
@@ -1773,10 +1876,10 @@ var SchemaTypeProgram = class {
|
|
|
1773
1876
|
...base,
|
|
1774
1877
|
// A tsconfig-less consumer gets ES5 by default, whose lib has no `Map`/`Set`/
|
|
1775
1878
|
// `Promise` for the schema libraries' declarations to lean on.
|
|
1776
|
-
target: base.target ??
|
|
1879
|
+
target: base.target ?? import_ts_morph7.ts.ScriptTarget.ES2022,
|
|
1777
1880
|
// With neither set, resolve the way a bundler does: package `exports`
|
|
1778
1881
|
// (`zod/v4`) and extensionless or `.js` relative imports all resolve.
|
|
1779
|
-
...base.module === void 0 && base.moduleResolution === void 0 ? { module:
|
|
1882
|
+
...base.module === void 0 && base.moduleResolution === void 0 ? { module: import_ts_morph7.ts.ModuleKind.ESNext, moduleResolution: import_ts_morph7.ts.ModuleResolutionKind.Bundler } : {},
|
|
1780
1883
|
// Without it `.nullable()` and `.optional()` would erase to the bare type.
|
|
1781
1884
|
strictNullChecks: true,
|
|
1782
1885
|
// No ambient `@types/*` (a tsconfig's `types: ['node']`): a schema does not
|
|
@@ -1784,17 +1887,16 @@ var SchemaTypeProgram = class {
|
|
|
1784
1887
|
types: [],
|
|
1785
1888
|
noEmit: true
|
|
1786
1889
|
};
|
|
1787
|
-
this.project = new
|
|
1890
|
+
this.project = new import_ts_morph7.Project({
|
|
1788
1891
|
skipAddingFilesFromTsConfig: true,
|
|
1789
1892
|
compilerOptions: this.options
|
|
1790
1893
|
});
|
|
1791
|
-
|
|
1792
|
-
this.flush();
|
|
1894
|
+
this.requestDiscoveryFiles();
|
|
1793
1895
|
}
|
|
1794
1896
|
project;
|
|
1795
1897
|
options;
|
|
1796
1898
|
/** Parses a file that is not in discovery's Project, without adding it there. */
|
|
1797
|
-
scratch = new
|
|
1899
|
+
scratch = new import_ts_morph7.Project({
|
|
1798
1900
|
skipAddingFilesFromTsConfig: true,
|
|
1799
1901
|
skipLoadingLibFiles: true,
|
|
1800
1902
|
skipFileDependencyResolution: true
|
|
@@ -1802,6 +1904,53 @@ var SchemaTypeProgram = class {
|
|
|
1802
1904
|
needs = /* @__PURE__ */ new Map();
|
|
1803
1905
|
/** Pruned text per file, as last written into {@link project}. */
|
|
1804
1906
|
written = /* @__PURE__ */ new Map();
|
|
1907
|
+
/** What {@link project} read from disk unpruned (packages, declaration files). */
|
|
1908
|
+
externalFiles = new DiskFingerprints();
|
|
1909
|
+
scratchFiles = new DiskFingerprints();
|
|
1910
|
+
/** The last pruning of each file, with the source text and needs it was pruned for. */
|
|
1911
|
+
pruned = /* @__PURE__ */ new Map();
|
|
1912
|
+
/**
|
|
1913
|
+
* Bring the program up to date with discovery's files and the disk, keeping the
|
|
1914
|
+
* lib and package declarations it has already parsed and checked. Leaves it
|
|
1915
|
+
* holding exactly the files a new program built now would hold, with the same
|
|
1916
|
+
* text. Returns false when a file the program read unpruned has changed on disk
|
|
1917
|
+
* (a package was reinstalled, a `.d.ts` was edited): the caller builds a new
|
|
1918
|
+
* program instead.
|
|
1919
|
+
*/
|
|
1920
|
+
refresh() {
|
|
1921
|
+
const program = this.project.getProgram().compilerObject;
|
|
1922
|
+
const external = program.getSourceFiles().filter(
|
|
1923
|
+
(file) => !program.isSourceFileDefaultLibrary(file) && !this.written.has(file.fileName)
|
|
1924
|
+
).map((file) => ({ path: file.fileName, text: file.text }));
|
|
1925
|
+
if (this.externalFiles.changed(external).length > 0) return false;
|
|
1926
|
+
const scratch = this.scratch.getSourceFiles().map((sf) => ({ path: sf.getFilePath(), text: sf.getFullText() }));
|
|
1927
|
+
for (const path of this.scratchFiles.changed(scratch)) {
|
|
1928
|
+
const sf = this.scratch.getSourceFile(path);
|
|
1929
|
+
if (sf?.refreshFromFileSystemSync() === import_ts_morph7.FileSystemRefreshResult.Deleted) {
|
|
1930
|
+
this.scratchFiles.forget(path);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
this.needs.clear();
|
|
1934
|
+
this.requestDiscoveryFiles();
|
|
1935
|
+
for (const path of [...this.written.keys()]) {
|
|
1936
|
+
if (this.needs.has(path)) continue;
|
|
1937
|
+
const sf = this.project.getSourceFile(path);
|
|
1938
|
+
if (sf) this.project.removeSourceFile(sf);
|
|
1939
|
+
this.written.delete(path);
|
|
1940
|
+
}
|
|
1941
|
+
return true;
|
|
1942
|
+
}
|
|
1943
|
+
/**
|
|
1944
|
+
* Everything discovery holds now (the controllers) goes in before the first
|
|
1945
|
+
* query: a file added afterwards discards the program and its checker, and
|
|
1946
|
+
* rebuilding them once per controller is exactly the cost this avoids.
|
|
1947
|
+
*/
|
|
1948
|
+
requestDiscoveryFiles() {
|
|
1949
|
+
for (const sf of this.discovery.getSourceFiles()) {
|
|
1950
|
+
this.request(sf.getFilePath(), { schema: true });
|
|
1951
|
+
}
|
|
1952
|
+
this.flush();
|
|
1953
|
+
}
|
|
1805
1954
|
/**
|
|
1806
1955
|
* The typed copy of a discovery file, with its schema positions kept. Adding one
|
|
1807
1956
|
* that was not there yet (a contract file discovery reached lazily) rebuilds the
|
|
@@ -1842,12 +1991,21 @@ var SchemaTypeProgram = class {
|
|
|
1842
1991
|
while (this.queue.length > 0) {
|
|
1843
1992
|
const path = this.queue.pop();
|
|
1844
1993
|
const original = this.original(path);
|
|
1845
|
-
if (!original)
|
|
1846
|
-
|
|
1847
|
-
|
|
1994
|
+
if (!original) {
|
|
1995
|
+
if (this.written.has(path)) changed.set(path, void 0);
|
|
1996
|
+
continue;
|
|
1997
|
+
}
|
|
1998
|
+
const { text, requests } = this.pruneCached(path, original, this.needs.get(path));
|
|
1999
|
+
for (const { path: target, want } of requests) this.request(target, want);
|
|
1848
2000
|
if (this.written.get(path) !== text) changed.set(path, text);
|
|
1849
2001
|
}
|
|
1850
2002
|
for (const [path, text] of changed) {
|
|
2003
|
+
if (text === void 0) {
|
|
2004
|
+
const sf = this.project.getSourceFile(path);
|
|
2005
|
+
if (sf) this.project.removeSourceFile(sf);
|
|
2006
|
+
this.written.delete(path);
|
|
2007
|
+
continue;
|
|
2008
|
+
}
|
|
1851
2009
|
this.project.createSourceFile(path, text, { overwrite: true });
|
|
1852
2010
|
this.written.set(path, text);
|
|
1853
2011
|
}
|
|
@@ -1856,11 +2014,29 @@ var SchemaTypeProgram = class {
|
|
|
1856
2014
|
original(path) {
|
|
1857
2015
|
return this.discovery.getSourceFile(path) ?? this.scratch.getSourceFile(path) ?? this.scratch.addSourceFileAtPathIfExists(path);
|
|
1858
2016
|
}
|
|
2017
|
+
/** {@link prune}, reusing the last result while the file's text and needs are the same. */
|
|
2018
|
+
pruneCached(path, sf, needs) {
|
|
2019
|
+
const source = sf.getFullText();
|
|
2020
|
+
const key = `${needs.schema}:${needs.all}:${[...needs.names].sort().join(",")}`;
|
|
2021
|
+
const last = this.pruned.get(path);
|
|
2022
|
+
if (last && last.source === source && last.needs === key) return last;
|
|
2023
|
+
const result = this.prune(sf, needs);
|
|
2024
|
+
if (result.resolved) this.pruned.set(path, { ...result, source, needs: key });
|
|
2025
|
+
else this.pruned.delete(path);
|
|
2026
|
+
return result;
|
|
2027
|
+
}
|
|
1859
2028
|
/**
|
|
1860
2029
|
* `sf`'s text with every import/re-export nothing in `needs` references blanked,
|
|
1861
|
-
*
|
|
2030
|
+
* and the names each kept one brings in from its target.
|
|
1862
2031
|
*/
|
|
1863
2032
|
prune(sf, needs) {
|
|
2033
|
+
const requests = [];
|
|
2034
|
+
let resolved = true;
|
|
2035
|
+
const resolveFrom = (specifier) => {
|
|
2036
|
+
const target = this.resolve(specifier, sf);
|
|
2037
|
+
if (target === null) resolved = false;
|
|
2038
|
+
return target ?? void 0;
|
|
2039
|
+
};
|
|
1864
2040
|
const locals = topLevelDeclarations(sf);
|
|
1865
2041
|
const roots = [];
|
|
1866
2042
|
if (needs.all) roots.push(...sf.getStatements());
|
|
@@ -1894,7 +2070,7 @@ var SchemaTypeProgram = class {
|
|
|
1894
2070
|
const seen = new Set(queue);
|
|
1895
2071
|
while (queue.length > 0) {
|
|
1896
2072
|
const node = queue.pop();
|
|
1897
|
-
const ids =
|
|
2073
|
+
const ids = import_ts_morph7.Node.isIdentifier(node) ? [node] : node.getDescendantsOfKind(import_ts_morph7.ts.SyntaxKind.Identifier);
|
|
1898
2074
|
for (const id of ids) {
|
|
1899
2075
|
const name = id.getText();
|
|
1900
2076
|
if (referenced.has(name)) continue;
|
|
@@ -1913,7 +2089,7 @@ var SchemaTypeProgram = class {
|
|
|
1913
2089
|
}
|
|
1914
2090
|
};
|
|
1915
2091
|
for (const decl of sf.getImportDeclarations()) {
|
|
1916
|
-
const target =
|
|
2092
|
+
const target = resolveFrom(decl.getModuleSpecifierValue());
|
|
1917
2093
|
const namespace = decl.getNamespaceImport()?.getText();
|
|
1918
2094
|
const def = decl.getDefaultImport()?.getText();
|
|
1919
2095
|
const named = decl.getNamedImports().map((n) => ({
|
|
@@ -1927,21 +2103,24 @@ var SchemaTypeProgram = class {
|
|
|
1927
2103
|
continue;
|
|
1928
2104
|
}
|
|
1929
2105
|
if (target) {
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
2106
|
+
requests.push({
|
|
2107
|
+
path: target,
|
|
2108
|
+
want: {
|
|
2109
|
+
all: wantsNamespace,
|
|
2110
|
+
names: [...wantsDefault ? ["default"] : [], ...named.map((n) => n.imported)]
|
|
2111
|
+
}
|
|
1933
2112
|
});
|
|
1934
2113
|
}
|
|
1935
2114
|
}
|
|
1936
2115
|
for (const exp of sf.getExportDeclarations()) {
|
|
1937
2116
|
const spec = exp.getModuleSpecifierValue();
|
|
1938
2117
|
if (spec === void 0) continue;
|
|
1939
|
-
const target =
|
|
2118
|
+
const target = resolveFrom(spec);
|
|
1940
2119
|
if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) {
|
|
1941
2120
|
if (!needs.all && unresolvedNames.length === 0) {
|
|
1942
2121
|
blank(exp);
|
|
1943
2122
|
} else if (target) {
|
|
1944
|
-
|
|
2123
|
+
requests.push({ path: target, want: { all: needs.all, names: unresolvedNames } });
|
|
1945
2124
|
}
|
|
1946
2125
|
continue;
|
|
1947
2126
|
}
|
|
@@ -1949,22 +2128,24 @@ var SchemaTypeProgram = class {
|
|
|
1949
2128
|
(n) => needs.all || needs.names.has((n.getAliasNode() ?? n.getNameNode()).getText())
|
|
1950
2129
|
).map((n) => n.getNameNode().getText());
|
|
1951
2130
|
if (wanted.length === 0) blank(exp);
|
|
1952
|
-
else if (target)
|
|
2131
|
+
else if (target) requests.push({ path: target, want: { names: wanted } });
|
|
1953
2132
|
}
|
|
1954
|
-
return chars.join("");
|
|
2133
|
+
return { text: chars.join(""), requests, resolved };
|
|
1955
2134
|
}
|
|
1956
2135
|
/**
|
|
1957
|
-
* The project source file a module specifier resolves to
|
|
1958
|
-
* package (read unpruned by the program itself)
|
|
2136
|
+
* The project source file a module specifier resolves to; undefined for a
|
|
2137
|
+
* package or a declaration file (read unpruned by the program itself), null for
|
|
2138
|
+
* one that does not resolve.
|
|
1959
2139
|
*/
|
|
1960
2140
|
resolve(specifier, from) {
|
|
1961
|
-
const resolved =
|
|
2141
|
+
const resolved = import_ts_morph7.ts.resolveModuleName(
|
|
1962
2142
|
specifier,
|
|
1963
2143
|
from.getFilePath(),
|
|
1964
2144
|
this.options,
|
|
1965
|
-
|
|
2145
|
+
import_ts_morph7.ts.sys
|
|
1966
2146
|
).resolvedModule;
|
|
1967
|
-
if (!resolved
|
|
2147
|
+
if (!resolved) return null;
|
|
2148
|
+
if (resolved.isExternalLibraryImport) return void 0;
|
|
1968
2149
|
const file = resolved.resolvedFileName;
|
|
1969
2150
|
if (file.endsWith(".d.ts") || !/\.(m|c)?tsx?$/.test(file)) return void 0;
|
|
1970
2151
|
return file;
|
|
@@ -1973,20 +2154,20 @@ var SchemaTypeProgram = class {
|
|
|
1973
2154
|
function schemaPositions(sf) {
|
|
1974
2155
|
const roots = [];
|
|
1975
2156
|
sf.forEachDescendant((node) => {
|
|
1976
|
-
if (
|
|
2157
|
+
if (import_ts_morph7.Node.isDecorator(node)) {
|
|
1977
2158
|
const name = node.getName();
|
|
1978
2159
|
if (name === "ApplyContract") {
|
|
1979
2160
|
roots.push(...node.getArguments());
|
|
1980
2161
|
} else if (PARAM_DECORATORS.has(name)) {
|
|
1981
2162
|
for (const arg of node.getArguments()) {
|
|
1982
|
-
if (
|
|
2163
|
+
if (import_ts_morph7.Node.isNewExpression(arg) || import_ts_morph7.Node.isCallExpression(arg)) {
|
|
1983
2164
|
roots.push(...arg.getArguments());
|
|
1984
2165
|
}
|
|
1985
2166
|
}
|
|
1986
2167
|
}
|
|
1987
|
-
} else if (
|
|
2168
|
+
} else if (import_ts_morph7.Node.isCallExpression(node)) {
|
|
1988
2169
|
const callee = node.getExpression();
|
|
1989
|
-
const name =
|
|
2170
|
+
const name = import_ts_morph7.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph7.Node.isPropertyAccessExpression(callee) ? callee.getName() : void 0;
|
|
1990
2171
|
if (name === "defineContract") roots.push(...node.getArguments());
|
|
1991
2172
|
}
|
|
1992
2173
|
});
|
|
@@ -2019,8 +2200,13 @@ function defaultExport(sf) {
|
|
|
2019
2200
|
|
|
2020
2201
|
// src/discovery/schema-type-inference.ts
|
|
2021
2202
|
var programs = /* @__PURE__ */ new WeakMap();
|
|
2203
|
+
var stale = /* @__PURE__ */ new WeakSet();
|
|
2022
2204
|
function programFor(discovery) {
|
|
2023
2205
|
let program = programs.get(discovery);
|
|
2206
|
+
if (program && stale.has(discovery)) {
|
|
2207
|
+
stale.delete(discovery);
|
|
2208
|
+
if (!program.refresh()) program = void 0;
|
|
2209
|
+
}
|
|
2024
2210
|
if (!program) {
|
|
2025
2211
|
program = new SchemaTypeProgram(discovery);
|
|
2026
2212
|
programs.set(discovery, program);
|
|
@@ -2029,6 +2215,10 @@ function programFor(discovery) {
|
|
|
2029
2215
|
}
|
|
2030
2216
|
function clearSchemaTypeProject(discovery) {
|
|
2031
2217
|
programs.delete(discovery);
|
|
2218
|
+
stale.delete(discovery);
|
|
2219
|
+
}
|
|
2220
|
+
function invalidateSchemaTypeProject(discovery) {
|
|
2221
|
+
if (programs.has(discovery)) stale.add(discovery);
|
|
2032
2222
|
}
|
|
2033
2223
|
function counterpart(typedSf, node) {
|
|
2034
2224
|
const start = node.getStart();
|
|
@@ -2092,7 +2282,7 @@ function objectKey(name) {
|
|
|
2092
2282
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
2093
2283
|
}
|
|
2094
2284
|
function isOptionalSymbol(sym) {
|
|
2095
|
-
return (sym.getFlags() &
|
|
2285
|
+
return (sym.getFlags() & import_ts_morph8.ts.SymbolFlags.Optional) !== 0;
|
|
2096
2286
|
}
|
|
2097
2287
|
function isSymbolKeyed(sym) {
|
|
2098
2288
|
return sym.getName().startsWith("__@");
|
|
@@ -2253,11 +2443,11 @@ function acceptsUndefined(types) {
|
|
|
2253
2443
|
}
|
|
2254
2444
|
|
|
2255
2445
|
// src/discovery/zod-ast-to-ts.ts
|
|
2256
|
-
var
|
|
2446
|
+
var import_ts_morph9 = require("ts-morph");
|
|
2257
2447
|
function zodAstToTs(node) {
|
|
2258
|
-
if (!
|
|
2448
|
+
if (!import_ts_morph9.Node.isCallExpression(node)) return "unknown";
|
|
2259
2449
|
const expr = node.getExpression();
|
|
2260
|
-
if (
|
|
2450
|
+
if (import_ts_morph9.Node.isPropertyAccessExpression(expr)) {
|
|
2261
2451
|
const methodName = expr.getName();
|
|
2262
2452
|
const receiver = expr.getExpression();
|
|
2263
2453
|
if (methodName === "optional") {
|
|
@@ -2281,17 +2471,17 @@ function zodAstToTs(node) {
|
|
|
2281
2471
|
case "literal": {
|
|
2282
2472
|
const lit = args[0];
|
|
2283
2473
|
if (!lit) return "unknown";
|
|
2284
|
-
if (
|
|
2285
|
-
if (
|
|
2286
|
-
if (lit.getKind() ===
|
|
2287
|
-
if (lit.getKind() ===
|
|
2474
|
+
if (import_ts_morph9.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
|
|
2475
|
+
if (import_ts_morph9.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
|
|
2476
|
+
if (lit.getKind() === import_ts_morph9.SyntaxKind.TrueKeyword) return "true";
|
|
2477
|
+
if (lit.getKind() === import_ts_morph9.SyntaxKind.FalseKeyword) return "false";
|
|
2288
2478
|
return "unknown";
|
|
2289
2479
|
}
|
|
2290
2480
|
case "enum": {
|
|
2291
2481
|
const arrArg = args[0];
|
|
2292
|
-
if (!arrArg || !
|
|
2482
|
+
if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
2293
2483
|
const members = arrArg.getElements().map(
|
|
2294
|
-
(el) =>
|
|
2484
|
+
(el) => import_ts_morph9.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
|
|
2295
2485
|
);
|
|
2296
2486
|
return members.join(" | ");
|
|
2297
2487
|
}
|
|
@@ -2302,10 +2492,10 @@ function zodAstToTs(node) {
|
|
|
2302
2492
|
}
|
|
2303
2493
|
case "object": {
|
|
2304
2494
|
const objArg = args[0];
|
|
2305
|
-
if (!objArg || !
|
|
2495
|
+
if (!objArg || !import_ts_morph9.Node.isObjectLiteralExpression(objArg)) return "unknown";
|
|
2306
2496
|
const lines = [];
|
|
2307
2497
|
for (const prop of objArg.getProperties()) {
|
|
2308
|
-
if (!
|
|
2498
|
+
if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
|
|
2309
2499
|
const key = prop.getName();
|
|
2310
2500
|
const valNode = prop.getInitializer();
|
|
2311
2501
|
if (!valNode) continue;
|
|
@@ -2317,7 +2507,7 @@ function zodAstToTs(node) {
|
|
|
2317
2507
|
}
|
|
2318
2508
|
case "union": {
|
|
2319
2509
|
const arrArg = args[0];
|
|
2320
|
-
if (!arrArg || !
|
|
2510
|
+
if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
2321
2511
|
return arrArg.getElements().map(zodAstToTs).join(" | ");
|
|
2322
2512
|
}
|
|
2323
2513
|
case "record": {
|
|
@@ -2327,7 +2517,7 @@ function zodAstToTs(node) {
|
|
|
2327
2517
|
}
|
|
2328
2518
|
case "tuple": {
|
|
2329
2519
|
const arrArg = args[0];
|
|
2330
|
-
if (!arrArg || !
|
|
2520
|
+
if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
2331
2521
|
return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
|
|
2332
2522
|
}
|
|
2333
2523
|
default:
|
|
@@ -2337,9 +2527,9 @@ function zodAstToTs(node) {
|
|
|
2337
2527
|
return "unknown";
|
|
2338
2528
|
}
|
|
2339
2529
|
function isOptionalChain(node) {
|
|
2340
|
-
if (!
|
|
2530
|
+
if (!import_ts_morph9.Node.isCallExpression(node)) return false;
|
|
2341
2531
|
const expr = node.getExpression();
|
|
2342
|
-
return
|
|
2532
|
+
return import_ts_morph9.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
|
|
2343
2533
|
}
|
|
2344
2534
|
function memberType(val, position, project) {
|
|
2345
2535
|
if (project) {
|
|
@@ -2351,13 +2541,13 @@ function memberType(val, position, project) {
|
|
|
2351
2541
|
return zodAstToTs(val);
|
|
2352
2542
|
}
|
|
2353
2543
|
function parseDefineContractCall(callExpr, project) {
|
|
2354
|
-
if (!
|
|
2544
|
+
if (!import_ts_morph9.Node.isCallExpression(callExpr)) return null;
|
|
2355
2545
|
const callee = callExpr.getExpression();
|
|
2356
|
-
const calleeName =
|
|
2546
|
+
const calleeName = import_ts_morph9.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph9.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
|
|
2357
2547
|
if (calleeName !== "defineContract") return null;
|
|
2358
2548
|
const args = callExpr.getArguments();
|
|
2359
2549
|
const optsArg = args[0];
|
|
2360
|
-
if (!optsArg || !
|
|
2550
|
+
if (!optsArg || !import_ts_morph9.Node.isObjectLiteralExpression(optsArg)) return null;
|
|
2361
2551
|
let query = null;
|
|
2362
2552
|
let body = null;
|
|
2363
2553
|
let response = "unknown";
|
|
@@ -2365,7 +2555,7 @@ function parseDefineContractCall(callExpr, project) {
|
|
|
2365
2555
|
let bodyZodText = null;
|
|
2366
2556
|
let queryZodText = null;
|
|
2367
2557
|
for (const prop of optsArg.getProperties()) {
|
|
2368
|
-
if (!
|
|
2558
|
+
if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
|
|
2369
2559
|
const propName = prop.getName();
|
|
2370
2560
|
const val = prop.getInitializer();
|
|
2371
2561
|
if (!val) continue;
|
|
@@ -2387,7 +2577,7 @@ function parseDefineContractCall(callExpr, project) {
|
|
|
2387
2577
|
// src/discovery/pipe-schema.ts
|
|
2388
2578
|
function pipeSchemaOf(decorator, project) {
|
|
2389
2579
|
for (const pipe of decorator.getArguments()) {
|
|
2390
|
-
if (!
|
|
2580
|
+
if (!import_ts_morph10.Node.isNewExpression(pipe) && !import_ts_morph10.Node.isCallExpression(pipe)) continue;
|
|
2391
2581
|
for (const arg of pipe.getArguments()) {
|
|
2392
2582
|
if (!couldBeSchema(arg)) continue;
|
|
2393
2583
|
const inferred = inferSchema(arg, project);
|
|
@@ -2409,15 +2599,15 @@ function pipeSchemaOf(decorator, project) {
|
|
|
2409
2599
|
return null;
|
|
2410
2600
|
}
|
|
2411
2601
|
function couldBeSchema(arg) {
|
|
2412
|
-
return
|
|
2602
|
+
return import_ts_morph10.Node.isIdentifier(arg) || import_ts_morph10.Node.isPropertyAccessExpression(arg) || import_ts_morph10.Node.isCallExpression(arg) || import_ts_morph10.Node.isAsExpression(arg) || import_ts_morph10.Node.isSatisfiesExpression(arg) || import_ts_morph10.Node.isParenthesizedExpression(arg);
|
|
2413
2603
|
}
|
|
2414
2604
|
function syntacticZodType(arg, project) {
|
|
2415
2605
|
let expr = arg;
|
|
2416
|
-
if (
|
|
2606
|
+
if (import_ts_morph10.Node.isIdentifier(arg)) {
|
|
2417
2607
|
const resolved = resolveImportedVariable(arg.getText(), arg.getSourceFile(), project);
|
|
2418
2608
|
expr = resolved?.decl.getInitializer();
|
|
2419
2609
|
}
|
|
2420
|
-
if (!expr || !
|
|
2610
|
+
if (!expr || !import_ts_morph10.Node.isCallExpression(expr)) return null;
|
|
2421
2611
|
const type = zodAstToTs(expr);
|
|
2422
2612
|
return type === "unknown" ? null : type;
|
|
2423
2613
|
}
|
|
@@ -2453,22 +2643,22 @@ var PASSTHROUGH_UTILITY = /* @__PURE__ */ new Set([
|
|
|
2453
2643
|
]);
|
|
2454
2644
|
function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /* @__PURE__ */ new Map()) {
|
|
2455
2645
|
if (depth <= 0) return "unknown";
|
|
2456
|
-
if (
|
|
2646
|
+
if (import_ts_morph11.Node.isArrayTypeNode(typeNode)) {
|
|
2457
2647
|
const elementType = typeNode.getElementTypeNode();
|
|
2458
2648
|
return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth, subst)}>`;
|
|
2459
2649
|
}
|
|
2460
|
-
if (
|
|
2650
|
+
if (import_ts_morph11.Node.isUnionTypeNode(typeNode)) {
|
|
2461
2651
|
return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" | ");
|
|
2462
2652
|
}
|
|
2463
|
-
if (
|
|
2653
|
+
if (import_ts_morph11.Node.isIntersectionTypeNode(typeNode)) {
|
|
2464
2654
|
return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" & ");
|
|
2465
2655
|
}
|
|
2466
|
-
if (
|
|
2656
|
+
if (import_ts_morph11.Node.isParenthesizedTypeNode(typeNode)) {
|
|
2467
2657
|
return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
|
|
2468
2658
|
}
|
|
2469
|
-
if (
|
|
2659
|
+
if (import_ts_morph11.Node.isTypeReference(typeNode)) {
|
|
2470
2660
|
const typeName = typeNode.getTypeName();
|
|
2471
|
-
const name =
|
|
2661
|
+
const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
|
|
2472
2662
|
const bound = subst.get(name);
|
|
2473
2663
|
if (bound !== void 0) return bound;
|
|
2474
2664
|
if (name === "string" || name === "number" || name === "boolean") return name;
|
|
@@ -2491,10 +2681,10 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
|
|
|
2491
2681
|
dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
|
|
2492
2682
|
return "unknown";
|
|
2493
2683
|
}
|
|
2494
|
-
if (
|
|
2684
|
+
if (import_ts_morph11.Node.isTypeLiteral(typeNode)) {
|
|
2495
2685
|
const members = [];
|
|
2496
2686
|
for (const member of typeNode.getMembers()) {
|
|
2497
|
-
if (
|
|
2687
|
+
if (import_ts_morph11.Node.isPropertySignature(member)) {
|
|
2498
2688
|
const memberTypeNode = member.getTypeNode();
|
|
2499
2689
|
const memberType2 = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
|
|
2500
2690
|
members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType2}`);
|
|
@@ -2505,11 +2695,11 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
|
|
|
2505
2695
|
return members.length > 0 ? `{ ${members.join("; ")} }` : "{}";
|
|
2506
2696
|
}
|
|
2507
2697
|
const kind = typeNode.getKind();
|
|
2508
|
-
if (kind ===
|
|
2509
|
-
if (kind ===
|
|
2510
|
-
if (kind ===
|
|
2511
|
-
if (kind ===
|
|
2512
|
-
if (kind ===
|
|
2698
|
+
if (kind === import_ts_morph11.SyntaxKind.StringKeyword) return "string";
|
|
2699
|
+
if (kind === import_ts_morph11.SyntaxKind.NumberKeyword) return "number";
|
|
2700
|
+
if (kind === import_ts_morph11.SyntaxKind.BooleanKeyword) return "boolean";
|
|
2701
|
+
if (kind === import_ts_morph11.SyntaxKind.UnknownKeyword) return "unknown";
|
|
2702
|
+
if (kind === import_ts_morph11.SyntaxKind.AnyKeyword) return "unknown";
|
|
2513
2703
|
return typeNode.getText();
|
|
2514
2704
|
}
|
|
2515
2705
|
function unwrapFirstTypeArg(typeNode, sourceFile, project, depth, mode, subst = /* @__PURE__ */ new Map()) {
|
|
@@ -2567,7 +2757,7 @@ function resolvePropertied(decl, sourceFile, project, depth, subst = /* @__PURE_
|
|
|
2567
2757
|
}
|
|
2568
2758
|
function namedField(decorator) {
|
|
2569
2759
|
const first = decorator.getArguments()[0];
|
|
2570
|
-
return first &&
|
|
2760
|
+
return first && import_ts_morph11.Node.isStringLiteral(first) ? first.getLiteralValue() : null;
|
|
2571
2761
|
}
|
|
2572
2762
|
function extractBodyType(method, sourceFile, project) {
|
|
2573
2763
|
for (const param of method.getParameters()) {
|
|
@@ -2617,8 +2807,8 @@ function extractQueryType(method, sourceFile, project) {
|
|
|
2617
2807
|
function isParamOptional(param) {
|
|
2618
2808
|
if (param.hasQuestionToken() || param.hasInitializer()) return true;
|
|
2619
2809
|
const typeNode = param.getTypeNode();
|
|
2620
|
-
if (typeNode &&
|
|
2621
|
-
return typeNode.getTypeNodes().some((t) => t.getKind() ===
|
|
2810
|
+
if (typeNode && import_ts_morph11.Node.isUnionTypeNode(typeNode)) {
|
|
2811
|
+
return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph11.SyntaxKind.UndefinedKeyword);
|
|
2622
2812
|
}
|
|
2623
2813
|
return false;
|
|
2624
2814
|
}
|
|
@@ -2630,7 +2820,7 @@ function extractParamsType(method, sourceFile, project) {
|
|
|
2630
2820
|
const paramArgs = paramDecorator.getArguments();
|
|
2631
2821
|
if (paramArgs.length === 0) continue;
|
|
2632
2822
|
const nameArg = paramArgs[0];
|
|
2633
|
-
if (!
|
|
2823
|
+
if (!import_ts_morph11.Node.isStringLiteral(nameArg)) continue;
|
|
2634
2824
|
const paramName = nameArg.getLiteralValue();
|
|
2635
2825
|
const typeNode = param.getTypeNode();
|
|
2636
2826
|
const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
|
|
@@ -2667,28 +2857,28 @@ function extractUploadedFiles(method) {
|
|
|
2667
2857
|
for (const decorator of method.getDecorators()) {
|
|
2668
2858
|
if (decorator.getName() !== "UseInterceptors") continue;
|
|
2669
2859
|
for (const arg of decorator.getArguments()) {
|
|
2670
|
-
if (!
|
|
2860
|
+
if (!import_ts_morph11.Node.isCallExpression(arg)) continue;
|
|
2671
2861
|
const interceptor = arg.getExpression().getText();
|
|
2672
2862
|
const callArgs = arg.getArguments();
|
|
2673
2863
|
const firstArg2 = callArgs[0];
|
|
2674
2864
|
if (interceptor === "FileInterceptor") {
|
|
2675
|
-
if (firstArg2 &&
|
|
2865
|
+
if (firstArg2 && import_ts_morph11.Node.isStringLiteral(firstArg2)) {
|
|
2676
2866
|
entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
|
|
2677
2867
|
multipart = true;
|
|
2678
2868
|
}
|
|
2679
2869
|
} else if (interceptor === "FilesInterceptor") {
|
|
2680
|
-
if (firstArg2 &&
|
|
2870
|
+
if (firstArg2 && import_ts_morph11.Node.isStringLiteral(firstArg2)) {
|
|
2681
2871
|
entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
|
|
2682
2872
|
multipart = true;
|
|
2683
2873
|
}
|
|
2684
2874
|
} else if (interceptor === "FileFieldsInterceptor") {
|
|
2685
|
-
if (firstArg2 &&
|
|
2875
|
+
if (firstArg2 && import_ts_morph11.Node.isArrayLiteralExpression(firstArg2)) {
|
|
2686
2876
|
for (const el of firstArg2.getElements()) {
|
|
2687
|
-
if (!
|
|
2877
|
+
if (!import_ts_morph11.Node.isObjectLiteralExpression(el)) continue;
|
|
2688
2878
|
const nameProp = el.getProperty("name");
|
|
2689
|
-
if (nameProp &&
|
|
2879
|
+
if (nameProp && import_ts_morph11.Node.isPropertyAssignment(nameProp)) {
|
|
2690
2880
|
const init = nameProp.getInitializer();
|
|
2691
|
-
if (init &&
|
|
2881
|
+
if (init && import_ts_morph11.Node.isStringLiteral(init)) {
|
|
2692
2882
|
entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
|
|
2693
2883
|
}
|
|
2694
2884
|
}
|
|
@@ -2708,13 +2898,13 @@ function extractResponseType(method, sourceFile, project) {
|
|
|
2708
2898
|
if (apiResponseDecorator) {
|
|
2709
2899
|
const args = apiResponseDecorator.getArguments();
|
|
2710
2900
|
const optsArg = args[0];
|
|
2711
|
-
if (optsArg &&
|
|
2901
|
+
if (optsArg && import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) {
|
|
2712
2902
|
for (const prop of optsArg.getProperties()) {
|
|
2713
|
-
if (!
|
|
2903
|
+
if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
|
|
2714
2904
|
if (prop.getName() !== "type") continue;
|
|
2715
2905
|
const val = prop.getInitializer();
|
|
2716
2906
|
if (!val) continue;
|
|
2717
|
-
if (
|
|
2907
|
+
if (import_ts_morph11.Node.isArrayLiteralExpression(val)) {
|
|
2718
2908
|
const elements = val.getElements();
|
|
2719
2909
|
const firstEl = elements[0];
|
|
2720
2910
|
if (elements.length > 0 && firstEl !== void 0) {
|
|
@@ -2735,24 +2925,24 @@ function extractResponseType(method, sourceFile, project) {
|
|
|
2735
2925
|
}
|
|
2736
2926
|
function apiResponseStatus(decorator) {
|
|
2737
2927
|
const optsArg = decorator.getArguments()[0];
|
|
2738
|
-
if (!optsArg || !
|
|
2928
|
+
if (!optsArg || !import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) return null;
|
|
2739
2929
|
for (const prop of optsArg.getProperties()) {
|
|
2740
|
-
if (!
|
|
2930
|
+
if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
|
|
2741
2931
|
if (prop.getName() !== "status") continue;
|
|
2742
2932
|
const val = prop.getInitializer();
|
|
2743
|
-
if (val &&
|
|
2933
|
+
if (val && import_ts_morph11.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
|
|
2744
2934
|
}
|
|
2745
2935
|
return null;
|
|
2746
2936
|
}
|
|
2747
2937
|
function apiResponseTypeNode(decorator) {
|
|
2748
2938
|
const optsArg = decorator.getArguments()[0];
|
|
2749
|
-
if (!optsArg || !
|
|
2939
|
+
if (!optsArg || !import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) return null;
|
|
2750
2940
|
for (const prop of optsArg.getProperties()) {
|
|
2751
|
-
if (!
|
|
2941
|
+
if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
|
|
2752
2942
|
if (prop.getName() !== "type") continue;
|
|
2753
2943
|
const val = prop.getInitializer();
|
|
2754
2944
|
if (!val) return null;
|
|
2755
|
-
if (
|
|
2945
|
+
if (import_ts_morph11.Node.isArrayLiteralExpression(val)) {
|
|
2756
2946
|
const first = val.getElements()[0];
|
|
2757
2947
|
return first ? { node: first, isArray: true } : null;
|
|
2758
2948
|
}
|
|
@@ -2770,7 +2960,7 @@ function extractErrorType(method, sourceFile, project) {
|
|
|
2770
2960
|
const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);
|
|
2771
2961
|
const type = typeInfo.isArray ? `Array<${inner}>` : inner;
|
|
2772
2962
|
let ref = null;
|
|
2773
|
-
if (
|
|
2963
|
+
if (import_ts_morph11.Node.isIdentifier(typeInfo.node)) {
|
|
2774
2964
|
const name = typeInfo.node.getText();
|
|
2775
2965
|
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
2776
2966
|
if (localDecl?.isExported()) {
|
|
@@ -2787,7 +2977,7 @@ function extractErrorType(method, sourceFile, project) {
|
|
|
2787
2977
|
return null;
|
|
2788
2978
|
}
|
|
2789
2979
|
function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
2790
|
-
if (!
|
|
2980
|
+
if (!import_ts_morph11.Node.isIdentifier(node)) return "unknown";
|
|
2791
2981
|
const name = node.getText();
|
|
2792
2982
|
const resolved = findType(name, sourceFile, project);
|
|
2793
2983
|
if (resolved) {
|
|
@@ -2807,9 +2997,9 @@ var STREAM_ENVELOPES = /* @__PURE__ */ new Set(["MessageEvent", "MessageEventLik
|
|
|
2807
2997
|
var BINARY_RESPONSE_TYPES = /* @__PURE__ */ new Set(["StreamableFile", "Buffer"]);
|
|
2808
2998
|
function detectBinaryResponse(method) {
|
|
2809
2999
|
const node = unwrapNamedContainer(method.getReturnTypeNode(), /* @__PURE__ */ new Set(["Promise"]));
|
|
2810
|
-
if (!node || !
|
|
3000
|
+
if (!node || !import_ts_morph11.Node.isTypeReference(node)) return false;
|
|
2811
3001
|
const typeName = node.getTypeName();
|
|
2812
|
-
const name =
|
|
3002
|
+
const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
|
|
2813
3003
|
return BINARY_RESPONSE_TYPES.has(name);
|
|
2814
3004
|
}
|
|
2815
3005
|
function detectStreamElement(method) {
|
|
@@ -2824,9 +3014,9 @@ function detectStreamElement(method) {
|
|
|
2824
3014
|
return null;
|
|
2825
3015
|
}
|
|
2826
3016
|
function streamContainerElement(node) {
|
|
2827
|
-
if (!node || !
|
|
3017
|
+
if (!node || !import_ts_morph11.Node.isTypeReference(node)) return null;
|
|
2828
3018
|
const typeName = node.getTypeName();
|
|
2829
|
-
const name =
|
|
3019
|
+
const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
|
|
2830
3020
|
if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {
|
|
2831
3021
|
return node.getTypeArguments()[0] ?? null;
|
|
2832
3022
|
}
|
|
@@ -2836,9 +3026,9 @@ function hasAsQueryDecorator(method) {
|
|
|
2836
3026
|
return method.getDecorators().some((d) => d.getName() === "AsQuery");
|
|
2837
3027
|
}
|
|
2838
3028
|
function unwrapNamedContainer(node, names) {
|
|
2839
|
-
if (!node || !
|
|
3029
|
+
if (!node || !import_ts_morph11.Node.isTypeReference(node)) return node;
|
|
2840
3030
|
const typeName = node.getTypeName();
|
|
2841
|
-
const name =
|
|
3031
|
+
const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
|
|
2842
3032
|
if (names.has(name)) {
|
|
2843
3033
|
return node.getTypeArguments()[0] ?? node;
|
|
2844
3034
|
}
|
|
@@ -2885,11 +3075,11 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
|
|
|
2885
3075
|
if (apiResp) {
|
|
2886
3076
|
const args = apiResp.getArguments();
|
|
2887
3077
|
const optsArg = args[0];
|
|
2888
|
-
if (optsArg &&
|
|
3078
|
+
if (optsArg && import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) {
|
|
2889
3079
|
for (const prop of optsArg.getProperties()) {
|
|
2890
|
-
if (
|
|
3080
|
+
if (import_ts_morph11.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
|
|
2891
3081
|
const val = prop.getInitializer();
|
|
2892
|
-
if (val &&
|
|
3082
|
+
if (val && import_ts_morph11.Node.isIdentifier(val)) {
|
|
2893
3083
|
const name = val.getText();
|
|
2894
3084
|
const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
|
|
2895
3085
|
if (localDecl?.isExported()) {
|
|
@@ -2969,26 +3159,26 @@ var NO_TSCONFIG_OPTIONS = {
|
|
|
2969
3159
|
strict: false
|
|
2970
3160
|
};
|
|
2971
3161
|
function loadDiscoveryTsconfig(tsconfigPath) {
|
|
2972
|
-
if (!(0,
|
|
2973
|
-
const read =
|
|
3162
|
+
if (!(0, import_node_fs2.existsSync)(tsconfigPath)) return { options: null, files: [] };
|
|
3163
|
+
const read = import_ts_morph12.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph12.ts.sys.readFile(path));
|
|
2974
3164
|
if (read.error) {
|
|
2975
3165
|
return {
|
|
2976
3166
|
options: null,
|
|
2977
3167
|
files: [tsconfigPath],
|
|
2978
|
-
error:
|
|
3168
|
+
error: import_ts_morph12.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
|
|
2979
3169
|
};
|
|
2980
3170
|
}
|
|
2981
3171
|
const host = {
|
|
2982
|
-
useCaseSensitiveFileNames:
|
|
3172
|
+
useCaseSensitiveFileNames: import_ts_morph12.ts.sys.useCaseSensitiveFileNames,
|
|
2983
3173
|
// The one line that keeps a tsconfig from being a filesystem walk.
|
|
2984
3174
|
readDirectory: () => [],
|
|
2985
|
-
fileExists: (path) =>
|
|
3175
|
+
fileExists: (path) => import_ts_morph12.ts.sys.fileExists(path),
|
|
2986
3176
|
// `extends` is resolved through the host, so a consumer whose `paths` live
|
|
2987
3177
|
// in a base tsconfig keeps working.
|
|
2988
|
-
readFile: (path) =>
|
|
3178
|
+
readFile: (path) => import_ts_morph12.ts.sys.readFile(path)
|
|
2989
3179
|
};
|
|
2990
|
-
const sourceFile =
|
|
2991
|
-
const parsed =
|
|
3180
|
+
const sourceFile = import_ts_morph12.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph12.ts.sys.readFile(path));
|
|
3181
|
+
const parsed = import_ts_morph12.ts.parseJsonSourceFileConfigFileContent(
|
|
2992
3182
|
sourceFile,
|
|
2993
3183
|
host,
|
|
2994
3184
|
(0, import_node_path3.dirname)(tsconfigPath),
|
|
@@ -3011,7 +3201,7 @@ function createDiscoveryProject(tsconfigPath, tsconfig = loadDiscoveryTsconfig(t
|
|
|
3011
3201
|
`[nestjs-codegen/fast] Could not load ${tsconfigPath}: ${tsconfig.error} \u2014 continuing WITHOUT its compiler options, so path alias imports (e.g. '@/...') will not resolve and controllers extending an alias-imported factory will contribute NO routes to the generated client.`
|
|
3012
3202
|
);
|
|
3013
3203
|
}
|
|
3014
|
-
return new
|
|
3204
|
+
return new import_ts_morph12.Project({
|
|
3015
3205
|
compilerOptions: tsconfig.options ?? { ...NO_TSCONFIG_OPTIONS },
|
|
3016
3206
|
skipAddingFilesFromTsConfig: true,
|
|
3017
3207
|
skipLoadingLibFiles: true,
|
|
@@ -3046,6 +3236,9 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
3046
3236
|
glob;
|
|
3047
3237
|
/** Absolute paths of the controllers currently loaded as extraction roots. */
|
|
3048
3238
|
controllerPaths = /* @__PURE__ */ new Set();
|
|
3239
|
+
/** Every file in {@link project}, as last read from disk. */
|
|
3240
|
+
files = new DiskFingerprints();
|
|
3241
|
+
unresolved = new UnresolvedImports();
|
|
3049
3242
|
constructor(project, cwd, glob) {
|
|
3050
3243
|
this.project = project;
|
|
3051
3244
|
this.cwd = cwd;
|
|
@@ -3071,6 +3264,8 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
3071
3264
|
}
|
|
3072
3265
|
/** Run the initial extraction (equivalent to a first `discoverContractsFast`). */
|
|
3073
3266
|
discover() {
|
|
3267
|
+
clearMixinTypeProject();
|
|
3268
|
+
clearSchemaTypeProject(this.project);
|
|
3074
3269
|
return this.runExtraction();
|
|
3075
3270
|
}
|
|
3076
3271
|
/**
|
|
@@ -3078,26 +3273,39 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
3078
3273
|
* from disk (controllers AND any lazily-loaded DTO/imported files), re-globs
|
|
3079
3274
|
* to pick up added/removed controllers, clears the per-Project caches, then
|
|
3080
3275
|
* re-extracts. `changedPaths` is a hint; correctness does not depend on it
|
|
3081
|
-
* being exhaustive because re-globbing +
|
|
3276
|
+
* being exhaustive because re-globbing + comparing every loaded file with the
|
|
3277
|
+
* disk covers the set.
|
|
3082
3278
|
*/
|
|
3083
|
-
async rediscover(changedPaths) {
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3279
|
+
async rediscover(changedPaths, options = {}) {
|
|
3280
|
+
const hinted = new Set([...changedPaths ?? []].map((p) => (0, import_node_path3.resolve)(p)));
|
|
3281
|
+
const program = this.project.getProgram().compilerObject;
|
|
3282
|
+
const sources = program.getSourceFiles().filter(
|
|
3283
|
+
(file) => !program.isSourceFileDefaultLibrary(file) && !program.isSourceFileFromExternalLibrary(file)
|
|
3284
|
+
).map((file) => ({ path: file.fileName, text: file.text }));
|
|
3285
|
+
for (const path of /* @__PURE__ */ new Set([...hinted, ...this.files.changed(sources)])) {
|
|
3286
|
+
const sf = this.project.getSourceFile(path);
|
|
3287
|
+
if (sf && await sf.refreshFromFileSystem() === import_ts_morph12.FileSystemRefreshResult.Deleted) {
|
|
3288
|
+
this.files.forget(path);
|
|
3091
3289
|
}
|
|
3092
3290
|
}
|
|
3291
|
+
const inProject = new Set(this.project.getSourceFiles().map((sf) => sf.getFilePath()));
|
|
3292
|
+
const definitions = this.project.getLanguageService().compilerObject.getProgram();
|
|
3293
|
+
for (const path of definitions ? this.unresolved.nowResolving(definitions) : []) {
|
|
3294
|
+
const sf = this.project.getSourceFile(path);
|
|
3295
|
+
if (!sf) continue;
|
|
3296
|
+
this.project.removeSourceFile(sf);
|
|
3297
|
+
if (inProject.has(path)) this.project.addSourceFileAtPathIfExists(path);
|
|
3298
|
+
}
|
|
3093
3299
|
const globbed = new Set(
|
|
3094
3300
|
await (0, import_fast_glob.default)(this.glob, { cwd: this.cwd, absolute: true, onlyFiles: true })
|
|
3095
3301
|
);
|
|
3302
|
+
let controllersChanged = false;
|
|
3096
3303
|
for (const f of globbed) {
|
|
3097
3304
|
if (!this.controllerPaths.has(f)) {
|
|
3098
3305
|
try {
|
|
3099
3306
|
this.project.addSourceFileAtPath(f);
|
|
3100
3307
|
this.controllerPaths.add(f);
|
|
3308
|
+
controllersChanged = true;
|
|
3101
3309
|
} catch {
|
|
3102
3310
|
}
|
|
3103
3311
|
}
|
|
@@ -3107,25 +3315,31 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
3107
3315
|
const sf = this.project.getSourceFile(f);
|
|
3108
3316
|
if (sf) this.project.removeSourceFile(sf);
|
|
3109
3317
|
this.controllerPaths.delete(f);
|
|
3318
|
+
controllersChanged = true;
|
|
3110
3319
|
}
|
|
3111
3320
|
}
|
|
3321
|
+
if (controllersChanged || options.filesAddedOrRemoved) {
|
|
3322
|
+
clearMixinTypeProject();
|
|
3323
|
+
clearSchemaTypeProject(this.project);
|
|
3324
|
+
} else {
|
|
3325
|
+
invalidateMixinTypeProject();
|
|
3326
|
+
invalidateSchemaTypeProject(this.project);
|
|
3327
|
+
}
|
|
3112
3328
|
return this.runExtraction();
|
|
3113
3329
|
}
|
|
3114
3330
|
/** Clear stale per-Project caches, then extract over the controller set. */
|
|
3115
3331
|
runExtraction() {
|
|
3116
3332
|
clearTypeResolutionCaches(this.project);
|
|
3117
3333
|
clearEnumCache(this.project);
|
|
3118
|
-
clearMixinTypeProject();
|
|
3119
|
-
clearSchemaTypeProject(this.project);
|
|
3120
3334
|
return extractRoutesFrom(this.project, this.controllerPaths);
|
|
3121
3335
|
}
|
|
3122
3336
|
};
|
|
3123
3337
|
function decoratorStringArg(decoratorExpr) {
|
|
3124
3338
|
if (!decoratorExpr) return void 0;
|
|
3125
|
-
if (
|
|
3126
|
-
if (
|
|
3339
|
+
if (import_ts_morph12.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
|
|
3340
|
+
if (import_ts_morph12.Node.isArrayLiteralExpression(decoratorExpr)) {
|
|
3127
3341
|
const first = decoratorExpr.getElements()[0];
|
|
3128
|
-
if (first &&
|
|
3342
|
+
if (first && import_ts_morph12.Node.isStringLiteral(first)) return first.getLiteralValue();
|
|
3129
3343
|
}
|
|
3130
3344
|
return void 0;
|
|
3131
3345
|
}
|
|
@@ -3246,9 +3460,9 @@ function extractContractRoute(args) {
|
|
|
3246
3460
|
let contractDef = null;
|
|
3247
3461
|
let bodyZodRef = null;
|
|
3248
3462
|
let queryZodRef = null;
|
|
3249
|
-
if (
|
|
3463
|
+
if (import_ts_morph12.Node.isCallExpression(firstDecoratorArg)) {
|
|
3250
3464
|
contractDef = parseDefineContractCall(firstDecoratorArg, project);
|
|
3251
|
-
} else if (
|
|
3465
|
+
} else if (import_ts_morph12.Node.isIdentifier(firstDecoratorArg)) {
|
|
3252
3466
|
const identName = firstDecoratorArg.getText();
|
|
3253
3467
|
const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
|
|
3254
3468
|
if (!resolvedVar) {
|
|
@@ -3432,7 +3646,7 @@ async function discoverPages(opts) {
|
|
|
3432
3646
|
const rel = (0, import_node_path4.relative)(opts.cwd, file);
|
|
3433
3647
|
const nameRel = (0, import_node_path4.relative)(pagesBase, file).split(import_node_path4.sep).join("/");
|
|
3434
3648
|
const name = `${prefix}${computeName(nameRel, opts.componentNameStrategy)}`;
|
|
3435
|
-
const source = await (0, import_promises2.readFile)(file, "utf8");
|
|
3649
|
+
const source = await (opts.read ? opts.read(file) : (0, import_promises2.readFile)(file, "utf8"));
|
|
3436
3650
|
const propsSource = extractPropsSource(source, opts.propsExport);
|
|
3437
3651
|
out.push({ name, absolutePath: file, relativePath: rel, propsSource, scope });
|
|
3438
3652
|
}
|
|
@@ -3440,10 +3654,14 @@ async function discoverPages(opts) {
|
|
|
3440
3654
|
assertUniqueNames(out);
|
|
3441
3655
|
return out;
|
|
3442
3656
|
}
|
|
3443
|
-
async function discoverPageScopes(config) {
|
|
3657
|
+
async function discoverPageScopes(config, read) {
|
|
3444
3658
|
const pages = config.pages;
|
|
3445
3659
|
if (!pages) return [];
|
|
3446
|
-
const common = {
|
|
3660
|
+
const common = {
|
|
3661
|
+
cwd: config.codegen.cwd,
|
|
3662
|
+
propsExport: pages.propsExport,
|
|
3663
|
+
...read ? { read } : {}
|
|
3664
|
+
};
|
|
3447
3665
|
const out = await discoverPages({
|
|
3448
3666
|
...common,
|
|
3449
3667
|
glob: pages.glob,
|
|
@@ -3518,8 +3736,9 @@ var import_promises11 = require("fs/promises");
|
|
|
3518
3736
|
var import_node_path15 = require("path");
|
|
3519
3737
|
|
|
3520
3738
|
// src/discovery/shared-props.ts
|
|
3739
|
+
var import_node_fs3 = require("fs");
|
|
3521
3740
|
var import_node_path5 = require("path");
|
|
3522
|
-
var
|
|
3741
|
+
var import_ts_morph13 = require("ts-morph");
|
|
3523
3742
|
function discoverSharedProps(project, moduleEntry) {
|
|
3524
3743
|
try {
|
|
3525
3744
|
let sourceFile = project.getSourceFile(moduleEntry);
|
|
@@ -3545,14 +3764,9 @@ function discoverSharedPropsFromConfig(config) {
|
|
|
3545
3764
|
const tsconfigPath = config.app.tsconfig ?? (0, import_node_path5.join)(config.codegen.cwd, "tsconfig.json");
|
|
3546
3765
|
let project;
|
|
3547
3766
|
try {
|
|
3548
|
-
project =
|
|
3549
|
-
tsConfigFilePath: tsconfigPath,
|
|
3550
|
-
skipAddingFilesFromTsConfig: true,
|
|
3551
|
-
skipLoadingLibFiles: true,
|
|
3552
|
-
skipFileDependencyResolution: true
|
|
3553
|
-
});
|
|
3767
|
+
project = sharedPropsProject(tsconfigPath);
|
|
3554
3768
|
} catch {
|
|
3555
|
-
project = new
|
|
3769
|
+
project = new import_ts_morph13.Project({
|
|
3556
3770
|
skipAddingFilesFromTsConfig: true,
|
|
3557
3771
|
skipLoadingLibFiles: true,
|
|
3558
3772
|
skipFileDependencyResolution: true,
|
|
@@ -3564,14 +3778,35 @@ function discoverSharedPropsFromConfig(config) {
|
|
|
3564
3778
|
return null;
|
|
3565
3779
|
}
|
|
3566
3780
|
}
|
|
3781
|
+
var parsedTsconfigs = /* @__PURE__ */ new Map();
|
|
3782
|
+
function readText(file) {
|
|
3783
|
+
try {
|
|
3784
|
+
return (0, import_node_fs3.readFileSync)(file, "utf8");
|
|
3785
|
+
} catch {
|
|
3786
|
+
return "\0missing";
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
function sharedPropsProject(tsconfigPath) {
|
|
3790
|
+
const text = loadDiscoveryTsconfig(tsconfigPath).files.map((file) => `${file}\0${readText(file)}`).join("\0");
|
|
3791
|
+
const flags = {
|
|
3792
|
+
skipAddingFilesFromTsConfig: true,
|
|
3793
|
+
skipLoadingLibFiles: true,
|
|
3794
|
+
skipFileDependencyResolution: true
|
|
3795
|
+
};
|
|
3796
|
+
const parsed = parsedTsconfigs.get(tsconfigPath);
|
|
3797
|
+
if (parsed?.text === text) return new import_ts_morph13.Project({ ...flags, compilerOptions: parsed.options });
|
|
3798
|
+
const project = new import_ts_morph13.Project({ ...flags, tsConfigFilePath: tsconfigPath });
|
|
3799
|
+
parsedTsconfigs.set(tsconfigPath, { text, options: project.getCompilerOptions() });
|
|
3800
|
+
return project;
|
|
3801
|
+
}
|
|
3567
3802
|
function findForRootCall(sourceFile) {
|
|
3568
|
-
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
3803
|
+
const callExpressions = sourceFile.getDescendantsOfKind(import_ts_morph13.SyntaxKind.CallExpression);
|
|
3569
3804
|
for (const call of callExpressions) {
|
|
3570
3805
|
const expr = call.getExpression();
|
|
3571
|
-
if (!
|
|
3806
|
+
if (!import_ts_morph13.Node.isPropertyAccessExpression(expr)) continue;
|
|
3572
3807
|
const methodName = expr.getName();
|
|
3573
3808
|
const objectExpr = expr.getExpression();
|
|
3574
|
-
if (methodName === "forRoot" &&
|
|
3809
|
+
if (methodName === "forRoot" && import_ts_morph13.Node.isIdentifier(objectExpr)) {
|
|
3575
3810
|
const name = objectExpr.getText();
|
|
3576
3811
|
if (name === "InertiaModule") {
|
|
3577
3812
|
return call;
|
|
@@ -3581,19 +3816,19 @@ function findForRootCall(sourceFile) {
|
|
|
3581
3816
|
return null;
|
|
3582
3817
|
}
|
|
3583
3818
|
function findShareInitializer(forRootCall) {
|
|
3584
|
-
if (!
|
|
3819
|
+
if (!import_ts_morph13.Node.isCallExpression(forRootCall)) return null;
|
|
3585
3820
|
const args = forRootCall.getArguments();
|
|
3586
3821
|
const firstArg2 = args[0];
|
|
3587
|
-
if (!firstArg2 || !
|
|
3822
|
+
if (!firstArg2 || !import_ts_morph13.Node.isObjectLiteralExpression(firstArg2)) return null;
|
|
3588
3823
|
for (const prop of firstArg2.getProperties()) {
|
|
3589
|
-
if (
|
|
3824
|
+
if (import_ts_morph13.Node.isPropertyAssignment(prop) && prop.getName() === "share") {
|
|
3590
3825
|
return prop.getInitializer() ?? null;
|
|
3591
3826
|
}
|
|
3592
3827
|
}
|
|
3593
3828
|
return null;
|
|
3594
3829
|
}
|
|
3595
3830
|
function extractShareType(node, sourceFile, project) {
|
|
3596
|
-
if (
|
|
3831
|
+
if (import_ts_morph13.Node.isIdentifier(node)) {
|
|
3597
3832
|
const ref = resolveIdentifierToImportRef(node, sourceFile, project);
|
|
3598
3833
|
if (ref) {
|
|
3599
3834
|
return {
|
|
@@ -3603,22 +3838,22 @@ function extractShareType(node, sourceFile, project) {
|
|
|
3603
3838
|
};
|
|
3604
3839
|
}
|
|
3605
3840
|
}
|
|
3606
|
-
if (
|
|
3841
|
+
if (import_ts_morph13.Node.isArrowFunction(node)) {
|
|
3607
3842
|
const result = extractFromFunctionLike(node, sourceFile);
|
|
3608
3843
|
return result ? { ...result, isImportRef: false } : null;
|
|
3609
3844
|
}
|
|
3610
|
-
if (
|
|
3845
|
+
if (import_ts_morph13.Node.isFunctionExpression(node)) {
|
|
3611
3846
|
const result = extractFromFunctionLike(node, sourceFile);
|
|
3612
3847
|
return result ? { ...result, isImportRef: false } : null;
|
|
3613
3848
|
}
|
|
3614
|
-
if (
|
|
3849
|
+
if (import_ts_morph13.Node.isObjectLiteralExpression(node)) {
|
|
3615
3850
|
const result = extractFromObjectLiteral(node);
|
|
3616
3851
|
return result ? { ...result, isImportRef: false } : null;
|
|
3617
3852
|
}
|
|
3618
3853
|
return null;
|
|
3619
3854
|
}
|
|
3620
3855
|
function resolveIdentifierToImportRef(id, sourceFile, project) {
|
|
3621
|
-
if (!
|
|
3856
|
+
if (!import_ts_morph13.Node.isIdentifier(id)) return null;
|
|
3622
3857
|
const name = id.getText();
|
|
3623
3858
|
const localFunc = sourceFile.getFunction(name);
|
|
3624
3859
|
if (localFunc?.isExported()) {
|
|
@@ -3652,37 +3887,37 @@ function resolveIdentifierToImportRef(id, sourceFile, project) {
|
|
|
3652
3887
|
return null;
|
|
3653
3888
|
}
|
|
3654
3889
|
function extractFromFunctionLike(node, _sourceFile) {
|
|
3655
|
-
const returnTypeNode =
|
|
3890
|
+
const returnTypeNode = import_ts_morph13.Node.isArrowFunction(node) || import_ts_morph13.Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;
|
|
3656
3891
|
if (returnTypeNode) {
|
|
3657
3892
|
return extractFromReturnTypeAnnotation(returnTypeNode);
|
|
3658
3893
|
}
|
|
3659
|
-
if (
|
|
3894
|
+
if (import_ts_morph13.Node.isArrowFunction(node)) {
|
|
3660
3895
|
const body = node.getBody();
|
|
3661
|
-
if (
|
|
3896
|
+
if (import_ts_morph13.Node.isParenthesizedExpression(body)) {
|
|
3662
3897
|
const inner = body.getExpression();
|
|
3663
|
-
if (
|
|
3898
|
+
if (import_ts_morph13.Node.isObjectLiteralExpression(inner)) {
|
|
3664
3899
|
return extractFromObjectLiteral(inner);
|
|
3665
3900
|
}
|
|
3666
3901
|
}
|
|
3667
|
-
if (
|
|
3902
|
+
if (import_ts_morph13.Node.isObjectLiteralExpression(body)) {
|
|
3668
3903
|
return extractFromObjectLiteral(body);
|
|
3669
3904
|
}
|
|
3670
|
-
if (
|
|
3905
|
+
if (import_ts_morph13.Node.isBlock(body)) {
|
|
3671
3906
|
return extractFromBlockReturn(body);
|
|
3672
3907
|
}
|
|
3673
3908
|
}
|
|
3674
|
-
if (
|
|
3909
|
+
if (import_ts_morph13.Node.isFunctionExpression(node)) {
|
|
3675
3910
|
const body = node.getBody();
|
|
3676
|
-
if (
|
|
3911
|
+
if (import_ts_morph13.Node.isBlock(body)) {
|
|
3677
3912
|
return extractFromBlockReturn(body);
|
|
3678
3913
|
}
|
|
3679
3914
|
}
|
|
3680
3915
|
return null;
|
|
3681
3916
|
}
|
|
3682
3917
|
function extractFromReturnTypeAnnotation(typeNode) {
|
|
3683
|
-
if (
|
|
3918
|
+
if (import_ts_morph13.Node.isTypeReference(typeNode)) {
|
|
3684
3919
|
const typeName = typeNode.getTypeName();
|
|
3685
|
-
if (
|
|
3920
|
+
if (import_ts_morph13.Node.isIdentifier(typeName) && typeName.getText() === "Promise") {
|
|
3686
3921
|
const typeArgs = typeNode.getTypeArguments();
|
|
3687
3922
|
const firstArg2 = typeArgs[0];
|
|
3688
3923
|
if (firstArg2) {
|
|
@@ -3691,10 +3926,10 @@ function extractFromReturnTypeAnnotation(typeNode) {
|
|
|
3691
3926
|
return null;
|
|
3692
3927
|
}
|
|
3693
3928
|
}
|
|
3694
|
-
if (
|
|
3929
|
+
if (import_ts_morph13.Node.isTypeLiteral(typeNode)) {
|
|
3695
3930
|
const properties = [];
|
|
3696
3931
|
for (const member of typeNode.getMembers()) {
|
|
3697
|
-
if (
|
|
3932
|
+
if (import_ts_morph13.Node.isPropertySignature(member)) {
|
|
3698
3933
|
const name = member.getName();
|
|
3699
3934
|
const memberTypeNode = member.getTypeNode();
|
|
3700
3935
|
const type = memberTypeNode ? memberTypeNode.getText() : "unknown";
|
|
@@ -3708,19 +3943,19 @@ function extractFromReturnTypeAnnotation(typeNode) {
|
|
|
3708
3943
|
return null;
|
|
3709
3944
|
}
|
|
3710
3945
|
function extractFromBlockReturn(block) {
|
|
3711
|
-
if (!
|
|
3946
|
+
if (!import_ts_morph13.Node.isBlock(block)) return null;
|
|
3712
3947
|
const statements = block.getStatements();
|
|
3713
3948
|
for (let i = statements.length - 1; i >= 0; i--) {
|
|
3714
3949
|
const stmt = statements[i];
|
|
3715
|
-
if (!
|
|
3950
|
+
if (!import_ts_morph13.Node.isReturnStatement(stmt)) continue;
|
|
3716
3951
|
const expr = stmt.getExpression();
|
|
3717
3952
|
if (!expr) continue;
|
|
3718
|
-
if (
|
|
3953
|
+
if (import_ts_morph13.Node.isObjectLiteralExpression(expr)) {
|
|
3719
3954
|
return extractFromObjectLiteral(expr);
|
|
3720
3955
|
}
|
|
3721
|
-
if (
|
|
3956
|
+
if (import_ts_morph13.Node.isParenthesizedExpression(expr)) {
|
|
3722
3957
|
const inner = expr.getExpression();
|
|
3723
|
-
if (
|
|
3958
|
+
if (import_ts_morph13.Node.isObjectLiteralExpression(inner)) {
|
|
3724
3959
|
return extractFromObjectLiteral(inner);
|
|
3725
3960
|
}
|
|
3726
3961
|
}
|
|
@@ -3729,10 +3964,10 @@ function extractFromBlockReturn(block) {
|
|
|
3729
3964
|
return null;
|
|
3730
3965
|
}
|
|
3731
3966
|
function extractFromObjectLiteral(objLiteral) {
|
|
3732
|
-
if (!
|
|
3967
|
+
if (!import_ts_morph13.Node.isObjectLiteralExpression(objLiteral)) return null;
|
|
3733
3968
|
const properties = [];
|
|
3734
3969
|
for (const prop of objLiteral.getProperties()) {
|
|
3735
|
-
if (!
|
|
3970
|
+
if (!import_ts_morph13.Node.isPropertyAssignment(prop)) continue;
|
|
3736
3971
|
const name = prop.getName();
|
|
3737
3972
|
const initializer = prop.getInitializer();
|
|
3738
3973
|
if (!initializer) continue;
|
|
@@ -3744,21 +3979,21 @@ function extractFromObjectLiteral(objLiteral) {
|
|
|
3744
3979
|
return { typeString, properties, isImportRef: false };
|
|
3745
3980
|
}
|
|
3746
3981
|
function inferExpressionType(node) {
|
|
3747
|
-
if (
|
|
3748
|
-
if (
|
|
3982
|
+
if (import_ts_morph13.Node.isStringLiteral(node)) return "string";
|
|
3983
|
+
if (import_ts_morph13.Node.isTemplateExpression(node) || import_ts_morph13.Node.isNoSubstitutionTemplateLiteral(node))
|
|
3749
3984
|
return "string";
|
|
3750
|
-
if (
|
|
3751
|
-
if (node.getKind() ===
|
|
3985
|
+
if (import_ts_morph13.Node.isNumericLiteral(node)) return "number";
|
|
3986
|
+
if (node.getKind() === import_ts_morph13.SyntaxKind.TrueKeyword || node.getKind() === import_ts_morph13.SyntaxKind.FalseKeyword) {
|
|
3752
3987
|
return "boolean";
|
|
3753
3988
|
}
|
|
3754
|
-
if (node.getKind() ===
|
|
3755
|
-
if (
|
|
3756
|
-
if (
|
|
3989
|
+
if (node.getKind() === import_ts_morph13.SyntaxKind.NullKeyword) return "null";
|
|
3990
|
+
if (import_ts_morph13.Node.isIdentifier(node) && node.getText() === "undefined") return "undefined";
|
|
3991
|
+
if (import_ts_morph13.Node.isObjectLiteralExpression(node)) {
|
|
3757
3992
|
const props = node.getProperties();
|
|
3758
3993
|
if (props.length === 0) return "Record<string, unknown>";
|
|
3759
3994
|
const entries = [];
|
|
3760
3995
|
for (const prop of props) {
|
|
3761
|
-
if (!
|
|
3996
|
+
if (!import_ts_morph13.Node.isPropertyAssignment(prop)) continue;
|
|
3762
3997
|
const key = prop.getName();
|
|
3763
3998
|
const init = prop.getInitializer();
|
|
3764
3999
|
if (!init) continue;
|
|
@@ -3767,23 +4002,23 @@ function inferExpressionType(node) {
|
|
|
3767
4002
|
if (entries.length === 0) return "Record<string, unknown>";
|
|
3768
4003
|
return `{ ${entries.join("; ")} }`;
|
|
3769
4004
|
}
|
|
3770
|
-
if (
|
|
4005
|
+
if (import_ts_morph13.Node.isArrayLiteralExpression(node)) {
|
|
3771
4006
|
const elements = node.getElements();
|
|
3772
4007
|
if (elements.length === 0) return "Array<unknown>";
|
|
3773
4008
|
const first = elements[0];
|
|
3774
4009
|
if (first) return `Array<${inferExpressionType(first)}>`;
|
|
3775
4010
|
return "Array<unknown>";
|
|
3776
4011
|
}
|
|
3777
|
-
if (
|
|
4012
|
+
if (import_ts_morph13.Node.isConditionalExpression(node)) {
|
|
3778
4013
|
const whenTrue = inferExpressionType(node.getWhenTrue());
|
|
3779
4014
|
const whenFalse = inferExpressionType(node.getWhenFalse());
|
|
3780
4015
|
if (whenTrue === whenFalse) return whenTrue;
|
|
3781
4016
|
return `${whenTrue} | ${whenFalse}`;
|
|
3782
4017
|
}
|
|
3783
|
-
if (
|
|
4018
|
+
if (import_ts_morph13.Node.isParenthesizedExpression(node)) {
|
|
3784
4019
|
return inferExpressionType(node.getExpression());
|
|
3785
4020
|
}
|
|
3786
|
-
if (
|
|
4021
|
+
if (import_ts_morph13.Node.isAsExpression(node)) {
|
|
3787
4022
|
const typeNode = node.getTypeNode();
|
|
3788
4023
|
if (typeNode) return typeNode.getText();
|
|
3789
4024
|
}
|
|
@@ -3796,7 +4031,7 @@ var import_node_path7 = require("path");
|
|
|
3796
4031
|
|
|
3797
4032
|
// src/extension/registry.ts
|
|
3798
4033
|
var import_node_path6 = require("path");
|
|
3799
|
-
var
|
|
4034
|
+
var import_ts_morph14 = require("ts-morph");
|
|
3800
4035
|
function resolveApiSlots(extensions) {
|
|
3801
4036
|
let layer;
|
|
3802
4037
|
let layerOwner;
|
|
@@ -3847,7 +4082,7 @@ function createExtensionContext(config, getRoutes, trackedInputs) {
|
|
|
3847
4082
|
},
|
|
3848
4083
|
project() {
|
|
3849
4084
|
if (!project) {
|
|
3850
|
-
project = new
|
|
4085
|
+
project = new import_ts_morph14.Project({
|
|
3851
4086
|
skipAddingFilesFromTsConfig: true,
|
|
3852
4087
|
skipLoadingLibFiles: true,
|
|
3853
4088
|
skipFileDependencyResolution: true,
|
|
@@ -5519,14 +5754,15 @@ function driftGuardMessage(outDir, previousEntryPoint, currentEntryPoint, differ
|
|
|
5519
5754
|
async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
5520
5755
|
setCodegenDebug(config.debug);
|
|
5521
5756
|
const manifest = await readManifest(config.codegen.outDir);
|
|
5522
|
-
const
|
|
5757
|
+
const inputs = await readInputs(config);
|
|
5758
|
+
const inputsHash = await computeInputsHash(config, manifest?.extraInputs ?? [], inputs);
|
|
5523
5759
|
if (await isManifestFresh(config.codegen.outDir, manifest, inputsHash)) {
|
|
5524
5760
|
console.log(`[nestjs-codegen] ${config.codegen.outDir} up to date, skipped`);
|
|
5525
5761
|
return;
|
|
5526
5762
|
}
|
|
5527
5763
|
const configHash = computeConfigHash(config);
|
|
5528
5764
|
const configKeyHashes = computeConfigKeyHashes(config);
|
|
5529
|
-
if (config.driftGuard && manifest?.entryPoint && manifest.entryPoint !== entryPoint && manifest.configHash && manifest.configHash !== configHash) {
|
|
5765
|
+
if (config.driftGuard && manifest?.version === VERSION && manifest?.entryPoint && manifest.entryPoint !== entryPoint && manifest.configHash && manifest.configHash !== configHash) {
|
|
5530
5766
|
throw new DriftGuardError(
|
|
5531
5767
|
driftGuardMessage(
|
|
5532
5768
|
config.codegen.outDir,
|
|
@@ -5547,7 +5783,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
|
5547
5783
|
}
|
|
5548
5784
|
if (config.pages) {
|
|
5549
5785
|
const pagesConfig = config.pages;
|
|
5550
|
-
const pages = await discoverPageScopes(config);
|
|
5786
|
+
const pages = await discoverPageScopes(config, (path) => readInput(inputs, path));
|
|
5551
5787
|
const sharedProps = discoverSharedPropsFromConfig(config);
|
|
5552
5788
|
await emitPages(pages, config.codegen.outDir, {
|
|
5553
5789
|
propsExport: pagesConfig.propsExport,
|
|
@@ -5597,7 +5833,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
|
5597
5833
|
}
|
|
5598
5834
|
const outputFiles = await listOutputFiles(config.codegen.outDir);
|
|
5599
5835
|
const extraInputs = [...trackedInputs].sort();
|
|
5600
|
-
const recordedHash = extraInputs.length > 0 ? await computeInputsHash(config, extraInputs) : inputsHash;
|
|
5836
|
+
const recordedHash = extraInputs.length > 0 ? await computeInputsHash(config, extraInputs, inputs) : inputsHash;
|
|
5601
5837
|
await writeManifest(config.codegen.outDir, {
|
|
5602
5838
|
version: VERSION,
|
|
5603
5839
|
hash: recordedHash,
|
|
@@ -5780,13 +6016,15 @@ async function watch(config, onChange, options = {}) {
|
|
|
5780
6016
|
pagesWatcher.on("unlink", schedulePagesRegenerate);
|
|
5781
6017
|
let contractsDebounceTimer;
|
|
5782
6018
|
const pendingChangedPaths = /* @__PURE__ */ new Set();
|
|
6019
|
+
let pendingAddedOrRemoved = false;
|
|
5783
6020
|
const contractsWatcher = import_chokidar.default.watch((0, import_node_path17.join)(config.codegen.cwd, config.contracts.glob), {
|
|
5784
6021
|
ignoreInitial: true,
|
|
5785
6022
|
persistent: true,
|
|
5786
6023
|
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
5787
6024
|
});
|
|
5788
|
-
function scheduleContractsRegenerate(changedPath) {
|
|
6025
|
+
function scheduleContractsRegenerate(changedPath, addedOrRemoved = false) {
|
|
5789
6026
|
if (typeof changedPath === "string") pendingChangedPaths.add(changedPath);
|
|
6027
|
+
if (addedOrRemoved) pendingAddedOrRemoved = true;
|
|
5790
6028
|
if (contractsDebounceTimer !== void 0) {
|
|
5791
6029
|
clearTimeout(contractsDebounceTimer);
|
|
5792
6030
|
}
|
|
@@ -5794,8 +6032,12 @@ async function watch(config, onChange, options = {}) {
|
|
|
5794
6032
|
contractsDebounceTimer = void 0;
|
|
5795
6033
|
const changed = [...pendingChangedPaths];
|
|
5796
6034
|
pendingChangedPaths.clear();
|
|
6035
|
+
const filesAddedOrRemoved = pendingAddedOrRemoved;
|
|
6036
|
+
pendingAddedOrRemoved = false;
|
|
5797
6037
|
try {
|
|
5798
|
-
const routes = await (await getDiscovery()).rediscover(changed
|
|
6038
|
+
const routes = await (await getDiscovery()).rediscover(changed, {
|
|
6039
|
+
filesAddedOrRemoved
|
|
6040
|
+
});
|
|
5799
6041
|
lastRoutes = routes;
|
|
5800
6042
|
await generateAndTrack(routes);
|
|
5801
6043
|
} catch (err) {
|
|
@@ -5807,20 +6049,25 @@ async function watch(config, onChange, options = {}) {
|
|
|
5807
6049
|
onChange?.();
|
|
5808
6050
|
}, config.contracts.debounceMs);
|
|
5809
6051
|
}
|
|
5810
|
-
contractsWatcher.on("add", (p) => scheduleContractsRegenerate(p));
|
|
6052
|
+
contractsWatcher.on("add", (p) => scheduleContractsRegenerate(p, true));
|
|
5811
6053
|
contractsWatcher.on("change", (p) => scheduleContractsRegenerate(p));
|
|
5812
|
-
contractsWatcher.on("unlink", (p) => scheduleContractsRegenerate(p));
|
|
6054
|
+
contractsWatcher.on("unlink", (p) => scheduleContractsRegenerate(p, true));
|
|
5813
6055
|
const formsWatcher = import_chokidar.default.watch((0, import_node_path17.join)(config.codegen.cwd, config.forms.watch), {
|
|
5814
6056
|
ignoreInitial: true,
|
|
5815
6057
|
persistent: true,
|
|
5816
6058
|
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
5817
6059
|
});
|
|
5818
|
-
formsWatcher.on("add", (p) => scheduleContractsRegenerate(p));
|
|
6060
|
+
formsWatcher.on("add", (p) => scheduleContractsRegenerate(p, true));
|
|
5819
6061
|
formsWatcher.on("change", (p) => scheduleContractsRegenerate(p));
|
|
5820
|
-
formsWatcher.on("unlink", (p) => scheduleContractsRegenerate(p));
|
|
5821
|
-
trackedWatcher.on("add", (p) => scheduleContractsRegenerate(p));
|
|
6062
|
+
formsWatcher.on("unlink", (p) => scheduleContractsRegenerate(p, true));
|
|
6063
|
+
trackedWatcher.on("add", (p) => scheduleContractsRegenerate(p, true));
|
|
5822
6064
|
trackedWatcher.on("change", (p) => scheduleContractsRegenerate(p));
|
|
5823
|
-
trackedWatcher.on("unlink", (p) => scheduleContractsRegenerate(p));
|
|
6065
|
+
trackedWatcher.on("unlink", (p) => scheduleContractsRegenerate(p, true));
|
|
6066
|
+
await Promise.all(
|
|
6067
|
+
[pagesWatcher, contractsWatcher, formsWatcher].map(
|
|
6068
|
+
(w) => new Promise((resolveReady) => w.once("ready", () => resolveReady()))
|
|
6069
|
+
)
|
|
6070
|
+
);
|
|
5824
6071
|
return {
|
|
5825
6072
|
close: async () => {
|
|
5826
6073
|
if (pagesDebounceTimer !== void 0) {
|
|
@@ -5841,7 +6088,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
5841
6088
|
}
|
|
5842
6089
|
|
|
5843
6090
|
// src/index.ts
|
|
5844
|
-
var VERSION = "0.
|
|
6091
|
+
var VERSION = "0.30.0";
|
|
5845
6092
|
|
|
5846
6093
|
// src/generate-manifest.ts
|
|
5847
6094
|
var MANIFEST_FILE = ".codegen-manifest.json";
|
|
@@ -5906,36 +6153,64 @@ async function discoverInputFiles(config) {
|
|
|
5906
6153
|
const matched = await (0, import_fast_glob3.default)(globs, { cwd, absolute: true, onlyFiles: true });
|
|
5907
6154
|
return [...new Set(matched)].sort();
|
|
5908
6155
|
}
|
|
5909
|
-
|
|
6156
|
+
var READ_CONCURRENCY = 64;
|
|
6157
|
+
async function readAll(paths, read) {
|
|
6158
|
+
const out = /* @__PURE__ */ new Map();
|
|
6159
|
+
for (let i = 0; i < paths.length; i += READ_CONCURRENCY) {
|
|
6160
|
+
const batch = paths.slice(i, i + READ_CONCURRENCY);
|
|
6161
|
+
const texts = await Promise.all(batch.map(read));
|
|
6162
|
+
batch.forEach((path, j) => out.set(path, texts[j]));
|
|
6163
|
+
}
|
|
6164
|
+
return out;
|
|
6165
|
+
}
|
|
6166
|
+
async function readInputs(config) {
|
|
6167
|
+
const cwd = config.codegen.cwd;
|
|
6168
|
+
const tsconfigPath = resolveTsconfigPath(cwd, config.app?.tsconfig ?? void 0);
|
|
6169
|
+
const extended = loadDiscoveryTsconfig(tsconfigPath).files;
|
|
6170
|
+
const tsconfigFiles = extended.length > 0 ? extended : [tsconfigPath];
|
|
6171
|
+
const files = await discoverInputFiles(config);
|
|
6172
|
+
const contents = /* @__PURE__ */ new Map();
|
|
6173
|
+
const tsconfigs = await readAll(
|
|
6174
|
+
tsconfigFiles,
|
|
6175
|
+
(file) => (0, import_promises15.readFile)(file, "utf8").catch(() => null)
|
|
6176
|
+
);
|
|
6177
|
+
for (const [file, text] of tsconfigs) contents.set(file, text);
|
|
6178
|
+
for (const [file, text] of await readAll(files, (file2) => (0, import_promises15.readFile)(file2, "utf8"))) {
|
|
6179
|
+
contents.set(file, text);
|
|
6180
|
+
}
|
|
6181
|
+
return { tsconfigFiles, files, contents, tracked: /* @__PURE__ */ new Map() };
|
|
6182
|
+
}
|
|
6183
|
+
async function readInput(snapshot, path) {
|
|
6184
|
+
return snapshot.contents.get(path) ?? (0, import_promises15.readFile)(path, "utf8");
|
|
6185
|
+
}
|
|
6186
|
+
async function computeInputsHash(config, extraInputs = [], snapshot) {
|
|
6187
|
+
const inputs = snapshot ?? await readInputs(config);
|
|
5910
6188
|
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
5911
6189
|
hash.update(`version:${VERSION}
|
|
5912
6190
|
`);
|
|
5913
6191
|
hash.update(`config:${serializeConfig(config)}
|
|
5914
6192
|
`);
|
|
5915
6193
|
const cwd = config.codegen.cwd;
|
|
5916
|
-
const
|
|
5917
|
-
const tsconfigFiles = loadDiscoveryTsconfig(tsconfigPath).files;
|
|
5918
|
-
for (const file of tsconfigFiles.length > 0 ? tsconfigFiles : [tsconfigPath]) {
|
|
5919
|
-
const contents = await (0, import_promises15.readFile)(file, "utf8").catch(() => null);
|
|
6194
|
+
for (const file of inputs.tsconfigFiles) {
|
|
5920
6195
|
hash.update(`tsconfig:${(0, import_node_path18.relative)(cwd, file)}
|
|
5921
6196
|
`);
|
|
5922
|
-
hash.update(contents ?? " missing");
|
|
6197
|
+
hash.update(inputs.contents.get(file) ?? " missing");
|
|
5923
6198
|
hash.update("\n");
|
|
5924
6199
|
}
|
|
5925
|
-
const
|
|
5926
|
-
const globbedRelative = new Set(globbed.map((file) => (0, import_node_path18.relative)(cwd, file)));
|
|
6200
|
+
const globbedRelative = new Set(inputs.files.map((file) => (0, import_node_path18.relative)(cwd, file)));
|
|
5927
6201
|
const extra = [...new Set(extraInputs)].filter((file) => !globbedRelative.has(file)).sort();
|
|
5928
|
-
for (const file of
|
|
5929
|
-
const contents = await (0, import_promises15.readFile)(file, "utf8");
|
|
6202
|
+
for (const file of inputs.files) {
|
|
5930
6203
|
hash.update(`file:${(0, import_node_path18.relative)(cwd, file)}
|
|
5931
6204
|
`);
|
|
5932
|
-
hash.update(contents);
|
|
6205
|
+
hash.update(inputs.contents.get(file));
|
|
5933
6206
|
hash.update("\n");
|
|
5934
6207
|
}
|
|
6208
|
+
const unread = extra.map((file) => (0, import_node_path18.join)(cwd, file)).filter((abs) => !inputs.tracked.has(abs));
|
|
6209
|
+
for (const [abs, text] of await readAll(unread, readTrackedInput)) inputs.tracked.set(abs, text);
|
|
5935
6210
|
for (const file of extra) {
|
|
5936
6211
|
hash.update(`extra:${file}
|
|
5937
6212
|
`);
|
|
5938
|
-
hash.update(
|
|
6213
|
+
hash.update(inputs.tracked.get((0, import_node_path18.join)(cwd, file)));
|
|
5939
6214
|
hash.update("\n");
|
|
5940
6215
|
}
|
|
5941
6216
|
return hash.digest("hex");
|