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