@suss/adapter-typescript 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +454 -107
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +454 -107
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -67,7 +67,7 @@ __export(index_exports, {
|
|
|
67
67
|
module.exports = __toCommonJS(index_exports);
|
|
68
68
|
|
|
69
69
|
// src/adapter.ts
|
|
70
|
-
var
|
|
70
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
71
71
|
var import_ts_morph60 = require("ts-morph");
|
|
72
72
|
var import_behavioral_ir8 = require("@suss/behavioral-ir");
|
|
73
73
|
var import_datalog6 = require("@suss/datalog");
|
|
@@ -1864,8 +1864,8 @@ function loadImportGraphsDepthFirstFromPaths(project, rootPaths) {
|
|
|
1864
1864
|
stack.pop();
|
|
1865
1865
|
loadOrder.push(top.path);
|
|
1866
1866
|
let deepest = 0;
|
|
1867
|
-
for (const
|
|
1868
|
-
deepest = Math.max(deepest, chainDepth.get(
|
|
1867
|
+
for (const path13 of top.deps) {
|
|
1868
|
+
deepest = Math.max(deepest, chainDepth.get(path13) ?? 0);
|
|
1869
1869
|
}
|
|
1870
1870
|
chainDepth.set(top.path, deepest + 1);
|
|
1871
1871
|
}
|
|
@@ -2210,11 +2210,11 @@ function walkAndWarm(root, reach) {
|
|
|
2210
2210
|
if (warmedFiles.get(target) !== void 0) {
|
|
2211
2211
|
continue;
|
|
2212
2212
|
}
|
|
2213
|
-
const
|
|
2214
|
-
if (visited.has(
|
|
2213
|
+
const path13 = target.getFilePath();
|
|
2214
|
+
if (visited.has(path13)) {
|
|
2215
2215
|
continue;
|
|
2216
2216
|
}
|
|
2217
|
-
visited.add(
|
|
2217
|
+
visited.add(path13);
|
|
2218
2218
|
stack.push(frameOf(target, reach));
|
|
2219
2219
|
continue;
|
|
2220
2220
|
}
|
|
@@ -2231,7 +2231,7 @@ function sitsOnWarmChains(file) {
|
|
|
2231
2231
|
return false;
|
|
2232
2232
|
}
|
|
2233
2233
|
const imported = importedFilePathsOf(project, file.getFilePath());
|
|
2234
|
-
return imported.length > 0 && imported.every((
|
|
2234
|
+
return imported.length > 0 && imported.every((path13) => warmed.has(path13));
|
|
2235
2235
|
}
|
|
2236
2236
|
function markWarmed(file) {
|
|
2237
2237
|
warmedFiles.set(file, true);
|
|
@@ -5848,9 +5848,9 @@ function createSourceFileLookup(project) {
|
|
|
5848
5848
|
if (sf === null) {
|
|
5849
5849
|
return null;
|
|
5850
5850
|
}
|
|
5851
|
-
const
|
|
5852
|
-
const index = functionsByFile.get(
|
|
5853
|
-
functionsByFile.set(
|
|
5851
|
+
const path13 = sf.getFilePath();
|
|
5852
|
+
const index = functionsByFile.get(path13) ?? indexFunctions(sf);
|
|
5853
|
+
functionsByFile.set(path13, index);
|
|
5854
5854
|
return index.get(rangeKey(location.range)) ?? null;
|
|
5855
5855
|
}
|
|
5856
5856
|
};
|
|
@@ -6377,7 +6377,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
6377
6377
|
}
|
|
6378
6378
|
const responses = [];
|
|
6379
6379
|
let method;
|
|
6380
|
-
let
|
|
6380
|
+
let path13;
|
|
6381
6381
|
for (const prop of endpointNode.getProperties()) {
|
|
6382
6382
|
if (!import_ts_morph28.Node.isPropertyAssignment(prop)) {
|
|
6383
6383
|
continue;
|
|
@@ -6392,7 +6392,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
6392
6392
|
if (propName === pattern.pathProperty) {
|
|
6393
6393
|
const val = prop.getInitializer();
|
|
6394
6394
|
if (val !== void 0 && import_ts_morph28.Node.isStringLiteral(val)) {
|
|
6395
|
-
|
|
6395
|
+
path13 = val.getLiteralValue();
|
|
6396
6396
|
}
|
|
6397
6397
|
}
|
|
6398
6398
|
if (propName === pattern.responseExtraction.property) {
|
|
@@ -6416,10 +6416,10 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
6416
6416
|
if (responses.length === 0) {
|
|
6417
6417
|
return null;
|
|
6418
6418
|
}
|
|
6419
|
-
const boundaryBinding = method !== void 0 ||
|
|
6419
|
+
const boundaryBinding = method !== void 0 || path13 !== void 0 ? (0, import_behavioral_ir2.restBinding)({
|
|
6420
6420
|
transport: "http",
|
|
6421
6421
|
method: method ?? null,
|
|
6422
|
-
path:
|
|
6422
|
+
path: path13 ?? null,
|
|
6423
6423
|
recognition: framework
|
|
6424
6424
|
}) : null;
|
|
6425
6425
|
return {
|
|
@@ -8334,7 +8334,34 @@ function joinRoutePath(prefix, suffix) {
|
|
|
8334
8334
|
}
|
|
8335
8335
|
return `/${segments.join("/")}`;
|
|
8336
8336
|
}
|
|
8337
|
-
function
|
|
8337
|
+
function declaredChannelOf(source, decorator, resolution) {
|
|
8338
|
+
if (source.from === "literal") {
|
|
8339
|
+
return source.value;
|
|
8340
|
+
}
|
|
8341
|
+
if (source.from === "unstated") {
|
|
8342
|
+
return null;
|
|
8343
|
+
}
|
|
8344
|
+
if (!import_ts_morph38.Node.isDecorator(decorator)) {
|
|
8345
|
+
return null;
|
|
8346
|
+
}
|
|
8347
|
+
const arg = decorator.getArguments()[source.position];
|
|
8348
|
+
if (arg === void 0) {
|
|
8349
|
+
return null;
|
|
8350
|
+
}
|
|
8351
|
+
const text = literalStringOf(arg, resolution);
|
|
8352
|
+
return text === null || text === "" ? null : text;
|
|
8353
|
+
}
|
|
8354
|
+
function literalStringOf(node, resolution) {
|
|
8355
|
+
if (import_ts_morph38.Node.isStringLiteral(node) || import_ts_morph38.Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
8356
|
+
return node.getLiteralValue();
|
|
8357
|
+
}
|
|
8358
|
+
const written = resolution?.resolveWrittenValue(node) ?? null;
|
|
8359
|
+
if (written === null || written === node) {
|
|
8360
|
+
return null;
|
|
8361
|
+
}
|
|
8362
|
+
return literalStringOf(written, resolution);
|
|
8363
|
+
}
|
|
8364
|
+
function discoverDecoratedRoutes(sourceFile, match, kind, resolution, binding) {
|
|
8338
8365
|
const acceptedModules = Array.isArray(match.importModule) ? match.importModule : [match.importModule];
|
|
8339
8366
|
const routeDecoratorNames = Object.keys(match.methodDecoratorRouteMap);
|
|
8340
8367
|
const importedRouteDecorators = /* @__PURE__ */ new Set();
|
|
@@ -8366,6 +8393,22 @@ function discoverDecoratedRoutes(sourceFile, match, kind, resolution) {
|
|
|
8366
8393
|
const pathPrefix = routePathOf(marker.args, resolution);
|
|
8367
8394
|
const className = cls.getName() ?? "<anon-class>";
|
|
8368
8395
|
for (const handler of decoratedCallablesOf(cls, routeDecoratorNames)) {
|
|
8396
|
+
if (binding !== void 0) {
|
|
8397
|
+
results.push({
|
|
8398
|
+
func: handler.func,
|
|
8399
|
+
kind,
|
|
8400
|
+
name: `${className}.${handler.name}`,
|
|
8401
|
+
channelInfo: {
|
|
8402
|
+
messageBus: binding.messageBus,
|
|
8403
|
+
channel: declaredChannelOf(
|
|
8404
|
+
binding.channel,
|
|
8405
|
+
handler.decorator,
|
|
8406
|
+
resolution
|
|
8407
|
+
)
|
|
8408
|
+
}
|
|
8409
|
+
});
|
|
8410
|
+
continue;
|
|
8411
|
+
}
|
|
8369
8412
|
const httpMethod = match.methodDecoratorRouteMap[handler.standsFor];
|
|
8370
8413
|
const pathSuffix = resolveRoutePathArg(handler.decorator, resolution);
|
|
8371
8414
|
const routePath = joinRoutePath(pathPrefix, pathSuffix);
|
|
@@ -9379,7 +9422,7 @@ function attributeValueOf(node, name) {
|
|
|
9379
9422
|
}
|
|
9380
9423
|
return null;
|
|
9381
9424
|
}
|
|
9382
|
-
function
|
|
9425
|
+
function literalStringOf2(value) {
|
|
9383
9426
|
const unwrapped2 = import_ts_morph43.Node.isJsxExpression(value) ? value.getExpression() ?? value : value;
|
|
9384
9427
|
if (import_ts_morph43.Node.isStringLiteral(unwrapped2) || import_ts_morph43.Node.isNoSubstitutionTemplateLiteral(unwrapped2)) {
|
|
9385
9428
|
return unwrapped2.getLiteralValue();
|
|
@@ -9389,7 +9432,7 @@ function literalStringOf(value) {
|
|
|
9389
9432
|
function ownPathOfJsx(node, match) {
|
|
9390
9433
|
const pathValue = attributeValueOf(node, match.pathAttribute);
|
|
9391
9434
|
if (pathValue !== null) {
|
|
9392
|
-
const literal =
|
|
9435
|
+
const literal = literalStringOf2(pathValue);
|
|
9393
9436
|
return literal !== null ? { kind: "literal", value: literal } : { kind: "unreadable" };
|
|
9394
9437
|
}
|
|
9395
9438
|
if (match.indexAttribute !== void 0 && attributeValueOf(node, match.indexAttribute) !== null) {
|
|
@@ -9480,14 +9523,14 @@ function unitForJsxRoute(node, match, routeNames, kind, resolution) {
|
|
|
9480
9523
|
}
|
|
9481
9524
|
return routeUnit(node, kind, match.method, resolved.path, target, resolution);
|
|
9482
9525
|
}
|
|
9483
|
-
function routeUnit(at, kind, method,
|
|
9484
|
-
const routeInfo = { method, path:
|
|
9526
|
+
function routeUnit(at, kind, method, path13, target, resolution) {
|
|
9527
|
+
const routeInfo = { method, path: path13 };
|
|
9485
9528
|
if (target.kind === "unreadable") {
|
|
9486
9529
|
return {
|
|
9487
9530
|
func: null,
|
|
9488
9531
|
announcedAt: at,
|
|
9489
9532
|
kind,
|
|
9490
|
-
name:
|
|
9533
|
+
name: path13,
|
|
9491
9534
|
nameKind: "label",
|
|
9492
9535
|
routeInfo
|
|
9493
9536
|
};
|
|
@@ -9657,7 +9700,7 @@ function unitsUnderRouteObject(object, match, kind, resolution, prefix, ancestry
|
|
|
9657
9700
|
function ownPathOfObject(object, match) {
|
|
9658
9701
|
const pathValue = routePropertyOf(object, match.pathAttribute);
|
|
9659
9702
|
if (pathValue !== null) {
|
|
9660
|
-
const literal =
|
|
9703
|
+
const literal = literalStringOf2(pathValue);
|
|
9661
9704
|
return literal !== null ? { kind: "literal", value: literal } : { kind: "unreadable" };
|
|
9662
9705
|
}
|
|
9663
9706
|
if (match.indexAttribute !== void 0) {
|
|
@@ -9917,6 +9960,9 @@ function resolvePackageExportsCached(packageJsonPath) {
|
|
|
9917
9960
|
return fresh;
|
|
9918
9961
|
}
|
|
9919
9962
|
function discoverPackageExports(sourceFile, match, kind) {
|
|
9963
|
+
if (match.packageJsonPath === void 0) {
|
|
9964
|
+
return [];
|
|
9965
|
+
}
|
|
9920
9966
|
const { entries } = resolvePackageExportsCached(match.packageJsonPath);
|
|
9921
9967
|
const filePath = sourceFile.getFilePath();
|
|
9922
9968
|
const matching = [];
|
|
@@ -10304,12 +10350,12 @@ function originEndOf(flattened) {
|
|
|
10304
10350
|
const slash = flattened.indexOf("/", opener[0].length);
|
|
10305
10351
|
return slash === -1 ? flattened.length : slash;
|
|
10306
10352
|
}
|
|
10307
|
-
function appendPathText(
|
|
10353
|
+
function appendPathText(path13, text) {
|
|
10308
10354
|
const idx = text.search(/[?#]/);
|
|
10309
10355
|
if (idx === -1) {
|
|
10310
|
-
return { path:
|
|
10356
|
+
return { path: path13 + text, stop: false };
|
|
10311
10357
|
}
|
|
10312
|
-
return { path:
|
|
10358
|
+
return { path: path13 + text.slice(0, idx), stop: true };
|
|
10313
10359
|
}
|
|
10314
10360
|
function parseAbsoluteUrl(text) {
|
|
10315
10361
|
try {
|
|
@@ -10333,8 +10379,8 @@ function pathnameOfAbsoluteLiteral(text) {
|
|
|
10333
10379
|
return stripQueryAndFragment(stripOriginManually(text));
|
|
10334
10380
|
}
|
|
10335
10381
|
function pathFromLiteralUrl(text) {
|
|
10336
|
-
const
|
|
10337
|
-
return
|
|
10382
|
+
const path13 = isAbsoluteUrlLiteral(text) ? pathnameOfAbsoluteLiteral(text) : stripQueryAndFragment(text);
|
|
10383
|
+
return path13 === "" ? void 0 : path13;
|
|
10338
10384
|
}
|
|
10339
10385
|
function pathFromTemplateUrl(arg, resolution) {
|
|
10340
10386
|
const headText = arg.getHead().getLiteralText();
|
|
@@ -10342,7 +10388,7 @@ function pathFromTemplateUrl(arg, resolution) {
|
|
|
10342
10388
|
const tails = spans.map((span) => span.getLiteral().getLiteralText());
|
|
10343
10389
|
const originEnd = originEndOf([headText, ...tails].join(SUBSTITUTION));
|
|
10344
10390
|
const head = appendPathText("", headText.slice(originEnd));
|
|
10345
|
-
let
|
|
10391
|
+
let path13 = head.path;
|
|
10346
10392
|
let stop = head.stop;
|
|
10347
10393
|
let at = headText.length;
|
|
10348
10394
|
for (let i = 0; i < spans.length && !stop; i++) {
|
|
@@ -10352,18 +10398,18 @@ function pathFromTemplateUrl(arg, resolution) {
|
|
|
10352
10398
|
continue;
|
|
10353
10399
|
}
|
|
10354
10400
|
if (at >= originEnd) {
|
|
10355
|
-
|
|
10401
|
+
path13 += holeText(span.getExpression(), resolution);
|
|
10356
10402
|
}
|
|
10357
10403
|
at += SUBSTITUTION.length;
|
|
10358
10404
|
const appended = appendPathText(
|
|
10359
|
-
|
|
10405
|
+
path13,
|
|
10360
10406
|
tailText.slice(Math.max(0, originEnd - at))
|
|
10361
10407
|
);
|
|
10362
|
-
|
|
10408
|
+
path13 = appended.path;
|
|
10363
10409
|
stop = appended.stop;
|
|
10364
10410
|
at += tailText.length;
|
|
10365
10411
|
}
|
|
10366
|
-
return
|
|
10412
|
+
return path13 === "" ? void 0 : path13;
|
|
10367
10413
|
}
|
|
10368
10414
|
function pathFromUrlNode(node, resolution) {
|
|
10369
10415
|
if (import_ts_morph48.Node.isStringLiteral(node)) {
|
|
@@ -10530,9 +10576,9 @@ function withMountPrefix(routeInfo, subjectNode, mountPrefixes) {
|
|
|
10530
10576
|
const prefix = mountPrefixes.effectivePrefixFor(subjectNode);
|
|
10531
10577
|
return prefix === "" ? routeInfo : { ...routeInfo, path: joinMountedPath(prefix, routeInfo.path) };
|
|
10532
10578
|
}
|
|
10533
|
-
function joinMountedPath(prefix,
|
|
10579
|
+
function joinMountedPath(prefix, path13) {
|
|
10534
10580
|
const trimmed = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
|
|
10535
|
-
return trimmed === "" ?
|
|
10581
|
+
return trimmed === "" ? path13 : trimmed + path13;
|
|
10536
10582
|
}
|
|
10537
10583
|
function registrationSubjectsOf(sourceFile, importModule, importName) {
|
|
10538
10584
|
let importedLocalName = null;
|
|
@@ -10696,11 +10742,11 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
10696
10742
|
return null;
|
|
10697
10743
|
}
|
|
10698
10744
|
const method2 = stringProperty(routeObject, binding.method.property);
|
|
10699
|
-
const
|
|
10700
|
-
if (method2 === null ||
|
|
10745
|
+
const path14 = stringProperty(routeObject, binding.path.property);
|
|
10746
|
+
if (method2 === null || path14 === null) {
|
|
10701
10747
|
return null;
|
|
10702
10748
|
}
|
|
10703
|
-
return { method: method2.toUpperCase(), path:
|
|
10749
|
+
return { method: method2.toUpperCase(), path: path14 };
|
|
10704
10750
|
}
|
|
10705
10751
|
if (binding.method.type !== "fromRegistration" || binding.path.type !== "fromArgument") {
|
|
10706
10752
|
return null;
|
|
@@ -10717,8 +10763,8 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
10717
10763
|
method = arg.getLiteralValue().toUpperCase();
|
|
10718
10764
|
}
|
|
10719
10765
|
const pathArg = call.getArguments()[binding.path.position];
|
|
10720
|
-
const
|
|
10721
|
-
return
|
|
10766
|
+
const path13 = pathArg === void 0 ? void 0 : pathFromArgument(pathArg, resolution);
|
|
10767
|
+
return path13 === void 0 ? null : { method, path: path13 };
|
|
10722
10768
|
}
|
|
10723
10769
|
|
|
10724
10770
|
// src/discovery/registrationLoop.ts
|
|
@@ -10841,7 +10887,7 @@ function bodyCallsOn(loop, routables) {
|
|
|
10841
10887
|
}
|
|
10842
10888
|
function readRouteSpec(element, shape, resolution) {
|
|
10843
10889
|
let method = null;
|
|
10844
|
-
let
|
|
10890
|
+
let path13 = null;
|
|
10845
10891
|
let handler = null;
|
|
10846
10892
|
for (const prop of element.getProperties()) {
|
|
10847
10893
|
if (import_ts_morph50.Node.isMethodDeclaration(prop) && prop.getName() === shape.handlerKey) {
|
|
@@ -10859,16 +10905,16 @@ function readRouteSpec(element, shape, resolution) {
|
|
|
10859
10905
|
if (name === shape.methodKey) {
|
|
10860
10906
|
method = readStringLiteralValue(init);
|
|
10861
10907
|
} else if (name === shape.pathKey) {
|
|
10862
|
-
|
|
10908
|
+
path13 = readStringLiteralValue(init);
|
|
10863
10909
|
} else if (name === shape.handlerKey) {
|
|
10864
10910
|
const func = functionValueOf(init, resolution);
|
|
10865
10911
|
handler = func === null ? null : { func, name: handlerName(init) };
|
|
10866
10912
|
}
|
|
10867
10913
|
}
|
|
10868
|
-
if (method === null ||
|
|
10914
|
+
if (method === null || path13 === null || handler === null) {
|
|
10869
10915
|
return null;
|
|
10870
10916
|
}
|
|
10871
|
-
return { method, path:
|
|
10917
|
+
return { method, path: path13, handler: handler.func, handlerName: handler.name };
|
|
10872
10918
|
}
|
|
10873
10919
|
function readStringLiteralValue(node) {
|
|
10874
10920
|
if (import_ts_morph50.Node.isStringLiteral(node) || import_ts_morph50.Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
@@ -10897,8 +10943,8 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution) {
|
|
|
10897
10943
|
}
|
|
10898
10944
|
const args = node.getArguments();
|
|
10899
10945
|
for (const reg of match.registrations) {
|
|
10900
|
-
const
|
|
10901
|
-
if (
|
|
10946
|
+
const path13 = substitutePath(reg.pathTemplate, args);
|
|
10947
|
+
if (path13 === null) {
|
|
10902
10948
|
continue;
|
|
10903
10949
|
}
|
|
10904
10950
|
const handler = resolveHandler(reg.handlerArg, args, resolution);
|
|
@@ -10911,7 +10957,7 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution) {
|
|
|
10911
10957
|
name: handler.name,
|
|
10912
10958
|
routeInfo: {
|
|
10913
10959
|
method: reg.method.toUpperCase(),
|
|
10914
|
-
path:
|
|
10960
|
+
path: path13
|
|
10915
10961
|
}
|
|
10916
10962
|
});
|
|
10917
10963
|
}
|
|
@@ -11237,7 +11283,8 @@ function runPattern(sourceFile, pattern, resolution, mountPrefixes) {
|
|
|
11237
11283
|
sourceFile,
|
|
11238
11284
|
pattern.match,
|
|
11239
11285
|
pattern.kind,
|
|
11240
|
-
resolution
|
|
11286
|
+
resolution,
|
|
11287
|
+
pattern.binding
|
|
11241
11288
|
);
|
|
11242
11289
|
}
|
|
11243
11290
|
if (pattern.match.type === "jsxElementRoute") {
|
|
@@ -12437,19 +12484,35 @@ function resolveCallee(call, calleeName, scan) {
|
|
|
12437
12484
|
}
|
|
12438
12485
|
};
|
|
12439
12486
|
}
|
|
12487
|
+
function resolveJsxReference(node) {
|
|
12488
|
+
if (!import_ts_morph56.Node.isJsxOpeningElement(node) && !import_ts_morph56.Node.isJsxSelfClosingElement(node)) {
|
|
12489
|
+
return null;
|
|
12490
|
+
}
|
|
12491
|
+
const tag = node.getTagNameNode();
|
|
12492
|
+
if (!import_ts_morph56.Node.isIdentifier(tag) || !/^[A-Z]/.test(tag.getText())) {
|
|
12493
|
+
return null;
|
|
12494
|
+
}
|
|
12495
|
+
const name = tag.getText();
|
|
12496
|
+
const declarations = declarationsBehind(tag.getSymbol());
|
|
12497
|
+
for (const decl of declarations) {
|
|
12498
|
+
const resolved = resolveDecl(decl, name);
|
|
12499
|
+
if (resolved !== null) {
|
|
12500
|
+
return { tag: name, outcome: { kind: "followed", candidate: resolved } };
|
|
12501
|
+
}
|
|
12502
|
+
}
|
|
12503
|
+
return {
|
|
12504
|
+
tag: name,
|
|
12505
|
+
outcome: {
|
|
12506
|
+
kind: "stopped",
|
|
12507
|
+
stop: { callee: name, reason: classifyStop(declarations) }
|
|
12508
|
+
}
|
|
12509
|
+
};
|
|
12510
|
+
}
|
|
12440
12511
|
function collectReachable(func, scan) {
|
|
12441
12512
|
const candidates = [];
|
|
12442
12513
|
const stops = [];
|
|
12443
12514
|
const seen = /* @__PURE__ */ new Set();
|
|
12444
|
-
|
|
12445
|
-
if (!import_ts_morph56.Node.isCallExpression(node)) {
|
|
12446
|
-
return;
|
|
12447
|
-
}
|
|
12448
|
-
const calleeText = normalizeCallee(node.getExpression().getText());
|
|
12449
|
-
const outcome = resolveCallee(node, calleeText, scan);
|
|
12450
|
-
if (outcome === null) {
|
|
12451
|
-
return;
|
|
12452
|
-
}
|
|
12515
|
+
const record = (outcome) => {
|
|
12453
12516
|
if (outcome.kind === "stopped") {
|
|
12454
12517
|
const stopKey = `${outcome.stop.reason}:${outcome.stop.callee}`;
|
|
12455
12518
|
if (!seen.has(stopKey) && worthRecording(outcome.stop.reason)) {
|
|
@@ -12464,6 +12527,22 @@ function collectReachable(func, scan) {
|
|
|
12464
12527
|
}
|
|
12465
12528
|
seen.add(key);
|
|
12466
12529
|
candidates.push(outcome.candidate);
|
|
12530
|
+
};
|
|
12531
|
+
func.forEachDescendant((node) => {
|
|
12532
|
+
const jsx = resolveJsxReference(node);
|
|
12533
|
+
if (jsx !== null) {
|
|
12534
|
+
record(jsx.outcome);
|
|
12535
|
+
return;
|
|
12536
|
+
}
|
|
12537
|
+
if (!import_ts_morph56.Node.isCallExpression(node)) {
|
|
12538
|
+
return;
|
|
12539
|
+
}
|
|
12540
|
+
const calleeText = normalizeCallee(node.getExpression().getText());
|
|
12541
|
+
const outcome = resolveCallee(node, calleeText, scan);
|
|
12542
|
+
if (outcome === null) {
|
|
12543
|
+
return;
|
|
12544
|
+
}
|
|
12545
|
+
record(outcome);
|
|
12467
12546
|
});
|
|
12468
12547
|
return { candidates, stops };
|
|
12469
12548
|
}
|
|
@@ -12502,7 +12581,38 @@ var REACHABLE_RULES = [
|
|
|
12502
12581
|
)
|
|
12503
12582
|
];
|
|
12504
12583
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
12505
|
-
function
|
|
12584
|
+
function recognizerOnlyRoots(packsByFile) {
|
|
12585
|
+
const roots = [];
|
|
12586
|
+
for (const [sourceFile, packs] of packsByFile) {
|
|
12587
|
+
const recognizerOnly = packs.some(
|
|
12588
|
+
(pack) => pack.discovery.length === 0 && pack.discoverUnits === void 0 && ((pack.invocationRecognizers?.length ?? 0) > 0 || (pack.accessRecognizers?.length ?? 0) > 0)
|
|
12589
|
+
);
|
|
12590
|
+
if (!recognizerOnly) {
|
|
12591
|
+
continue;
|
|
12592
|
+
}
|
|
12593
|
+
for (const declaration of sourceFile.getFunctions()) {
|
|
12594
|
+
if (declaration.isExported() && hasBody(declaration)) {
|
|
12595
|
+
roots.push({
|
|
12596
|
+
func: declaration,
|
|
12597
|
+
name: declaration.getName() ?? "<anon>"
|
|
12598
|
+
});
|
|
12599
|
+
}
|
|
12600
|
+
}
|
|
12601
|
+
for (const variableStatement of sourceFile.getVariableStatements()) {
|
|
12602
|
+
if (!variableStatement.isExported()) {
|
|
12603
|
+
continue;
|
|
12604
|
+
}
|
|
12605
|
+
for (const declaration of variableStatement.getDeclarations()) {
|
|
12606
|
+
const init = declaration.getInitializer();
|
|
12607
|
+
if (init !== void 0 && (import_ts_morph56.Node.isArrowFunction(init) || import_ts_morph56.Node.isFunctionExpression(init)) && hasBody(init)) {
|
|
12608
|
+
roots.push({ func: init, name: declaration.getName() });
|
|
12609
|
+
}
|
|
12610
|
+
}
|
|
12611
|
+
}
|
|
12612
|
+
}
|
|
12613
|
+
return roots;
|
|
12614
|
+
}
|
|
12615
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = [], extraRoots = []) {
|
|
12506
12616
|
const lookup = createSourceFileLookup(project);
|
|
12507
12617
|
const db = facts?.db ?? new import_datalog4.Database();
|
|
12508
12618
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
@@ -12522,6 +12632,13 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
12522
12632
|
db.add("entry", [key]);
|
|
12523
12633
|
}
|
|
12524
12634
|
}
|
|
12635
|
+
for (const root of extraRoots) {
|
|
12636
|
+
const key = nodeKey2(root.func);
|
|
12637
|
+
if (!functionByKey.has(key)) {
|
|
12638
|
+
functionByKey.set(key, root);
|
|
12639
|
+
}
|
|
12640
|
+
db.add("entry", [key]);
|
|
12641
|
+
}
|
|
12525
12642
|
const knownKeys = /* @__PURE__ */ new Set();
|
|
12526
12643
|
for (const summary of alreadySummarized) {
|
|
12527
12644
|
const func = lookup.functionAt(summary.location);
|
|
@@ -13583,6 +13700,185 @@ function computeAdapterPacksDigest(packVersions) {
|
|
|
13583
13700
|
return `${adapterStamp}|${sortedPacks.join(",")}`;
|
|
13584
13701
|
}
|
|
13585
13702
|
|
|
13703
|
+
// src/workspacePatterns.ts
|
|
13704
|
+
var import_node_crypto4 = require("crypto");
|
|
13705
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
13706
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
13707
|
+
function readJson(filePath) {
|
|
13708
|
+
try {
|
|
13709
|
+
return JSON.parse(import_node_fs6.default.readFileSync(filePath, "utf8"));
|
|
13710
|
+
} catch {
|
|
13711
|
+
return void 0;
|
|
13712
|
+
}
|
|
13713
|
+
}
|
|
13714
|
+
function pnpmWorkspaceGlobs(yamlText) {
|
|
13715
|
+
const globs = [];
|
|
13716
|
+
let inPackages = false;
|
|
13717
|
+
for (const line of yamlText.split("\n")) {
|
|
13718
|
+
if (/^packages\s*:/.test(line)) {
|
|
13719
|
+
inPackages = true;
|
|
13720
|
+
continue;
|
|
13721
|
+
}
|
|
13722
|
+
if (inPackages) {
|
|
13723
|
+
const item = line.match(/^\s+-\s+["']?([^"'#\s]+)["']?/);
|
|
13724
|
+
if (item !== null) {
|
|
13725
|
+
globs.push(item[1]);
|
|
13726
|
+
continue;
|
|
13727
|
+
}
|
|
13728
|
+
if (/^\S/.test(line)) {
|
|
13729
|
+
inPackages = false;
|
|
13730
|
+
}
|
|
13731
|
+
}
|
|
13732
|
+
}
|
|
13733
|
+
return globs;
|
|
13734
|
+
}
|
|
13735
|
+
function workspaceGlobsAt(dir) {
|
|
13736
|
+
const pkg = readJson(import_node_path9.default.join(dir, "package.json"));
|
|
13737
|
+
if (typeof pkg === "object" && pkg !== null && "workspaces" in pkg) {
|
|
13738
|
+
const ws = pkg.workspaces;
|
|
13739
|
+
if (Array.isArray(ws)) {
|
|
13740
|
+
return ws.filter((g) => typeof g === "string");
|
|
13741
|
+
}
|
|
13742
|
+
if (typeof ws === "object" && ws !== null && Array.isArray(ws.packages)) {
|
|
13743
|
+
return ws.packages.filter(
|
|
13744
|
+
(g) => typeof g === "string"
|
|
13745
|
+
);
|
|
13746
|
+
}
|
|
13747
|
+
}
|
|
13748
|
+
const pnpmPath = import_node_path9.default.join(dir, "pnpm-workspace.yaml");
|
|
13749
|
+
if (import_node_fs6.default.existsSync(pnpmPath)) {
|
|
13750
|
+
try {
|
|
13751
|
+
return pnpmWorkspaceGlobs(import_node_fs6.default.readFileSync(pnpmPath, "utf8"));
|
|
13752
|
+
} catch {
|
|
13753
|
+
return null;
|
|
13754
|
+
}
|
|
13755
|
+
}
|
|
13756
|
+
return null;
|
|
13757
|
+
}
|
|
13758
|
+
function isDirectory(candidate) {
|
|
13759
|
+
try {
|
|
13760
|
+
return import_node_fs6.default.statSync(candidate).isDirectory();
|
|
13761
|
+
} catch {
|
|
13762
|
+
return false;
|
|
13763
|
+
}
|
|
13764
|
+
}
|
|
13765
|
+
function subdirectoriesOf(dir) {
|
|
13766
|
+
try {
|
|
13767
|
+
return import_node_fs6.default.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
13768
|
+
} catch {
|
|
13769
|
+
return [];
|
|
13770
|
+
}
|
|
13771
|
+
}
|
|
13772
|
+
function segmentToRegExp(segment) {
|
|
13773
|
+
const escaped = segment.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13774
|
+
return new RegExp(`^${escaped.replace(/\*/g, "[^/]*")}$`);
|
|
13775
|
+
}
|
|
13776
|
+
function directoriesMatchingGlob(root, glob) {
|
|
13777
|
+
let current2 = [root];
|
|
13778
|
+
for (const segment of glob.split("/").filter((s) => s.length > 0)) {
|
|
13779
|
+
const next = [];
|
|
13780
|
+
if (segment.includes("*")) {
|
|
13781
|
+
const pattern = segmentToRegExp(segment);
|
|
13782
|
+
for (const dir of current2) {
|
|
13783
|
+
for (const entry of subdirectoriesOf(dir)) {
|
|
13784
|
+
if (pattern.test(entry)) {
|
|
13785
|
+
next.push(import_node_path9.default.join(dir, entry));
|
|
13786
|
+
}
|
|
13787
|
+
}
|
|
13788
|
+
}
|
|
13789
|
+
} else {
|
|
13790
|
+
for (const dir of current2) {
|
|
13791
|
+
next.push(import_node_path9.default.join(dir, segment));
|
|
13792
|
+
}
|
|
13793
|
+
}
|
|
13794
|
+
current2 = next.filter(isDirectory);
|
|
13795
|
+
}
|
|
13796
|
+
return current2;
|
|
13797
|
+
}
|
|
13798
|
+
function packageAt(dir) {
|
|
13799
|
+
const packageJsonPath = import_node_path9.default.join(dir, "package.json");
|
|
13800
|
+
const pkg = readJson(packageJsonPath);
|
|
13801
|
+
if (typeof pkg === "object" && pkg !== null && typeof pkg.name === "string") {
|
|
13802
|
+
return { name: pkg.name, packageJsonPath };
|
|
13803
|
+
}
|
|
13804
|
+
return null;
|
|
13805
|
+
}
|
|
13806
|
+
function workspacePackagesFrom(anchor) {
|
|
13807
|
+
let dir = import_node_path9.default.resolve(anchor);
|
|
13808
|
+
for (; ; ) {
|
|
13809
|
+
const globs = workspaceGlobsAt(dir);
|
|
13810
|
+
if (globs !== null) {
|
|
13811
|
+
const found = /* @__PURE__ */ new Map();
|
|
13812
|
+
for (const glob of globs) {
|
|
13813
|
+
if (glob.startsWith("!")) {
|
|
13814
|
+
continue;
|
|
13815
|
+
}
|
|
13816
|
+
for (const match of directoriesMatchingGlob(dir, glob)) {
|
|
13817
|
+
const pkg = packageAt(match);
|
|
13818
|
+
if (pkg !== null) {
|
|
13819
|
+
found.set(pkg.packageJsonPath, pkg);
|
|
13820
|
+
}
|
|
13821
|
+
}
|
|
13822
|
+
}
|
|
13823
|
+
return [...found.values()].sort(
|
|
13824
|
+
(a, b) => a.packageJsonPath.localeCompare(b.packageJsonPath)
|
|
13825
|
+
);
|
|
13826
|
+
}
|
|
13827
|
+
const parent = import_node_path9.default.dirname(dir);
|
|
13828
|
+
if (parent === dir) {
|
|
13829
|
+
return [];
|
|
13830
|
+
}
|
|
13831
|
+
dir = parent;
|
|
13832
|
+
}
|
|
13833
|
+
}
|
|
13834
|
+
function isWorkspaceMarked(pattern) {
|
|
13835
|
+
const match = pattern.match;
|
|
13836
|
+
return (match.type === "packageExports" || match.type === "packageImport") && match.workspaces === true;
|
|
13837
|
+
}
|
|
13838
|
+
function expandPattern(pattern, packages) {
|
|
13839
|
+
const match = pattern.match;
|
|
13840
|
+
if (match.type === "packageExports" && match.workspaces === true) {
|
|
13841
|
+
const { workspaces: _workspaces, ...rest } = match;
|
|
13842
|
+
return packages.map((pkg) => ({
|
|
13843
|
+
...pattern,
|
|
13844
|
+
match: { ...rest, packageJsonPath: pkg.packageJsonPath }
|
|
13845
|
+
}));
|
|
13846
|
+
}
|
|
13847
|
+
if (match.type === "packageImport" && match.workspaces === true) {
|
|
13848
|
+
const listed = match.packages ?? [];
|
|
13849
|
+
const names = [.../* @__PURE__ */ new Set([...listed, ...packages.map((p) => p.name)])];
|
|
13850
|
+
if (names.length === 0) {
|
|
13851
|
+
return [];
|
|
13852
|
+
}
|
|
13853
|
+
return [{ ...pattern, match: { type: "packageImport", packages: names } }];
|
|
13854
|
+
}
|
|
13855
|
+
return [pattern];
|
|
13856
|
+
}
|
|
13857
|
+
function workspaceExpansionStamp(frameworks) {
|
|
13858
|
+
const paths = frameworks.flatMap((pack) => pack.discovery).flatMap(
|
|
13859
|
+
(pattern) => pattern.match.type === "packageExports" && pattern.match.packageJsonPath !== void 0 ? [pattern.match.packageJsonPath] : []
|
|
13860
|
+
).sort();
|
|
13861
|
+
if (paths.length === 0) {
|
|
13862
|
+
return "none";
|
|
13863
|
+
}
|
|
13864
|
+
return (0, import_node_crypto4.createHash)("sha256").update(paths.join("\n")).digest("hex").slice(0, 12);
|
|
13865
|
+
}
|
|
13866
|
+
function expandWorkspacePatterns(frameworks, anchor) {
|
|
13867
|
+
const marked = frameworks.some(
|
|
13868
|
+
(pack) => pack.discovery.some(isWorkspaceMarked)
|
|
13869
|
+
);
|
|
13870
|
+
if (!marked) {
|
|
13871
|
+
return frameworks;
|
|
13872
|
+
}
|
|
13873
|
+
const packages = anchor !== void 0 ? workspacePackagesFrom(anchor) : [];
|
|
13874
|
+
return frameworks.map((pack) => ({
|
|
13875
|
+
...pack,
|
|
13876
|
+
discovery: pack.discovery.flatMap(
|
|
13877
|
+
(pattern) => expandPattern(pattern, packages)
|
|
13878
|
+
)
|
|
13879
|
+
}));
|
|
13880
|
+
}
|
|
13881
|
+
|
|
13586
13882
|
// src/adapter.ts
|
|
13587
13883
|
var raise = (msg) => {
|
|
13588
13884
|
throw new Error(msg);
|
|
@@ -13993,11 +14289,11 @@ function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
|
13993
14289
|
return null;
|
|
13994
14290
|
}
|
|
13995
14291
|
const method = extractBindingMethod(binding, callSite, pack, resolution);
|
|
13996
|
-
const
|
|
14292
|
+
const path13 = extractBindingPath(binding, callSite, pack, resolution);
|
|
13997
14293
|
return (0, import_behavioral_ir8.restBinding)({
|
|
13998
14294
|
transport: pack.protocol,
|
|
13999
14295
|
method: method ?? null,
|
|
14000
|
-
path:
|
|
14296
|
+
path: path13 ?? null,
|
|
14001
14297
|
recognition: pack.name
|
|
14002
14298
|
});
|
|
14003
14299
|
}
|
|
@@ -14122,8 +14418,8 @@ function collectAccessRecognizers(frameworks, tallies) {
|
|
|
14122
14418
|
}
|
|
14123
14419
|
return out;
|
|
14124
14420
|
}
|
|
14125
|
-
function computeSubUnitBarriers(unit,
|
|
14126
|
-
if (
|
|
14421
|
+
function computeSubUnitBarriers(unit, packs, ctx, tallies, file) {
|
|
14422
|
+
if (unit.func === null) {
|
|
14127
14423
|
return NO_BARRIERS;
|
|
14128
14424
|
}
|
|
14129
14425
|
const parentHandle = {
|
|
@@ -14131,27 +14427,27 @@ function computeSubUnitBarriers(unit, pack, ctx, tally, file) {
|
|
|
14131
14427
|
name: unit.name,
|
|
14132
14428
|
kind: unit.kind
|
|
14133
14429
|
};
|
|
14134
|
-
|
|
14135
|
-
|
|
14136
|
-
if (subUnits
|
|
14137
|
-
|
|
14430
|
+
const barriers = /* @__PURE__ */ new Set();
|
|
14431
|
+
for (const pack of packs) {
|
|
14432
|
+
if (pack.subUnits === void 0) {
|
|
14433
|
+
continue;
|
|
14138
14434
|
}
|
|
14139
|
-
|
|
14140
|
-
|
|
14141
|
-
|
|
14435
|
+
try {
|
|
14436
|
+
for (const su of pack.subUnits(parentHandle, ctx)) {
|
|
14437
|
+
barriers.add(su.func);
|
|
14438
|
+
}
|
|
14439
|
+
} catch (err) {
|
|
14440
|
+
process.stderr.write(
|
|
14441
|
+
recordPackFailure(tallies?.get(pack.name), {
|
|
14442
|
+
pack: pack.name,
|
|
14443
|
+
hook: "subUnits",
|
|
14444
|
+
file,
|
|
14445
|
+
error: err
|
|
14446
|
+
})
|
|
14447
|
+
);
|
|
14142
14448
|
}
|
|
14143
|
-
return barriers;
|
|
14144
|
-
} catch (err) {
|
|
14145
|
-
process.stderr.write(
|
|
14146
|
-
recordPackFailure(tally, {
|
|
14147
|
-
pack: pack.name,
|
|
14148
|
-
hook: "subUnits",
|
|
14149
|
-
file,
|
|
14150
|
-
error: err
|
|
14151
|
-
})
|
|
14152
|
-
);
|
|
14153
|
-
return NO_BARRIERS;
|
|
14154
14449
|
}
|
|
14450
|
+
return barriers.size === 0 ? NO_BARRIERS : barriers;
|
|
14155
14451
|
}
|
|
14156
14452
|
function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, tallies, resolution, mountPrefixes) {
|
|
14157
14453
|
const summaries = [];
|
|
@@ -14233,9 +14529,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
14233
14529
|
}
|
|
14234
14530
|
const barriers = computeSubUnitBarriers(
|
|
14235
14531
|
unit,
|
|
14236
|
-
|
|
14532
|
+
frameworks,
|
|
14237
14533
|
subUnitCtx,
|
|
14238
|
-
|
|
14534
|
+
tallies,
|
|
14239
14535
|
sourceFile.getFilePath()
|
|
14240
14536
|
);
|
|
14241
14537
|
const raw = extractCodeStructure(
|
|
@@ -14609,8 +14905,8 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
14609
14905
|
if (pathArg === void 0) {
|
|
14610
14906
|
continue;
|
|
14611
14907
|
}
|
|
14612
|
-
const
|
|
14613
|
-
if (
|
|
14908
|
+
const path13 = pathFromArgument(pathArg, resolution);
|
|
14909
|
+
if (path13 === void 0) {
|
|
14614
14910
|
continue;
|
|
14615
14911
|
}
|
|
14616
14912
|
const callerFunc = enclosingFunction(callExpr);
|
|
@@ -14622,7 +14918,7 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
14622
14918
|
continue;
|
|
14623
14919
|
}
|
|
14624
14920
|
seen.add(dedupKey);
|
|
14625
|
-
out.push(buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
14921
|
+
out.push(buildCallerSummary(wrapper, callerFunc, callExpr, path13, options));
|
|
14626
14922
|
}
|
|
14627
14923
|
return out;
|
|
14628
14924
|
}
|
|
@@ -14679,7 +14975,7 @@ function callerName(func) {
|
|
|
14679
14975
|
}
|
|
14680
14976
|
return "anonymous";
|
|
14681
14977
|
}
|
|
14682
|
-
function buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
14978
|
+
function buildCallerSummary(wrapper, callerFunc, callExpr, path13, options) {
|
|
14683
14979
|
const wrapperBinding = wrapper.summary.identity.boundaryBinding;
|
|
14684
14980
|
const wrapperRest = wrapperBinding?.semantics.name === "rest" ? wrapperBinding.semantics : null;
|
|
14685
14981
|
const syntheticPack = {
|
|
@@ -14711,7 +15007,7 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path12, options) {
|
|
|
14711
15007
|
raw.boundaryBinding = (0, import_behavioral_ir8.restBinding)({
|
|
14712
15008
|
transport: wrapperBinding?.transport ?? "http",
|
|
14713
15009
|
method: wrapperRest?.method ?? null,
|
|
14714
|
-
path:
|
|
15010
|
+
path: path13,
|
|
14715
15011
|
recognition: wrapperBinding?.recognition ?? "unknown"
|
|
14716
15012
|
});
|
|
14717
15013
|
const summary = (0, import_extractor5.assembleSummary)(raw, options);
|
|
@@ -14777,25 +15073,32 @@ function loadRunFiles(project, candidatePaths, timer) {
|
|
|
14777
15073
|
);
|
|
14778
15074
|
return { sourceFiles, deep };
|
|
14779
15075
|
}
|
|
14780
|
-
function createTypeScriptAdapter(
|
|
15076
|
+
function createTypeScriptAdapter(suppliedConfig) {
|
|
15077
|
+
const config = {
|
|
15078
|
+
...suppliedConfig,
|
|
15079
|
+
frameworks: expandWorkspacePatterns(
|
|
15080
|
+
suppliedConfig.frameworks,
|
|
15081
|
+
suppliedConfig.projectRoot ?? (suppliedConfig.tsConfigFilePath !== void 0 ? import_node_path10.default.dirname(suppliedConfig.tsConfigFilePath) : void 0)
|
|
15082
|
+
)
|
|
15083
|
+
};
|
|
14781
15084
|
const project = config.project ?? new import_ts_morph60.Project(
|
|
14782
15085
|
config.tsConfigFilePath !== void 0 ? {
|
|
14783
15086
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
14784
15087
|
skipAddingFilesFromTsConfig: true
|
|
14785
15088
|
} : { skipAddingFilesFromTsConfig: true }
|
|
14786
15089
|
);
|
|
14787
|
-
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(
|
|
15090
|
+
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(import_node_path10.default.dirname(config.tsConfigFilePath)) : void 0);
|
|
14788
15091
|
let lazyBootstrapped = false;
|
|
14789
15092
|
let projectFileSet;
|
|
14790
15093
|
const cacheDir = declineWhenRunFromSource(
|
|
14791
|
-
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ?
|
|
15094
|
+
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ? import_node_path10.default.join(import_node_path10.default.dirname(config.tsConfigFilePath), ".suss", "cache") : null)
|
|
14792
15095
|
);
|
|
14793
15096
|
const cache = createCacheLayer(cacheDir);
|
|
14794
15097
|
const adapterPacksDigest = `${computeAdapterPacksDigest(
|
|
14795
15098
|
config.frameworks.map(
|
|
14796
15099
|
(p) => p.version !== void 0 ? { name: p.name, version: p.version } : { name: p.name }
|
|
14797
15100
|
)
|
|
14798
|
-
)}|${extractionConfigStamp(config)}`;
|
|
15101
|
+
)}|${extractionConfigStamp(config)}|ws:${workspaceExpansionStamp(config.frameworks)}`;
|
|
14799
15102
|
const packWrappers = config.frameworks.flatMap(
|
|
14800
15103
|
(pack) => pack.transparentWrappers ?? []
|
|
14801
15104
|
);
|
|
@@ -14997,6 +15300,7 @@ function createTypeScriptAdapter(config) {
|
|
|
14997
15300
|
pipeline,
|
|
14998
15301
|
project,
|
|
14999
15302
|
config.frameworks,
|
|
15303
|
+
packsByFile,
|
|
15000
15304
|
config.extractorOptions,
|
|
15001
15305
|
tallies,
|
|
15002
15306
|
(created, parent) => {
|
|
@@ -15031,7 +15335,12 @@ function createTypeScriptAdapter(config) {
|
|
|
15031
15335
|
},
|
|
15032
15336
|
// Reached units the cache already serves emit nothing,
|
|
15033
15337
|
// the way a cold run's seeds do not.
|
|
15034
|
-
reused?.summaries ?? []
|
|
15338
|
+
reused?.summaries ?? [],
|
|
15339
|
+
// A recognizer-only pack's effects need a function to
|
|
15340
|
+
// live on even when nothing discovers units in its
|
|
15341
|
+
// files, so those files' exports join the walk as
|
|
15342
|
+
// roots.
|
|
15343
|
+
recognizerOnlyRoots(packsByFile)
|
|
15035
15344
|
)
|
|
15036
15345
|
) : withSubUnits;
|
|
15037
15346
|
const closureOwnership = caching && config.includeReachable !== false ? timer.time(
|
|
@@ -15332,11 +15641,15 @@ function buildCacheAttribution(args) {
|
|
|
15332
15641
|
];
|
|
15333
15642
|
return { roots, owners };
|
|
15334
15643
|
}
|
|
15335
|
-
function synthesizeSubUnits(summaries, project, frameworks, options, tallies, onCreated) {
|
|
15644
|
+
function synthesizeSubUnits(summaries, project, frameworks, packsByFile, options, tallies, onCreated) {
|
|
15336
15645
|
const packByRecognition = /* @__PURE__ */ new Map();
|
|
15337
15646
|
for (const pack of frameworks) {
|
|
15338
15647
|
packByRecognition.set(pack.name, pack);
|
|
15339
15648
|
}
|
|
15649
|
+
const packsByPath = /* @__PURE__ */ new Map();
|
|
15650
|
+
for (const [sf, packs] of packsByFile) {
|
|
15651
|
+
packsByPath.set(sf.getFilePath(), packs);
|
|
15652
|
+
}
|
|
15340
15653
|
const allInvocationRecognizers = collectInvocationRecognizers(
|
|
15341
15654
|
frameworks,
|
|
15342
15655
|
tallies
|
|
@@ -15350,8 +15663,15 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies, on
|
|
|
15350
15663
|
if (binding === null) {
|
|
15351
15664
|
continue;
|
|
15352
15665
|
}
|
|
15353
|
-
const
|
|
15354
|
-
|
|
15666
|
+
const discovering = packByRecognition.get(binding.recognition);
|
|
15667
|
+
const applicable = packsByPath.get(parent.location.file) ?? (discovering !== void 0 ? [discovering] : []);
|
|
15668
|
+
const hooked = [
|
|
15669
|
+
...discovering?.subUnits !== void 0 ? [discovering] : [],
|
|
15670
|
+
...applicable.filter(
|
|
15671
|
+
(one) => one.subUnits !== void 0 && one !== discovering
|
|
15672
|
+
)
|
|
15673
|
+
];
|
|
15674
|
+
if (hooked.length === 0) {
|
|
15355
15675
|
continue;
|
|
15356
15676
|
}
|
|
15357
15677
|
lookup ??= createSourceFileLookup(project);
|
|
@@ -15364,7 +15684,17 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies, on
|
|
|
15364
15684
|
name: parent.identity.name,
|
|
15365
15685
|
kind: parent.kind
|
|
15366
15686
|
};
|
|
15367
|
-
const
|
|
15687
|
+
const claimedFuncs = /* @__PURE__ */ new Set();
|
|
15688
|
+
const subUnits = [];
|
|
15689
|
+
for (const pack of hooked) {
|
|
15690
|
+
for (const subUnit of pack.subUnits?.(parentHandle, subUnitCtx) ?? []) {
|
|
15691
|
+
if (claimedFuncs.has(subUnit.func)) {
|
|
15692
|
+
continue;
|
|
15693
|
+
}
|
|
15694
|
+
claimedFuncs.add(subUnit.func);
|
|
15695
|
+
subUnits.push(subUnit);
|
|
15696
|
+
}
|
|
15697
|
+
}
|
|
15368
15698
|
for (const subUnit of subUnits) {
|
|
15369
15699
|
const summary = buildSubUnitSummary(
|
|
15370
15700
|
subUnit,
|
|
@@ -15428,8 +15758,8 @@ function buildSubUnitSummary(subUnit, parent, invocationRecognizers, accessRecog
|
|
|
15428
15758
|
}
|
|
15429
15759
|
|
|
15430
15760
|
// src/bootstrap/noTsconfigProject.ts
|
|
15431
|
-
var
|
|
15432
|
-
var
|
|
15761
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
15762
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
15433
15763
|
var import_ts_morph61 = require("ts-morph");
|
|
15434
15764
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
15435
15765
|
".ts",
|
|
@@ -15460,7 +15790,7 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
15460
15790
|
const found = [];
|
|
15461
15791
|
let entries;
|
|
15462
15792
|
try {
|
|
15463
|
-
entries =
|
|
15793
|
+
entries = import_node_fs7.default.readdirSync(rootDir, { withFileTypes: true });
|
|
15464
15794
|
} catch {
|
|
15465
15795
|
return [];
|
|
15466
15796
|
}
|
|
@@ -15468,10 +15798,10 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
15468
15798
|
if (entry.name.startsWith(".") || SKIP_DIRECTORIES.has(entry.name)) {
|
|
15469
15799
|
continue;
|
|
15470
15800
|
}
|
|
15471
|
-
const full =
|
|
15801
|
+
const full = import_node_path11.default.join(rootDir, entry.name);
|
|
15472
15802
|
if (entry.isDirectory()) {
|
|
15473
15803
|
found.push(...findSourceFiles(full, depth + 1));
|
|
15474
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
15804
|
+
} else if (SOURCE_EXTENSIONS.has(import_node_path11.default.extname(entry.name)) && !entry.name.endsWith(".d.ts")) {
|
|
15475
15805
|
found.push(full);
|
|
15476
15806
|
}
|
|
15477
15807
|
}
|
|
@@ -15506,15 +15836,15 @@ function createProjectWithoutTsconfig(rootDir) {
|
|
|
15506
15836
|
return { project, files };
|
|
15507
15837
|
}
|
|
15508
15838
|
function findNearestTsconfig(startDir) {
|
|
15509
|
-
let dir =
|
|
15839
|
+
let dir = import_node_path11.default.resolve(startDir);
|
|
15510
15840
|
while (true) {
|
|
15511
15841
|
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
15512
|
-
const candidate =
|
|
15513
|
-
if (
|
|
15842
|
+
const candidate = import_node_path11.default.join(dir, name);
|
|
15843
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
15514
15844
|
return candidate;
|
|
15515
15845
|
}
|
|
15516
15846
|
}
|
|
15517
|
-
const parent =
|
|
15847
|
+
const parent = import_node_path11.default.dirname(dir);
|
|
15518
15848
|
if (parent === dir) {
|
|
15519
15849
|
return null;
|
|
15520
15850
|
}
|
|
@@ -15523,7 +15853,7 @@ function findNearestTsconfig(startDir) {
|
|
|
15523
15853
|
}
|
|
15524
15854
|
|
|
15525
15855
|
// src/facts/why.ts
|
|
15526
|
-
var
|
|
15856
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
15527
15857
|
var import_ts_morph62 = require("ts-morph");
|
|
15528
15858
|
var import_resolution2 = require("@suss/resolution");
|
|
15529
15859
|
var JS_PHRASES = {
|
|
@@ -15536,7 +15866,7 @@ var WhySession = class {
|
|
|
15536
15866
|
store;
|
|
15537
15867
|
root;
|
|
15538
15868
|
constructor(options) {
|
|
15539
|
-
this.root =
|
|
15869
|
+
this.root = import_node_path12.default.resolve(options.dir);
|
|
15540
15870
|
const tsconfig = findNearestTsconfig(this.root);
|
|
15541
15871
|
this.project = tsconfig === null ? createProjectWithoutTsconfig(this.root).project : new import_ts_morph62.Project({ tsConfigFilePath: tsconfig });
|
|
15542
15872
|
this.store = new ResolutionStore();
|
|
@@ -15625,7 +15955,7 @@ var WhySession = class {
|
|
|
15625
15955
|
};
|
|
15626
15956
|
}
|
|
15627
15957
|
sourceFileAt(file) {
|
|
15628
|
-
const absolute =
|
|
15958
|
+
const absolute = import_node_path12.default.resolve(this.root, file);
|
|
15629
15959
|
const loaded = this.project.getSourceFile(absolute);
|
|
15630
15960
|
if (loaded !== void 0) {
|
|
15631
15961
|
return loaded;
|
|
@@ -15639,7 +15969,7 @@ var WhySession = class {
|
|
|
15639
15969
|
/** A module key: a file path said relative to the root, or a package name. */
|
|
15640
15970
|
displayPath(key) {
|
|
15641
15971
|
if (key.startsWith(this.root)) {
|
|
15642
|
-
return
|
|
15972
|
+
return import_node_path12.default.relative(this.root, key);
|
|
15643
15973
|
}
|
|
15644
15974
|
return key;
|
|
15645
15975
|
}
|
|
@@ -15710,6 +16040,17 @@ function funnelDrops(packs) {
|
|
|
15710
16040
|
}
|
|
15711
16041
|
return violations;
|
|
15712
16042
|
}
|
|
16043
|
+
function recognizersWithNoUnits(packs) {
|
|
16044
|
+
return packs.filter(
|
|
16045
|
+
(funnel) => funnel.recognizes && !funnel.discovers && funnel.gates.length > 0 && funnel.unresolvedGates.length === 0 && funnel.candidateFiles > 0 && funnel.unitsInGatedFiles === 0 && // The closure walks a recognizer-only pack's gated exports as
|
|
16046
|
+
// roots, so effects recognized there mean the run worked and
|
|
16047
|
+
// the missing framework pack costs attribution, not existence.
|
|
16048
|
+
funnel.effectsRecognized === 0
|
|
16049
|
+
).map((funnel) => ({
|
|
16050
|
+
label: funnel.pack,
|
|
16051
|
+
detail: `${funnel.candidateFiles} gated files, and no pack in this run discovered a unit in them. ${funnel.pack} reads calls inside units another pack finds, so add the pack that finds this project's handlers (-f express, -f fastify, ...), or run suss init to work out which.`
|
|
16052
|
+
}));
|
|
16053
|
+
}
|
|
15713
16054
|
function unversionedPacks(packs) {
|
|
15714
16055
|
return packs.filter((funnel) => funnel.version === null).map((funnel) => ({
|
|
15715
16056
|
label: funnel.pack,
|
|
@@ -15804,6 +16145,12 @@ function evaluatePackHealth(report) {
|
|
|
15804
16145
|
audience: "run",
|
|
15805
16146
|
violations: selfCollisions(report.packs)
|
|
15806
16147
|
},
|
|
16148
|
+
{
|
|
16149
|
+
name: "every recognizer had units to look inside",
|
|
16150
|
+
code: "no-units",
|
|
16151
|
+
audience: "run",
|
|
16152
|
+
violations: recognizersWithNoUnits(report.packs)
|
|
16153
|
+
},
|
|
15807
16154
|
{
|
|
15808
16155
|
name: "every pack declares a version",
|
|
15809
16156
|
code: "no-version",
|