@suss/adapter-typescript 0.14.0 → 0.15.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 +142 -45
- package/dist/index.js +142 -45
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -2688,7 +2688,7 @@ var ORIGIN = {
|
|
|
2688
2688
|
declaredBy: (origin, receiver) => receiver.callee !== null && origin.importedFrom.some(
|
|
2689
2689
|
(module2) => methodDeclaredIn(receiver.callee, module2, receiver.resolve)
|
|
2690
2690
|
),
|
|
2691
|
-
constructed: (origin, receiver) => madeFromNamed(origin,
|
|
2691
|
+
constructed: (origin, receiver) => madeFromNamed(origin, madeExpression(receiver)) && origin.importedFrom.some(
|
|
2692
2692
|
(module2) => isImportedFrom(madeBy(receiver), module2)
|
|
2693
2693
|
)
|
|
2694
2694
|
};
|
|
@@ -2696,14 +2696,15 @@ function madeFromNamed(origin, made) {
|
|
|
2696
2696
|
if (origin.origin !== "constructed" || origin.named === void 0) {
|
|
2697
2697
|
return true;
|
|
2698
2698
|
}
|
|
2699
|
-
return origin.named.includes(made
|
|
2699
|
+
return origin.named.includes(constructorName(made));
|
|
2700
|
+
}
|
|
2701
|
+
function constructorName(made) {
|
|
2702
|
+
const expression = import_ts_morph14.Node.isNewExpression(made) || import_ts_morph14.Node.isCallExpression(made) ? made.getExpression() : made;
|
|
2703
|
+
return import_ts_morph14.Node.isPropertyAccessExpression(expression) ? expression.getName() : expression.getText();
|
|
2700
2704
|
}
|
|
2701
2705
|
var CALL_ORIGIN = {
|
|
2702
2706
|
declaredBy: ORIGIN.declaredBy,
|
|
2703
|
-
constructed: (origin, receiver) => madeFromNamed(
|
|
2704
|
-
origin,
|
|
2705
|
-
rootIdentifier(receiver.expression) ?? receiver.expression
|
|
2706
|
-
) && origin.importedFrom.some(
|
|
2707
|
+
constructed: (origin, receiver) => madeFromNamed(origin, receiver.expression) && origin.importedFrom.some(
|
|
2707
2708
|
(module2) => isImportedFrom(
|
|
2708
2709
|
rootIdentifier(receiver.expression) ?? receiver.expression,
|
|
2709
2710
|
module2
|
|
@@ -2711,14 +2712,19 @@ var CALL_ORIGIN = {
|
|
|
2711
2712
|
)
|
|
2712
2713
|
};
|
|
2713
2714
|
function madeBy(receiver) {
|
|
2715
|
+
const made = madeExpression(receiver);
|
|
2716
|
+
const expression = import_ts_morph14.Node.isNewExpression(made) || import_ts_morph14.Node.isCallExpression(made) ? made.getExpression() : made;
|
|
2717
|
+
return rootIdentifier(expression) ?? expression;
|
|
2718
|
+
}
|
|
2719
|
+
function madeExpression(receiver) {
|
|
2714
2720
|
if (receiver.callee === null) {
|
|
2715
|
-
return
|
|
2721
|
+
return receiver.expression;
|
|
2716
2722
|
}
|
|
2717
2723
|
const written = receiver.resolve(receiver.callee.getExpression());
|
|
2718
2724
|
if (written === null || !import_ts_morph14.Node.isNewExpression(written) && !import_ts_morph14.Node.isCallExpression(written)) {
|
|
2719
2725
|
return receiver.callee;
|
|
2720
2726
|
}
|
|
2721
|
-
return
|
|
2727
|
+
return written;
|
|
2722
2728
|
}
|
|
2723
2729
|
function callOpsFor(call, resolveWrittenValue) {
|
|
2724
2730
|
const resolve2 = resolveWrittenValue ?? (() => null);
|
|
@@ -2759,6 +2765,7 @@ function valueOpsFor(value, resolve2) {
|
|
|
2759
2765
|
flag: () => literalFlag(written()),
|
|
2760
2766
|
entries: (unsettled) => entriesOf(written(), unsettled, resolve2),
|
|
2761
2767
|
items: () => itemsOf(written(), resolve2),
|
|
2768
|
+
asArg: () => effectArgOf(written()),
|
|
2762
2769
|
property: (name) => {
|
|
2763
2770
|
const object = written();
|
|
2764
2771
|
const inside = import_ts_morph14.Node.isObjectLiteralExpression(object) ? initializerOf(object, name) : null;
|
|
@@ -3246,6 +3253,9 @@ var MAX_ARG_DEPTH = 8;
|
|
|
3246
3253
|
function extractArgs(call) {
|
|
3247
3254
|
return call.getArguments().map((arg) => extractArg(arg, MAX_ARG_DEPTH));
|
|
3248
3255
|
}
|
|
3256
|
+
function effectArgOf(node) {
|
|
3257
|
+
return extractArg(node, MAX_ARG_DEPTH);
|
|
3258
|
+
}
|
|
3249
3259
|
function extractArg(node, depth) {
|
|
3250
3260
|
if (import_ts_morph15.Node.isAsExpression(node) || import_ts_morph15.Node.isTypeAssertion(node) || import_ts_morph15.Node.isSatisfiesExpression(node) || import_ts_morph15.Node.isNonNullExpression(node)) {
|
|
3251
3261
|
return extractArg(node.getExpression(), depth);
|
|
@@ -7871,6 +7881,31 @@ function constructionRef(node, localNames, resolution) {
|
|
|
7871
7881
|
// src/discovery/clientCall.ts
|
|
7872
7882
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
7873
7883
|
var import_ts_morph34 = require("ts-morph");
|
|
7884
|
+
|
|
7885
|
+
// src/discovery/resolveImport.ts
|
|
7886
|
+
function resolveImportedLocalName(sourceFile, importModule, importName) {
|
|
7887
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
7888
|
+
if (importDecl.getModuleSpecifierValue() !== importModule) {
|
|
7889
|
+
continue;
|
|
7890
|
+
}
|
|
7891
|
+
for (const named2 of importDecl.getNamedImports()) {
|
|
7892
|
+
if (named2.getName() === importName || named2.getAliasNode()?.getText() === importName) {
|
|
7893
|
+
return named2.getAliasNode()?.getText() ?? named2.getName();
|
|
7894
|
+
}
|
|
7895
|
+
}
|
|
7896
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
7897
|
+
if (defaultImport !== void 0 && defaultImport.getText() === importName) {
|
|
7898
|
+
return defaultImport.getText();
|
|
7899
|
+
}
|
|
7900
|
+
const namespaceImport = importDecl.getNamespaceImport();
|
|
7901
|
+
if (namespaceImport !== void 0 && namespaceImport.getText() === importName) {
|
|
7902
|
+
return namespaceImport.getText();
|
|
7903
|
+
}
|
|
7904
|
+
}
|
|
7905
|
+
return null;
|
|
7906
|
+
}
|
|
7907
|
+
|
|
7908
|
+
// src/discovery/clientCall.ts
|
|
7874
7909
|
function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
7875
7910
|
const results = [];
|
|
7876
7911
|
const isGlobal = match.importModule === "global";
|
|
@@ -7889,7 +7924,7 @@ function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
|
7889
7924
|
if (!isGlobal && importedLocalName !== null) {
|
|
7890
7925
|
for (const varDecl of sourceFile.getVariableDeclarations()) {
|
|
7891
7926
|
const init = varDecl.getInitializer();
|
|
7892
|
-
if (init !== void 0 && import_ts_morph34.Node.isCallExpression(init) && isInstanceCreationCall(init, importedLocalName, match.factoryMethods)) {
|
|
7927
|
+
if (init !== void 0 && (import_ts_morph34.Node.isCallExpression(init) || import_ts_morph34.Node.isNewExpression(init)) && isInstanceCreationCall(init, importedLocalName, match.factoryMethods)) {
|
|
7893
7928
|
clientVarNames.add(varDecl.getName());
|
|
7894
7929
|
}
|
|
7895
7930
|
}
|
|
@@ -7934,12 +7969,50 @@ function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
|
7934
7969
|
});
|
|
7935
7970
|
return results;
|
|
7936
7971
|
}
|
|
7972
|
+
function clientReceiverCheckFor(sourceFile, match, resolution) {
|
|
7973
|
+
const localName = resolveImportedLocalName(
|
|
7974
|
+
sourceFile,
|
|
7975
|
+
match.importModule,
|
|
7976
|
+
match.importName
|
|
7977
|
+
);
|
|
7978
|
+
const constructedHere = /* @__PURE__ */ new Set();
|
|
7979
|
+
if (localName !== null) {
|
|
7980
|
+
sourceFile.forEachDescendant((node) => {
|
|
7981
|
+
if (import_ts_morph34.Node.isVariableDeclaration(node)) {
|
|
7982
|
+
const init = node.getInitializer();
|
|
7983
|
+
if (init !== void 0 && (import_ts_morph34.Node.isCallExpression(init) || import_ts_morph34.Node.isNewExpression(init)) && isInstanceCreationCall(init, localName, match.factoryMethods) || typedAsClient(node.getTypeNode(), localName)) {
|
|
7984
|
+
constructedHere.add(node.getName());
|
|
7985
|
+
}
|
|
7986
|
+
return;
|
|
7987
|
+
}
|
|
7988
|
+
if (import_ts_morph34.Node.isParameterDeclaration(node) && typedAsClient(node.getTypeNode(), localName)) {
|
|
7989
|
+
const written = node.getNameNode();
|
|
7990
|
+
if (import_ts_morph34.Node.isIdentifier(written)) {
|
|
7991
|
+
constructedHere.add(written.getText());
|
|
7992
|
+
}
|
|
7993
|
+
}
|
|
7994
|
+
});
|
|
7995
|
+
}
|
|
7996
|
+
const full = {
|
|
7997
|
+
type: "clientCall",
|
|
7998
|
+
importModule: match.importModule,
|
|
7999
|
+
importName: match.importName,
|
|
8000
|
+
...match.factoryMethods === void 0 ? {} : { factoryMethods: match.factoryMethods }
|
|
8001
|
+
};
|
|
8002
|
+
return (subject) => localName !== null && import_ts_morph34.Node.isIdentifier(subject) && subject.getText() === localName || import_ts_morph34.Node.isIdentifier(subject) && constructedHere.has(subject.getText()) || resolvesToKnownInstance(subject, full, resolution);
|
|
8003
|
+
}
|
|
8004
|
+
function typedAsClient(typeNode, localName) {
|
|
8005
|
+
if (typeNode === void 0 || !import_ts_morph34.Node.isTypeReference(typeNode)) {
|
|
8006
|
+
return false;
|
|
8007
|
+
}
|
|
8008
|
+
return typeNode.getTypeName().getText() === localName;
|
|
8009
|
+
}
|
|
7937
8010
|
function resolvesToKnownInstance(subject, match, resolution) {
|
|
7938
8011
|
if (resolution === void 0 || match.importModule === "global") {
|
|
7939
8012
|
return false;
|
|
7940
8013
|
}
|
|
7941
8014
|
const written = writtenNodeOf(subject, resolution);
|
|
7942
|
-
if (written === null || !import_ts_morph34.Node.isCallExpression(written)) {
|
|
8015
|
+
if (written === null || !import_ts_morph34.Node.isCallExpression(written) && !import_ts_morph34.Node.isNewExpression(written)) {
|
|
7943
8016
|
return false;
|
|
7944
8017
|
}
|
|
7945
8018
|
const writtenLocalName = resolvedImportLocalName(
|
|
@@ -9134,40 +9207,8 @@ function discoverGraphqlHookCalls(sourceFile, match, kind, resolution) {
|
|
|
9134
9207
|
|
|
9135
9208
|
// src/discovery/graphqlImperativeCall.ts
|
|
9136
9209
|
var import_ts_morph42 = require("ts-morph");
|
|
9137
|
-
|
|
9138
|
-
// src/discovery/resolveImport.ts
|
|
9139
|
-
function resolveImportedLocalName(sourceFile, importModule, importName) {
|
|
9140
|
-
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
9141
|
-
if (importDecl.getModuleSpecifierValue() !== importModule) {
|
|
9142
|
-
continue;
|
|
9143
|
-
}
|
|
9144
|
-
for (const named2 of importDecl.getNamedImports()) {
|
|
9145
|
-
if (named2.getName() === importName || named2.getAliasNode()?.getText() === importName) {
|
|
9146
|
-
return named2.getAliasNode()?.getText() ?? named2.getName();
|
|
9147
|
-
}
|
|
9148
|
-
}
|
|
9149
|
-
const defaultImport = importDecl.getDefaultImport();
|
|
9150
|
-
if (defaultImport !== void 0 && defaultImport.getText() === importName) {
|
|
9151
|
-
return defaultImport.getText();
|
|
9152
|
-
}
|
|
9153
|
-
const namespaceImport = importDecl.getNamespaceImport();
|
|
9154
|
-
if (namespaceImport !== void 0 && namespaceImport.getText() === importName) {
|
|
9155
|
-
return namespaceImport.getText();
|
|
9156
|
-
}
|
|
9157
|
-
}
|
|
9158
|
-
return null;
|
|
9159
|
-
}
|
|
9160
|
-
|
|
9161
|
-
// src/discovery/graphqlImperativeCall.ts
|
|
9162
9210
|
function discoverGraphqlImperativeCalls(sourceFile, match, kind, resolution) {
|
|
9163
|
-
const
|
|
9164
|
-
sourceFile,
|
|
9165
|
-
match.importModule,
|
|
9166
|
-
match.importName
|
|
9167
|
-
);
|
|
9168
|
-
if (localName === null) {
|
|
9169
|
-
return [];
|
|
9170
|
-
}
|
|
9211
|
+
const isTheClient = clientReceiverCheckFor(sourceFile, match, resolution);
|
|
9171
9212
|
const methodSpec = /* @__PURE__ */ new Map();
|
|
9172
9213
|
for (const method of match.methods) {
|
|
9173
9214
|
methodSpec.set(method.methodName, {
|
|
@@ -9189,6 +9230,9 @@ function discoverGraphqlImperativeCalls(sourceFile, match, kind, resolution) {
|
|
|
9189
9230
|
if (spec === void 0) {
|
|
9190
9231
|
return;
|
|
9191
9232
|
}
|
|
9233
|
+
if (!isTheClient(callee.getExpression())) {
|
|
9234
|
+
return;
|
|
9235
|
+
}
|
|
9192
9236
|
const args = node.getArguments();
|
|
9193
9237
|
if (args.length === 0 || !import_ts_morph42.Node.isObjectLiteralExpression(args[0])) {
|
|
9194
9238
|
return;
|
|
@@ -10331,8 +10375,24 @@ function pathFromUrlNode(node, resolution) {
|
|
|
10331
10375
|
if (import_ts_morph48.Node.isTemplateExpression(node)) {
|
|
10332
10376
|
return pathFromTemplateUrl(node, resolution);
|
|
10333
10377
|
}
|
|
10378
|
+
if (import_ts_morph48.Node.isBinaryExpression(node)) {
|
|
10379
|
+
const joined = joinedStringOf(node, resolution);
|
|
10380
|
+
return joined === void 0 ? void 0 : pathFromLiteralUrl(joined);
|
|
10381
|
+
}
|
|
10334
10382
|
return void 0;
|
|
10335
10383
|
}
|
|
10384
|
+
function joinedStringOf(node, resolution) {
|
|
10385
|
+
if (import_ts_morph48.Node.isStringLiteral(node) || import_ts_morph48.Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
10386
|
+
return node.getLiteralValue();
|
|
10387
|
+
}
|
|
10388
|
+
if (import_ts_morph48.Node.isBinaryExpression(node) && node.getOperatorToken().getText() === "+") {
|
|
10389
|
+
const left = joinedStringOf(node.getLeft(), resolution);
|
|
10390
|
+
const right = joinedStringOf(node.getRight(), resolution);
|
|
10391
|
+
return left === void 0 || right === void 0 ? void 0 : left + right;
|
|
10392
|
+
}
|
|
10393
|
+
const written = resolution?.resolveWrittenValue(node) ?? null;
|
|
10394
|
+
return written === null || written === node ? void 0 : joinedStringOf(written, resolution);
|
|
10395
|
+
}
|
|
10336
10396
|
function placeholderName(expr) {
|
|
10337
10397
|
if (import_ts_morph48.Node.isIdentifier(expr)) {
|
|
10338
10398
|
return expr.getText();
|
|
@@ -10665,18 +10725,38 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
10665
10725
|
var import_ts_morph50 = require("ts-morph");
|
|
10666
10726
|
function discoverRegistrationLoops(sourceFile, match, kind, resolution) {
|
|
10667
10727
|
const results = [];
|
|
10728
|
+
const routables = routableNames(sourceFile, match);
|
|
10729
|
+
if (routables !== null && routables.size === 0) {
|
|
10730
|
+
return results;
|
|
10731
|
+
}
|
|
10668
10732
|
sourceFile.forEachDescendant((node) => {
|
|
10669
10733
|
if (!import_ts_morph50.Node.isForOfStatement(node)) {
|
|
10670
10734
|
return;
|
|
10671
10735
|
}
|
|
10672
|
-
const expanded = tryExpandLoop(node, match, kind, resolution);
|
|
10736
|
+
const expanded = tryExpandLoop(node, match, kind, resolution, routables);
|
|
10673
10737
|
if (expanded !== null) {
|
|
10674
10738
|
results.push(...expanded);
|
|
10675
10739
|
}
|
|
10676
10740
|
});
|
|
10677
10741
|
return results;
|
|
10678
10742
|
}
|
|
10679
|
-
function
|
|
10743
|
+
function routableNames(sourceFile, match) {
|
|
10744
|
+
if (match.receiver === void 0) {
|
|
10745
|
+
return null;
|
|
10746
|
+
}
|
|
10747
|
+
const names = /* @__PURE__ */ new Set();
|
|
10748
|
+
for (const importName of match.receiver.importNames) {
|
|
10749
|
+
for (const name of registrationSubjectsOf(
|
|
10750
|
+
sourceFile,
|
|
10751
|
+
match.receiver.importModule,
|
|
10752
|
+
importName
|
|
10753
|
+
).keys()) {
|
|
10754
|
+
names.add(name);
|
|
10755
|
+
}
|
|
10756
|
+
}
|
|
10757
|
+
return names;
|
|
10758
|
+
}
|
|
10759
|
+
function tryExpandLoop(loop, match, kind, resolution, routables) {
|
|
10680
10760
|
const loopVar = loopVariableName(loop);
|
|
10681
10761
|
if (loopVar === null) {
|
|
10682
10762
|
return null;
|
|
@@ -10684,6 +10764,9 @@ function tryExpandLoop(loop, match, kind, resolution) {
|
|
|
10684
10764
|
if (!bodyReferencesLoopVar(loop, loopVar)) {
|
|
10685
10765
|
return null;
|
|
10686
10766
|
}
|
|
10767
|
+
if (routables !== null && !bodyCallsOn(loop, routables)) {
|
|
10768
|
+
return null;
|
|
10769
|
+
}
|
|
10687
10770
|
const arrayLit = arrayLiteralOf(loop.getExpression(), resolution);
|
|
10688
10771
|
if (arrayLit === null) {
|
|
10689
10772
|
return null;
|
|
@@ -10742,6 +10825,20 @@ function bodyReferencesLoopVar(loop, name) {
|
|
|
10742
10825
|
});
|
|
10743
10826
|
return referenced;
|
|
10744
10827
|
}
|
|
10828
|
+
function bodyCallsOn(loop, routables) {
|
|
10829
|
+
let found = false;
|
|
10830
|
+
loop.getStatement().forEachDescendant((node) => {
|
|
10831
|
+
if (found || !import_ts_morph50.Node.isCallExpression(node)) {
|
|
10832
|
+
return;
|
|
10833
|
+
}
|
|
10834
|
+
const callee = node.getExpression();
|
|
10835
|
+
const subject = import_ts_morph50.Node.isPropertyAccessExpression(callee) || import_ts_morph50.Node.isElementAccessExpression(callee) ? callee.getExpression() : null;
|
|
10836
|
+
if (subject !== null && import_ts_morph50.Node.isIdentifier(subject) && routables.has(subject.getText())) {
|
|
10837
|
+
found = true;
|
|
10838
|
+
}
|
|
10839
|
+
});
|
|
10840
|
+
return found;
|
|
10841
|
+
}
|
|
10745
10842
|
function readRouteSpec(element, shape, resolution) {
|
|
10746
10843
|
let method = null;
|
|
10747
10844
|
let path12 = null;
|
package/dist/index.js
CHANGED
|
@@ -2651,7 +2651,7 @@ var ORIGIN = {
|
|
|
2651
2651
|
declaredBy: (origin, receiver) => receiver.callee !== null && origin.importedFrom.some(
|
|
2652
2652
|
(module) => methodDeclaredIn(receiver.callee, module, receiver.resolve)
|
|
2653
2653
|
),
|
|
2654
|
-
constructed: (origin, receiver) => madeFromNamed(origin,
|
|
2654
|
+
constructed: (origin, receiver) => madeFromNamed(origin, madeExpression(receiver)) && origin.importedFrom.some(
|
|
2655
2655
|
(module) => isImportedFrom(madeBy(receiver), module)
|
|
2656
2656
|
)
|
|
2657
2657
|
};
|
|
@@ -2659,14 +2659,15 @@ function madeFromNamed(origin, made) {
|
|
|
2659
2659
|
if (origin.origin !== "constructed" || origin.named === void 0) {
|
|
2660
2660
|
return true;
|
|
2661
2661
|
}
|
|
2662
|
-
return origin.named.includes(made
|
|
2662
|
+
return origin.named.includes(constructorName(made));
|
|
2663
|
+
}
|
|
2664
|
+
function constructorName(made) {
|
|
2665
|
+
const expression = Node13.isNewExpression(made) || Node13.isCallExpression(made) ? made.getExpression() : made;
|
|
2666
|
+
return Node13.isPropertyAccessExpression(expression) ? expression.getName() : expression.getText();
|
|
2663
2667
|
}
|
|
2664
2668
|
var CALL_ORIGIN = {
|
|
2665
2669
|
declaredBy: ORIGIN.declaredBy,
|
|
2666
|
-
constructed: (origin, receiver) => madeFromNamed(
|
|
2667
|
-
origin,
|
|
2668
|
-
rootIdentifier(receiver.expression) ?? receiver.expression
|
|
2669
|
-
) && origin.importedFrom.some(
|
|
2670
|
+
constructed: (origin, receiver) => madeFromNamed(origin, receiver.expression) && origin.importedFrom.some(
|
|
2670
2671
|
(module) => isImportedFrom(
|
|
2671
2672
|
rootIdentifier(receiver.expression) ?? receiver.expression,
|
|
2672
2673
|
module
|
|
@@ -2674,14 +2675,19 @@ var CALL_ORIGIN = {
|
|
|
2674
2675
|
)
|
|
2675
2676
|
};
|
|
2676
2677
|
function madeBy(receiver) {
|
|
2678
|
+
const made = madeExpression(receiver);
|
|
2679
|
+
const expression = Node13.isNewExpression(made) || Node13.isCallExpression(made) ? made.getExpression() : made;
|
|
2680
|
+
return rootIdentifier(expression) ?? expression;
|
|
2681
|
+
}
|
|
2682
|
+
function madeExpression(receiver) {
|
|
2677
2683
|
if (receiver.callee === null) {
|
|
2678
|
-
return
|
|
2684
|
+
return receiver.expression;
|
|
2679
2685
|
}
|
|
2680
2686
|
const written = receiver.resolve(receiver.callee.getExpression());
|
|
2681
2687
|
if (written === null || !Node13.isNewExpression(written) && !Node13.isCallExpression(written)) {
|
|
2682
2688
|
return receiver.callee;
|
|
2683
2689
|
}
|
|
2684
|
-
return
|
|
2690
|
+
return written;
|
|
2685
2691
|
}
|
|
2686
2692
|
function callOpsFor(call, resolveWrittenValue) {
|
|
2687
2693
|
const resolve2 = resolveWrittenValue ?? (() => null);
|
|
@@ -2722,6 +2728,7 @@ function valueOpsFor(value, resolve2) {
|
|
|
2722
2728
|
flag: () => literalFlag(written()),
|
|
2723
2729
|
entries: (unsettled) => entriesOf(written(), unsettled, resolve2),
|
|
2724
2730
|
items: () => itemsOf(written(), resolve2),
|
|
2731
|
+
asArg: () => effectArgOf(written()),
|
|
2725
2732
|
property: (name) => {
|
|
2726
2733
|
const object = written();
|
|
2727
2734
|
const inside = Node13.isObjectLiteralExpression(object) ? initializerOf(object, name) : null;
|
|
@@ -3209,6 +3216,9 @@ var MAX_ARG_DEPTH = 8;
|
|
|
3209
3216
|
function extractArgs(call) {
|
|
3210
3217
|
return call.getArguments().map((arg) => extractArg(arg, MAX_ARG_DEPTH));
|
|
3211
3218
|
}
|
|
3219
|
+
function effectArgOf(node) {
|
|
3220
|
+
return extractArg(node, MAX_ARG_DEPTH);
|
|
3221
|
+
}
|
|
3212
3222
|
function extractArg(node, depth) {
|
|
3213
3223
|
if (Node14.isAsExpression(node) || Node14.isTypeAssertion(node) || Node14.isSatisfiesExpression(node) || Node14.isNonNullExpression(node)) {
|
|
3214
3224
|
return extractArg(node.getExpression(), depth);
|
|
@@ -7848,6 +7858,31 @@ function constructionRef(node, localNames, resolution) {
|
|
|
7848
7858
|
// src/discovery/clientCall.ts
|
|
7849
7859
|
import path4 from "path";
|
|
7850
7860
|
import { Node as Node32 } from "ts-morph";
|
|
7861
|
+
|
|
7862
|
+
// src/discovery/resolveImport.ts
|
|
7863
|
+
function resolveImportedLocalName(sourceFile, importModule, importName) {
|
|
7864
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
7865
|
+
if (importDecl.getModuleSpecifierValue() !== importModule) {
|
|
7866
|
+
continue;
|
|
7867
|
+
}
|
|
7868
|
+
for (const named2 of importDecl.getNamedImports()) {
|
|
7869
|
+
if (named2.getName() === importName || named2.getAliasNode()?.getText() === importName) {
|
|
7870
|
+
return named2.getAliasNode()?.getText() ?? named2.getName();
|
|
7871
|
+
}
|
|
7872
|
+
}
|
|
7873
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
7874
|
+
if (defaultImport !== void 0 && defaultImport.getText() === importName) {
|
|
7875
|
+
return defaultImport.getText();
|
|
7876
|
+
}
|
|
7877
|
+
const namespaceImport = importDecl.getNamespaceImport();
|
|
7878
|
+
if (namespaceImport !== void 0 && namespaceImport.getText() === importName) {
|
|
7879
|
+
return namespaceImport.getText();
|
|
7880
|
+
}
|
|
7881
|
+
}
|
|
7882
|
+
return null;
|
|
7883
|
+
}
|
|
7884
|
+
|
|
7885
|
+
// src/discovery/clientCall.ts
|
|
7851
7886
|
function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
7852
7887
|
const results = [];
|
|
7853
7888
|
const isGlobal = match.importModule === "global";
|
|
@@ -7866,7 +7901,7 @@ function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
|
7866
7901
|
if (!isGlobal && importedLocalName !== null) {
|
|
7867
7902
|
for (const varDecl of sourceFile.getVariableDeclarations()) {
|
|
7868
7903
|
const init = varDecl.getInitializer();
|
|
7869
|
-
if (init !== void 0 && Node32.isCallExpression(init) && isInstanceCreationCall(init, importedLocalName, match.factoryMethods)) {
|
|
7904
|
+
if (init !== void 0 && (Node32.isCallExpression(init) || Node32.isNewExpression(init)) && isInstanceCreationCall(init, importedLocalName, match.factoryMethods)) {
|
|
7870
7905
|
clientVarNames.add(varDecl.getName());
|
|
7871
7906
|
}
|
|
7872
7907
|
}
|
|
@@ -7911,12 +7946,50 @@ function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
|
7911
7946
|
});
|
|
7912
7947
|
return results;
|
|
7913
7948
|
}
|
|
7949
|
+
function clientReceiverCheckFor(sourceFile, match, resolution) {
|
|
7950
|
+
const localName = resolveImportedLocalName(
|
|
7951
|
+
sourceFile,
|
|
7952
|
+
match.importModule,
|
|
7953
|
+
match.importName
|
|
7954
|
+
);
|
|
7955
|
+
const constructedHere = /* @__PURE__ */ new Set();
|
|
7956
|
+
if (localName !== null) {
|
|
7957
|
+
sourceFile.forEachDescendant((node) => {
|
|
7958
|
+
if (Node32.isVariableDeclaration(node)) {
|
|
7959
|
+
const init = node.getInitializer();
|
|
7960
|
+
if (init !== void 0 && (Node32.isCallExpression(init) || Node32.isNewExpression(init)) && isInstanceCreationCall(init, localName, match.factoryMethods) || typedAsClient(node.getTypeNode(), localName)) {
|
|
7961
|
+
constructedHere.add(node.getName());
|
|
7962
|
+
}
|
|
7963
|
+
return;
|
|
7964
|
+
}
|
|
7965
|
+
if (Node32.isParameterDeclaration(node) && typedAsClient(node.getTypeNode(), localName)) {
|
|
7966
|
+
const written = node.getNameNode();
|
|
7967
|
+
if (Node32.isIdentifier(written)) {
|
|
7968
|
+
constructedHere.add(written.getText());
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7971
|
+
});
|
|
7972
|
+
}
|
|
7973
|
+
const full = {
|
|
7974
|
+
type: "clientCall",
|
|
7975
|
+
importModule: match.importModule,
|
|
7976
|
+
importName: match.importName,
|
|
7977
|
+
...match.factoryMethods === void 0 ? {} : { factoryMethods: match.factoryMethods }
|
|
7978
|
+
};
|
|
7979
|
+
return (subject) => localName !== null && Node32.isIdentifier(subject) && subject.getText() === localName || Node32.isIdentifier(subject) && constructedHere.has(subject.getText()) || resolvesToKnownInstance(subject, full, resolution);
|
|
7980
|
+
}
|
|
7981
|
+
function typedAsClient(typeNode, localName) {
|
|
7982
|
+
if (typeNode === void 0 || !Node32.isTypeReference(typeNode)) {
|
|
7983
|
+
return false;
|
|
7984
|
+
}
|
|
7985
|
+
return typeNode.getTypeName().getText() === localName;
|
|
7986
|
+
}
|
|
7914
7987
|
function resolvesToKnownInstance(subject, match, resolution) {
|
|
7915
7988
|
if (resolution === void 0 || match.importModule === "global") {
|
|
7916
7989
|
return false;
|
|
7917
7990
|
}
|
|
7918
7991
|
const written = writtenNodeOf(subject, resolution);
|
|
7919
|
-
if (written === null || !Node32.isCallExpression(written)) {
|
|
7992
|
+
if (written === null || !Node32.isCallExpression(written) && !Node32.isNewExpression(written)) {
|
|
7920
7993
|
return false;
|
|
7921
7994
|
}
|
|
7922
7995
|
const writtenLocalName = resolvedImportLocalName(
|
|
@@ -9117,40 +9190,8 @@ function discoverGraphqlHookCalls(sourceFile, match, kind, resolution) {
|
|
|
9117
9190
|
|
|
9118
9191
|
// src/discovery/graphqlImperativeCall.ts
|
|
9119
9192
|
import { Node as Node40 } from "ts-morph";
|
|
9120
|
-
|
|
9121
|
-
// src/discovery/resolveImport.ts
|
|
9122
|
-
function resolveImportedLocalName(sourceFile, importModule, importName) {
|
|
9123
|
-
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
9124
|
-
if (importDecl.getModuleSpecifierValue() !== importModule) {
|
|
9125
|
-
continue;
|
|
9126
|
-
}
|
|
9127
|
-
for (const named2 of importDecl.getNamedImports()) {
|
|
9128
|
-
if (named2.getName() === importName || named2.getAliasNode()?.getText() === importName) {
|
|
9129
|
-
return named2.getAliasNode()?.getText() ?? named2.getName();
|
|
9130
|
-
}
|
|
9131
|
-
}
|
|
9132
|
-
const defaultImport = importDecl.getDefaultImport();
|
|
9133
|
-
if (defaultImport !== void 0 && defaultImport.getText() === importName) {
|
|
9134
|
-
return defaultImport.getText();
|
|
9135
|
-
}
|
|
9136
|
-
const namespaceImport = importDecl.getNamespaceImport();
|
|
9137
|
-
if (namespaceImport !== void 0 && namespaceImport.getText() === importName) {
|
|
9138
|
-
return namespaceImport.getText();
|
|
9139
|
-
}
|
|
9140
|
-
}
|
|
9141
|
-
return null;
|
|
9142
|
-
}
|
|
9143
|
-
|
|
9144
|
-
// src/discovery/graphqlImperativeCall.ts
|
|
9145
9193
|
function discoverGraphqlImperativeCalls(sourceFile, match, kind, resolution) {
|
|
9146
|
-
const
|
|
9147
|
-
sourceFile,
|
|
9148
|
-
match.importModule,
|
|
9149
|
-
match.importName
|
|
9150
|
-
);
|
|
9151
|
-
if (localName === null) {
|
|
9152
|
-
return [];
|
|
9153
|
-
}
|
|
9194
|
+
const isTheClient = clientReceiverCheckFor(sourceFile, match, resolution);
|
|
9154
9195
|
const methodSpec = /* @__PURE__ */ new Map();
|
|
9155
9196
|
for (const method of match.methods) {
|
|
9156
9197
|
methodSpec.set(method.methodName, {
|
|
@@ -9172,6 +9213,9 @@ function discoverGraphqlImperativeCalls(sourceFile, match, kind, resolution) {
|
|
|
9172
9213
|
if (spec === void 0) {
|
|
9173
9214
|
return;
|
|
9174
9215
|
}
|
|
9216
|
+
if (!isTheClient(callee.getExpression())) {
|
|
9217
|
+
return;
|
|
9218
|
+
}
|
|
9175
9219
|
const args = node.getArguments();
|
|
9176
9220
|
if (args.length === 0 || !Node40.isObjectLiteralExpression(args[0])) {
|
|
9177
9221
|
return;
|
|
@@ -10314,8 +10358,24 @@ function pathFromUrlNode(node, resolution) {
|
|
|
10314
10358
|
if (Node46.isTemplateExpression(node)) {
|
|
10315
10359
|
return pathFromTemplateUrl(node, resolution);
|
|
10316
10360
|
}
|
|
10361
|
+
if (Node46.isBinaryExpression(node)) {
|
|
10362
|
+
const joined = joinedStringOf(node, resolution);
|
|
10363
|
+
return joined === void 0 ? void 0 : pathFromLiteralUrl(joined);
|
|
10364
|
+
}
|
|
10317
10365
|
return void 0;
|
|
10318
10366
|
}
|
|
10367
|
+
function joinedStringOf(node, resolution) {
|
|
10368
|
+
if (Node46.isStringLiteral(node) || Node46.isNoSubstitutionTemplateLiteral(node)) {
|
|
10369
|
+
return node.getLiteralValue();
|
|
10370
|
+
}
|
|
10371
|
+
if (Node46.isBinaryExpression(node) && node.getOperatorToken().getText() === "+") {
|
|
10372
|
+
const left = joinedStringOf(node.getLeft(), resolution);
|
|
10373
|
+
const right = joinedStringOf(node.getRight(), resolution);
|
|
10374
|
+
return left === void 0 || right === void 0 ? void 0 : left + right;
|
|
10375
|
+
}
|
|
10376
|
+
const written = resolution?.resolveWrittenValue(node) ?? null;
|
|
10377
|
+
return written === null || written === node ? void 0 : joinedStringOf(written, resolution);
|
|
10378
|
+
}
|
|
10319
10379
|
function placeholderName(expr) {
|
|
10320
10380
|
if (Node46.isIdentifier(expr)) {
|
|
10321
10381
|
return expr.getText();
|
|
@@ -10648,18 +10708,38 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
10648
10708
|
import { Node as Node48 } from "ts-morph";
|
|
10649
10709
|
function discoverRegistrationLoops(sourceFile, match, kind, resolution) {
|
|
10650
10710
|
const results = [];
|
|
10711
|
+
const routables = routableNames(sourceFile, match);
|
|
10712
|
+
if (routables !== null && routables.size === 0) {
|
|
10713
|
+
return results;
|
|
10714
|
+
}
|
|
10651
10715
|
sourceFile.forEachDescendant((node) => {
|
|
10652
10716
|
if (!Node48.isForOfStatement(node)) {
|
|
10653
10717
|
return;
|
|
10654
10718
|
}
|
|
10655
|
-
const expanded = tryExpandLoop(node, match, kind, resolution);
|
|
10719
|
+
const expanded = tryExpandLoop(node, match, kind, resolution, routables);
|
|
10656
10720
|
if (expanded !== null) {
|
|
10657
10721
|
results.push(...expanded);
|
|
10658
10722
|
}
|
|
10659
10723
|
});
|
|
10660
10724
|
return results;
|
|
10661
10725
|
}
|
|
10662
|
-
function
|
|
10726
|
+
function routableNames(sourceFile, match) {
|
|
10727
|
+
if (match.receiver === void 0) {
|
|
10728
|
+
return null;
|
|
10729
|
+
}
|
|
10730
|
+
const names = /* @__PURE__ */ new Set();
|
|
10731
|
+
for (const importName of match.receiver.importNames) {
|
|
10732
|
+
for (const name of registrationSubjectsOf(
|
|
10733
|
+
sourceFile,
|
|
10734
|
+
match.receiver.importModule,
|
|
10735
|
+
importName
|
|
10736
|
+
).keys()) {
|
|
10737
|
+
names.add(name);
|
|
10738
|
+
}
|
|
10739
|
+
}
|
|
10740
|
+
return names;
|
|
10741
|
+
}
|
|
10742
|
+
function tryExpandLoop(loop, match, kind, resolution, routables) {
|
|
10663
10743
|
const loopVar = loopVariableName(loop);
|
|
10664
10744
|
if (loopVar === null) {
|
|
10665
10745
|
return null;
|
|
@@ -10667,6 +10747,9 @@ function tryExpandLoop(loop, match, kind, resolution) {
|
|
|
10667
10747
|
if (!bodyReferencesLoopVar(loop, loopVar)) {
|
|
10668
10748
|
return null;
|
|
10669
10749
|
}
|
|
10750
|
+
if (routables !== null && !bodyCallsOn(loop, routables)) {
|
|
10751
|
+
return null;
|
|
10752
|
+
}
|
|
10670
10753
|
const arrayLit = arrayLiteralOf(loop.getExpression(), resolution);
|
|
10671
10754
|
if (arrayLit === null) {
|
|
10672
10755
|
return null;
|
|
@@ -10725,6 +10808,20 @@ function bodyReferencesLoopVar(loop, name) {
|
|
|
10725
10808
|
});
|
|
10726
10809
|
return referenced;
|
|
10727
10810
|
}
|
|
10811
|
+
function bodyCallsOn(loop, routables) {
|
|
10812
|
+
let found = false;
|
|
10813
|
+
loop.getStatement().forEachDescendant((node) => {
|
|
10814
|
+
if (found || !Node48.isCallExpression(node)) {
|
|
10815
|
+
return;
|
|
10816
|
+
}
|
|
10817
|
+
const callee = node.getExpression();
|
|
10818
|
+
const subject = Node48.isPropertyAccessExpression(callee) || Node48.isElementAccessExpression(callee) ? callee.getExpression() : null;
|
|
10819
|
+
if (subject !== null && Node48.isIdentifier(subject) && routables.has(subject.getText())) {
|
|
10820
|
+
found = true;
|
|
10821
|
+
}
|
|
10822
|
+
});
|
|
10823
|
+
return found;
|
|
10824
|
+
}
|
|
10728
10825
|
function readRouteSpec(element, shape, resolution) {
|
|
10729
10826
|
let method = null;
|
|
10730
10827
|
let path12 = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-typescript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TypeScript adapter for suss — walks source files with ts-morph and emits raw extractions for the suss pipeline.",
|
|
6
6
|
"keywords": [
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@suss/behavioral-ir": "0.
|
|
50
|
-
"@suss/datalog": "0.
|
|
51
|
-
"@suss/extractor": "0.
|
|
52
|
-
"@suss/resolution": "0.
|
|
49
|
+
"@suss/behavioral-ir": "0.15.0",
|
|
50
|
+
"@suss/datalog": "0.15.0",
|
|
51
|
+
"@suss/extractor": "0.15.0",
|
|
52
|
+
"@suss/resolution": "0.15.0",
|
|
53
53
|
"graphql": "^16.8.0",
|
|
54
54
|
"picomatch": "^4.0.4",
|
|
55
55
|
"ts-morph": "^23.0.0"
|