@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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/adapter.ts
|
|
2
|
-
import
|
|
2
|
+
import path10 from "path";
|
|
3
3
|
import {
|
|
4
4
|
Node as Node58,
|
|
5
5
|
Project,
|
|
@@ -1827,8 +1827,8 @@ function loadImportGraphsDepthFirstFromPaths(project, rootPaths) {
|
|
|
1827
1827
|
stack.pop();
|
|
1828
1828
|
loadOrder.push(top.path);
|
|
1829
1829
|
let deepest = 0;
|
|
1830
|
-
for (const
|
|
1831
|
-
deepest = Math.max(deepest, chainDepth.get(
|
|
1830
|
+
for (const path13 of top.deps) {
|
|
1831
|
+
deepest = Math.max(deepest, chainDepth.get(path13) ?? 0);
|
|
1832
1832
|
}
|
|
1833
1833
|
chainDepth.set(top.path, deepest + 1);
|
|
1834
1834
|
}
|
|
@@ -2173,11 +2173,11 @@ function walkAndWarm(root, reach) {
|
|
|
2173
2173
|
if (warmedFiles.get(target) !== void 0) {
|
|
2174
2174
|
continue;
|
|
2175
2175
|
}
|
|
2176
|
-
const
|
|
2177
|
-
if (visited.has(
|
|
2176
|
+
const path13 = target.getFilePath();
|
|
2177
|
+
if (visited.has(path13)) {
|
|
2178
2178
|
continue;
|
|
2179
2179
|
}
|
|
2180
|
-
visited.add(
|
|
2180
|
+
visited.add(path13);
|
|
2181
2181
|
stack.push(frameOf(target, reach));
|
|
2182
2182
|
continue;
|
|
2183
2183
|
}
|
|
@@ -2194,7 +2194,7 @@ function sitsOnWarmChains(file) {
|
|
|
2194
2194
|
return false;
|
|
2195
2195
|
}
|
|
2196
2196
|
const imported = importedFilePathsOf(project, file.getFilePath());
|
|
2197
|
-
return imported.length > 0 && imported.every((
|
|
2197
|
+
return imported.length > 0 && imported.every((path13) => warmed.has(path13));
|
|
2198
2198
|
}
|
|
2199
2199
|
function markWarmed(file) {
|
|
2200
2200
|
warmedFiles.set(file, true);
|
|
@@ -5818,9 +5818,9 @@ function createSourceFileLookup(project) {
|
|
|
5818
5818
|
if (sf === null) {
|
|
5819
5819
|
return null;
|
|
5820
5820
|
}
|
|
5821
|
-
const
|
|
5822
|
-
const index = functionsByFile.get(
|
|
5823
|
-
functionsByFile.set(
|
|
5821
|
+
const path13 = sf.getFilePath();
|
|
5822
|
+
const index = functionsByFile.get(path13) ?? indexFunctions(sf);
|
|
5823
|
+
functionsByFile.set(path13, index);
|
|
5824
5824
|
return index.get(rangeKey(location.range)) ?? null;
|
|
5825
5825
|
}
|
|
5826
5826
|
};
|
|
@@ -6347,7 +6347,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
6347
6347
|
}
|
|
6348
6348
|
const responses = [];
|
|
6349
6349
|
let method;
|
|
6350
|
-
let
|
|
6350
|
+
let path13;
|
|
6351
6351
|
for (const prop of endpointNode.getProperties()) {
|
|
6352
6352
|
if (!Node27.isPropertyAssignment(prop)) {
|
|
6353
6353
|
continue;
|
|
@@ -6362,7 +6362,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
6362
6362
|
if (propName === pattern.pathProperty) {
|
|
6363
6363
|
const val = prop.getInitializer();
|
|
6364
6364
|
if (val !== void 0 && Node27.isStringLiteral(val)) {
|
|
6365
|
-
|
|
6365
|
+
path13 = val.getLiteralValue();
|
|
6366
6366
|
}
|
|
6367
6367
|
}
|
|
6368
6368
|
if (propName === pattern.responseExtraction.property) {
|
|
@@ -6386,10 +6386,10 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
6386
6386
|
if (responses.length === 0) {
|
|
6387
6387
|
return null;
|
|
6388
6388
|
}
|
|
6389
|
-
const boundaryBinding = method !== void 0 ||
|
|
6389
|
+
const boundaryBinding = method !== void 0 || path13 !== void 0 ? restBinding({
|
|
6390
6390
|
transport: "http",
|
|
6391
6391
|
method: method ?? null,
|
|
6392
|
-
path:
|
|
6392
|
+
path: path13 ?? null,
|
|
6393
6393
|
recognition: framework
|
|
6394
6394
|
}) : null;
|
|
6395
6395
|
return {
|
|
@@ -8311,7 +8311,34 @@ function joinRoutePath(prefix, suffix) {
|
|
|
8311
8311
|
}
|
|
8312
8312
|
return `/${segments.join("/")}`;
|
|
8313
8313
|
}
|
|
8314
|
-
function
|
|
8314
|
+
function declaredChannelOf(source, decorator, resolution) {
|
|
8315
|
+
if (source.from === "literal") {
|
|
8316
|
+
return source.value;
|
|
8317
|
+
}
|
|
8318
|
+
if (source.from === "unstated") {
|
|
8319
|
+
return null;
|
|
8320
|
+
}
|
|
8321
|
+
if (!Node36.isDecorator(decorator)) {
|
|
8322
|
+
return null;
|
|
8323
|
+
}
|
|
8324
|
+
const arg = decorator.getArguments()[source.position];
|
|
8325
|
+
if (arg === void 0) {
|
|
8326
|
+
return null;
|
|
8327
|
+
}
|
|
8328
|
+
const text = literalStringOf(arg, resolution);
|
|
8329
|
+
return text === null || text === "" ? null : text;
|
|
8330
|
+
}
|
|
8331
|
+
function literalStringOf(node, resolution) {
|
|
8332
|
+
if (Node36.isStringLiteral(node) || Node36.isNoSubstitutionTemplateLiteral(node)) {
|
|
8333
|
+
return node.getLiteralValue();
|
|
8334
|
+
}
|
|
8335
|
+
const written = resolution?.resolveWrittenValue(node) ?? null;
|
|
8336
|
+
if (written === null || written === node) {
|
|
8337
|
+
return null;
|
|
8338
|
+
}
|
|
8339
|
+
return literalStringOf(written, resolution);
|
|
8340
|
+
}
|
|
8341
|
+
function discoverDecoratedRoutes(sourceFile, match, kind, resolution, binding) {
|
|
8315
8342
|
const acceptedModules = Array.isArray(match.importModule) ? match.importModule : [match.importModule];
|
|
8316
8343
|
const routeDecoratorNames = Object.keys(match.methodDecoratorRouteMap);
|
|
8317
8344
|
const importedRouteDecorators = /* @__PURE__ */ new Set();
|
|
@@ -8343,6 +8370,22 @@ function discoverDecoratedRoutes(sourceFile, match, kind, resolution) {
|
|
|
8343
8370
|
const pathPrefix = routePathOf(marker.args, resolution);
|
|
8344
8371
|
const className = cls.getName() ?? "<anon-class>";
|
|
8345
8372
|
for (const handler of decoratedCallablesOf(cls, routeDecoratorNames)) {
|
|
8373
|
+
if (binding !== void 0) {
|
|
8374
|
+
results.push({
|
|
8375
|
+
func: handler.func,
|
|
8376
|
+
kind,
|
|
8377
|
+
name: `${className}.${handler.name}`,
|
|
8378
|
+
channelInfo: {
|
|
8379
|
+
messageBus: binding.messageBus,
|
|
8380
|
+
channel: declaredChannelOf(
|
|
8381
|
+
binding.channel,
|
|
8382
|
+
handler.decorator,
|
|
8383
|
+
resolution
|
|
8384
|
+
)
|
|
8385
|
+
}
|
|
8386
|
+
});
|
|
8387
|
+
continue;
|
|
8388
|
+
}
|
|
8346
8389
|
const httpMethod = match.methodDecoratorRouteMap[handler.standsFor];
|
|
8347
8390
|
const pathSuffix = resolveRoutePathArg(handler.decorator, resolution);
|
|
8348
8391
|
const routePath = joinRoutePath(pathPrefix, pathSuffix);
|
|
@@ -9362,7 +9405,7 @@ function attributeValueOf(node, name) {
|
|
|
9362
9405
|
}
|
|
9363
9406
|
return null;
|
|
9364
9407
|
}
|
|
9365
|
-
function
|
|
9408
|
+
function literalStringOf2(value) {
|
|
9366
9409
|
const unwrapped2 = Node41.isJsxExpression(value) ? value.getExpression() ?? value : value;
|
|
9367
9410
|
if (Node41.isStringLiteral(unwrapped2) || Node41.isNoSubstitutionTemplateLiteral(unwrapped2)) {
|
|
9368
9411
|
return unwrapped2.getLiteralValue();
|
|
@@ -9372,7 +9415,7 @@ function literalStringOf(value) {
|
|
|
9372
9415
|
function ownPathOfJsx(node, match) {
|
|
9373
9416
|
const pathValue = attributeValueOf(node, match.pathAttribute);
|
|
9374
9417
|
if (pathValue !== null) {
|
|
9375
|
-
const literal =
|
|
9418
|
+
const literal = literalStringOf2(pathValue);
|
|
9376
9419
|
return literal !== null ? { kind: "literal", value: literal } : { kind: "unreadable" };
|
|
9377
9420
|
}
|
|
9378
9421
|
if (match.indexAttribute !== void 0 && attributeValueOf(node, match.indexAttribute) !== null) {
|
|
@@ -9463,14 +9506,14 @@ function unitForJsxRoute(node, match, routeNames, kind, resolution) {
|
|
|
9463
9506
|
}
|
|
9464
9507
|
return routeUnit(node, kind, match.method, resolved.path, target, resolution);
|
|
9465
9508
|
}
|
|
9466
|
-
function routeUnit(at, kind, method,
|
|
9467
|
-
const routeInfo = { method, path:
|
|
9509
|
+
function routeUnit(at, kind, method, path13, target, resolution) {
|
|
9510
|
+
const routeInfo = { method, path: path13 };
|
|
9468
9511
|
if (target.kind === "unreadable") {
|
|
9469
9512
|
return {
|
|
9470
9513
|
func: null,
|
|
9471
9514
|
announcedAt: at,
|
|
9472
9515
|
kind,
|
|
9473
|
-
name:
|
|
9516
|
+
name: path13,
|
|
9474
9517
|
nameKind: "label",
|
|
9475
9518
|
routeInfo
|
|
9476
9519
|
};
|
|
@@ -9640,7 +9683,7 @@ function unitsUnderRouteObject(object, match, kind, resolution, prefix, ancestry
|
|
|
9640
9683
|
function ownPathOfObject(object, match) {
|
|
9641
9684
|
const pathValue = routePropertyOf(object, match.pathAttribute);
|
|
9642
9685
|
if (pathValue !== null) {
|
|
9643
|
-
const literal =
|
|
9686
|
+
const literal = literalStringOf2(pathValue);
|
|
9644
9687
|
return literal !== null ? { kind: "literal", value: literal } : { kind: "unreadable" };
|
|
9645
9688
|
}
|
|
9646
9689
|
if (match.indexAttribute !== void 0) {
|
|
@@ -9900,6 +9943,9 @@ function resolvePackageExportsCached(packageJsonPath) {
|
|
|
9900
9943
|
return fresh;
|
|
9901
9944
|
}
|
|
9902
9945
|
function discoverPackageExports(sourceFile, match, kind) {
|
|
9946
|
+
if (match.packageJsonPath === void 0) {
|
|
9947
|
+
return [];
|
|
9948
|
+
}
|
|
9903
9949
|
const { entries } = resolvePackageExportsCached(match.packageJsonPath);
|
|
9904
9950
|
const filePath = sourceFile.getFilePath();
|
|
9905
9951
|
const matching = [];
|
|
@@ -10287,12 +10333,12 @@ function originEndOf(flattened) {
|
|
|
10287
10333
|
const slash = flattened.indexOf("/", opener[0].length);
|
|
10288
10334
|
return slash === -1 ? flattened.length : slash;
|
|
10289
10335
|
}
|
|
10290
|
-
function appendPathText(
|
|
10336
|
+
function appendPathText(path13, text) {
|
|
10291
10337
|
const idx = text.search(/[?#]/);
|
|
10292
10338
|
if (idx === -1) {
|
|
10293
|
-
return { path:
|
|
10339
|
+
return { path: path13 + text, stop: false };
|
|
10294
10340
|
}
|
|
10295
|
-
return { path:
|
|
10341
|
+
return { path: path13 + text.slice(0, idx), stop: true };
|
|
10296
10342
|
}
|
|
10297
10343
|
function parseAbsoluteUrl(text) {
|
|
10298
10344
|
try {
|
|
@@ -10316,8 +10362,8 @@ function pathnameOfAbsoluteLiteral(text) {
|
|
|
10316
10362
|
return stripQueryAndFragment(stripOriginManually(text));
|
|
10317
10363
|
}
|
|
10318
10364
|
function pathFromLiteralUrl(text) {
|
|
10319
|
-
const
|
|
10320
|
-
return
|
|
10365
|
+
const path13 = isAbsoluteUrlLiteral(text) ? pathnameOfAbsoluteLiteral(text) : stripQueryAndFragment(text);
|
|
10366
|
+
return path13 === "" ? void 0 : path13;
|
|
10321
10367
|
}
|
|
10322
10368
|
function pathFromTemplateUrl(arg, resolution) {
|
|
10323
10369
|
const headText = arg.getHead().getLiteralText();
|
|
@@ -10325,7 +10371,7 @@ function pathFromTemplateUrl(arg, resolution) {
|
|
|
10325
10371
|
const tails = spans.map((span) => span.getLiteral().getLiteralText());
|
|
10326
10372
|
const originEnd = originEndOf([headText, ...tails].join(SUBSTITUTION));
|
|
10327
10373
|
const head = appendPathText("", headText.slice(originEnd));
|
|
10328
|
-
let
|
|
10374
|
+
let path13 = head.path;
|
|
10329
10375
|
let stop = head.stop;
|
|
10330
10376
|
let at = headText.length;
|
|
10331
10377
|
for (let i = 0; i < spans.length && !stop; i++) {
|
|
@@ -10335,18 +10381,18 @@ function pathFromTemplateUrl(arg, resolution) {
|
|
|
10335
10381
|
continue;
|
|
10336
10382
|
}
|
|
10337
10383
|
if (at >= originEnd) {
|
|
10338
|
-
|
|
10384
|
+
path13 += holeText(span.getExpression(), resolution);
|
|
10339
10385
|
}
|
|
10340
10386
|
at += SUBSTITUTION.length;
|
|
10341
10387
|
const appended = appendPathText(
|
|
10342
|
-
|
|
10388
|
+
path13,
|
|
10343
10389
|
tailText.slice(Math.max(0, originEnd - at))
|
|
10344
10390
|
);
|
|
10345
|
-
|
|
10391
|
+
path13 = appended.path;
|
|
10346
10392
|
stop = appended.stop;
|
|
10347
10393
|
at += tailText.length;
|
|
10348
10394
|
}
|
|
10349
|
-
return
|
|
10395
|
+
return path13 === "" ? void 0 : path13;
|
|
10350
10396
|
}
|
|
10351
10397
|
function pathFromUrlNode(node, resolution) {
|
|
10352
10398
|
if (Node46.isStringLiteral(node)) {
|
|
@@ -10513,9 +10559,9 @@ function withMountPrefix(routeInfo, subjectNode, mountPrefixes) {
|
|
|
10513
10559
|
const prefix = mountPrefixes.effectivePrefixFor(subjectNode);
|
|
10514
10560
|
return prefix === "" ? routeInfo : { ...routeInfo, path: joinMountedPath(prefix, routeInfo.path) };
|
|
10515
10561
|
}
|
|
10516
|
-
function joinMountedPath(prefix,
|
|
10562
|
+
function joinMountedPath(prefix, path13) {
|
|
10517
10563
|
const trimmed = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
|
|
10518
|
-
return trimmed === "" ?
|
|
10564
|
+
return trimmed === "" ? path13 : trimmed + path13;
|
|
10519
10565
|
}
|
|
10520
10566
|
function registrationSubjectsOf(sourceFile, importModule, importName) {
|
|
10521
10567
|
let importedLocalName = null;
|
|
@@ -10679,11 +10725,11 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
10679
10725
|
return null;
|
|
10680
10726
|
}
|
|
10681
10727
|
const method2 = stringProperty(routeObject, binding.method.property);
|
|
10682
|
-
const
|
|
10683
|
-
if (method2 === null ||
|
|
10728
|
+
const path14 = stringProperty(routeObject, binding.path.property);
|
|
10729
|
+
if (method2 === null || path14 === null) {
|
|
10684
10730
|
return null;
|
|
10685
10731
|
}
|
|
10686
|
-
return { method: method2.toUpperCase(), path:
|
|
10732
|
+
return { method: method2.toUpperCase(), path: path14 };
|
|
10687
10733
|
}
|
|
10688
10734
|
if (binding.method.type !== "fromRegistration" || binding.path.type !== "fromArgument") {
|
|
10689
10735
|
return null;
|
|
@@ -10700,8 +10746,8 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
10700
10746
|
method = arg.getLiteralValue().toUpperCase();
|
|
10701
10747
|
}
|
|
10702
10748
|
const pathArg = call.getArguments()[binding.path.position];
|
|
10703
|
-
const
|
|
10704
|
-
return
|
|
10749
|
+
const path13 = pathArg === void 0 ? void 0 : pathFromArgument(pathArg, resolution);
|
|
10750
|
+
return path13 === void 0 ? null : { method, path: path13 };
|
|
10705
10751
|
}
|
|
10706
10752
|
|
|
10707
10753
|
// src/discovery/registrationLoop.ts
|
|
@@ -10824,7 +10870,7 @@ function bodyCallsOn(loop, routables) {
|
|
|
10824
10870
|
}
|
|
10825
10871
|
function readRouteSpec(element, shape, resolution) {
|
|
10826
10872
|
let method = null;
|
|
10827
|
-
let
|
|
10873
|
+
let path13 = null;
|
|
10828
10874
|
let handler = null;
|
|
10829
10875
|
for (const prop of element.getProperties()) {
|
|
10830
10876
|
if (Node48.isMethodDeclaration(prop) && prop.getName() === shape.handlerKey) {
|
|
@@ -10842,16 +10888,16 @@ function readRouteSpec(element, shape, resolution) {
|
|
|
10842
10888
|
if (name === shape.methodKey) {
|
|
10843
10889
|
method = readStringLiteralValue(init);
|
|
10844
10890
|
} else if (name === shape.pathKey) {
|
|
10845
|
-
|
|
10891
|
+
path13 = readStringLiteralValue(init);
|
|
10846
10892
|
} else if (name === shape.handlerKey) {
|
|
10847
10893
|
const func = functionValueOf(init, resolution);
|
|
10848
10894
|
handler = func === null ? null : { func, name: handlerName(init) };
|
|
10849
10895
|
}
|
|
10850
10896
|
}
|
|
10851
|
-
if (method === null ||
|
|
10897
|
+
if (method === null || path13 === null || handler === null) {
|
|
10852
10898
|
return null;
|
|
10853
10899
|
}
|
|
10854
|
-
return { method, path:
|
|
10900
|
+
return { method, path: path13, handler: handler.func, handlerName: handler.name };
|
|
10855
10901
|
}
|
|
10856
10902
|
function readStringLiteralValue(node) {
|
|
10857
10903
|
if (Node48.isStringLiteral(node) || Node48.isNoSubstitutionTemplateLiteral(node)) {
|
|
@@ -10880,8 +10926,8 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution) {
|
|
|
10880
10926
|
}
|
|
10881
10927
|
const args = node.getArguments();
|
|
10882
10928
|
for (const reg of match.registrations) {
|
|
10883
|
-
const
|
|
10884
|
-
if (
|
|
10929
|
+
const path13 = substitutePath(reg.pathTemplate, args);
|
|
10930
|
+
if (path13 === null) {
|
|
10885
10931
|
continue;
|
|
10886
10932
|
}
|
|
10887
10933
|
const handler = resolveHandler(reg.handlerArg, args, resolution);
|
|
@@ -10894,7 +10940,7 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution) {
|
|
|
10894
10940
|
name: handler.name,
|
|
10895
10941
|
routeInfo: {
|
|
10896
10942
|
method: reg.method.toUpperCase(),
|
|
10897
|
-
path:
|
|
10943
|
+
path: path13
|
|
10898
10944
|
}
|
|
10899
10945
|
});
|
|
10900
10946
|
}
|
|
@@ -11220,7 +11266,8 @@ function runPattern(sourceFile, pattern, resolution, mountPrefixes) {
|
|
|
11220
11266
|
sourceFile,
|
|
11221
11267
|
pattern.match,
|
|
11222
11268
|
pattern.kind,
|
|
11223
|
-
resolution
|
|
11269
|
+
resolution,
|
|
11270
|
+
pattern.binding
|
|
11224
11271
|
);
|
|
11225
11272
|
}
|
|
11226
11273
|
if (pattern.match.type === "jsxElementRoute") {
|
|
@@ -12443,19 +12490,35 @@ function resolveCallee(call, calleeName, scan) {
|
|
|
12443
12490
|
}
|
|
12444
12491
|
};
|
|
12445
12492
|
}
|
|
12493
|
+
function resolveJsxReference(node) {
|
|
12494
|
+
if (!Node54.isJsxOpeningElement(node) && !Node54.isJsxSelfClosingElement(node)) {
|
|
12495
|
+
return null;
|
|
12496
|
+
}
|
|
12497
|
+
const tag = node.getTagNameNode();
|
|
12498
|
+
if (!Node54.isIdentifier(tag) || !/^[A-Z]/.test(tag.getText())) {
|
|
12499
|
+
return null;
|
|
12500
|
+
}
|
|
12501
|
+
const name = tag.getText();
|
|
12502
|
+
const declarations = declarationsBehind(tag.getSymbol());
|
|
12503
|
+
for (const decl of declarations) {
|
|
12504
|
+
const resolved = resolveDecl(decl, name);
|
|
12505
|
+
if (resolved !== null) {
|
|
12506
|
+
return { tag: name, outcome: { kind: "followed", candidate: resolved } };
|
|
12507
|
+
}
|
|
12508
|
+
}
|
|
12509
|
+
return {
|
|
12510
|
+
tag: name,
|
|
12511
|
+
outcome: {
|
|
12512
|
+
kind: "stopped",
|
|
12513
|
+
stop: { callee: name, reason: classifyStop(declarations) }
|
|
12514
|
+
}
|
|
12515
|
+
};
|
|
12516
|
+
}
|
|
12446
12517
|
function collectReachable(func, scan) {
|
|
12447
12518
|
const candidates = [];
|
|
12448
12519
|
const stops = [];
|
|
12449
12520
|
const seen = /* @__PURE__ */ new Set();
|
|
12450
|
-
|
|
12451
|
-
if (!Node54.isCallExpression(node)) {
|
|
12452
|
-
return;
|
|
12453
|
-
}
|
|
12454
|
-
const calleeText = normalizeCallee(node.getExpression().getText());
|
|
12455
|
-
const outcome = resolveCallee(node, calleeText, scan);
|
|
12456
|
-
if (outcome === null) {
|
|
12457
|
-
return;
|
|
12458
|
-
}
|
|
12521
|
+
const record = (outcome) => {
|
|
12459
12522
|
if (outcome.kind === "stopped") {
|
|
12460
12523
|
const stopKey = `${outcome.stop.reason}:${outcome.stop.callee}`;
|
|
12461
12524
|
if (!seen.has(stopKey) && worthRecording(outcome.stop.reason)) {
|
|
@@ -12470,6 +12533,22 @@ function collectReachable(func, scan) {
|
|
|
12470
12533
|
}
|
|
12471
12534
|
seen.add(key);
|
|
12472
12535
|
candidates.push(outcome.candidate);
|
|
12536
|
+
};
|
|
12537
|
+
func.forEachDescendant((node) => {
|
|
12538
|
+
const jsx = resolveJsxReference(node);
|
|
12539
|
+
if (jsx !== null) {
|
|
12540
|
+
record(jsx.outcome);
|
|
12541
|
+
return;
|
|
12542
|
+
}
|
|
12543
|
+
if (!Node54.isCallExpression(node)) {
|
|
12544
|
+
return;
|
|
12545
|
+
}
|
|
12546
|
+
const calleeText = normalizeCallee(node.getExpression().getText());
|
|
12547
|
+
const outcome = resolveCallee(node, calleeText, scan);
|
|
12548
|
+
if (outcome === null) {
|
|
12549
|
+
return;
|
|
12550
|
+
}
|
|
12551
|
+
record(outcome);
|
|
12473
12552
|
});
|
|
12474
12553
|
return { candidates, stops };
|
|
12475
12554
|
}
|
|
@@ -12508,7 +12587,38 @@ var REACHABLE_RULES = [
|
|
|
12508
12587
|
)
|
|
12509
12588
|
];
|
|
12510
12589
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
12511
|
-
function
|
|
12590
|
+
function recognizerOnlyRoots(packsByFile) {
|
|
12591
|
+
const roots = [];
|
|
12592
|
+
for (const [sourceFile, packs] of packsByFile) {
|
|
12593
|
+
const recognizerOnly = packs.some(
|
|
12594
|
+
(pack) => pack.discovery.length === 0 && pack.discoverUnits === void 0 && ((pack.invocationRecognizers?.length ?? 0) > 0 || (pack.accessRecognizers?.length ?? 0) > 0)
|
|
12595
|
+
);
|
|
12596
|
+
if (!recognizerOnly) {
|
|
12597
|
+
continue;
|
|
12598
|
+
}
|
|
12599
|
+
for (const declaration of sourceFile.getFunctions()) {
|
|
12600
|
+
if (declaration.isExported() && hasBody(declaration)) {
|
|
12601
|
+
roots.push({
|
|
12602
|
+
func: declaration,
|
|
12603
|
+
name: declaration.getName() ?? "<anon>"
|
|
12604
|
+
});
|
|
12605
|
+
}
|
|
12606
|
+
}
|
|
12607
|
+
for (const variableStatement of sourceFile.getVariableStatements()) {
|
|
12608
|
+
if (!variableStatement.isExported()) {
|
|
12609
|
+
continue;
|
|
12610
|
+
}
|
|
12611
|
+
for (const declaration of variableStatement.getDeclarations()) {
|
|
12612
|
+
const init = declaration.getInitializer();
|
|
12613
|
+
if (init !== void 0 && (Node54.isArrowFunction(init) || Node54.isFunctionExpression(init)) && hasBody(init)) {
|
|
12614
|
+
roots.push({ func: init, name: declaration.getName() });
|
|
12615
|
+
}
|
|
12616
|
+
}
|
|
12617
|
+
}
|
|
12618
|
+
}
|
|
12619
|
+
return roots;
|
|
12620
|
+
}
|
|
12621
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = [], extraRoots = []) {
|
|
12512
12622
|
const lookup = createSourceFileLookup(project);
|
|
12513
12623
|
const db = facts?.db ?? new Database3();
|
|
12514
12624
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
@@ -12528,6 +12638,13 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
12528
12638
|
db.add("entry", [key]);
|
|
12529
12639
|
}
|
|
12530
12640
|
}
|
|
12641
|
+
for (const root of extraRoots) {
|
|
12642
|
+
const key = nodeKey2(root.func);
|
|
12643
|
+
if (!functionByKey.has(key)) {
|
|
12644
|
+
functionByKey.set(key, root);
|
|
12645
|
+
}
|
|
12646
|
+
db.add("entry", [key]);
|
|
12647
|
+
}
|
|
12531
12648
|
const knownKeys = /* @__PURE__ */ new Set();
|
|
12532
12649
|
for (const summary of alreadySummarized) {
|
|
12533
12650
|
const func = lookup.functionAt(summary.location);
|
|
@@ -13595,6 +13712,185 @@ function computeAdapterPacksDigest(packVersions) {
|
|
|
13595
13712
|
return `${adapterStamp}|${sortedPacks.join(",")}`;
|
|
13596
13713
|
}
|
|
13597
13714
|
|
|
13715
|
+
// src/workspacePatterns.ts
|
|
13716
|
+
import { createHash as createHash4 } from "crypto";
|
|
13717
|
+
import fs8 from "fs";
|
|
13718
|
+
import path9 from "path";
|
|
13719
|
+
function readJson(filePath) {
|
|
13720
|
+
try {
|
|
13721
|
+
return JSON.parse(fs8.readFileSync(filePath, "utf8"));
|
|
13722
|
+
} catch {
|
|
13723
|
+
return void 0;
|
|
13724
|
+
}
|
|
13725
|
+
}
|
|
13726
|
+
function pnpmWorkspaceGlobs(yamlText) {
|
|
13727
|
+
const globs = [];
|
|
13728
|
+
let inPackages = false;
|
|
13729
|
+
for (const line of yamlText.split("\n")) {
|
|
13730
|
+
if (/^packages\s*:/.test(line)) {
|
|
13731
|
+
inPackages = true;
|
|
13732
|
+
continue;
|
|
13733
|
+
}
|
|
13734
|
+
if (inPackages) {
|
|
13735
|
+
const item = line.match(/^\s+-\s+["']?([^"'#\s]+)["']?/);
|
|
13736
|
+
if (item !== null) {
|
|
13737
|
+
globs.push(item[1]);
|
|
13738
|
+
continue;
|
|
13739
|
+
}
|
|
13740
|
+
if (/^\S/.test(line)) {
|
|
13741
|
+
inPackages = false;
|
|
13742
|
+
}
|
|
13743
|
+
}
|
|
13744
|
+
}
|
|
13745
|
+
return globs;
|
|
13746
|
+
}
|
|
13747
|
+
function workspaceGlobsAt(dir) {
|
|
13748
|
+
const pkg = readJson(path9.join(dir, "package.json"));
|
|
13749
|
+
if (typeof pkg === "object" && pkg !== null && "workspaces" in pkg) {
|
|
13750
|
+
const ws = pkg.workspaces;
|
|
13751
|
+
if (Array.isArray(ws)) {
|
|
13752
|
+
return ws.filter((g) => typeof g === "string");
|
|
13753
|
+
}
|
|
13754
|
+
if (typeof ws === "object" && ws !== null && Array.isArray(ws.packages)) {
|
|
13755
|
+
return ws.packages.filter(
|
|
13756
|
+
(g) => typeof g === "string"
|
|
13757
|
+
);
|
|
13758
|
+
}
|
|
13759
|
+
}
|
|
13760
|
+
const pnpmPath = path9.join(dir, "pnpm-workspace.yaml");
|
|
13761
|
+
if (fs8.existsSync(pnpmPath)) {
|
|
13762
|
+
try {
|
|
13763
|
+
return pnpmWorkspaceGlobs(fs8.readFileSync(pnpmPath, "utf8"));
|
|
13764
|
+
} catch {
|
|
13765
|
+
return null;
|
|
13766
|
+
}
|
|
13767
|
+
}
|
|
13768
|
+
return null;
|
|
13769
|
+
}
|
|
13770
|
+
function isDirectory(candidate) {
|
|
13771
|
+
try {
|
|
13772
|
+
return fs8.statSync(candidate).isDirectory();
|
|
13773
|
+
} catch {
|
|
13774
|
+
return false;
|
|
13775
|
+
}
|
|
13776
|
+
}
|
|
13777
|
+
function subdirectoriesOf(dir) {
|
|
13778
|
+
try {
|
|
13779
|
+
return fs8.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
13780
|
+
} catch {
|
|
13781
|
+
return [];
|
|
13782
|
+
}
|
|
13783
|
+
}
|
|
13784
|
+
function segmentToRegExp(segment) {
|
|
13785
|
+
const escaped = segment.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13786
|
+
return new RegExp(`^${escaped.replace(/\*/g, "[^/]*")}$`);
|
|
13787
|
+
}
|
|
13788
|
+
function directoriesMatchingGlob(root, glob) {
|
|
13789
|
+
let current2 = [root];
|
|
13790
|
+
for (const segment of glob.split("/").filter((s) => s.length > 0)) {
|
|
13791
|
+
const next = [];
|
|
13792
|
+
if (segment.includes("*")) {
|
|
13793
|
+
const pattern = segmentToRegExp(segment);
|
|
13794
|
+
for (const dir of current2) {
|
|
13795
|
+
for (const entry of subdirectoriesOf(dir)) {
|
|
13796
|
+
if (pattern.test(entry)) {
|
|
13797
|
+
next.push(path9.join(dir, entry));
|
|
13798
|
+
}
|
|
13799
|
+
}
|
|
13800
|
+
}
|
|
13801
|
+
} else {
|
|
13802
|
+
for (const dir of current2) {
|
|
13803
|
+
next.push(path9.join(dir, segment));
|
|
13804
|
+
}
|
|
13805
|
+
}
|
|
13806
|
+
current2 = next.filter(isDirectory);
|
|
13807
|
+
}
|
|
13808
|
+
return current2;
|
|
13809
|
+
}
|
|
13810
|
+
function packageAt(dir) {
|
|
13811
|
+
const packageJsonPath = path9.join(dir, "package.json");
|
|
13812
|
+
const pkg = readJson(packageJsonPath);
|
|
13813
|
+
if (typeof pkg === "object" && pkg !== null && typeof pkg.name === "string") {
|
|
13814
|
+
return { name: pkg.name, packageJsonPath };
|
|
13815
|
+
}
|
|
13816
|
+
return null;
|
|
13817
|
+
}
|
|
13818
|
+
function workspacePackagesFrom(anchor) {
|
|
13819
|
+
let dir = path9.resolve(anchor);
|
|
13820
|
+
for (; ; ) {
|
|
13821
|
+
const globs = workspaceGlobsAt(dir);
|
|
13822
|
+
if (globs !== null) {
|
|
13823
|
+
const found = /* @__PURE__ */ new Map();
|
|
13824
|
+
for (const glob of globs) {
|
|
13825
|
+
if (glob.startsWith("!")) {
|
|
13826
|
+
continue;
|
|
13827
|
+
}
|
|
13828
|
+
for (const match of directoriesMatchingGlob(dir, glob)) {
|
|
13829
|
+
const pkg = packageAt(match);
|
|
13830
|
+
if (pkg !== null) {
|
|
13831
|
+
found.set(pkg.packageJsonPath, pkg);
|
|
13832
|
+
}
|
|
13833
|
+
}
|
|
13834
|
+
}
|
|
13835
|
+
return [...found.values()].sort(
|
|
13836
|
+
(a, b) => a.packageJsonPath.localeCompare(b.packageJsonPath)
|
|
13837
|
+
);
|
|
13838
|
+
}
|
|
13839
|
+
const parent = path9.dirname(dir);
|
|
13840
|
+
if (parent === dir) {
|
|
13841
|
+
return [];
|
|
13842
|
+
}
|
|
13843
|
+
dir = parent;
|
|
13844
|
+
}
|
|
13845
|
+
}
|
|
13846
|
+
function isWorkspaceMarked(pattern) {
|
|
13847
|
+
const match = pattern.match;
|
|
13848
|
+
return (match.type === "packageExports" || match.type === "packageImport") && match.workspaces === true;
|
|
13849
|
+
}
|
|
13850
|
+
function expandPattern(pattern, packages) {
|
|
13851
|
+
const match = pattern.match;
|
|
13852
|
+
if (match.type === "packageExports" && match.workspaces === true) {
|
|
13853
|
+
const { workspaces: _workspaces, ...rest } = match;
|
|
13854
|
+
return packages.map((pkg) => ({
|
|
13855
|
+
...pattern,
|
|
13856
|
+
match: { ...rest, packageJsonPath: pkg.packageJsonPath }
|
|
13857
|
+
}));
|
|
13858
|
+
}
|
|
13859
|
+
if (match.type === "packageImport" && match.workspaces === true) {
|
|
13860
|
+
const listed = match.packages ?? [];
|
|
13861
|
+
const names = [.../* @__PURE__ */ new Set([...listed, ...packages.map((p) => p.name)])];
|
|
13862
|
+
if (names.length === 0) {
|
|
13863
|
+
return [];
|
|
13864
|
+
}
|
|
13865
|
+
return [{ ...pattern, match: { type: "packageImport", packages: names } }];
|
|
13866
|
+
}
|
|
13867
|
+
return [pattern];
|
|
13868
|
+
}
|
|
13869
|
+
function workspaceExpansionStamp(frameworks) {
|
|
13870
|
+
const paths = frameworks.flatMap((pack) => pack.discovery).flatMap(
|
|
13871
|
+
(pattern) => pattern.match.type === "packageExports" && pattern.match.packageJsonPath !== void 0 ? [pattern.match.packageJsonPath] : []
|
|
13872
|
+
).sort();
|
|
13873
|
+
if (paths.length === 0) {
|
|
13874
|
+
return "none";
|
|
13875
|
+
}
|
|
13876
|
+
return createHash4("sha256").update(paths.join("\n")).digest("hex").slice(0, 12);
|
|
13877
|
+
}
|
|
13878
|
+
function expandWorkspacePatterns(frameworks, anchor) {
|
|
13879
|
+
const marked = frameworks.some(
|
|
13880
|
+
(pack) => pack.discovery.some(isWorkspaceMarked)
|
|
13881
|
+
);
|
|
13882
|
+
if (!marked) {
|
|
13883
|
+
return frameworks;
|
|
13884
|
+
}
|
|
13885
|
+
const packages = anchor !== void 0 ? workspacePackagesFrom(anchor) : [];
|
|
13886
|
+
return frameworks.map((pack) => ({
|
|
13887
|
+
...pack,
|
|
13888
|
+
discovery: pack.discovery.flatMap(
|
|
13889
|
+
(pattern) => expandPattern(pattern, packages)
|
|
13890
|
+
)
|
|
13891
|
+
}));
|
|
13892
|
+
}
|
|
13893
|
+
|
|
13598
13894
|
// src/adapter.ts
|
|
13599
13895
|
var raise = (msg) => {
|
|
13600
13896
|
throw new Error(msg);
|
|
@@ -14005,11 +14301,11 @@ function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
|
14005
14301
|
return null;
|
|
14006
14302
|
}
|
|
14007
14303
|
const method = extractBindingMethod(binding, callSite, pack, resolution);
|
|
14008
|
-
const
|
|
14304
|
+
const path13 = extractBindingPath(binding, callSite, pack, resolution);
|
|
14009
14305
|
return restBinding2({
|
|
14010
14306
|
transport: pack.protocol,
|
|
14011
14307
|
method: method ?? null,
|
|
14012
|
-
path:
|
|
14308
|
+
path: path13 ?? null,
|
|
14013
14309
|
recognition: pack.name
|
|
14014
14310
|
});
|
|
14015
14311
|
}
|
|
@@ -14134,8 +14430,8 @@ function collectAccessRecognizers(frameworks, tallies) {
|
|
|
14134
14430
|
}
|
|
14135
14431
|
return out;
|
|
14136
14432
|
}
|
|
14137
|
-
function computeSubUnitBarriers(unit,
|
|
14138
|
-
if (
|
|
14433
|
+
function computeSubUnitBarriers(unit, packs, ctx, tallies, file) {
|
|
14434
|
+
if (unit.func === null) {
|
|
14139
14435
|
return NO_BARRIERS;
|
|
14140
14436
|
}
|
|
14141
14437
|
const parentHandle = {
|
|
@@ -14143,27 +14439,27 @@ function computeSubUnitBarriers(unit, pack, ctx, tally, file) {
|
|
|
14143
14439
|
name: unit.name,
|
|
14144
14440
|
kind: unit.kind
|
|
14145
14441
|
};
|
|
14146
|
-
|
|
14147
|
-
|
|
14148
|
-
if (subUnits
|
|
14149
|
-
|
|
14442
|
+
const barriers = /* @__PURE__ */ new Set();
|
|
14443
|
+
for (const pack of packs) {
|
|
14444
|
+
if (pack.subUnits === void 0) {
|
|
14445
|
+
continue;
|
|
14150
14446
|
}
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14447
|
+
try {
|
|
14448
|
+
for (const su of pack.subUnits(parentHandle, ctx)) {
|
|
14449
|
+
barriers.add(su.func);
|
|
14450
|
+
}
|
|
14451
|
+
} catch (err) {
|
|
14452
|
+
process.stderr.write(
|
|
14453
|
+
recordPackFailure(tallies?.get(pack.name), {
|
|
14454
|
+
pack: pack.name,
|
|
14455
|
+
hook: "subUnits",
|
|
14456
|
+
file,
|
|
14457
|
+
error: err
|
|
14458
|
+
})
|
|
14459
|
+
);
|
|
14154
14460
|
}
|
|
14155
|
-
return barriers;
|
|
14156
|
-
} catch (err) {
|
|
14157
|
-
process.stderr.write(
|
|
14158
|
-
recordPackFailure(tally, {
|
|
14159
|
-
pack: pack.name,
|
|
14160
|
-
hook: "subUnits",
|
|
14161
|
-
file,
|
|
14162
|
-
error: err
|
|
14163
|
-
})
|
|
14164
|
-
);
|
|
14165
|
-
return NO_BARRIERS;
|
|
14166
14461
|
}
|
|
14462
|
+
return barriers.size === 0 ? NO_BARRIERS : barriers;
|
|
14167
14463
|
}
|
|
14168
14464
|
function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, tallies, resolution, mountPrefixes) {
|
|
14169
14465
|
const summaries = [];
|
|
@@ -14245,9 +14541,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
14245
14541
|
}
|
|
14246
14542
|
const barriers = computeSubUnitBarriers(
|
|
14247
14543
|
unit,
|
|
14248
|
-
|
|
14544
|
+
frameworks,
|
|
14249
14545
|
subUnitCtx,
|
|
14250
|
-
|
|
14546
|
+
tallies,
|
|
14251
14547
|
sourceFile.getFilePath()
|
|
14252
14548
|
);
|
|
14253
14549
|
const raw = extractCodeStructure(
|
|
@@ -14621,8 +14917,8 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
14621
14917
|
if (pathArg === void 0) {
|
|
14622
14918
|
continue;
|
|
14623
14919
|
}
|
|
14624
|
-
const
|
|
14625
|
-
if (
|
|
14920
|
+
const path13 = pathFromArgument(pathArg, resolution);
|
|
14921
|
+
if (path13 === void 0) {
|
|
14626
14922
|
continue;
|
|
14627
14923
|
}
|
|
14628
14924
|
const callerFunc = enclosingFunction(callExpr);
|
|
@@ -14634,7 +14930,7 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
14634
14930
|
continue;
|
|
14635
14931
|
}
|
|
14636
14932
|
seen.add(dedupKey);
|
|
14637
|
-
out.push(buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
14933
|
+
out.push(buildCallerSummary(wrapper, callerFunc, callExpr, path13, options));
|
|
14638
14934
|
}
|
|
14639
14935
|
return out;
|
|
14640
14936
|
}
|
|
@@ -14691,7 +14987,7 @@ function callerName(func) {
|
|
|
14691
14987
|
}
|
|
14692
14988
|
return "anonymous";
|
|
14693
14989
|
}
|
|
14694
|
-
function buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
14990
|
+
function buildCallerSummary(wrapper, callerFunc, callExpr, path13, options) {
|
|
14695
14991
|
const wrapperBinding = wrapper.summary.identity.boundaryBinding;
|
|
14696
14992
|
const wrapperRest = wrapperBinding?.semantics.name === "rest" ? wrapperBinding.semantics : null;
|
|
14697
14993
|
const syntheticPack = {
|
|
@@ -14723,7 +15019,7 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path12, options) {
|
|
|
14723
15019
|
raw.boundaryBinding = restBinding2({
|
|
14724
15020
|
transport: wrapperBinding?.transport ?? "http",
|
|
14725
15021
|
method: wrapperRest?.method ?? null,
|
|
14726
|
-
path:
|
|
15022
|
+
path: path13,
|
|
14727
15023
|
recognition: wrapperBinding?.recognition ?? "unknown"
|
|
14728
15024
|
});
|
|
14729
15025
|
const summary = assembleSummary3(raw, options);
|
|
@@ -14789,25 +15085,32 @@ function loadRunFiles(project, candidatePaths, timer) {
|
|
|
14789
15085
|
);
|
|
14790
15086
|
return { sourceFiles, deep };
|
|
14791
15087
|
}
|
|
14792
|
-
function createTypeScriptAdapter(
|
|
15088
|
+
function createTypeScriptAdapter(suppliedConfig) {
|
|
15089
|
+
const config = {
|
|
15090
|
+
...suppliedConfig,
|
|
15091
|
+
frameworks: expandWorkspacePatterns(
|
|
15092
|
+
suppliedConfig.frameworks,
|
|
15093
|
+
suppliedConfig.projectRoot ?? (suppliedConfig.tsConfigFilePath !== void 0 ? path10.dirname(suppliedConfig.tsConfigFilePath) : void 0)
|
|
15094
|
+
)
|
|
15095
|
+
};
|
|
14793
15096
|
const project = config.project ?? new Project(
|
|
14794
15097
|
config.tsConfigFilePath !== void 0 ? {
|
|
14795
15098
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
14796
15099
|
skipAddingFilesFromTsConfig: true
|
|
14797
15100
|
} : { skipAddingFilesFromTsConfig: true }
|
|
14798
15101
|
);
|
|
14799
|
-
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(
|
|
15102
|
+
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(path10.dirname(config.tsConfigFilePath)) : void 0);
|
|
14800
15103
|
let lazyBootstrapped = false;
|
|
14801
15104
|
let projectFileSet;
|
|
14802
15105
|
const cacheDir = declineWhenRunFromSource(
|
|
14803
|
-
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ?
|
|
15106
|
+
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ? path10.join(path10.dirname(config.tsConfigFilePath), ".suss", "cache") : null)
|
|
14804
15107
|
);
|
|
14805
15108
|
const cache = createCacheLayer(cacheDir);
|
|
14806
15109
|
const adapterPacksDigest = `${computeAdapterPacksDigest(
|
|
14807
15110
|
config.frameworks.map(
|
|
14808
15111
|
(p) => p.version !== void 0 ? { name: p.name, version: p.version } : { name: p.name }
|
|
14809
15112
|
)
|
|
14810
|
-
)}|${extractionConfigStamp(config)}`;
|
|
15113
|
+
)}|${extractionConfigStamp(config)}|ws:${workspaceExpansionStamp(config.frameworks)}`;
|
|
14811
15114
|
const packWrappers = config.frameworks.flatMap(
|
|
14812
15115
|
(pack) => pack.transparentWrappers ?? []
|
|
14813
15116
|
);
|
|
@@ -15009,6 +15312,7 @@ function createTypeScriptAdapter(config) {
|
|
|
15009
15312
|
pipeline,
|
|
15010
15313
|
project,
|
|
15011
15314
|
config.frameworks,
|
|
15315
|
+
packsByFile,
|
|
15012
15316
|
config.extractorOptions,
|
|
15013
15317
|
tallies,
|
|
15014
15318
|
(created, parent) => {
|
|
@@ -15043,7 +15347,12 @@ function createTypeScriptAdapter(config) {
|
|
|
15043
15347
|
},
|
|
15044
15348
|
// Reached units the cache already serves emit nothing,
|
|
15045
15349
|
// the way a cold run's seeds do not.
|
|
15046
|
-
reused?.summaries ?? []
|
|
15350
|
+
reused?.summaries ?? [],
|
|
15351
|
+
// A recognizer-only pack's effects need a function to
|
|
15352
|
+
// live on even when nothing discovers units in its
|
|
15353
|
+
// files, so those files' exports join the walk as
|
|
15354
|
+
// roots.
|
|
15355
|
+
recognizerOnlyRoots(packsByFile)
|
|
15047
15356
|
)
|
|
15048
15357
|
) : withSubUnits;
|
|
15049
15358
|
const closureOwnership = caching && config.includeReachable !== false ? timer.time(
|
|
@@ -15344,11 +15653,15 @@ function buildCacheAttribution(args) {
|
|
|
15344
15653
|
];
|
|
15345
15654
|
return { roots, owners };
|
|
15346
15655
|
}
|
|
15347
|
-
function synthesizeSubUnits(summaries, project, frameworks, options, tallies, onCreated) {
|
|
15656
|
+
function synthesizeSubUnits(summaries, project, frameworks, packsByFile, options, tallies, onCreated) {
|
|
15348
15657
|
const packByRecognition = /* @__PURE__ */ new Map();
|
|
15349
15658
|
for (const pack of frameworks) {
|
|
15350
15659
|
packByRecognition.set(pack.name, pack);
|
|
15351
15660
|
}
|
|
15661
|
+
const packsByPath = /* @__PURE__ */ new Map();
|
|
15662
|
+
for (const [sf, packs] of packsByFile) {
|
|
15663
|
+
packsByPath.set(sf.getFilePath(), packs);
|
|
15664
|
+
}
|
|
15352
15665
|
const allInvocationRecognizers = collectInvocationRecognizers(
|
|
15353
15666
|
frameworks,
|
|
15354
15667
|
tallies
|
|
@@ -15362,8 +15675,15 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies, on
|
|
|
15362
15675
|
if (binding === null) {
|
|
15363
15676
|
continue;
|
|
15364
15677
|
}
|
|
15365
|
-
const
|
|
15366
|
-
|
|
15678
|
+
const discovering = packByRecognition.get(binding.recognition);
|
|
15679
|
+
const applicable = packsByPath.get(parent.location.file) ?? (discovering !== void 0 ? [discovering] : []);
|
|
15680
|
+
const hooked = [
|
|
15681
|
+
...discovering?.subUnits !== void 0 ? [discovering] : [],
|
|
15682
|
+
...applicable.filter(
|
|
15683
|
+
(one) => one.subUnits !== void 0 && one !== discovering
|
|
15684
|
+
)
|
|
15685
|
+
];
|
|
15686
|
+
if (hooked.length === 0) {
|
|
15367
15687
|
continue;
|
|
15368
15688
|
}
|
|
15369
15689
|
lookup ??= createSourceFileLookup(project);
|
|
@@ -15376,7 +15696,17 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies, on
|
|
|
15376
15696
|
name: parent.identity.name,
|
|
15377
15697
|
kind: parent.kind
|
|
15378
15698
|
};
|
|
15379
|
-
const
|
|
15699
|
+
const claimedFuncs = /* @__PURE__ */ new Set();
|
|
15700
|
+
const subUnits = [];
|
|
15701
|
+
for (const pack of hooked) {
|
|
15702
|
+
for (const subUnit of pack.subUnits?.(parentHandle, subUnitCtx) ?? []) {
|
|
15703
|
+
if (claimedFuncs.has(subUnit.func)) {
|
|
15704
|
+
continue;
|
|
15705
|
+
}
|
|
15706
|
+
claimedFuncs.add(subUnit.func);
|
|
15707
|
+
subUnits.push(subUnit);
|
|
15708
|
+
}
|
|
15709
|
+
}
|
|
15380
15710
|
for (const subUnit of subUnits) {
|
|
15381
15711
|
const summary = buildSubUnitSummary(
|
|
15382
15712
|
subUnit,
|
|
@@ -15440,8 +15770,8 @@ function buildSubUnitSummary(subUnit, parent, invocationRecognizers, accessRecog
|
|
|
15440
15770
|
}
|
|
15441
15771
|
|
|
15442
15772
|
// src/bootstrap/noTsconfigProject.ts
|
|
15443
|
-
import
|
|
15444
|
-
import
|
|
15773
|
+
import fs9 from "fs";
|
|
15774
|
+
import path11 from "path";
|
|
15445
15775
|
import {
|
|
15446
15776
|
ModuleKind,
|
|
15447
15777
|
ModuleResolutionKind,
|
|
@@ -15477,7 +15807,7 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
15477
15807
|
const found = [];
|
|
15478
15808
|
let entries;
|
|
15479
15809
|
try {
|
|
15480
|
-
entries =
|
|
15810
|
+
entries = fs9.readdirSync(rootDir, { withFileTypes: true });
|
|
15481
15811
|
} catch {
|
|
15482
15812
|
return [];
|
|
15483
15813
|
}
|
|
@@ -15485,10 +15815,10 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
15485
15815
|
if (entry.name.startsWith(".") || SKIP_DIRECTORIES.has(entry.name)) {
|
|
15486
15816
|
continue;
|
|
15487
15817
|
}
|
|
15488
|
-
const full =
|
|
15818
|
+
const full = path11.join(rootDir, entry.name);
|
|
15489
15819
|
if (entry.isDirectory()) {
|
|
15490
15820
|
found.push(...findSourceFiles(full, depth + 1));
|
|
15491
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
15821
|
+
} else if (SOURCE_EXTENSIONS.has(path11.extname(entry.name)) && !entry.name.endsWith(".d.ts")) {
|
|
15492
15822
|
found.push(full);
|
|
15493
15823
|
}
|
|
15494
15824
|
}
|
|
@@ -15523,15 +15853,15 @@ function createProjectWithoutTsconfig(rootDir) {
|
|
|
15523
15853
|
return { project, files };
|
|
15524
15854
|
}
|
|
15525
15855
|
function findNearestTsconfig(startDir) {
|
|
15526
|
-
let dir =
|
|
15856
|
+
let dir = path11.resolve(startDir);
|
|
15527
15857
|
while (true) {
|
|
15528
15858
|
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
15529
|
-
const candidate =
|
|
15530
|
-
if (
|
|
15859
|
+
const candidate = path11.join(dir, name);
|
|
15860
|
+
if (fs9.existsSync(candidate)) {
|
|
15531
15861
|
return candidate;
|
|
15532
15862
|
}
|
|
15533
15863
|
}
|
|
15534
|
-
const parent =
|
|
15864
|
+
const parent = path11.dirname(dir);
|
|
15535
15865
|
if (parent === dir) {
|
|
15536
15866
|
return null;
|
|
15537
15867
|
}
|
|
@@ -15540,7 +15870,7 @@ function findNearestTsconfig(startDir) {
|
|
|
15540
15870
|
}
|
|
15541
15871
|
|
|
15542
15872
|
// src/facts/why.ts
|
|
15543
|
-
import
|
|
15873
|
+
import path12 from "path";
|
|
15544
15874
|
import { Node as Node59, Project as Project3, SyntaxKind as SyntaxKind13 } from "ts-morph";
|
|
15545
15875
|
import { explainResolutionProof, renderExplanation } from "@suss/resolution";
|
|
15546
15876
|
var JS_PHRASES = {
|
|
@@ -15553,7 +15883,7 @@ var WhySession = class {
|
|
|
15553
15883
|
store;
|
|
15554
15884
|
root;
|
|
15555
15885
|
constructor(options) {
|
|
15556
|
-
this.root =
|
|
15886
|
+
this.root = path12.resolve(options.dir);
|
|
15557
15887
|
const tsconfig = findNearestTsconfig(this.root);
|
|
15558
15888
|
this.project = tsconfig === null ? createProjectWithoutTsconfig(this.root).project : new Project3({ tsConfigFilePath: tsconfig });
|
|
15559
15889
|
this.store = new ResolutionStore();
|
|
@@ -15642,7 +15972,7 @@ var WhySession = class {
|
|
|
15642
15972
|
};
|
|
15643
15973
|
}
|
|
15644
15974
|
sourceFileAt(file) {
|
|
15645
|
-
const absolute =
|
|
15975
|
+
const absolute = path12.resolve(this.root, file);
|
|
15646
15976
|
const loaded = this.project.getSourceFile(absolute);
|
|
15647
15977
|
if (loaded !== void 0) {
|
|
15648
15978
|
return loaded;
|
|
@@ -15656,7 +15986,7 @@ var WhySession = class {
|
|
|
15656
15986
|
/** A module key: a file path said relative to the root, or a package name. */
|
|
15657
15987
|
displayPath(key) {
|
|
15658
15988
|
if (key.startsWith(this.root)) {
|
|
15659
|
-
return
|
|
15989
|
+
return path12.relative(this.root, key);
|
|
15660
15990
|
}
|
|
15661
15991
|
return key;
|
|
15662
15992
|
}
|
|
@@ -15727,6 +16057,17 @@ function funnelDrops(packs) {
|
|
|
15727
16057
|
}
|
|
15728
16058
|
return violations;
|
|
15729
16059
|
}
|
|
16060
|
+
function recognizersWithNoUnits(packs) {
|
|
16061
|
+
return packs.filter(
|
|
16062
|
+
(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
|
|
16063
|
+
// roots, so effects recognized there mean the run worked and
|
|
16064
|
+
// the missing framework pack costs attribution, not existence.
|
|
16065
|
+
funnel.effectsRecognized === 0
|
|
16066
|
+
).map((funnel) => ({
|
|
16067
|
+
label: funnel.pack,
|
|
16068
|
+
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.`
|
|
16069
|
+
}));
|
|
16070
|
+
}
|
|
15730
16071
|
function unversionedPacks(packs) {
|
|
15731
16072
|
return packs.filter((funnel) => funnel.version === null).map((funnel) => ({
|
|
15732
16073
|
label: funnel.pack,
|
|
@@ -15821,6 +16162,12 @@ function evaluatePackHealth(report) {
|
|
|
15821
16162
|
audience: "run",
|
|
15822
16163
|
violations: selfCollisions(report.packs)
|
|
15823
16164
|
},
|
|
16165
|
+
{
|
|
16166
|
+
name: "every recognizer had units to look inside",
|
|
16167
|
+
code: "no-units",
|
|
16168
|
+
audience: "run",
|
|
16169
|
+
violations: recognizersWithNoUnits(report.packs)
|
|
16170
|
+
},
|
|
15824
16171
|
{
|
|
15825
16172
|
name: "every pack declares a version",
|
|
15826
16173
|
code: "no-version",
|