@suss/adapter-typescript 0.15.0 → 0.16.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 +365 -72
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +365 -72
- 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") {
|
|
@@ -12502,7 +12549,38 @@ var REACHABLE_RULES = [
|
|
|
12502
12549
|
)
|
|
12503
12550
|
];
|
|
12504
12551
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
12505
|
-
function
|
|
12552
|
+
function recognizerOnlyRoots(packsByFile) {
|
|
12553
|
+
const roots = [];
|
|
12554
|
+
for (const [sourceFile, packs] of packsByFile) {
|
|
12555
|
+
const recognizerOnly = packs.some(
|
|
12556
|
+
(pack) => pack.discovery.length === 0 && pack.discoverUnits === void 0 && ((pack.invocationRecognizers?.length ?? 0) > 0 || (pack.accessRecognizers?.length ?? 0) > 0)
|
|
12557
|
+
);
|
|
12558
|
+
if (!recognizerOnly) {
|
|
12559
|
+
continue;
|
|
12560
|
+
}
|
|
12561
|
+
for (const declaration of sourceFile.getFunctions()) {
|
|
12562
|
+
if (declaration.isExported() && hasBody(declaration)) {
|
|
12563
|
+
roots.push({
|
|
12564
|
+
func: declaration,
|
|
12565
|
+
name: declaration.getName() ?? "<anon>"
|
|
12566
|
+
});
|
|
12567
|
+
}
|
|
12568
|
+
}
|
|
12569
|
+
for (const variableStatement of sourceFile.getVariableStatements()) {
|
|
12570
|
+
if (!variableStatement.isExported()) {
|
|
12571
|
+
continue;
|
|
12572
|
+
}
|
|
12573
|
+
for (const declaration of variableStatement.getDeclarations()) {
|
|
12574
|
+
const init = declaration.getInitializer();
|
|
12575
|
+
if (init !== void 0 && (import_ts_morph56.Node.isArrowFunction(init) || import_ts_morph56.Node.isFunctionExpression(init)) && hasBody(init)) {
|
|
12576
|
+
roots.push({ func: init, name: declaration.getName() });
|
|
12577
|
+
}
|
|
12578
|
+
}
|
|
12579
|
+
}
|
|
12580
|
+
}
|
|
12581
|
+
return roots;
|
|
12582
|
+
}
|
|
12583
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = [], extraRoots = []) {
|
|
12506
12584
|
const lookup = createSourceFileLookup(project);
|
|
12507
12585
|
const db = facts?.db ?? new import_datalog4.Database();
|
|
12508
12586
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
@@ -12522,6 +12600,13 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
12522
12600
|
db.add("entry", [key]);
|
|
12523
12601
|
}
|
|
12524
12602
|
}
|
|
12603
|
+
for (const root of extraRoots) {
|
|
12604
|
+
const key = nodeKey2(root.func);
|
|
12605
|
+
if (!functionByKey.has(key)) {
|
|
12606
|
+
functionByKey.set(key, root);
|
|
12607
|
+
}
|
|
12608
|
+
db.add("entry", [key]);
|
|
12609
|
+
}
|
|
12525
12610
|
const knownKeys = /* @__PURE__ */ new Set();
|
|
12526
12611
|
for (const summary of alreadySummarized) {
|
|
12527
12612
|
const func = lookup.functionAt(summary.location);
|
|
@@ -13583,6 +13668,185 @@ function computeAdapterPacksDigest(packVersions) {
|
|
|
13583
13668
|
return `${adapterStamp}|${sortedPacks.join(",")}`;
|
|
13584
13669
|
}
|
|
13585
13670
|
|
|
13671
|
+
// src/workspacePatterns.ts
|
|
13672
|
+
var import_node_crypto4 = require("crypto");
|
|
13673
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
13674
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
13675
|
+
function readJson(filePath) {
|
|
13676
|
+
try {
|
|
13677
|
+
return JSON.parse(import_node_fs6.default.readFileSync(filePath, "utf8"));
|
|
13678
|
+
} catch {
|
|
13679
|
+
return void 0;
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
function pnpmWorkspaceGlobs(yamlText) {
|
|
13683
|
+
const globs = [];
|
|
13684
|
+
let inPackages = false;
|
|
13685
|
+
for (const line of yamlText.split("\n")) {
|
|
13686
|
+
if (/^packages\s*:/.test(line)) {
|
|
13687
|
+
inPackages = true;
|
|
13688
|
+
continue;
|
|
13689
|
+
}
|
|
13690
|
+
if (inPackages) {
|
|
13691
|
+
const item = line.match(/^\s+-\s+["']?([^"'#\s]+)["']?/);
|
|
13692
|
+
if (item !== null) {
|
|
13693
|
+
globs.push(item[1]);
|
|
13694
|
+
continue;
|
|
13695
|
+
}
|
|
13696
|
+
if (/^\S/.test(line)) {
|
|
13697
|
+
inPackages = false;
|
|
13698
|
+
}
|
|
13699
|
+
}
|
|
13700
|
+
}
|
|
13701
|
+
return globs;
|
|
13702
|
+
}
|
|
13703
|
+
function workspaceGlobsAt(dir) {
|
|
13704
|
+
const pkg = readJson(import_node_path9.default.join(dir, "package.json"));
|
|
13705
|
+
if (typeof pkg === "object" && pkg !== null && "workspaces" in pkg) {
|
|
13706
|
+
const ws = pkg.workspaces;
|
|
13707
|
+
if (Array.isArray(ws)) {
|
|
13708
|
+
return ws.filter((g) => typeof g === "string");
|
|
13709
|
+
}
|
|
13710
|
+
if (typeof ws === "object" && ws !== null && Array.isArray(ws.packages)) {
|
|
13711
|
+
return ws.packages.filter(
|
|
13712
|
+
(g) => typeof g === "string"
|
|
13713
|
+
);
|
|
13714
|
+
}
|
|
13715
|
+
}
|
|
13716
|
+
const pnpmPath = import_node_path9.default.join(dir, "pnpm-workspace.yaml");
|
|
13717
|
+
if (import_node_fs6.default.existsSync(pnpmPath)) {
|
|
13718
|
+
try {
|
|
13719
|
+
return pnpmWorkspaceGlobs(import_node_fs6.default.readFileSync(pnpmPath, "utf8"));
|
|
13720
|
+
} catch {
|
|
13721
|
+
return null;
|
|
13722
|
+
}
|
|
13723
|
+
}
|
|
13724
|
+
return null;
|
|
13725
|
+
}
|
|
13726
|
+
function isDirectory(candidate) {
|
|
13727
|
+
try {
|
|
13728
|
+
return import_node_fs6.default.statSync(candidate).isDirectory();
|
|
13729
|
+
} catch {
|
|
13730
|
+
return false;
|
|
13731
|
+
}
|
|
13732
|
+
}
|
|
13733
|
+
function subdirectoriesOf(dir) {
|
|
13734
|
+
try {
|
|
13735
|
+
return import_node_fs6.default.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
13736
|
+
} catch {
|
|
13737
|
+
return [];
|
|
13738
|
+
}
|
|
13739
|
+
}
|
|
13740
|
+
function segmentToRegExp(segment) {
|
|
13741
|
+
const escaped = segment.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13742
|
+
return new RegExp(`^${escaped.replace(/\*/g, "[^/]*")}$`);
|
|
13743
|
+
}
|
|
13744
|
+
function directoriesMatchingGlob(root, glob) {
|
|
13745
|
+
let current2 = [root];
|
|
13746
|
+
for (const segment of glob.split("/").filter((s) => s.length > 0)) {
|
|
13747
|
+
const next = [];
|
|
13748
|
+
if (segment.includes("*")) {
|
|
13749
|
+
const pattern = segmentToRegExp(segment);
|
|
13750
|
+
for (const dir of current2) {
|
|
13751
|
+
for (const entry of subdirectoriesOf(dir)) {
|
|
13752
|
+
if (pattern.test(entry)) {
|
|
13753
|
+
next.push(import_node_path9.default.join(dir, entry));
|
|
13754
|
+
}
|
|
13755
|
+
}
|
|
13756
|
+
}
|
|
13757
|
+
} else {
|
|
13758
|
+
for (const dir of current2) {
|
|
13759
|
+
next.push(import_node_path9.default.join(dir, segment));
|
|
13760
|
+
}
|
|
13761
|
+
}
|
|
13762
|
+
current2 = next.filter(isDirectory);
|
|
13763
|
+
}
|
|
13764
|
+
return current2;
|
|
13765
|
+
}
|
|
13766
|
+
function packageAt(dir) {
|
|
13767
|
+
const packageJsonPath = import_node_path9.default.join(dir, "package.json");
|
|
13768
|
+
const pkg = readJson(packageJsonPath);
|
|
13769
|
+
if (typeof pkg === "object" && pkg !== null && typeof pkg.name === "string") {
|
|
13770
|
+
return { name: pkg.name, packageJsonPath };
|
|
13771
|
+
}
|
|
13772
|
+
return null;
|
|
13773
|
+
}
|
|
13774
|
+
function workspacePackagesFrom(anchor) {
|
|
13775
|
+
let dir = import_node_path9.default.resolve(anchor);
|
|
13776
|
+
for (; ; ) {
|
|
13777
|
+
const globs = workspaceGlobsAt(dir);
|
|
13778
|
+
if (globs !== null) {
|
|
13779
|
+
const found = /* @__PURE__ */ new Map();
|
|
13780
|
+
for (const glob of globs) {
|
|
13781
|
+
if (glob.startsWith("!")) {
|
|
13782
|
+
continue;
|
|
13783
|
+
}
|
|
13784
|
+
for (const match of directoriesMatchingGlob(dir, glob)) {
|
|
13785
|
+
const pkg = packageAt(match);
|
|
13786
|
+
if (pkg !== null) {
|
|
13787
|
+
found.set(pkg.packageJsonPath, pkg);
|
|
13788
|
+
}
|
|
13789
|
+
}
|
|
13790
|
+
}
|
|
13791
|
+
return [...found.values()].sort(
|
|
13792
|
+
(a, b) => a.packageJsonPath.localeCompare(b.packageJsonPath)
|
|
13793
|
+
);
|
|
13794
|
+
}
|
|
13795
|
+
const parent = import_node_path9.default.dirname(dir);
|
|
13796
|
+
if (parent === dir) {
|
|
13797
|
+
return [];
|
|
13798
|
+
}
|
|
13799
|
+
dir = parent;
|
|
13800
|
+
}
|
|
13801
|
+
}
|
|
13802
|
+
function isWorkspaceMarked(pattern) {
|
|
13803
|
+
const match = pattern.match;
|
|
13804
|
+
return (match.type === "packageExports" || match.type === "packageImport") && match.workspaces === true;
|
|
13805
|
+
}
|
|
13806
|
+
function expandPattern(pattern, packages) {
|
|
13807
|
+
const match = pattern.match;
|
|
13808
|
+
if (match.type === "packageExports" && match.workspaces === true) {
|
|
13809
|
+
const { workspaces: _workspaces, ...rest } = match;
|
|
13810
|
+
return packages.map((pkg) => ({
|
|
13811
|
+
...pattern,
|
|
13812
|
+
match: { ...rest, packageJsonPath: pkg.packageJsonPath }
|
|
13813
|
+
}));
|
|
13814
|
+
}
|
|
13815
|
+
if (match.type === "packageImport" && match.workspaces === true) {
|
|
13816
|
+
const listed = match.packages ?? [];
|
|
13817
|
+
const names = [.../* @__PURE__ */ new Set([...listed, ...packages.map((p) => p.name)])];
|
|
13818
|
+
if (names.length === 0) {
|
|
13819
|
+
return [];
|
|
13820
|
+
}
|
|
13821
|
+
return [{ ...pattern, match: { type: "packageImport", packages: names } }];
|
|
13822
|
+
}
|
|
13823
|
+
return [pattern];
|
|
13824
|
+
}
|
|
13825
|
+
function workspaceExpansionStamp(frameworks) {
|
|
13826
|
+
const paths = frameworks.flatMap((pack) => pack.discovery).flatMap(
|
|
13827
|
+
(pattern) => pattern.match.type === "packageExports" && pattern.match.packageJsonPath !== void 0 ? [pattern.match.packageJsonPath] : []
|
|
13828
|
+
).sort();
|
|
13829
|
+
if (paths.length === 0) {
|
|
13830
|
+
return "none";
|
|
13831
|
+
}
|
|
13832
|
+
return (0, import_node_crypto4.createHash)("sha256").update(paths.join("\n")).digest("hex").slice(0, 12);
|
|
13833
|
+
}
|
|
13834
|
+
function expandWorkspacePatterns(frameworks, anchor) {
|
|
13835
|
+
const marked = frameworks.some(
|
|
13836
|
+
(pack) => pack.discovery.some(isWorkspaceMarked)
|
|
13837
|
+
);
|
|
13838
|
+
if (!marked) {
|
|
13839
|
+
return frameworks;
|
|
13840
|
+
}
|
|
13841
|
+
const packages = anchor !== void 0 ? workspacePackagesFrom(anchor) : [];
|
|
13842
|
+
return frameworks.map((pack) => ({
|
|
13843
|
+
...pack,
|
|
13844
|
+
discovery: pack.discovery.flatMap(
|
|
13845
|
+
(pattern) => expandPattern(pattern, packages)
|
|
13846
|
+
)
|
|
13847
|
+
}));
|
|
13848
|
+
}
|
|
13849
|
+
|
|
13586
13850
|
// src/adapter.ts
|
|
13587
13851
|
var raise = (msg) => {
|
|
13588
13852
|
throw new Error(msg);
|
|
@@ -13993,11 +14257,11 @@ function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
|
13993
14257
|
return null;
|
|
13994
14258
|
}
|
|
13995
14259
|
const method = extractBindingMethod(binding, callSite, pack, resolution);
|
|
13996
|
-
const
|
|
14260
|
+
const path13 = extractBindingPath(binding, callSite, pack, resolution);
|
|
13997
14261
|
return (0, import_behavioral_ir8.restBinding)({
|
|
13998
14262
|
transport: pack.protocol,
|
|
13999
14263
|
method: method ?? null,
|
|
14000
|
-
path:
|
|
14264
|
+
path: path13 ?? null,
|
|
14001
14265
|
recognition: pack.name
|
|
14002
14266
|
});
|
|
14003
14267
|
}
|
|
@@ -14609,8 +14873,8 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
14609
14873
|
if (pathArg === void 0) {
|
|
14610
14874
|
continue;
|
|
14611
14875
|
}
|
|
14612
|
-
const
|
|
14613
|
-
if (
|
|
14876
|
+
const path13 = pathFromArgument(pathArg, resolution);
|
|
14877
|
+
if (path13 === void 0) {
|
|
14614
14878
|
continue;
|
|
14615
14879
|
}
|
|
14616
14880
|
const callerFunc = enclosingFunction(callExpr);
|
|
@@ -14622,7 +14886,7 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
14622
14886
|
continue;
|
|
14623
14887
|
}
|
|
14624
14888
|
seen.add(dedupKey);
|
|
14625
|
-
out.push(buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
14889
|
+
out.push(buildCallerSummary(wrapper, callerFunc, callExpr, path13, options));
|
|
14626
14890
|
}
|
|
14627
14891
|
return out;
|
|
14628
14892
|
}
|
|
@@ -14679,7 +14943,7 @@ function callerName(func) {
|
|
|
14679
14943
|
}
|
|
14680
14944
|
return "anonymous";
|
|
14681
14945
|
}
|
|
14682
|
-
function buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
14946
|
+
function buildCallerSummary(wrapper, callerFunc, callExpr, path13, options) {
|
|
14683
14947
|
const wrapperBinding = wrapper.summary.identity.boundaryBinding;
|
|
14684
14948
|
const wrapperRest = wrapperBinding?.semantics.name === "rest" ? wrapperBinding.semantics : null;
|
|
14685
14949
|
const syntheticPack = {
|
|
@@ -14711,7 +14975,7 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path12, options) {
|
|
|
14711
14975
|
raw.boundaryBinding = (0, import_behavioral_ir8.restBinding)({
|
|
14712
14976
|
transport: wrapperBinding?.transport ?? "http",
|
|
14713
14977
|
method: wrapperRest?.method ?? null,
|
|
14714
|
-
path:
|
|
14978
|
+
path: path13,
|
|
14715
14979
|
recognition: wrapperBinding?.recognition ?? "unknown"
|
|
14716
14980
|
});
|
|
14717
14981
|
const summary = (0, import_extractor5.assembleSummary)(raw, options);
|
|
@@ -14777,25 +15041,32 @@ function loadRunFiles(project, candidatePaths, timer) {
|
|
|
14777
15041
|
);
|
|
14778
15042
|
return { sourceFiles, deep };
|
|
14779
15043
|
}
|
|
14780
|
-
function createTypeScriptAdapter(
|
|
15044
|
+
function createTypeScriptAdapter(suppliedConfig) {
|
|
15045
|
+
const config = {
|
|
15046
|
+
...suppliedConfig,
|
|
15047
|
+
frameworks: expandWorkspacePatterns(
|
|
15048
|
+
suppliedConfig.frameworks,
|
|
15049
|
+
suppliedConfig.projectRoot ?? (suppliedConfig.tsConfigFilePath !== void 0 ? import_node_path10.default.dirname(suppliedConfig.tsConfigFilePath) : void 0)
|
|
15050
|
+
)
|
|
15051
|
+
};
|
|
14781
15052
|
const project = config.project ?? new import_ts_morph60.Project(
|
|
14782
15053
|
config.tsConfigFilePath !== void 0 ? {
|
|
14783
15054
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
14784
15055
|
skipAddingFilesFromTsConfig: true
|
|
14785
15056
|
} : { skipAddingFilesFromTsConfig: true }
|
|
14786
15057
|
);
|
|
14787
|
-
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(
|
|
15058
|
+
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(import_node_path10.default.dirname(config.tsConfigFilePath)) : void 0);
|
|
14788
15059
|
let lazyBootstrapped = false;
|
|
14789
15060
|
let projectFileSet;
|
|
14790
15061
|
const cacheDir = declineWhenRunFromSource(
|
|
14791
|
-
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ?
|
|
15062
|
+
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
15063
|
);
|
|
14793
15064
|
const cache = createCacheLayer(cacheDir);
|
|
14794
15065
|
const adapterPacksDigest = `${computeAdapterPacksDigest(
|
|
14795
15066
|
config.frameworks.map(
|
|
14796
15067
|
(p) => p.version !== void 0 ? { name: p.name, version: p.version } : { name: p.name }
|
|
14797
15068
|
)
|
|
14798
|
-
)}|${extractionConfigStamp(config)}`;
|
|
15069
|
+
)}|${extractionConfigStamp(config)}|ws:${workspaceExpansionStamp(config.frameworks)}`;
|
|
14799
15070
|
const packWrappers = config.frameworks.flatMap(
|
|
14800
15071
|
(pack) => pack.transparentWrappers ?? []
|
|
14801
15072
|
);
|
|
@@ -15031,7 +15302,12 @@ function createTypeScriptAdapter(config) {
|
|
|
15031
15302
|
},
|
|
15032
15303
|
// Reached units the cache already serves emit nothing,
|
|
15033
15304
|
// the way a cold run's seeds do not.
|
|
15034
|
-
reused?.summaries ?? []
|
|
15305
|
+
reused?.summaries ?? [],
|
|
15306
|
+
// A recognizer-only pack's effects need a function to
|
|
15307
|
+
// live on even when nothing discovers units in its
|
|
15308
|
+
// files, so those files' exports join the walk as
|
|
15309
|
+
// roots.
|
|
15310
|
+
recognizerOnlyRoots(packsByFile)
|
|
15035
15311
|
)
|
|
15036
15312
|
) : withSubUnits;
|
|
15037
15313
|
const closureOwnership = caching && config.includeReachable !== false ? timer.time(
|
|
@@ -15428,8 +15704,8 @@ function buildSubUnitSummary(subUnit, parent, invocationRecognizers, accessRecog
|
|
|
15428
15704
|
}
|
|
15429
15705
|
|
|
15430
15706
|
// src/bootstrap/noTsconfigProject.ts
|
|
15431
|
-
var
|
|
15432
|
-
var
|
|
15707
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
15708
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
15433
15709
|
var import_ts_morph61 = require("ts-morph");
|
|
15434
15710
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
15435
15711
|
".ts",
|
|
@@ -15460,7 +15736,7 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
15460
15736
|
const found = [];
|
|
15461
15737
|
let entries;
|
|
15462
15738
|
try {
|
|
15463
|
-
entries =
|
|
15739
|
+
entries = import_node_fs7.default.readdirSync(rootDir, { withFileTypes: true });
|
|
15464
15740
|
} catch {
|
|
15465
15741
|
return [];
|
|
15466
15742
|
}
|
|
@@ -15468,10 +15744,10 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
15468
15744
|
if (entry.name.startsWith(".") || SKIP_DIRECTORIES.has(entry.name)) {
|
|
15469
15745
|
continue;
|
|
15470
15746
|
}
|
|
15471
|
-
const full =
|
|
15747
|
+
const full = import_node_path11.default.join(rootDir, entry.name);
|
|
15472
15748
|
if (entry.isDirectory()) {
|
|
15473
15749
|
found.push(...findSourceFiles(full, depth + 1));
|
|
15474
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
15750
|
+
} else if (SOURCE_EXTENSIONS.has(import_node_path11.default.extname(entry.name)) && !entry.name.endsWith(".d.ts")) {
|
|
15475
15751
|
found.push(full);
|
|
15476
15752
|
}
|
|
15477
15753
|
}
|
|
@@ -15506,15 +15782,15 @@ function createProjectWithoutTsconfig(rootDir) {
|
|
|
15506
15782
|
return { project, files };
|
|
15507
15783
|
}
|
|
15508
15784
|
function findNearestTsconfig(startDir) {
|
|
15509
|
-
let dir =
|
|
15785
|
+
let dir = import_node_path11.default.resolve(startDir);
|
|
15510
15786
|
while (true) {
|
|
15511
15787
|
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
15512
|
-
const candidate =
|
|
15513
|
-
if (
|
|
15788
|
+
const candidate = import_node_path11.default.join(dir, name);
|
|
15789
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
15514
15790
|
return candidate;
|
|
15515
15791
|
}
|
|
15516
15792
|
}
|
|
15517
|
-
const parent =
|
|
15793
|
+
const parent = import_node_path11.default.dirname(dir);
|
|
15518
15794
|
if (parent === dir) {
|
|
15519
15795
|
return null;
|
|
15520
15796
|
}
|
|
@@ -15523,7 +15799,7 @@ function findNearestTsconfig(startDir) {
|
|
|
15523
15799
|
}
|
|
15524
15800
|
|
|
15525
15801
|
// src/facts/why.ts
|
|
15526
|
-
var
|
|
15802
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
15527
15803
|
var import_ts_morph62 = require("ts-morph");
|
|
15528
15804
|
var import_resolution2 = require("@suss/resolution");
|
|
15529
15805
|
var JS_PHRASES = {
|
|
@@ -15536,7 +15812,7 @@ var WhySession = class {
|
|
|
15536
15812
|
store;
|
|
15537
15813
|
root;
|
|
15538
15814
|
constructor(options) {
|
|
15539
|
-
this.root =
|
|
15815
|
+
this.root = import_node_path12.default.resolve(options.dir);
|
|
15540
15816
|
const tsconfig = findNearestTsconfig(this.root);
|
|
15541
15817
|
this.project = tsconfig === null ? createProjectWithoutTsconfig(this.root).project : new import_ts_morph62.Project({ tsConfigFilePath: tsconfig });
|
|
15542
15818
|
this.store = new ResolutionStore();
|
|
@@ -15625,7 +15901,7 @@ var WhySession = class {
|
|
|
15625
15901
|
};
|
|
15626
15902
|
}
|
|
15627
15903
|
sourceFileAt(file) {
|
|
15628
|
-
const absolute =
|
|
15904
|
+
const absolute = import_node_path12.default.resolve(this.root, file);
|
|
15629
15905
|
const loaded = this.project.getSourceFile(absolute);
|
|
15630
15906
|
if (loaded !== void 0) {
|
|
15631
15907
|
return loaded;
|
|
@@ -15639,7 +15915,7 @@ var WhySession = class {
|
|
|
15639
15915
|
/** A module key: a file path said relative to the root, or a package name. */
|
|
15640
15916
|
displayPath(key) {
|
|
15641
15917
|
if (key.startsWith(this.root)) {
|
|
15642
|
-
return
|
|
15918
|
+
return import_node_path12.default.relative(this.root, key);
|
|
15643
15919
|
}
|
|
15644
15920
|
return key;
|
|
15645
15921
|
}
|
|
@@ -15710,6 +15986,17 @@ function funnelDrops(packs) {
|
|
|
15710
15986
|
}
|
|
15711
15987
|
return violations;
|
|
15712
15988
|
}
|
|
15989
|
+
function recognizersWithNoUnits(packs) {
|
|
15990
|
+
return packs.filter(
|
|
15991
|
+
(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
|
|
15992
|
+
// roots, so effects recognized there mean the run worked and
|
|
15993
|
+
// the missing framework pack costs attribution, not existence.
|
|
15994
|
+
funnel.effectsRecognized === 0
|
|
15995
|
+
).map((funnel) => ({
|
|
15996
|
+
label: funnel.pack,
|
|
15997
|
+
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.`
|
|
15998
|
+
}));
|
|
15999
|
+
}
|
|
15713
16000
|
function unversionedPacks(packs) {
|
|
15714
16001
|
return packs.filter((funnel) => funnel.version === null).map((funnel) => ({
|
|
15715
16002
|
label: funnel.pack,
|
|
@@ -15804,6 +16091,12 @@ function evaluatePackHealth(report) {
|
|
|
15804
16091
|
audience: "run",
|
|
15805
16092
|
violations: selfCollisions(report.packs)
|
|
15806
16093
|
},
|
|
16094
|
+
{
|
|
16095
|
+
name: "every recognizer had units to look inside",
|
|
16096
|
+
code: "no-units",
|
|
16097
|
+
audience: "run",
|
|
16098
|
+
violations: recognizersWithNoUnits(report.packs)
|
|
16099
|
+
},
|
|
15807
16100
|
{
|
|
15808
16101
|
name: "every pack declares a version",
|
|
15809
16102
|
code: "no-version",
|