@emeryld/rrroutes-contract 2.7.6 → 2.7.8
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/README.md +1 -0
- package/dist/export/defaultViewerTemplate.d.ts +1 -1
- package/dist/export/exportFinalizedLeaves.d.ts +7 -1
- package/dist/export/extractLeafSourceByAst.d.ts +8 -0
- package/dist/index.cjs +248 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +248 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/tools/finalized-leaves-viewer.html +55 -29
package/dist/index.mjs
CHANGED
|
@@ -688,18 +688,18 @@ var DEFAULT_VIEWER_TEMPLATE = `<!doctype html>
|
|
|
688
688
|
<title>Finalized Leaves Viewer</title>
|
|
689
689
|
<style>
|
|
690
690
|
:root {
|
|
691
|
-
--bg: #
|
|
692
|
-
--surface: #
|
|
693
|
-
--border: #
|
|
694
|
-
--text: #
|
|
695
|
-
--muted: #
|
|
696
|
-
--accent: #
|
|
691
|
+
--bg: #212121;
|
|
692
|
+
--surface: #2a2a2a;
|
|
693
|
+
--border: #4a4a4a;
|
|
694
|
+
--text: #fffafa;
|
|
695
|
+
--muted: #c8c2c2;
|
|
696
|
+
--accent: #a764d3;
|
|
697
697
|
}
|
|
698
698
|
body {
|
|
699
699
|
margin: 0;
|
|
700
700
|
font-family: 'Iosevka Web', 'SFMono-Regular', Menlo, Consolas, monospace;
|
|
701
701
|
color: var(--text);
|
|
702
|
-
background:
|
|
702
|
+
background: var(--bg);
|
|
703
703
|
}
|
|
704
704
|
.wrap { max-width: 1100px; margin: 0 auto; padding: 20px; }
|
|
705
705
|
.card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px; }
|
|
@@ -707,7 +707,7 @@ var DEFAULT_VIEWER_TEMPLATE = `<!doctype html>
|
|
|
707
707
|
#results { margin-top: 12px; display: grid; gap: 8px; }
|
|
708
708
|
details { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; }
|
|
709
709
|
summary { cursor: pointer; font-weight: 700; color: var(--accent); }
|
|
710
|
-
pre { margin: 10px 0 0; overflow: auto; border: 1px solid var(--border); border-radius: 8px; padding: 10px; background: #
|
|
710
|
+
pre { margin: 10px 0 0; overflow: auto; border: 1px solid var(--border); border-radius: 8px; padding: 10px; background: #303030; color: var(--text); }
|
|
711
711
|
</style>
|
|
712
712
|
</head>
|
|
713
713
|
<body>
|
|
@@ -738,6 +738,10 @@ var DEFAULT_VIEWER_TEMPLATE = `<!doctype html>
|
|
|
738
738
|
return prefix + encodeURI(normalizedPath)
|
|
739
739
|
}
|
|
740
740
|
|
|
741
|
+
const sourceDisplay = (source) => {
|
|
742
|
+
return ''
|
|
743
|
+
}
|
|
744
|
+
|
|
741
745
|
payload.leaves.forEach((leaf) => {
|
|
742
746
|
const details = document.createElement('details')
|
|
743
747
|
const summary = document.createElement('summary')
|
|
@@ -759,13 +763,7 @@ var DEFAULT_VIEWER_TEMPLATE = `<!doctype html>
|
|
|
759
763
|
link.href = definitionHref
|
|
760
764
|
link.target = '_blank'
|
|
761
765
|
link.rel = 'noopener noreferrer'
|
|
762
|
-
link.textContent =
|
|
763
|
-
'definition: ' +
|
|
764
|
-
source.definition.file +
|
|
765
|
-
':' +
|
|
766
|
-
source.definition.line +
|
|
767
|
-
':' +
|
|
768
|
-
source.definition.column
|
|
766
|
+
link.textContent = 'definition'
|
|
769
767
|
label.appendChild(link)
|
|
770
768
|
sourceWrap.appendChild(label)
|
|
771
769
|
}
|
|
@@ -781,16 +779,7 @@ var DEFAULT_VIEWER_TEMPLATE = `<!doctype html>
|
|
|
781
779
|
link.target = '_blank'
|
|
782
780
|
link.rel = 'noopener noreferrer'
|
|
783
781
|
link.textContent =
|
|
784
|
-
name +
|
|
785
|
-
': ' +
|
|
786
|
-
(schema.sourceName || schema.tag || '<anonymous>') +
|
|
787
|
-
' (' +
|
|
788
|
-
schema.file +
|
|
789
|
-
':' +
|
|
790
|
-
schema.line +
|
|
791
|
-
':' +
|
|
792
|
-
schema.column +
|
|
793
|
-
')'
|
|
782
|
+
name + ': ' + (schema.sourceName || schema.tag || '<anonymous>')
|
|
794
783
|
row.appendChild(link)
|
|
795
784
|
} else {
|
|
796
785
|
row.textContent = name + ': ' + (schema.sourceName || schema.tag || '<anonymous>')
|
|
@@ -824,6 +813,7 @@ var SCHEMA_KEYS = [
|
|
|
824
813
|
"queryExtensionSchema"
|
|
825
814
|
];
|
|
826
815
|
var HTTP_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete"]);
|
|
816
|
+
var MAX_RECURSION_DEPTH = 120;
|
|
827
817
|
function toLocation(node) {
|
|
828
818
|
const sourceFile = node.getSourceFile();
|
|
829
819
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(
|
|
@@ -835,6 +825,10 @@ function toLocation(node) {
|
|
|
835
825
|
column: character + 1
|
|
836
826
|
};
|
|
837
827
|
}
|
|
828
|
+
function markFile(ctx, sourceFile) {
|
|
829
|
+
if (!sourceFile) return;
|
|
830
|
+
ctx.visitedFilePaths.add(path.resolve(sourceFile.fileName));
|
|
831
|
+
}
|
|
838
832
|
function trimPreview(text, max = 80) {
|
|
839
833
|
const normalized = text.replace(/\s+/g, " ").trim();
|
|
840
834
|
return normalized.length > max ? `${normalized.slice(0, max)}...` : normalized;
|
|
@@ -892,7 +886,7 @@ function findSourceFile(program, filePath) {
|
|
|
892
886
|
const normalizedWanted = path.normalize(wanted);
|
|
893
887
|
return program.getSourceFiles().find((file) => path.normalize(path.resolve(file.fileName)) === normalizedWanted);
|
|
894
888
|
}
|
|
895
|
-
function
|
|
889
|
+
function declarationToExpression(declaration) {
|
|
896
890
|
if (!declaration) return void 0;
|
|
897
891
|
if (ts.isVariableDeclaration(declaration)) {
|
|
898
892
|
return declaration.initializer;
|
|
@@ -909,14 +903,95 @@ function expressionFromDeclaration(declaration) {
|
|
|
909
903
|
if (ts.isBindingElement(declaration)) {
|
|
910
904
|
return declaration.initializer;
|
|
911
905
|
}
|
|
906
|
+
if (ts.isEnumMember(declaration)) {
|
|
907
|
+
return declaration.initializer;
|
|
908
|
+
}
|
|
912
909
|
return void 0;
|
|
913
910
|
}
|
|
914
|
-
function
|
|
915
|
-
const
|
|
916
|
-
if (!
|
|
911
|
+
function symbolKey(symbol) {
|
|
912
|
+
const decl = symbol.declarations?.[0];
|
|
913
|
+
if (!decl) return `${symbol.getName()}#${symbol.flags}`;
|
|
914
|
+
const file = path.resolve(decl.getSourceFile().fileName);
|
|
915
|
+
return `${file}:${decl.getStart()}:${symbol.getName()}`;
|
|
916
|
+
}
|
|
917
|
+
function resolveSymbolFromNode(node, ctx) {
|
|
918
|
+
const symbol = ctx.checker.getSymbolAtLocation(node);
|
|
919
|
+
if (!symbol) {
|
|
920
|
+
ctx.unresolvedReferences += 1;
|
|
921
|
+
return void 0;
|
|
922
|
+
}
|
|
917
923
|
const target = getAliasedSymbolIfNeeded(ctx.checker, symbol);
|
|
918
|
-
const
|
|
919
|
-
|
|
924
|
+
const key = symbolKey(target);
|
|
925
|
+
ctx.visitedSymbolKeys.add(key);
|
|
926
|
+
return target;
|
|
927
|
+
}
|
|
928
|
+
function getExpressionFromSymbol(symbol, ctx, depth) {
|
|
929
|
+
const key = symbolKey(symbol);
|
|
930
|
+
if (ctx.activeSymbols.has(key)) return void 0;
|
|
931
|
+
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
932
|
+
ctx.activeSymbols.add(key);
|
|
933
|
+
try {
|
|
934
|
+
const declaration = symbol.declarations?.[0];
|
|
935
|
+
markFile(ctx, declaration?.getSourceFile());
|
|
936
|
+
const direct = declarationToExpression(declaration);
|
|
937
|
+
if (direct) return direct;
|
|
938
|
+
if (declaration && ts.isImportSpecifier(declaration)) {
|
|
939
|
+
const target = getAliasedSymbolIfNeeded(ctx.checker, symbol);
|
|
940
|
+
if (target !== symbol) {
|
|
941
|
+
return getExpressionFromSymbol(target, ctx, depth + 1);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
return void 0;
|
|
945
|
+
} finally {
|
|
946
|
+
ctx.activeSymbols.delete(key);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
function resolveIdentifierExpression(identifier, ctx, depth) {
|
|
950
|
+
const symbol = resolveSymbolFromNode(identifier, ctx);
|
|
951
|
+
if (!symbol) return void 0;
|
|
952
|
+
return getExpressionFromSymbol(symbol, ctx, depth);
|
|
953
|
+
}
|
|
954
|
+
function resolvePropertyExpression(expression, ctx, depth) {
|
|
955
|
+
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
956
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
957
|
+
const symbol = resolveSymbolFromNode(expression.name, ctx);
|
|
958
|
+
if (symbol) {
|
|
959
|
+
const fromSymbol = getExpressionFromSymbol(symbol, ctx, depth + 1);
|
|
960
|
+
if (fromSymbol) return fromSymbol;
|
|
961
|
+
}
|
|
962
|
+
} else if (expression.argumentExpression) {
|
|
963
|
+
const symbol = resolveSymbolFromNode(expression.argumentExpression, ctx);
|
|
964
|
+
if (symbol) {
|
|
965
|
+
const fromSymbol = getExpressionFromSymbol(symbol, ctx, depth + 1);
|
|
966
|
+
if (fromSymbol) return fromSymbol;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
const ownerExpr = evaluateExpressionReference(expression.expression, ctx, depth + 1);
|
|
970
|
+
const owner = ownerExpr ? maybeObjectLiteral(ownerExpr, ctx, depth + 1) : void 0;
|
|
971
|
+
if (!owner) return void 0;
|
|
972
|
+
const propName = ts.isPropertyAccessExpression(expression) ? expression.name.text : expression.argumentExpression && ts.isStringLiteralLike(expression.argumentExpression) ? expression.argumentExpression.text : void 0;
|
|
973
|
+
if (!propName) return void 0;
|
|
974
|
+
for (const property of owner.properties) {
|
|
975
|
+
if (ts.isPropertyAssignment(property) && getTextName(property.name) === propName) {
|
|
976
|
+
return property.initializer;
|
|
977
|
+
}
|
|
978
|
+
if (ts.isShorthandPropertyAssignment(property) && property.name.text === propName) {
|
|
979
|
+
return property.name;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return void 0;
|
|
983
|
+
}
|
|
984
|
+
function evaluateExpressionReference(expression, ctx, depth) {
|
|
985
|
+
const resolved = unwrapExpression(expression);
|
|
986
|
+
markFile(ctx, resolved.getSourceFile());
|
|
987
|
+
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
988
|
+
if (ts.isIdentifier(resolved)) {
|
|
989
|
+
return resolveIdentifierExpression(resolved, ctx, depth + 1);
|
|
990
|
+
}
|
|
991
|
+
if (ts.isPropertyAccessExpression(resolved) || ts.isElementAccessExpression(resolved)) {
|
|
992
|
+
return resolvePropertyExpression(resolved, ctx, depth + 1);
|
|
993
|
+
}
|
|
994
|
+
return void 0;
|
|
920
995
|
}
|
|
921
996
|
function resolveExportExpression(sourceFile, exportName, checker) {
|
|
922
997
|
const moduleSymbol = getModuleSymbol(checker, sourceFile);
|
|
@@ -925,12 +1000,12 @@ function resolveExportExpression(sourceFile, exportName, checker) {
|
|
|
925
1000
|
const explicit = exports.find((entry) => entry.getName() === exportName);
|
|
926
1001
|
if (explicit) {
|
|
927
1002
|
const declaration = getAliasedSymbolIfNeeded(checker, explicit).declarations?.[0];
|
|
928
|
-
return
|
|
1003
|
+
return declarationToExpression(declaration);
|
|
929
1004
|
}
|
|
930
1005
|
const defaultExport = exports.find((entry) => entry.getName() === "default");
|
|
931
1006
|
if (!defaultExport) return void 0;
|
|
932
1007
|
const defaultDecl = getAliasedSymbolIfNeeded(checker, defaultExport).declarations?.[0];
|
|
933
|
-
const defaultExpr =
|
|
1008
|
+
const defaultExpr = declarationToExpression(defaultDecl);
|
|
934
1009
|
if (!defaultExpr) return void 0;
|
|
935
1010
|
const resolved = unwrapExpression(defaultExpr);
|
|
936
1011
|
if (!ts.isObjectLiteralExpression(resolved)) return void 0;
|
|
@@ -942,24 +1017,25 @@ function resolveExportExpression(sourceFile, exportName, checker) {
|
|
|
942
1017
|
}
|
|
943
1018
|
return void 0;
|
|
944
1019
|
}
|
|
945
|
-
function maybeObjectLiteral(expression, ctx) {
|
|
946
|
-
if (!expression) return void 0;
|
|
1020
|
+
function maybeObjectLiteral(expression, ctx, depth = 0) {
|
|
1021
|
+
if (!expression || depth > MAX_RECURSION_DEPTH) return void 0;
|
|
947
1022
|
const resolved = unwrapExpression(expression);
|
|
1023
|
+
markFile(ctx, resolved.getSourceFile());
|
|
948
1024
|
if (ts.isObjectLiteralExpression(resolved)) return resolved;
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
return maybeObjectLiteral(target, ctx);
|
|
953
|
-
}
|
|
954
|
-
return void 0;
|
|
1025
|
+
const referenced = evaluateExpressionReference(resolved, ctx, depth + 1);
|
|
1026
|
+
if (!referenced) return void 0;
|
|
1027
|
+
return maybeObjectLiteral(referenced, ctx, depth + 1);
|
|
955
1028
|
}
|
|
956
|
-
function collectSchemaExpressionsFromObject(objectLiteral, ctx) {
|
|
1029
|
+
function collectSchemaExpressionsFromObject(objectLiteral, ctx, depth) {
|
|
957
1030
|
const schemas = {};
|
|
958
1031
|
for (const property of objectLiteral.properties) {
|
|
959
1032
|
if (ts.isSpreadAssignment(property)) {
|
|
960
|
-
const spreadObject = maybeObjectLiteral(property.expression, ctx);
|
|
1033
|
+
const spreadObject = maybeObjectLiteral(property.expression, ctx, depth + 1);
|
|
961
1034
|
if (!spreadObject) continue;
|
|
962
|
-
Object.assign(
|
|
1035
|
+
Object.assign(
|
|
1036
|
+
schemas,
|
|
1037
|
+
collectSchemaExpressionsFromObject(spreadObject, ctx, depth + 1)
|
|
1038
|
+
);
|
|
963
1039
|
continue;
|
|
964
1040
|
}
|
|
965
1041
|
if (ts.isPropertyAssignment(property)) {
|
|
@@ -976,10 +1052,10 @@ function collectSchemaExpressionsFromObject(objectLiteral, ctx) {
|
|
|
976
1052
|
}
|
|
977
1053
|
return schemas;
|
|
978
1054
|
}
|
|
979
|
-
function extractSchemaExpressions(cfgExpression, ctx) {
|
|
980
|
-
const objectLiteral = maybeObjectLiteral(cfgExpression, ctx);
|
|
1055
|
+
function extractSchemaExpressions(cfgExpression, ctx, depth) {
|
|
1056
|
+
const objectLiteral = maybeObjectLiteral(cfgExpression, ctx, depth);
|
|
981
1057
|
if (!objectLiteral) return {};
|
|
982
|
-
return collectSchemaExpressionsFromObject(objectLiteral, ctx);
|
|
1058
|
+
return collectSchemaExpressionsFromObject(objectLiteral, ctx, depth);
|
|
983
1059
|
}
|
|
984
1060
|
function getNearestVariableName(node) {
|
|
985
1061
|
let current = node;
|
|
@@ -991,31 +1067,45 @@ function getNearestVariableName(node) {
|
|
|
991
1067
|
}
|
|
992
1068
|
return void 0;
|
|
993
1069
|
}
|
|
994
|
-
function
|
|
1070
|
+
function isAllAccess(expression) {
|
|
1071
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
1072
|
+
return expression.name.text === "all";
|
|
1073
|
+
}
|
|
1074
|
+
return Boolean(
|
|
1075
|
+
expression.argumentExpression && ts.isStringLiteralLike(expression.argumentExpression) && expression.argumentExpression.text === "all"
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
function evaluateBranchExpression(expression, ctx, depth) {
|
|
995
1079
|
const resolved = unwrapExpression(expression);
|
|
1080
|
+
markFile(ctx, resolved.getSourceFile());
|
|
1081
|
+
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
996
1082
|
if (ts.isIdentifier(resolved)) {
|
|
997
|
-
const valueExpr = resolveIdentifierExpression(resolved, ctx);
|
|
1083
|
+
const valueExpr = resolveIdentifierExpression(resolved, ctx, depth + 1);
|
|
998
1084
|
if (!valueExpr) return void 0;
|
|
999
|
-
return evaluateBranchExpression(valueExpr, ctx);
|
|
1085
|
+
return evaluateBranchExpression(valueExpr, ctx, depth + 1);
|
|
1000
1086
|
}
|
|
1001
1087
|
if (!ts.isCallExpression(resolved)) return void 0;
|
|
1002
1088
|
const call = resolved;
|
|
1003
1089
|
if (ts.isIdentifier(call.expression) && call.expression.text === "resource") {
|
|
1004
1090
|
const firstArg = call.arguments[0];
|
|
1005
|
-
if (!firstArg || !ts.isStringLiteralLike(firstArg))
|
|
1091
|
+
if (!firstArg || !ts.isStringLiteralLike(firstArg)) {
|
|
1092
|
+
ctx.unsupportedShapeSeen = true;
|
|
1093
|
+
return void 0;
|
|
1094
|
+
}
|
|
1006
1095
|
return { base: normalizeResourceBase(firstArg.text), leaves: [] };
|
|
1007
1096
|
}
|
|
1008
|
-
if (!ts.isPropertyAccessExpression(call.expression))
|
|
1097
|
+
if (!ts.isPropertyAccessExpression(call.expression)) {
|
|
1098
|
+
ctx.unsupportedShapeSeen = true;
|
|
1099
|
+
return void 0;
|
|
1100
|
+
}
|
|
1009
1101
|
const owner = call.expression.expression;
|
|
1010
1102
|
const method = call.expression.name.text;
|
|
1011
|
-
const branch = evaluateBranchExpression(owner, ctx);
|
|
1103
|
+
const branch = evaluateBranchExpression(owner, ctx, depth + 1);
|
|
1012
1104
|
if (!branch) return void 0;
|
|
1013
|
-
if (method === "with")
|
|
1014
|
-
return branch;
|
|
1015
|
-
}
|
|
1105
|
+
if (method === "with") return branch;
|
|
1016
1106
|
if (HTTP_METHODS.has(method)) {
|
|
1017
1107
|
const cfgExpression = call.arguments[0];
|
|
1018
|
-
const schemas = extractSchemaExpressions(cfgExpression, ctx);
|
|
1108
|
+
const schemas = extractSchemaExpressions(cfgExpression, ctx, depth + 1);
|
|
1019
1109
|
const nextLeaf = {
|
|
1020
1110
|
method,
|
|
1021
1111
|
path: branch.base,
|
|
@@ -1029,7 +1119,7 @@ function evaluateBranchExpression(expression, ctx) {
|
|
|
1029
1119
|
}
|
|
1030
1120
|
if (method === "sub") {
|
|
1031
1121
|
const mountedLeaves = call.arguments.flatMap(
|
|
1032
|
-
(arg) => evaluateLeavesFromExpression(arg, ctx)
|
|
1122
|
+
(arg) => evaluateLeavesFromExpression(arg, ctx, depth + 1)
|
|
1033
1123
|
);
|
|
1034
1124
|
const prefixed = mountedLeaves.map((leaf) => ({
|
|
1035
1125
|
...leaf,
|
|
@@ -1040,29 +1130,44 @@ function evaluateBranchExpression(expression, ctx) {
|
|
|
1040
1130
|
leaves: [...branch.leaves, ...prefixed]
|
|
1041
1131
|
};
|
|
1042
1132
|
}
|
|
1133
|
+
ctx.unsupportedShapeSeen = true;
|
|
1043
1134
|
return void 0;
|
|
1044
1135
|
}
|
|
1045
|
-
function
|
|
1136
|
+
function expressionKey(expression) {
|
|
1137
|
+
const source = expression.getSourceFile();
|
|
1138
|
+
return `${path.resolve(source.fileName)}:${expression.getStart(source)}:${expression.getEnd()}:${expression.kind}`;
|
|
1139
|
+
}
|
|
1140
|
+
function evaluateLeavesFromExpression(expression, ctx, depth = 0) {
|
|
1046
1141
|
const resolved = unwrapExpression(expression);
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
ctx.
|
|
1142
|
+
markFile(ctx, resolved.getSourceFile());
|
|
1143
|
+
const key = expressionKey(resolved);
|
|
1144
|
+
if (ctx.activeExpressionKeys.has(key)) return [];
|
|
1145
|
+
if (depth > MAX_RECURSION_DEPTH) return [];
|
|
1146
|
+
ctx.activeExpressionKeys.add(key);
|
|
1052
1147
|
try {
|
|
1053
1148
|
if (ts.isIdentifier(resolved)) {
|
|
1054
|
-
const valueExpr = resolveIdentifierExpression(resolved, ctx);
|
|
1149
|
+
const valueExpr = resolveIdentifierExpression(resolved, ctx, depth + 1);
|
|
1055
1150
|
if (!valueExpr) return [];
|
|
1056
|
-
return evaluateLeavesFromExpression(valueExpr, ctx);
|
|
1151
|
+
return evaluateLeavesFromExpression(valueExpr, ctx, depth + 1);
|
|
1152
|
+
}
|
|
1153
|
+
if (ts.isPropertyAccessExpression(resolved) || ts.isElementAccessExpression(resolved)) {
|
|
1154
|
+
if (isAllAccess(resolved)) {
|
|
1155
|
+
return evaluateLeavesFromExpression(resolved.expression, ctx, depth + 1);
|
|
1156
|
+
}
|
|
1157
|
+
const refExpr = resolvePropertyExpression(resolved, ctx, depth + 1);
|
|
1158
|
+
if (refExpr) {
|
|
1159
|
+
return evaluateLeavesFromExpression(refExpr, ctx, depth + 1);
|
|
1160
|
+
}
|
|
1161
|
+
return [];
|
|
1057
1162
|
}
|
|
1058
1163
|
if (ts.isArrayLiteralExpression(resolved)) {
|
|
1059
1164
|
const leaves = [];
|
|
1060
1165
|
for (const element of resolved.elements) {
|
|
1061
1166
|
if (ts.isSpreadElement(element)) {
|
|
1062
|
-
leaves.push(...evaluateLeavesFromExpression(element.expression, ctx));
|
|
1167
|
+
leaves.push(...evaluateLeavesFromExpression(element.expression, ctx, depth + 1));
|
|
1063
1168
|
continue;
|
|
1064
1169
|
}
|
|
1065
|
-
leaves.push(...evaluateLeavesFromExpression(element, ctx));
|
|
1170
|
+
leaves.push(...evaluateLeavesFromExpression(element, ctx, depth + 1));
|
|
1066
1171
|
}
|
|
1067
1172
|
return leaves;
|
|
1068
1173
|
}
|
|
@@ -1072,34 +1177,43 @@ function evaluateLeavesFromExpression(expression, ctx) {
|
|
|
1072
1177
|
if (callName === "finalize") {
|
|
1073
1178
|
const arg = resolved.arguments[0];
|
|
1074
1179
|
if (!arg) return [];
|
|
1075
|
-
return evaluateLeavesFromExpression(arg, ctx);
|
|
1180
|
+
return evaluateLeavesFromExpression(arg, ctx, depth + 1);
|
|
1076
1181
|
}
|
|
1077
1182
|
if (callName === "mergeArrays") {
|
|
1078
1183
|
return resolved.arguments.flatMap(
|
|
1079
|
-
(arg) => evaluateLeavesFromExpression(arg, ctx)
|
|
1184
|
+
(arg) => evaluateLeavesFromExpression(arg, ctx, depth + 1)
|
|
1080
1185
|
);
|
|
1081
1186
|
}
|
|
1082
1187
|
}
|
|
1083
1188
|
if (ts.isPropertyAccessExpression(resolved.expression)) {
|
|
1084
1189
|
const prop = resolved.expression.name.text;
|
|
1085
1190
|
if (prop === "done") {
|
|
1086
|
-
const branch2 = evaluateBranchExpression(
|
|
1191
|
+
const branch2 = evaluateBranchExpression(
|
|
1192
|
+
resolved.expression.expression,
|
|
1193
|
+
ctx,
|
|
1194
|
+
depth + 1
|
|
1195
|
+
);
|
|
1087
1196
|
return branch2?.leaves ?? [];
|
|
1088
1197
|
}
|
|
1089
1198
|
}
|
|
1199
|
+
const refExpr = evaluateExpressionReference(resolved, ctx, depth + 1);
|
|
1200
|
+
if (refExpr) return evaluateLeavesFromExpression(refExpr, ctx, depth + 1);
|
|
1201
|
+
ctx.unsupportedShapeSeen = true;
|
|
1202
|
+
return [];
|
|
1090
1203
|
}
|
|
1091
|
-
const branch = evaluateBranchExpression(resolved, ctx);
|
|
1092
|
-
return branch
|
|
1204
|
+
const branch = evaluateBranchExpression(resolved, ctx, depth + 1);
|
|
1205
|
+
if (branch) return branch.leaves;
|
|
1206
|
+
ctx.unsupportedShapeSeen = true;
|
|
1207
|
+
return [];
|
|
1093
1208
|
} finally {
|
|
1094
|
-
ctx.
|
|
1209
|
+
ctx.activeExpressionKeys.delete(key);
|
|
1095
1210
|
}
|
|
1096
1211
|
}
|
|
1097
1212
|
function resolveSchemaMetadata(expression, ctx) {
|
|
1098
1213
|
const resolved = unwrapExpression(expression);
|
|
1099
1214
|
if (ts.isIdentifier(resolved)) {
|
|
1100
|
-
const symbol =
|
|
1101
|
-
const
|
|
1102
|
-
const declaration = target?.declarations?.[0];
|
|
1215
|
+
const symbol = resolveSymbolFromNode(resolved, ctx);
|
|
1216
|
+
const declaration = symbol?.declarations?.[0];
|
|
1103
1217
|
const locationNode = declaration ? ts.isVariableDeclaration(declaration) ? declaration.name : declaration : resolved;
|
|
1104
1218
|
const sourceName = declaration && ts.isVariableDeclaration(declaration) && ts.isIdentifier(declaration.name) ? declaration.name.text : resolved.text;
|
|
1105
1219
|
return {
|
|
@@ -1137,13 +1251,25 @@ function parseTsConfig(cwd, tsconfigPath) {
|
|
|
1137
1251
|
void 0,
|
|
1138
1252
|
resolvedTsconfig
|
|
1139
1253
|
);
|
|
1140
|
-
|
|
1254
|
+
const nonEmptyInputErrors = parsed.errors.filter((entry) => entry.code !== 18003);
|
|
1255
|
+
if (nonEmptyInputErrors.length > 0) {
|
|
1141
1256
|
throw new Error(
|
|
1142
|
-
|
|
1257
|
+
nonEmptyInputErrors.map((entry) => ts.flattenDiagnosticMessageText(entry.messageText, "\n")).join("\n")
|
|
1143
1258
|
);
|
|
1144
1259
|
}
|
|
1145
1260
|
return { resolvedTsconfig, parsed };
|
|
1146
1261
|
}
|
|
1262
|
+
function createProgramWithFallback(parsed, moduleFileAbs) {
|
|
1263
|
+
const base = ts.createProgram({
|
|
1264
|
+
rootNames: parsed.fileNames,
|
|
1265
|
+
options: parsed.options
|
|
1266
|
+
});
|
|
1267
|
+
if (findSourceFile(base, moduleFileAbs)) {
|
|
1268
|
+
return base;
|
|
1269
|
+
}
|
|
1270
|
+
const rootNames = Array.from(/* @__PURE__ */ new Set([...parsed.fileNames, moduleFileAbs]));
|
|
1271
|
+
return ts.createProgram({ rootNames, options: parsed.options });
|
|
1272
|
+
}
|
|
1147
1273
|
function extractLeafSourceByAst({
|
|
1148
1274
|
modulePath,
|
|
1149
1275
|
exportName,
|
|
@@ -1152,32 +1278,43 @@ function extractLeafSourceByAst({
|
|
|
1152
1278
|
}) {
|
|
1153
1279
|
const parsedConfig = parseTsConfig(cwd, tsconfigPath);
|
|
1154
1280
|
if (!parsedConfig) {
|
|
1155
|
-
return {
|
|
1281
|
+
return {
|
|
1282
|
+
sourceByLeaf: {},
|
|
1283
|
+
reason: "module_not_in_program",
|
|
1284
|
+
stats: { visitedSymbols: 0, visitedFiles: 0, unresolvedReferences: 0 }
|
|
1285
|
+
};
|
|
1156
1286
|
}
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
options: parsedConfig.parsed.options
|
|
1160
|
-
});
|
|
1287
|
+
const moduleAbs = path.resolve(cwd, modulePath);
|
|
1288
|
+
const program = createProgramWithFallback(parsedConfig.parsed, moduleAbs);
|
|
1161
1289
|
const checker = program.getTypeChecker();
|
|
1162
|
-
const moduleFile = findSourceFile(program,
|
|
1290
|
+
const moduleFile = findSourceFile(program, moduleAbs);
|
|
1163
1291
|
if (!moduleFile) {
|
|
1164
1292
|
return {
|
|
1165
1293
|
sourceByLeaf: {},
|
|
1166
|
-
tsconfigPath: parsedConfig.resolvedTsconfig
|
|
1294
|
+
tsconfigPath: parsedConfig.resolvedTsconfig,
|
|
1295
|
+
reason: "module_not_in_program",
|
|
1296
|
+
stats: { visitedSymbols: 0, visitedFiles: 0, unresolvedReferences: 0 }
|
|
1167
1297
|
};
|
|
1168
1298
|
}
|
|
1169
1299
|
const exportedExpression = resolveExportExpression(moduleFile, exportName, checker);
|
|
1170
1300
|
if (!exportedExpression) {
|
|
1171
1301
|
return {
|
|
1172
1302
|
sourceByLeaf: {},
|
|
1173
|
-
tsconfigPath: parsedConfig.resolvedTsconfig
|
|
1303
|
+
tsconfigPath: parsedConfig.resolvedTsconfig,
|
|
1304
|
+
reason: "export_not_found",
|
|
1305
|
+
stats: { visitedSymbols: 0, visitedFiles: 1, unresolvedReferences: 0 }
|
|
1174
1306
|
};
|
|
1175
1307
|
}
|
|
1176
1308
|
const ctx = {
|
|
1177
1309
|
checker,
|
|
1178
|
-
|
|
1310
|
+
activeExpressionKeys: /* @__PURE__ */ new Set(),
|
|
1311
|
+
activeSymbols: /* @__PURE__ */ new Set(),
|
|
1312
|
+
visitedSymbolKeys: /* @__PURE__ */ new Set(),
|
|
1313
|
+
visitedFilePaths: /* @__PURE__ */ new Set([path.resolve(moduleFile.fileName)]),
|
|
1314
|
+
unresolvedReferences: 0,
|
|
1315
|
+
unsupportedShapeSeen: false
|
|
1179
1316
|
};
|
|
1180
|
-
const evaluatedLeaves = evaluateLeavesFromExpression(exportedExpression, ctx);
|
|
1317
|
+
const evaluatedLeaves = evaluateLeavesFromExpression(exportedExpression, ctx, 0);
|
|
1181
1318
|
const sourceByLeaf = {};
|
|
1182
1319
|
for (const leaf of evaluatedLeaves) {
|
|
1183
1320
|
const key = buildLeafKey(leaf.method, leaf.path);
|
|
@@ -1185,17 +1322,27 @@ function extractLeafSourceByAst({
|
|
|
1185
1322
|
...toLocation(leaf.definitionNode),
|
|
1186
1323
|
symbolName: getNearestVariableName(leaf.definitionNode)
|
|
1187
1324
|
};
|
|
1325
|
+
ctx.visitedFilePaths.add(definition.file);
|
|
1188
1326
|
const schemas = {};
|
|
1189
1327
|
for (const schemaKey of SCHEMA_KEYS) {
|
|
1190
1328
|
const schemaExpression = leaf.schemas[schemaKey];
|
|
1191
1329
|
if (!schemaExpression) continue;
|
|
1192
|
-
|
|
1330
|
+
const schemaMeta = resolveSchemaMetadata(schemaExpression, ctx);
|
|
1331
|
+
ctx.visitedFilePaths.add(schemaMeta.file);
|
|
1332
|
+
schemas[schemaKey] = schemaMeta;
|
|
1193
1333
|
}
|
|
1194
1334
|
sourceByLeaf[key] = { definition, schemas };
|
|
1195
1335
|
}
|
|
1336
|
+
const reason = Object.keys(sourceByLeaf).length > 0 ? void 0 : ctx.unsupportedShapeSeen ? "unsupported_expression_shape" : "resolved_zero_leaves";
|
|
1196
1337
|
return {
|
|
1197
1338
|
sourceByLeaf,
|
|
1198
|
-
tsconfigPath: parsedConfig.resolvedTsconfig
|
|
1339
|
+
tsconfigPath: parsedConfig.resolvedTsconfig,
|
|
1340
|
+
reason,
|
|
1341
|
+
stats: {
|
|
1342
|
+
visitedSymbols: ctx.visitedSymbolKeys.size,
|
|
1343
|
+
visitedFiles: ctx.visitedFilePaths.size,
|
|
1344
|
+
unresolvedReferences: ctx.unresolvedReferences
|
|
1345
|
+
}
|
|
1199
1346
|
};
|
|
1200
1347
|
}
|
|
1201
1348
|
|
|
@@ -1378,7 +1525,9 @@ async function exportFinalizedLeaves(input, options = {}) {
|
|
|
1378
1525
|
modulePath: path2.resolve(modulePath),
|
|
1379
1526
|
exportName,
|
|
1380
1527
|
tsconfigPath: extracted.tsconfigPath,
|
|
1381
|
-
resolvedLeafCount: Object.keys(sourceByLeaf).length
|
|
1528
|
+
resolvedLeafCount: Object.keys(sourceByLeaf).length,
|
|
1529
|
+
reason: extracted.reason,
|
|
1530
|
+
stats: extracted.stats
|
|
1382
1531
|
};
|
|
1383
1532
|
} else {
|
|
1384
1533
|
sourceExtraction = {
|
|
@@ -1386,7 +1535,13 @@ async function exportFinalizedLeaves(input, options = {}) {
|
|
|
1386
1535
|
enabled: false,
|
|
1387
1536
|
exportName,
|
|
1388
1537
|
tsconfigPath: options.tsconfigPath ? path2.resolve(options.tsconfigPath) : void 0,
|
|
1389
|
-
resolvedLeafCount: 0
|
|
1538
|
+
resolvedLeafCount: 0,
|
|
1539
|
+
reason: "resolved_zero_leaves",
|
|
1540
|
+
stats: {
|
|
1541
|
+
visitedSymbols: 0,
|
|
1542
|
+
visitedFiles: 0,
|
|
1543
|
+
unresolvedReferences: 0
|
|
1544
|
+
}
|
|
1390
1545
|
};
|
|
1391
1546
|
}
|
|
1392
1547
|
}
|