@c4a/extract-ts 0.7.4 → 0.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.
Files changed (2) hide show
  1. package/index.js +1260 -788
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -12532,6 +12532,753 @@ var detectEntries = async (manifest, fs) => {
12532
12532
  };
12533
12533
  };
12534
12534
 
12535
+ // src/componentContract.ts
12536
+ import ts from "typescript";
12537
+ function componentPropsNode(node2) {
12538
+ if (node2 === undefined || !ts.isTypeReferenceNode(node2))
12539
+ return;
12540
+ if (!["FC", "React.FC", "FunctionComponent", "React.FunctionComponent"].includes(node2.typeName.getText()))
12541
+ return;
12542
+ return node2.typeArguments?.length === 1 ? node2.typeArguments[0] : undefined;
12543
+ }
12544
+ function componentLocalPropsNode(node2, checker) {
12545
+ if (ts.isParenthesizedTypeNode(node2))
12546
+ return componentLocalPropsNode(node2.type, checker);
12547
+ if (!ts.isTypeReferenceNode(node2) || node2.typeArguments?.length !== 1)
12548
+ return;
12549
+ const name = node2.typeName;
12550
+ const identifier = ts.isIdentifier(name) ? name : ts.isIdentifier(name.left) ? name.left : undefined;
12551
+ if (identifier === undefined)
12552
+ return;
12553
+ const imported = checker.getSymbolAtLocation(identifier)?.declarations?.find((declaration) => ts.isImportSpecifier(declaration) || ts.isNamespaceImport(declaration) || ts.isImportClause(declaration));
12554
+ if (imported === undefined)
12555
+ return;
12556
+ let owner = imported;
12557
+ while (!ts.isImportDeclaration(owner) && owner.parent !== undefined)
12558
+ owner = owner.parent;
12559
+ if (!ts.isImportDeclaration(owner) || !ts.isStringLiteral(owner.moduleSpecifier) || owner.moduleSpecifier.text !== "react")
12560
+ return;
12561
+ const wrapper = ts.isIdentifier(name) ? ts.isImportSpecifier(imported) ? (imported.propertyName ?? imported.name).text : undefined : ts.isNamespaceImport(imported) || ts.isImportClause(imported) ? name.right.text : undefined;
12562
+ return wrapper === "PropsWithChildren" ? node2.typeArguments[0] : undefined;
12563
+ }
12564
+ function componentPropsName(annotation) {
12565
+ const source = ts.createSourceFile("contract.ts", `type Contract = ${annotation};`, ts.ScriptTarget.Latest, true);
12566
+ const declaration = source.statements[0];
12567
+ if (declaration === undefined || !ts.isTypeAliasDeclaration(declaration))
12568
+ return;
12569
+ const props = componentPropsNode(declaration.type);
12570
+ return props !== undefined && ts.isTypeReferenceNode(props) && ts.isIdentifier(props.typeName) && !props.typeArguments?.length ? props.typeName.text : undefined;
12571
+ }
12572
+ function componentBindingDefaults(pattern) {
12573
+ const source = ts.createSourceFile("contract.ts", `function input(${pattern}) {}`, ts.ScriptTarget.Latest, true);
12574
+ const diagnostics = source.parseDiagnostics;
12575
+ const fn = source.statements[0];
12576
+ if (diagnostics.length || source.statements.length !== 1 || fn === undefined || !ts.isFunctionDeclaration(fn) || fn.parameters.length !== 1 || fn.body?.statements.length)
12577
+ return {};
12578
+ const name = fn.parameters[0].name;
12579
+ return componentDefaultsFromBinding(name, source);
12580
+ }
12581
+ function componentDefaultsFromBinding(name, source) {
12582
+ if (!ts.isObjectBindingPattern(name))
12583
+ return {};
12584
+ const defaults = Object.create(null);
12585
+ for (const element of name.elements) {
12586
+ const key = element.propertyName ?? element.name;
12587
+ if (element.initializer === undefined || element.dotDotDotToken !== undefined || !ts.isIdentifier(key) && !ts.isStringLiteral(key) && !ts.isNumericLiteral(key))
12588
+ continue;
12589
+ defaults[key.text] = element.initializer.getText(source);
12590
+ }
12591
+ return defaults;
12592
+ }
12593
+
12594
+ // src/federationContracts.ts
12595
+ import ts2 from "typescript";
12596
+ function federationContracts(source) {
12597
+ const factories = new Set;
12598
+ for (const statement of source.statements) {
12599
+ if (!ts2.isImportDeclaration(statement) || !ts2.isStringLiteral(statement.moduleSpecifier))
12600
+ continue;
12601
+ const module = statement.moduleSpecifier.text;
12602
+ const clause = statement.importClause;
12603
+ if (module === "webpack" && clause?.name !== undefined)
12604
+ factories.add(`${clause.name.text}.container.ModuleFederationPlugin`);
12605
+ if (!["webpack", "@module-federation/enhanced/webpack", "@module-federation/enhanced/rspack", "@module-federation/vite"].includes(module))
12606
+ continue;
12607
+ if (clause?.namedBindings !== undefined && ts2.isNamedImports(clause.namedBindings)) {
12608
+ for (const item of clause.namedBindings.elements) {
12609
+ if (["ModuleFederationPlugin", "federation"].includes((item.propertyName ?? item.name).text))
12610
+ factories.add(item.name.text);
12611
+ if (module === "webpack" && (item.propertyName ?? item.name).text === "container")
12612
+ factories.add(`${item.name.text}.ModuleFederationPlugin`);
12613
+ }
12614
+ }
12615
+ }
12616
+ const results = [];
12617
+ const visit = (node2) => {
12618
+ if ((ts2.isCallExpression(node2) || ts2.isNewExpression(node2)) && factories.has(node2.expression.getText(source))) {
12619
+ const config = node2.arguments?.[0];
12620
+ if (config !== undefined && ts2.isObjectLiteralExpression(config)) {
12621
+ const members = [];
12622
+ for (const property of config.properties) {
12623
+ if (!ts2.isPropertyAssignment(property))
12624
+ continue;
12625
+ const key = property.name.getText(source).replace(/^['"]|['"]$/gu, "");
12626
+ if (!["name", "filename", "exposes", "remotes", "shared"].includes(key))
12627
+ continue;
12628
+ const properties = ts2.isObjectLiteralExpression(property.initializer) ? property.initializer.properties.filter(ts2.isPropertyAssignment) : [property];
12629
+ for (const value of properties)
12630
+ members.push({
12631
+ name: value === property ? key : `${key}.${value.name.getText(source).replace(/^['"]|['"]$/gu, "")}`,
12632
+ kind: "config" /* Config */,
12633
+ visibility: "exported" /* Exported */,
12634
+ file: source.fileName.replace(/^\//u, ""),
12635
+ line: source.getLineAndCharacterOfPosition(value.getStart()).line + 1,
12636
+ endLine: source.getLineAndCharacterOfPosition(value.end).line + 1,
12637
+ typeAnnotation: value.initializer.getText(source)
12638
+ });
12639
+ }
12640
+ results.push({
12641
+ name: "Module federation configuration",
12642
+ kind: "config" /* Config */,
12643
+ visibility: "exported" /* Exported */,
12644
+ file: source.fileName.replace(/^\//u, ""),
12645
+ line: source.getLineAndCharacterOfPosition(node2.getStart()).line + 1,
12646
+ endLine: source.getLineAndCharacterOfPosition(node2.end).line + 1,
12647
+ signature: node2.expression.getText(source),
12648
+ members
12649
+ });
12650
+ }
12651
+ }
12652
+ ts2.forEachChild(node2, visit);
12653
+ };
12654
+ visit(source);
12655
+ return results;
12656
+ }
12657
+
12658
+ // src/publicContracts.ts
12659
+ import { posix as posix3 } from "node:path";
12660
+ import ts5 from "typescript";
12661
+
12662
+ // src/typeReferences.ts
12663
+ import ts3 from "typescript";
12664
+ var BUILTIN_TYPES = new Set([
12665
+ "Array",
12666
+ "Boolean",
12667
+ "Date",
12668
+ "Error",
12669
+ "Map",
12670
+ "Number",
12671
+ "Object",
12672
+ "Promise",
12673
+ "ReadonlyArray",
12674
+ "Record",
12675
+ "Set",
12676
+ "String"
12677
+ ]);
12678
+ function referencedTypeNames(text) {
12679
+ if (!text)
12680
+ return [];
12681
+ const file = ts3.createSourceFile("type.ts", `type __Value = ${text};`, ts3.ScriptTarget.Latest, true);
12682
+ const declaration = file.statements[0];
12683
+ if (!declaration || !ts3.isTypeAliasDeclaration(declaration))
12684
+ return [];
12685
+ const result = new Set;
12686
+ const visit = (node2, bound) => {
12687
+ const scope = new Set(bound);
12688
+ if ("typeParameters" in node2) {
12689
+ for (const parameter of node2.typeParameters ?? []) {
12690
+ scope.add(parameter.name.text);
12691
+ }
12692
+ }
12693
+ if (ts3.isMappedTypeNode(node2)) {
12694
+ if (node2.typeParameter.constraint)
12695
+ visit(node2.typeParameter.constraint, bound);
12696
+ scope.add(node2.typeParameter.name.text);
12697
+ if (node2.nameType)
12698
+ visit(node2.nameType, scope);
12699
+ if (node2.type)
12700
+ visit(node2.type, scope);
12701
+ return;
12702
+ }
12703
+ if (ts3.isConditionalTypeNode(node2)) {
12704
+ visit(node2.checkType, scope);
12705
+ visit(node2.extendsType, scope);
12706
+ const inferred = new Set(scope);
12707
+ const collect = (child) => {
12708
+ if (ts3.isInferTypeNode(child))
12709
+ inferred.add(child.typeParameter.name.text);
12710
+ else if (!ts3.isConditionalTypeNode(child))
12711
+ ts3.forEachChild(child, collect);
12712
+ };
12713
+ collect(node2.extendsType);
12714
+ visit(node2.trueType, inferred);
12715
+ visit(node2.falseType, scope);
12716
+ return;
12717
+ }
12718
+ if (ts3.isTypeReferenceNode(node2)) {
12719
+ const name = node2.typeName.getText(file);
12720
+ if (!scope.has(name.split(".")[0]) && !BUILTIN_TYPES.has(name))
12721
+ result.add(name);
12722
+ }
12723
+ ts3.forEachChild(node2, (child) => visit(child, scope));
12724
+ };
12725
+ visit(declaration.type, new Set);
12726
+ return [...result];
12727
+ }
12728
+
12729
+ // src/symbolExtractorAst.ts
12730
+ var DECLARATION_TYPES = new Set([
12731
+ "function_declaration",
12732
+ "class_declaration",
12733
+ "interface_declaration",
12734
+ "type_alias_declaration",
12735
+ "enum_declaration",
12736
+ "lexical_declaration"
12737
+ ]);
12738
+ var countLines = (source) => {
12739
+ if (!source)
12740
+ return 0;
12741
+ return source.split(/\r\n|\r|\n/).filter((line) => line.trim().length > 0).length;
12742
+ };
12743
+ var createRelation = (type, from, to, isExternal, line) => ({
12744
+ type,
12745
+ from,
12746
+ to,
12747
+ isExternal,
12748
+ grounding: "code" /* Code */,
12749
+ confidence: 1,
12750
+ source: "ast" /* Ast */,
12751
+ ...line ? { line } : {}
12752
+ });
12753
+ var getLine = (node2) => node2.startPosition.row + 1;
12754
+ var getEndLine = (node2) => node2.endPosition.row + 1;
12755
+ var extractJSDoc = (node2) => {
12756
+ const prev = node2.previousNamedSibling ?? node2.parent?.previousNamedSibling;
12757
+ if (!prev || prev.type !== "comment")
12758
+ return;
12759
+ const text = prev.text;
12760
+ if (!text.startsWith("/**"))
12761
+ return;
12762
+ const cleaned = text.replace(/^\/\*\*\s*/, "").replace(/\s*\*\/$/, "").replace(/^\s*\* ?/gm, "").trim();
12763
+ return cleaned || undefined;
12764
+ };
12765
+ var extractTypeAnnotation = (node2) => {
12766
+ if (!node2)
12767
+ return null;
12768
+ return node2.text.replace(/^:\s*/, "").trim() || null;
12769
+ };
12770
+ var getNameNodeText = (node2) => node2?.text?.trim() ? node2.text.trim() : null;
12771
+ var getReturnType = (node2) => {
12772
+ const returnNode = node2.childForFieldName("return_type") ?? node2.namedChildren.find((child) => child.type === "type_annotation") ?? null;
12773
+ return extractTypeAnnotation(returnNode);
12774
+ };
12775
+ var getInitializer = (node2) => node2.childForFieldName("value") ?? node2.namedChildren.find((child) => child.type === "arrow_function" || child.type === "function" || child.type === "call_expression") ?? null;
12776
+ var getCallableFromInitializer = (node2) => {
12777
+ if (!node2)
12778
+ return null;
12779
+ if (node2.type === "arrow_function" || node2.type === "function")
12780
+ return node2;
12781
+ if (node2.type === "call_expression") {
12782
+ return node2.namedChildren.find((child) => child.type === "arrow_function" || child.type === "function") ?? null;
12783
+ }
12784
+ return null;
12785
+ };
12786
+ var getInitializerTypeAnnotation = (node2, options = {}) => {
12787
+ if (!node2 || node2.type !== "call_expression")
12788
+ return null;
12789
+ const typeArguments = node2.namedChildren.find((child) => child.type === "type_arguments") ?? null;
12790
+ if (!typeArguments)
12791
+ return null;
12792
+ if (options.referencesOnly) {
12793
+ return `[${typeArguments.namedChildren.filter((child) => child.type !== "comment").map((child) => child.text).join(", ")}]`;
12794
+ }
12795
+ const callee = node2.namedChildren.find((child) => child.type !== "type_arguments" && child.type !== "arguments") ?? null;
12796
+ const calleeText = callee?.text?.trim();
12797
+ return calleeText ? `${calleeText}${typeArguments.text}` : typeArguments.text;
12798
+ };
12799
+ var getInitializerText = (node2, options = {}) => {
12800
+ if (!node2)
12801
+ return null;
12802
+ if ((node2.type === "arrow_function" || node2.type === "function") && !options.includeCallable)
12803
+ return null;
12804
+ const text = node2.text.trim();
12805
+ if ((node2.type === "arrow_function" || node2.type === "function") && text.length > 600)
12806
+ return null;
12807
+ return text.length > 0 ? text : null;
12808
+ };
12809
+ var inferReturnType = (node2) => {
12810
+ if (!node2)
12811
+ return null;
12812
+ return containsJsx(node2) ? "JSX.Element" : null;
12813
+ };
12814
+ var containsJsx = (node2) => {
12815
+ if (node2.type.startsWith("jsx_"))
12816
+ return true;
12817
+ return node2.namedChildren.some(containsJsx);
12818
+ };
12819
+ var resolveTypeBinding = (typeName, importBindings, declarations) => {
12820
+ const localName = typeName.split(".")[0] ?? typeName;
12821
+ const importBinding = importBindings.get(localName);
12822
+ if (importBinding)
12823
+ return importBinding.isExternal;
12824
+ if (declarations.has(localName))
12825
+ return false;
12826
+ return false;
12827
+ };
12828
+ var appendTypeRelations = (relations, relationType, from, typeText, importBindings, declarations, line) => {
12829
+ for (const typeName of referencedTypeNames(typeText)) {
12830
+ relations.push(createRelation(relationType, from, typeName, resolveTypeBinding(typeName, importBindings, declarations), line));
12831
+ }
12832
+ };
12833
+ var classifyVariable = (name, filePath) => {
12834
+ if ((filePath.endsWith(".tsx") || filePath.endsWith(".jsx")) && /^[A-Z]/.test(name)) {
12835
+ return "component" /* Component */;
12836
+ }
12837
+ return "variable" /* Variable */;
12838
+ };
12839
+ var collectParams = (node2) => {
12840
+ if (!node2)
12841
+ return [];
12842
+ return node2.namedChildren.map((child) => {
12843
+ const wrapper = child;
12844
+ const target = child.type === "required_parameter" || child.type === "optional_parameter" ? child.namedChildren[0] ?? child : child;
12845
+ const nameNode = target.childForFieldName("name") ?? target.namedChildren.find((candidate) => candidate.type === "identifier" || candidate.type === "property_identifier") ?? target.namedChildren[0] ?? target;
12846
+ const typeNode = wrapper.childForFieldName("type") ?? wrapper.namedChildren.find((candidate) => candidate.type === "type_annotation") ?? target.childForFieldName("type") ?? target.namedChildren.find((candidate) => candidate.type === "type_annotation") ?? null;
12847
+ return {
12848
+ name: nameNode.text,
12849
+ type: extractTypeAnnotation(typeNode),
12850
+ optional: wrapper.type === "optional_parameter" || wrapper.children.some((child2) => child2.text === "?"),
12851
+ rest: wrapper.text.trimStart().startsWith("..."),
12852
+ ...wrapper.childForFieldName("value") === null ? {} : { defaultValue: wrapper.childForFieldName("value").text }
12853
+ };
12854
+ });
12855
+ };
12856
+ var collectMembers = (node2, declarations, importBindings, ownerName, relations) => {
12857
+ if (!node2)
12858
+ return;
12859
+ const members = [];
12860
+ for (const child of node2.namedChildren) {
12861
+ if (child.type === "public_field_definition" || child.type === "property_signature") {
12862
+ const nameNode = child.childForFieldName("name") ?? child.namedChildren.find((candidate) => candidate.type === "property_identifier" || candidate.type === "identifier");
12863
+ if (!nameNode)
12864
+ continue;
12865
+ const typeNode = child.childForFieldName("type") ?? child.namedChildren.find((candidate) => candidate.type === "type_annotation") ?? null;
12866
+ const typeAnnotation = extractTypeAnnotation(typeNode);
12867
+ const propDoc = extractJSDoc(child);
12868
+ members.push({
12869
+ name: nameNode.text,
12870
+ kind: "prop" /* Prop */,
12871
+ visibility: "internal" /* Internal */,
12872
+ file: "",
12873
+ line: getLine(child),
12874
+ endLine: getEndLine(child),
12875
+ optional: child.children.some((token) => token.text === "?"),
12876
+ readonly: child.children.some((token) => token.text === "readonly"),
12877
+ ...typeAnnotation ? { typeAnnotation } : {},
12878
+ ...propDoc ? { doc: propDoc } : {}
12879
+ });
12880
+ appendTypeRelations(relations, "of_type" /* OfType */, ownerName, typeAnnotation, importBindings, declarations, getLine(child));
12881
+ continue;
12882
+ }
12883
+ const indexMember = indexSignatureMember(child);
12884
+ if (indexMember) {
12885
+ members.push(indexMember.info);
12886
+ appendTypeRelations(relations, "of_type" /* OfType */, ownerName, indexMember.typeAnnotation, importBindings, declarations, getLine(child));
12887
+ continue;
12888
+ }
12889
+ if (child.type === "method_definition" || child.type === "method_signature") {
12890
+ const nameNode = child.childForFieldName("name") ?? child.namedChildren.find((candidate) => candidate.type === "property_identifier" || candidate.type === "identifier");
12891
+ if (!nameNode)
12892
+ continue;
12893
+ const paramsNode = child.childForFieldName("parameters") ?? child.namedChildren.find((candidate) => candidate.type === "formal_parameters") ?? null;
12894
+ const params = collectParams(paramsNode);
12895
+ const returnType = getReturnType(child);
12896
+ const methodDoc = extractJSDoc(child);
12897
+ members.push({
12898
+ name: nameNode.text,
12899
+ kind: "method" /* Method */,
12900
+ visibility: "internal" /* Internal */,
12901
+ file: "",
12902
+ line: getLine(child),
12903
+ endLine: getEndLine(child),
12904
+ ...params.length > 0 ? { params } : {},
12905
+ ...returnType ? { returnType } : {},
12906
+ ...methodDoc ? { doc: methodDoc } : {}
12907
+ });
12908
+ for (const param of params) {
12909
+ appendTypeRelations(relations, "param_type" /* ParamType */, ownerName, param.type, importBindings, declarations, getLine(child));
12910
+ }
12911
+ appendTypeRelations(relations, "return_type" /* ReturnType */, ownerName, returnType, importBindings, declarations, getLine(child));
12912
+ }
12913
+ }
12914
+ return members.length > 0 ? members : undefined;
12915
+ };
12916
+ var indexSignatureMember = (node2) => {
12917
+ if (node2.type !== "index_signature")
12918
+ return null;
12919
+ const match = /^\s*(\[[^\]]+\])\s*:?\s*([^;]+)?;?\s*$/u.exec(node2.text);
12920
+ const name = match?.[1]?.trim();
12921
+ const typeAnnotation = match?.[2]?.trim();
12922
+ if (!name)
12923
+ return null;
12924
+ const propDoc = extractJSDoc(node2);
12925
+ return {
12926
+ info: {
12927
+ name,
12928
+ kind: "prop" /* Prop */,
12929
+ visibility: "internal" /* Internal */,
12930
+ file: "",
12931
+ line: getLine(node2),
12932
+ endLine: getEndLine(node2),
12933
+ ...typeAnnotation ? { typeAnnotation } : {},
12934
+ ...propDoc ? { doc: propDoc } : {}
12935
+ },
12936
+ typeAnnotation
12937
+ };
12938
+ };
12939
+ var collectEnumValues = (node2) => {
12940
+ const body = node2.namedChildren.find((child) => child.type === "enum_body") ?? null;
12941
+ if (!body)
12942
+ return;
12943
+ const values = [];
12944
+ for (const member of body.namedChildren.filter((child) => child.type === "enum_assignment" || child.type === "property_identifier")) {
12945
+ if (member.type === "property_identifier") {
12946
+ values.push(member.text);
12947
+ continue;
12948
+ }
12949
+ const name = member.childForFieldName("name")?.text ?? member.namedChildren[0]?.text;
12950
+ if (!name)
12951
+ continue;
12952
+ const valueNode = member.childForFieldName("value") ?? member.namedChildren.find((child) => child !== member.childForFieldName("name")) ?? null;
12953
+ const rawValue = valueNode?.text.replace(/^['"]|['"]$/gu, "");
12954
+ values.push(rawValue ? `${name} = ${rawValue}` : name);
12955
+ }
12956
+ return values.length > 0 ? values : undefined;
12957
+ };
12958
+ var extractUnionLiteralValues = (typeNode) => {
12959
+ if (!typeNode)
12960
+ return;
12961
+ if (typeNode.type === "literal_type") {
12962
+ const text = typeNode.text.replace(/^['"]|['"]$/g, "");
12963
+ return text ? [text] : undefined;
12964
+ }
12965
+ if (typeNode.type === "union_type") {
12966
+ const values = [];
12967
+ for (const child of typeNode.namedChildren) {
12968
+ if (child.type === "literal_type") {
12969
+ const text = child.text.replace(/^['"]|['"]$/g, "");
12970
+ if (text)
12971
+ values.push(text);
12972
+ } else if (child.type === "union_type") {
12973
+ const nested = extractUnionLiteralValues(child);
12974
+ if (!nested)
12975
+ return;
12976
+ values.push(...nested);
12977
+ } else {
12978
+ return;
12979
+ }
12980
+ }
12981
+ return values.length > 0 ? values : undefined;
12982
+ }
12983
+ return;
12984
+ };
12985
+ var findObjectTypeNodes = (node2) => {
12986
+ if (!node2)
12987
+ return [];
12988
+ if (node2.type === "object_type")
12989
+ return [node2];
12990
+ if (node2.type === "intersection_type" || node2.type === "union_type") {
12991
+ return node2.namedChildren.flatMap(findObjectTypeNodes);
12992
+ }
12993
+ if (node2.type === "parenthesized_type" && node2.namedChildCount > 0) {
12994
+ return findObjectTypeNodes(node2.namedChildren[0]);
12995
+ }
12996
+ return [];
12997
+ };
12998
+
12999
+ // src/runtimeRegistrations.ts
13000
+ import ts4 from "typescript";
13001
+ function runtimeRegistrations(source) {
13002
+ const imports = new Map;
13003
+ const receivers = new Map;
13004
+ const middleware = new Map;
13005
+ const result = [];
13006
+ const supported = new Set(["express", "fastify", "hono", "node-cron", "node:events", "events"]);
13007
+ for (const statement of source.statements) {
13008
+ if (!ts4.isImportDeclaration(statement) || !ts4.isStringLiteral(statement.moduleSpecifier))
13009
+ continue;
13010
+ const module = statement.moduleSpecifier.text;
13011
+ if (!supported.has(module))
13012
+ continue;
13013
+ const clause = statement.importClause;
13014
+ if (clause?.name !== undefined)
13015
+ imports.set(clause.name.text, module);
13016
+ if (clause?.namedBindings !== undefined) {
13017
+ if (ts4.isNamespaceImport(clause.namedBindings))
13018
+ imports.set(clause.namedBindings.name.text, module);
13019
+ else
13020
+ for (const item of clause.namedBindings.elements)
13021
+ imports.set(item.name.text, module);
13022
+ }
13023
+ }
13024
+ const rootName = (node2) => ts4.isIdentifier(node2) ? node2.text : ts4.isPropertyAccessExpression(node2) ? rootName(node2.expression) : undefined;
13025
+ const visit = (node2) => {
13026
+ if (ts4.isVariableDeclaration(node2) && ts4.isIdentifier(node2.name) && node2.initializer !== undefined && (ts4.isCallExpression(node2.initializer) || ts4.isNewExpression(node2.initializer))) {
13027
+ const root = rootName(node2.initializer.expression);
13028
+ const module = root === undefined ? undefined : imports.get(root);
13029
+ if (module !== undefined)
13030
+ receivers.set(node2.name.text, module);
13031
+ }
13032
+ if (ts4.isCallExpression(node2) && ts4.isPropertyAccessExpression(node2.expression)) {
13033
+ const receiver = node2.expression.expression.getText(source);
13034
+ const module = receivers.get(receiver) ?? imports.get(receiver);
13035
+ const operation = node2.expression.name.text;
13036
+ if (module !== undefined) {
13037
+ const args = node2.arguments;
13038
+ const http = ["express", "fastify", "hono"].includes(module);
13039
+ if (http && operation === "use") {
13040
+ middleware.set(receiver, [...middleware.get(receiver) ?? [], ...args.map((arg) => arg.getText(source))]);
13041
+ }
13042
+ const kind = http && ["get", "post", "put", "patch", "delete", "head", "options", "all"].includes(operation) ? "http" : module === "node-cron" && operation === "schedule" ? "schedule" : ["events", "node:events"].includes(module) && ["on", "once"].includes(operation) ? "event" : undefined;
13043
+ const first = args[0];
13044
+ if (kind !== undefined && first !== undefined && ts4.isStringLiteralLike(first) && args.length >= 2) {
13045
+ const handler = args.at(-1).getText(source);
13046
+ const line = source.getLineAndCharacterOfPosition(node2.getStart()).line + 1;
13047
+ result.push({
13048
+ name: `${kind === "http" ? operation.toUpperCase() : kind} ${first.text}`,
13049
+ kind: kind === "http" ? "endpoint" /* Endpoint */ : "process" /* Process */,
13050
+ visibility: "exported" /* Exported */,
13051
+ file: source.fileName.replace(/^\//u, ""),
13052
+ line,
13053
+ endLine: source.getLineAndCharacterOfPosition(node2.end).line + 1,
13054
+ signature: `${operation} ${first.text} → ${handler}`,
13055
+ registration: {
13056
+ kind,
13057
+ key: first.text,
13058
+ handler,
13059
+ ...kind === "http" ? { method: operation.toUpperCase() } : {},
13060
+ middleware: [...middleware.get(receiver) ?? [], ...args.slice(1, -1).map((arg) => arg.getText(source))]
13061
+ }
13062
+ });
13063
+ }
13064
+ }
13065
+ }
13066
+ ts4.forEachChild(node2, visit);
13067
+ };
13068
+ visit(source);
13069
+ return result;
13070
+ }
13071
+
13072
+ // src/publicContracts.ts
13073
+ var format = ts5.TypeFormatFlags.NoTruncation | ts5.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
13074
+ function declarationAt(source, symbol) {
13075
+ const candidates = [];
13076
+ const visit = (node2) => {
13077
+ const line = source.getLineAndCharacterOfPosition(node2.getStart(source)).line + 1;
13078
+ if (line > symbol.endLine)
13079
+ return;
13080
+ if (line === symbol.line && (ts5.isFunctionDeclaration(node2) || ts5.isVariableDeclaration(node2) || ts5.isInterfaceDeclaration(node2) || ts5.isTypeAliasDeclaration(node2) || ts5.isClassDeclaration(node2))) {
13081
+ candidates.push(node2);
13082
+ }
13083
+ ts5.forEachChild(node2, visit);
13084
+ };
13085
+ visit(source);
13086
+ return candidates.find((node2) => ("name" in node2) && node2.name?.getText(source) === symbol.name) ?? (candidates.length === 1 ? candidates[0] : undefined);
13087
+ }
13088
+ function declaredObjectTypes(node2, checker, seen = new Set) {
13089
+ if (seen.has(node2))
13090
+ return [];
13091
+ seen.add(node2);
13092
+ if (ts5.isTypeAliasDeclaration(node2))
13093
+ return declaredObjectTypes(node2.type, checker, seen);
13094
+ if (ts5.isParenthesizedTypeNode(node2))
13095
+ return declaredObjectTypes(node2.type, checker, seen);
13096
+ if (ts5.isIntersectionTypeNode(node2))
13097
+ return node2.types.flatMap((type) => declaredObjectTypes(type, checker, seen));
13098
+ if (ts5.isTypeReferenceNode(node2) && !node2.typeArguments?.length) {
13099
+ let symbol = checker.getSymbolAtLocation(node2.typeName);
13100
+ if (symbol !== undefined && (symbol.flags & ts5.SymbolFlags.Alias) !== 0)
13101
+ symbol = checker.getAliasedSymbol(symbol);
13102
+ return (symbol?.declarations ?? []).flatMap((declaration) => declaredObjectTypes(declaration, checker, seen));
13103
+ }
13104
+ return ts5.isTypeLiteralNode(node2) || ts5.isInterfaceDeclaration(node2) ? [node2] : [];
13105
+ }
13106
+ function memberTypeText(checker, type, member, annotation) {
13107
+ const text = checker.typeToString(type, member, format);
13108
+ if (annotation === undefined)
13109
+ return { text, complete: (type.flags & (ts5.TypeFlags.Any | ts5.TypeFlags.Unknown)) === 0 };
13110
+ if (annotation.kind === ts5.SyntaxKind.AnyKeyword || annotation.kind === ts5.SyntaxKind.UnknownKeyword) {
13111
+ return { text: annotation.getText(), complete: true };
13112
+ }
13113
+ let incomplete = (type.flags & (ts5.TypeFlags.Any | ts5.TypeFlags.Unknown)) !== 0 || text === "{}" && !ts5.isTypeLiteralNode(annotation);
13114
+ const visit = (node2) => {
13115
+ if (ts5.isArrayTypeNode(node2) || ts5.isTupleTypeNode(node2) || ts5.isTypeReferenceNode(node2)) {
13116
+ const resolved = checker.getTypeFromTypeNode(node2);
13117
+ const rendered = checker.typeToString(resolved, node2, format);
13118
+ if ((resolved.flags & (ts5.TypeFlags.Any | ts5.TypeFlags.Unknown)) !== 0 || ts5.isArrayTypeNode(node2) && rendered === "{}")
13119
+ incomplete = true;
13120
+ }
13121
+ ts5.forEachChild(node2, visit);
13122
+ };
13123
+ visit(annotation);
13124
+ return { text: incomplete ? annotation.getText() : text, complete: !incomplete };
13125
+ }
13126
+ function callable(node2) {
13127
+ if (ts5.isFunctionDeclaration(node2))
13128
+ return node2;
13129
+ if (!ts5.isVariableDeclaration(node2))
13130
+ return;
13131
+ let value = node2.initializer;
13132
+ if (value !== undefined && ts5.isCallExpression(value)) {
13133
+ value = value.arguments.find((argument) => ts5.isArrowFunction(argument) || ts5.isFunctionExpression(argument));
13134
+ }
13135
+ return value !== undefined && (ts5.isArrowFunction(value) || ts5.isFunctionExpression(value)) ? value : undefined;
13136
+ }
13137
+ async function enrichPublicContracts(input) {
13138
+ const sources = new Map;
13139
+ for (const path2 of input.paths) {
13140
+ const source = await input.fs.readFile(path2);
13141
+ const absolute = posix3.resolve("/", path2);
13142
+ sources.set(absolute, ts5.createSourceFile(absolute, source, ts5.ScriptTarget.Latest, true));
13143
+ }
13144
+ const options = {
13145
+ noLib: true,
13146
+ skipLibCheck: true,
13147
+ allowJs: true,
13148
+ jsx: ts5.JsxEmit.Preserve,
13149
+ moduleResolution: ts5.ModuleResolutionKind.Node10,
13150
+ baseUrl: "/",
13151
+ paths: Object.fromEntries((input.resolver?.mappings ?? []).map((mapping) => [mapping.pattern, mapping.targets.map((target) => posix3.resolve("/", target))]))
13152
+ };
13153
+ const host = {
13154
+ getSourceFile: (path2) => sources.get(posix3.resolve("/", path2)),
13155
+ getDefaultLibFileName: () => "",
13156
+ writeFile: () => {},
13157
+ getCurrentDirectory: () => "/",
13158
+ getDirectories: () => [],
13159
+ fileExists: (path2) => sources.has(posix3.resolve("/", path2)),
13160
+ readFile: (path2) => sources.get(posix3.resolve("/", path2))?.text,
13161
+ getCanonicalFileName: (path2) => posix3.resolve("/", path2),
13162
+ useCaseSensitiveFileNames: () => true,
13163
+ getNewLine: () => `
13164
+ `
13165
+ };
13166
+ const program = ts5.createProgram([...sources.keys()], options, host);
13167
+ for (const source of sources.values())
13168
+ input.symbols.push(...runtimeRegistrations(source), ...federationContracts(source));
13169
+ const checker = program.getTypeChecker();
13170
+ const diagnosticsByFile = new Map;
13171
+ for (const symbol of input.symbols) {
13172
+ if (symbol.visibility !== "exported" /* Exported */)
13173
+ continue;
13174
+ const source = sources.get(posix3.resolve("/", symbol.file));
13175
+ if (source === undefined)
13176
+ continue;
13177
+ const declaration = declarationAt(source, symbol);
13178
+ if (declaration === undefined)
13179
+ continue;
13180
+ symbol.contractResolution = "declaration-only";
13181
+ const fn = callable(declaration);
13182
+ if (fn !== undefined) {
13183
+ symbol.params = fn.parameters.map((parameter) => ({
13184
+ name: parameter.name.getText(source),
13185
+ type: parameter.type?.getText(source) ?? checker.typeToString(checker.getTypeAtLocation(parameter), parameter, format),
13186
+ optional: parameter.questionToken !== undefined || parameter.initializer !== undefined,
13187
+ rest: parameter.dotDotDotToken !== undefined,
13188
+ ...parameter.initializer === undefined ? {} : { defaultValue: parameter.initializer.getText(source) }
13189
+ }));
13190
+ if (fn.typeParameters !== undefined)
13191
+ symbol.typeParameters = `<${fn.typeParameters.map((item) => item.getText(source)).join(", ")}>`;
13192
+ }
13193
+ const valueType = checker.getTypeAtLocation(declaration);
13194
+ const signatures = valueType.getCallSignatures();
13195
+ const declaredSignatures = signatures.flatMap((signature) => {
13196
+ const declared = signature.getDeclaration();
13197
+ if (declared === undefined || !sources.has(declared.getSourceFile().fileName))
13198
+ return [];
13199
+ const body = "body" in declared ? declared.body : undefined;
13200
+ return [declared.getSourceFile().text.slice(declared.getStart(), body?.pos ?? declared.getEnd()).trim().replace(/;$/u, "")];
13201
+ });
13202
+ if (declaredSignatures.length > 1)
13203
+ symbol.overloads = declaredSignatures;
13204
+ let contractType;
13205
+ let localProps;
13206
+ if (symbol.kind === "component" /* Component */) {
13207
+ const parameter = signatures[0]?.parameters[0];
13208
+ if (parameter !== undefined) {
13209
+ contractType = checker.getTypeOfSymbolAtLocation(parameter, declaration);
13210
+ symbol.propsType = checker.typeToString(contractType, declaration, format);
13211
+ }
13212
+ const annotation = fn?.parameters[0]?.type ?? (ts5.isVariableDeclaration(declaration) ? componentPropsNode(declaration.type) : undefined);
13213
+ if (annotation !== undefined) {
13214
+ contractType = checker.getTypeFromTypeNode(annotation);
13215
+ symbol.propsType = annotation.getText(source);
13216
+ localProps = componentLocalPropsNode(annotation, checker);
13217
+ }
13218
+ } else if (ts5.isInterfaceDeclaration(declaration) || ts5.isTypeAliasDeclaration(declaration)) {
13219
+ contractType = checker.getTypeAtLocation(declaration);
13220
+ }
13221
+ if (contractType === undefined)
13222
+ continue;
13223
+ const unresolved = (contractType.flags & (ts5.TypeFlags.Any | ts5.TypeFlags.Unknown)) !== 0;
13224
+ const localType = unresolved && localProps !== undefined ? checker.getTypeFromTypeNode(localProps) : undefined;
13225
+ const knownType = localType ?? contractType;
13226
+ const properties = (knownType.flags & (ts5.TypeFlags.Any | ts5.TypeFlags.Unknown)) !== 0 ? declaredObjectTypes(localProps ?? declaration, checker).flatMap((node2) => checker.getPropertiesOfType(checker.getTypeAtLocation(node2))) : checker.getPropertiesOfType(knownType);
13227
+ if (properties.length === 0)
13228
+ continue;
13229
+ if (symbol.kind === "component" /* Component */ && symbol.propsType !== undefined && input.relations !== undefined) {
13230
+ const typeSymbol = knownType.aliasSymbol ?? knownType.getSymbol();
13231
+ const declaration2 = typeSymbol?.declarations?.[0];
13232
+ if (typeSymbol !== undefined && declaration2 !== undefined)
13233
+ input.relations.push({ ...createRelation("of_type" /* OfType */, symbol.name, typeSymbol.name, !sources.has(declaration2.getSourceFile().fileName), symbol.line), file: symbol.file });
13234
+ }
13235
+ const pattern = fn?.parameters[0]?.name;
13236
+ const defaults = pattern === undefined ? {} : componentDefaultsFromBinding(pattern, source);
13237
+ const members = [];
13238
+ let completeMembers = true;
13239
+ for (const property of properties) {
13240
+ const member = property.valueDeclaration ?? property.declarations?.[0];
13241
+ if (member === undefined || !sources.has(member.getSourceFile().fileName))
13242
+ continue;
13243
+ const memberSource = member.getSourceFile();
13244
+ const modifiers = ts5.canHaveModifiers(member) ? ts5.getModifiers(member) : undefined;
13245
+ const propertyType = checker.getTypeOfSymbolAtLocation(property, member);
13246
+ const annotation = "type" in member ? member.type : undefined;
13247
+ const documentedDefault = ts5.getJSDocTags(member).find((tag) => tag.tagName.text === "default" || tag.tagName.text === "defaultValue");
13248
+ const defaultComment = documentedDefault?.comment;
13249
+ const defaultText = typeof defaultComment === "string" ? defaultComment.trim() : defaultComment === undefined ? undefined : defaultComment.map((part) => part.getText(memberSource)).join("").trim();
13250
+ const defaultValue = (Object.hasOwn(defaults, property.name) ? defaults[property.name] : undefined) ?? (defaultText || undefined);
13251
+ const hidden = ts5.getJSDocTags(member).some((tag) => ["internal", "private"].includes(tag.tagName.text)) || modifiers?.some((modifier) => modifier.kind === ts5.SyntaxKind.PrivateKeyword || modifier.kind === ts5.SyntaxKind.ProtectedKeyword);
13252
+ if (hidden)
13253
+ continue;
13254
+ const renderedType = memberTypeText(checker, propertyType, member, annotation);
13255
+ completeMembers &&= renderedType.complete;
13256
+ members.push({
13257
+ name: property.name,
13258
+ kind: "prop" /* Prop */,
13259
+ visibility: "exported" /* Exported */,
13260
+ file: posix3.relative("/", memberSource.fileName),
13261
+ line: memberSource.getLineAndCharacterOfPosition(member.getStart()).line + 1,
13262
+ endLine: memberSource.getLineAndCharacterOfPosition(member.getEnd()).line + 1,
13263
+ optional: (property.flags & ts5.SymbolFlags.Optional) !== 0,
13264
+ ...defaultValue === undefined ? {} : { defaultValue },
13265
+ readonly: modifiers?.some((modifier) => modifier.kind === ts5.SyntaxKind.ReadonlyKeyword) ?? false,
13266
+ typeAnnotation: renderedType.text,
13267
+ doc: ts5.displayPartsToString(property.getDocumentationComment(checker))
13268
+ });
13269
+ }
13270
+ if (properties.length > 0) {
13271
+ symbol.members = members;
13272
+ let diagnostics = diagnosticsByFile.get(source.fileName);
13273
+ if (diagnostics === undefined) {
13274
+ diagnostics = program.getSemanticDiagnostics(source);
13275
+ diagnosticsByFile.set(source.fileName, diagnostics);
13276
+ }
13277
+ symbol.contractResolution = !unresolved && completeMembers && diagnostics.length === 0 ? "resolved" : "declaration-only";
13278
+ }
13279
+ }
13280
+ }
13281
+
12535
13282
  // ../extract/src/types.ts
12536
13283
  var symbolKindSchema2 = exports_external.enum(Object.values(SymbolKind));
12537
13284
  var visibilitySchema2 = exports_external.enum(Object.values(Visibility));
@@ -12555,7 +13302,17 @@ var relationSourceSchema = exports_external.enum([
12555
13302
  var packageKindSchema2 = exports_external.enum(Object.values(PackageKind));
12556
13303
  var symbolParamSchema = exports_external.object({
12557
13304
  name: exports_external.string().min(1),
12558
- type: exports_external.string().min(1).nullable()
13305
+ type: exports_external.string().min(1).nullable(),
13306
+ optional: exports_external.boolean().optional(),
13307
+ rest: exports_external.boolean().optional(),
13308
+ defaultValue: exports_external.string().optional()
13309
+ });
13310
+ var registrationSchema = exports_external.object({
13311
+ kind: exports_external.enum(["http", "schedule", "event"]),
13312
+ key: exports_external.string(),
13313
+ handler: exports_external.string(),
13314
+ method: exports_external.string().optional(),
13315
+ middleware: exports_external.array(exports_external.string())
12559
13316
  });
12560
13317
  var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
12561
13318
  name: exports_external.string().min(1),
@@ -12566,6 +13323,14 @@ var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
12566
13323
  endLine: exports_external.number().int().positive(),
12567
13324
  members: exports_external.array(symbolInfoSchema).optional(),
12568
13325
  params: exports_external.array(symbolParamSchema).optional(),
13326
+ optional: exports_external.boolean().optional(),
13327
+ readonly: exports_external.boolean().optional(),
13328
+ defaultValue: exports_external.string().optional(),
13329
+ typeParameters: exports_external.string().optional(),
13330
+ overloads: exports_external.array(exports_external.string()).optional(),
13331
+ publicEntrypoints: exports_external.array(exports_external.string()).optional(),
13332
+ contractResolution: exports_external.enum(["resolved", "declaration-only"]).optional(),
13333
+ registration: registrationSchema.optional(),
12569
13334
  returnType: exports_external.string().min(1).nullable().optional(),
12570
13335
  typeAnnotation: exports_external.string().min(1).nullable().optional(),
12571
13336
  extends: exports_external.string().min(1).nullable().optional(),
@@ -12580,6 +13345,7 @@ var relationInfoSchema = exports_external.object({
12580
13345
  type: relationTypeSchema,
12581
13346
  from: exports_external.string().min(1),
12582
13347
  to: exports_external.string().min(1),
13348
+ file: exports_external.string().min(1).optional(),
12583
13349
  isExternal: exports_external.boolean(),
12584
13350
  grounding: groundingSchema,
12585
13351
  confidence: exports_external.number().min(0).max(1),
@@ -12860,6 +13626,8 @@ function semanticExtractionPayload(extraction) {
12860
13626
  };
12861
13627
  }
12862
13628
  function relationSourceFile(relation, symbols, filePaths) {
13629
+ if (relation.file !== undefined)
13630
+ return filePaths.has(relation.file) ? relation.file : null;
12863
13631
  if (filePaths.has(relation.from))
12864
13632
  return relation.from;
12865
13633
  const candidates = symbols.filter((symbol) => symbol.name === relation.from);
@@ -12941,6 +13709,10 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12941
13709
  }
12942
13710
  const facts = [];
12943
13711
  if (coverageFile.disposition === "analyzed" && fileInfo) {
13712
+ const source = invocation.source_files?.[normalizedPath2];
13713
+ if (invocation.source_files !== undefined && source === undefined) {
13714
+ throw new TypeError(`Analyzed file ${normalizedPath2} has no scoped source text`);
13715
+ }
12944
13716
  facts.push(fact2({
12945
13717
  sourceRef: invocation.authorized_scope.source_ref,
12946
13718
  moduleRef: invocation.module_ref,
@@ -12948,7 +13720,11 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12948
13720
  qualifiedItemPath: "file",
12949
13721
  kind: "source-file",
12950
13722
  signature: { path: normalizedPath2, language: fileInfo.language },
12951
- payload: fileInfo,
13723
+ payload: source === undefined ? fileInfo : {
13724
+ ...fileInfo,
13725
+ line: 1,
13726
+ endLine: source.split(/\r\n|\r|\n/u).length
13727
+ },
12952
13728
  denominator: ownsDenominators ? "eligible-file" : "none"
12953
13729
  }));
12954
13730
  facts.push(fact2({
@@ -13692,27 +14468,27 @@ var parseFile = async (source, isTsx) => {
13692
14468
  }
13693
14469
  };
13694
14470
  // src/commonJsModule.ts
13695
- import ts2 from "typescript";
14471
+ import ts7 from "typescript";
13696
14472
 
13697
14473
  // src/typescriptAst.ts
13698
- import ts from "typescript";
14474
+ import ts6 from "typescript";
13699
14475
  var scriptKind = (filePath) => {
13700
14476
  const lower = filePath.toLowerCase();
13701
14477
  if (lower.endsWith(".tsx"))
13702
- return ts.ScriptKind.TSX;
14478
+ return ts6.ScriptKind.TSX;
13703
14479
  if (lower.endsWith(".jsx"))
13704
- return ts.ScriptKind.JSX;
14480
+ return ts6.ScriptKind.JSX;
13705
14481
  if (lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".cjs")) {
13706
- return ts.ScriptKind.JS;
14482
+ return ts6.ScriptKind.JS;
13707
14483
  }
13708
- return ts.ScriptKind.TS;
14484
+ return ts6.ScriptKind.TS;
13709
14485
  };
13710
- var createEcmaScriptSourceFile = (source, filePath) => ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, scriptKind(filePath));
14486
+ var createEcmaScriptSourceFile = (source, filePath) => ts6.createSourceFile(filePath, source, ts6.ScriptTarget.Latest, true, scriptKind(filePath));
13711
14487
  var treeSitterCompatibleJsxSource = (sourceFile, source) => {
13712
14488
  const characters = source.split("");
13713
14489
  let changed = false;
13714
14490
  const visit2 = (node2) => {
13715
- const jsxPresentationLiteral = ts.isJsxText(node2) || ts.isStringLiteral(node2) && ts.isJsxAttribute(node2.parent);
14491
+ const jsxPresentationLiteral = ts6.isJsxText(node2) || ts6.isStringLiteral(node2) && ts6.isJsxAttribute(node2.parent);
13716
14492
  if (jsxPresentationLiteral) {
13717
14493
  for (let index = node2.getStart(sourceFile);index < node2.getEnd(); index += 1) {
13718
14494
  if (characters[index] === "&") {
@@ -13721,7 +14497,7 @@ var treeSitterCompatibleJsxSource = (sourceFile, source) => {
13721
14497
  }
13722
14498
  }
13723
14499
  }
13724
- ts.forEachChild(node2, visit2);
14500
+ ts6.forEachChild(node2, visit2);
13725
14501
  };
13726
14502
  visit2(sourceFile);
13727
14503
  return changed ? characters.join("") : source;
@@ -13752,25 +14528,25 @@ var nodeLocation = (sourceFile, node2) => {
13752
14528
  var staticStringValue = (node2) => {
13753
14529
  if (!node2)
13754
14530
  return null;
13755
- if (ts.isStringLiteral(node2) || ts.isNoSubstitutionTemplateLiteral(node2))
14531
+ if (ts6.isStringLiteral(node2) || ts6.isNoSubstitutionTemplateLiteral(node2))
13756
14532
  return node2.text;
13757
14533
  return null;
13758
14534
  };
13759
14535
 
13760
14536
  // src/commonJsModule.ts
13761
- var requireCall = (node2) => ts2.isCallExpression(node2) && ts2.isIdentifier(node2.expression) && node2.expression.text === "require" ? node2 : null;
14537
+ var requireCall = (node2) => ts7.isCallExpression(node2) && ts7.isIdentifier(node2.expression) && node2.expression.text === "require" ? node2 : null;
13762
14538
  var requireReference = (node2) => {
13763
14539
  const direct = requireCall(node2);
13764
14540
  if (direct) {
13765
14541
  const source = staticStringValue(direct.arguments[0]);
13766
14542
  return source ? { source, importedName: "*" } : null;
13767
14543
  }
13768
- if (ts2.isPropertyAccessExpression(node2)) {
14544
+ if (ts7.isPropertyAccessExpression(node2)) {
13769
14545
  const call = requireCall(node2.expression);
13770
14546
  const source = call ? staticStringValue(call.arguments[0]) : null;
13771
14547
  return source ? { source, importedName: node2.name.text } : null;
13772
14548
  }
13773
- if (ts2.isElementAccessExpression(node2)) {
14549
+ if (ts7.isElementAccessExpression(node2)) {
13774
14550
  const call = requireCall(node2.expression);
13775
14551
  const source = call ? staticStringValue(call.arguments[0]) : null;
13776
14552
  const importedName = staticStringValue(node2.argumentExpression);
@@ -13779,20 +14555,20 @@ var requireReference = (node2) => {
13779
14555
  return null;
13780
14556
  };
13781
14557
  var isModuleExports = (node2) => {
13782
- if (ts2.isPropertyAccessExpression(node2) && ts2.isIdentifier(node2.expression) && node2.expression.text === "module" && node2.name.text === "exports")
14558
+ if (ts7.isPropertyAccessExpression(node2) && ts7.isIdentifier(node2.expression) && node2.expression.text === "module" && node2.name.text === "exports")
13783
14559
  return true;
13784
- return ts2.isElementAccessExpression(node2) && ts2.isIdentifier(node2.expression) && node2.expression.text === "module" && staticStringValue(node2.argumentExpression) === "exports";
14560
+ return ts7.isElementAccessExpression(node2) && ts7.isIdentifier(node2.expression) && node2.expression.text === "module" && staticStringValue(node2.argumentExpression) === "exports";
13785
14561
  };
13786
- var isExportsObject = (node2) => ts2.isIdentifier(node2) && node2.text === "exports" || isModuleExports(node2);
14562
+ var isExportsObject = (node2) => ts7.isIdentifier(node2) && node2.text === "exports" || isModuleExports(node2);
13787
14563
  var isUnsupportedExportMutationCall = (node2) => {
13788
- if (ts2.isPropertyAccessExpression(node2.expression) && ts2.isIdentifier(node2.expression.expression) && node2.expression.expression.text === "Object" && ["assign", "defineProperties", "defineProperty"].includes(node2.expression.name.text) && node2.arguments[0] && isExportsObject(node2.arguments[0])) {
14564
+ if (ts7.isPropertyAccessExpression(node2.expression) && ts7.isIdentifier(node2.expression.expression) && node2.expression.expression.text === "Object" && ["assign", "defineProperties", "defineProperty"].includes(node2.expression.name.text) && node2.arguments[0] && isExportsObject(node2.arguments[0])) {
13789
14565
  return !(node2.expression.name.text === "defineProperty" && staticStringValue(node2.arguments[1]) === "__esModule");
13790
14566
  }
13791
- return ts2.isIdentifier(node2.expression) && ["__createBinding", "__export", "__exportStar"].includes(node2.expression.text) && node2.arguments.some(isExportsObject);
14567
+ return ts7.isIdentifier(node2.expression) && ["__createBinding", "__export", "__exportStar"].includes(node2.expression.text) && node2.arguments.some(isExportsObject);
13792
14568
  };
13793
14569
  var commonJsExportTarget = (node2) => {
13794
- if (ts2.isPropertyAccessExpression(node2)) {
13795
- if (ts2.isIdentifier(node2.expression) && node2.expression.text === "exports") {
14570
+ if (ts7.isPropertyAccessExpression(node2)) {
14571
+ if (ts7.isIdentifier(node2.expression) && node2.expression.text === "exports") {
13796
14572
  return { kind: "named", exportedName: node2.name.text };
13797
14573
  }
13798
14574
  if (isModuleExports(node2.expression)) {
@@ -13801,9 +14577,9 @@ var commonJsExportTarget = (node2) => {
13801
14577
  if (isModuleExports(node2))
13802
14578
  return { kind: "whole" };
13803
14579
  }
13804
- if (ts2.isElementAccessExpression(node2)) {
14580
+ if (ts7.isElementAccessExpression(node2)) {
13805
14581
  const property = staticStringValue(node2.argumentExpression);
13806
- if (ts2.isIdentifier(node2.expression) && node2.expression.text === "exports" && property) {
14582
+ if (ts7.isIdentifier(node2.expression) && node2.expression.text === "exports" && property) {
13807
14583
  return { kind: "named", exportedName: property };
13808
14584
  }
13809
14585
  if (isModuleExports(node2.expression) && property) {
@@ -13815,7 +14591,7 @@ var commonJsExportTarget = (node2) => {
13815
14591
  return null;
13816
14592
  };
13817
14593
  var localReference = (expression, bindings) => {
13818
- if (ts2.isIdentifier(expression)) {
14594
+ if (ts7.isIdentifier(expression)) {
13819
14595
  const binding = bindings.get(expression.text);
13820
14596
  if (binding) {
13821
14597
  return {
@@ -13825,7 +14601,7 @@ var localReference = (expression, bindings) => {
13825
14601
  }
13826
14602
  return { localName: expression.text };
13827
14603
  }
13828
- if (ts2.isPropertyAccessExpression(expression) && ts2.isIdentifier(expression.expression)) {
14604
+ if (ts7.isPropertyAccessExpression(expression) && ts7.isIdentifier(expression.expression)) {
13829
14605
  const binding = bindings.get(expression.expression.text);
13830
14606
  if (binding)
13831
14607
  return { source: binding.source, importedName: expression.name.text };
@@ -13835,7 +14611,7 @@ var localReference = (expression, bindings) => {
13835
14611
  };
13836
14612
  var syntheticDeclaration = (name, expression, sourceFile) => {
13837
14613
  const location = nodeLocation(sourceFile, expression);
13838
- if (ts2.isFunctionExpression(expression) || ts2.isArrowFunction(expression)) {
14614
+ if (ts7.isFunctionExpression(expression) || ts7.isArrowFunction(expression)) {
13839
14615
  return {
13840
14616
  name,
13841
14617
  kind: "function",
@@ -13844,10 +14620,10 @@ var syntheticDeclaration = (name, expression, sourceFile) => {
13844
14620
  params: expression.parameters.map((parameter) => parameter.name.getText(sourceFile))
13845
14621
  };
13846
14622
  }
13847
- if (ts2.isClassExpression(expression)) {
14623
+ if (ts7.isClassExpression(expression)) {
13848
14624
  return { name, kind: "class", line: location.line, endLine: location.endLine, params: [] };
13849
14625
  }
13850
- if (ts2.isObjectLiteralExpression(expression) || ts2.isArrayLiteralExpression(expression) || ts2.isLiteralExpression(expression)) {
14626
+ if (ts7.isObjectLiteralExpression(expression) || ts7.isArrayLiteralExpression(expression) || ts7.isLiteralExpression(expression)) {
13851
14627
  return { name, kind: "variable", line: location.line, endLine: location.endLine, params: [] };
13852
14628
  }
13853
14629
  return null;
@@ -13881,430 +14657,192 @@ var appendUnsupportedExportDiagnostic = (result, sourceFile, node2) => {
13881
14657
  var collectBindings = (sourceFile) => {
13882
14658
  const bindings = [];
13883
14659
  for (const statement of sourceFile.statements) {
13884
- if (!ts2.isVariableStatement(statement))
14660
+ if (!ts7.isVariableStatement(statement))
13885
14661
  continue;
13886
14662
  for (const declaration of statement.declarationList.declarations) {
13887
14663
  if (!declaration.initializer)
13888
14664
  continue;
13889
14665
  const line = nodeLocation(sourceFile, declaration).line;
13890
- if (ts2.isIdentifier(declaration.name)) {
14666
+ if (ts7.isIdentifier(declaration.name)) {
13891
14667
  const reference = requireReference(declaration.initializer);
13892
14668
  if (reference)
13893
14669
  bindings.push({ localName: declaration.name.text, ...reference, line });
13894
14670
  continue;
13895
14671
  }
13896
- const direct = requireCall(declaration.initializer);
13897
- const source = direct ? staticStringValue(direct.arguments[0]) : null;
13898
- if (!source || !ts2.isObjectBindingPattern(declaration.name))
13899
- continue;
13900
- for (const element of declaration.name.elements) {
13901
- if (!ts2.isIdentifier(element.name))
13902
- continue;
13903
- const importedName = element.propertyName?.getText(sourceFile) ?? element.name.text;
13904
- bindings.push({ localName: element.name.text, source, importedName, line });
13905
- }
13906
- }
13907
- }
13908
- return bindings;
13909
- };
13910
- var collectDynamicDiagnostics = (sourceFile) => {
13911
- const diagnostics = [];
13912
- const visit2 = (node2) => {
13913
- if (ts2.isCallExpression(node2) && ts2.isIdentifier(node2.expression) && node2.expression.text === "require") {
13914
- if (staticStringValue(node2.arguments[0]) === null) {
13915
- const location = nodeLocation(sourceFile, node2);
13916
- diagnostics.push({
13917
- code: "dynamic-commonjs-require",
13918
- severity: "error",
13919
- file: sourceFile.fileName,
13920
- line: location.line,
13921
- column: location.column
13922
- });
13923
- }
13924
- }
13925
- if (ts2.isCallExpression(node2) && isUnsupportedExportMutationCall(node2)) {
13926
- const location = nodeLocation(sourceFile, node2);
13927
- diagnostics.push({
13928
- code: "unsupported-commonjs-export-form",
13929
- severity: "error",
13930
- file: sourceFile.fileName,
13931
- line: location.line,
13932
- column: location.column
13933
- });
13934
- }
13935
- if (ts2.isBinaryExpression(node2) && node2.operatorToken.kind === ts2.SyntaxKind.EqualsToken) {
13936
- if (ts2.isElementAccessExpression(node2.left)) {
13937
- const isCommonJsTarget = ts2.isIdentifier(node2.left.expression) && node2.left.expression.text === "exports" || isModuleExports(node2.left.expression) || isModuleExports(node2.left);
13938
- if (isCommonJsTarget && commonJsExportTarget(node2.left) === null) {
13939
- const location = nodeLocation(sourceFile, node2.left);
13940
- diagnostics.push({
13941
- code: "dynamic-commonjs-export",
13942
- severity: "error",
13943
- file: sourceFile.fileName,
13944
- line: location.line,
13945
- column: location.column
13946
- });
13947
- }
13948
- }
13949
- }
13950
- ts2.forEachChild(node2, visit2);
13951
- };
13952
- visit2(sourceFile);
13953
- return diagnostics;
13954
- };
13955
- var analyzeCommonJsModule = (source, filePath) => {
13956
- const sourceFile = createEcmaScriptSourceFile(source, filePath);
13957
- const bindings = collectBindings(sourceFile);
13958
- const bindingMap = new Map(bindings.map((binding) => [binding.localName, binding]));
13959
- const result = {
13960
- bindings,
13961
- exports: [],
13962
- wildcardSources: [],
13963
- syntheticDeclarations: [],
13964
- diagnostics: collectDynamicDiagnostics(sourceFile)
13965
- };
13966
- for (const statement of sourceFile.statements) {
13967
- if (!ts2.isExpressionStatement(statement) || !ts2.isBinaryExpression(statement.expression))
13968
- continue;
13969
- const assignment = statement.expression;
13970
- if (assignment.operatorToken.kind !== ts2.SyntaxKind.EqualsToken)
13971
- continue;
13972
- const target = commonJsExportTarget(assignment.left);
13973
- if (!target)
13974
- continue;
13975
- const line = nodeLocation(sourceFile, assignment).line;
13976
- if (target.kind === "named") {
13977
- if (!pushExport(result, target.exportedName, assignment.right, line, bindingMap, sourceFile)) {
13978
- appendUnsupportedExportDiagnostic(result, sourceFile, assignment.right);
13979
- }
13980
- continue;
13981
- }
13982
- const directRequire = requireReference(assignment.right);
13983
- if (directRequire?.importedName === "*") {
13984
- result.wildcardSources.push(directRequire.source);
13985
- continue;
13986
- }
13987
- if (ts2.isObjectLiteralExpression(assignment.right)) {
13988
- for (const property of assignment.right.properties) {
13989
- if (ts2.isShorthandPropertyAssignment(property)) {
13990
- pushExport(result, property.name.text, property.name, line, bindingMap, sourceFile);
13991
- continue;
13992
- }
13993
- if (ts2.isPropertyAssignment(property)) {
13994
- const name = property.name && (ts2.isIdentifier(property.name) || ts2.isStringLiteral(property.name)) ? property.name.text : null;
13995
- if (name) {
13996
- if (!pushExport(result, name, property.initializer, line, bindingMap, sourceFile)) {
13997
- appendUnsupportedExportDiagnostic(result, sourceFile, property.initializer);
13998
- }
13999
- } else {
14000
- appendUnsupportedExportDiagnostic(result, sourceFile, property);
14001
- }
14002
- continue;
14003
- }
14004
- if (ts2.isMethodDeclaration(property) && property.name && ts2.isIdentifier(property.name)) {
14005
- const location = nodeLocation(sourceFile, property);
14006
- result.syntheticDeclarations.push({
14007
- name: property.name.text,
14008
- kind: "function",
14009
- line: location.line,
14010
- endLine: location.endLine,
14011
- params: property.parameters.map((parameter) => parameter.name.getText(sourceFile))
14012
- });
14013
- result.exports.push({
14014
- exportedName: property.name.text,
14015
- localName: property.name.text,
14016
- line
14017
- });
14018
- continue;
14019
- }
14020
- appendUnsupportedExportDiagnostic(result, sourceFile, property);
14021
- }
14022
- continue;
14023
- }
14024
- if (ts2.isIdentifier(assignment.right)) {
14025
- const binding = bindingMap.get(assignment.right.text);
14026
- if (binding?.importedName === "*") {
14027
- result.wildcardSources.push(binding.source);
14028
- continue;
14029
- }
14030
- if (!pushExport(result, assignment.right.text, assignment.right, line, bindingMap, sourceFile)) {
14031
- appendUnsupportedExportDiagnostic(result, sourceFile, assignment.right);
14032
- }
14033
- continue;
14034
- }
14035
- if (!pushExport(result, "default", assignment.right, line, bindingMap, sourceFile)) {
14036
- appendUnsupportedExportDiagnostic(result, sourceFile, assignment.right);
14037
- }
14038
- }
14039
- result.bindings.sort((left, right) => left.localName.localeCompare(right.localName));
14040
- result.exports.sort((left, right) => left.exportedName.localeCompare(right.exportedName) || left.line - right.line);
14041
- result.wildcardSources = [...new Set(result.wildcardSources)].sort();
14042
- result.syntheticDeclarations.sort((left, right) => left.name.localeCompare(right.name));
14043
- result.diagnostics.sort((left, right) => left.line - right.line || left.column - right.column);
14044
- return result;
14045
- };
14046
-
14047
- // src/commonJsExportTrace.ts
14048
- var traceCommonJsExports = async (input) => {
14049
- const traced = [];
14050
- for (const item of input.analysis.exports) {
14051
- if (item.localName && input.localDeclarations.has(item.localName)) {
14052
- traced.push({
14053
- exportedName: item.exportedName,
14054
- localName: item.localName,
14055
- declarationFile: input.filePath
14056
- });
14057
- continue;
14058
- }
14059
- if (item.source && item.importedName) {
14060
- traced.push(...await input.traceImported(item.source, item.importedName, item.exportedName));
14061
- }
14062
- }
14063
- for (const source of input.analysis.wildcardSources) {
14064
- traced.push(...await input.traceWildcard(source));
14065
- }
14066
- return traced;
14067
- };
14068
-
14069
- // src/exportTracer.ts
14070
- var DECLARATION_TYPES = new Set([
14071
- "function_declaration",
14072
- "class_declaration",
14073
- "interface_declaration",
14074
- "type_alias_declaration",
14075
- "enum_declaration",
14076
- "lexical_declaration"
14077
- ]);
14078
- var stripQuotes = (value) => value.replace(/^['"]/, "").replace(/['"]$/, "");
14079
- var getDeclarationName = (node2) => {
14080
- if (node2.type === "lexical_declaration") {
14081
- return node2.namedChildren.filter((child) => child.type === "variable_declarator").map((child) => child.childForFieldName("name")?.text ?? child.namedChildren[0]?.text ?? "").filter(Boolean);
14082
- }
14083
- const nameNode = node2.childForFieldName("name") ?? node2.namedChildren.find((child) => child.type === "identifier" || child.type === "type_identifier");
14084
- return nameNode?.text ? [nameNode.text] : [];
14085
- };
14086
- var collectLocalDeclarations = (root) => {
14087
- const declarations = new Map;
14088
- const register = (node2) => {
14089
- for (const name of getDeclarationName(node2)) {
14090
- if (!declarations.has(name)) {
14091
- declarations.set(name, name);
14092
- }
14093
- }
14094
- };
14095
- for (const child of root.namedChildren) {
14096
- if (DECLARATION_TYPES.has(child.type)) {
14097
- register(child);
14098
- continue;
14099
- }
14100
- if (child.type !== "export_statement")
14101
- continue;
14102
- const declaration = child.namedChildren.find((node2) => DECLARATION_TYPES.has(node2.type));
14103
- if (declaration) {
14104
- register(declaration);
14105
- }
14106
- }
14107
- return declarations;
14108
- };
14109
- var parseExportSpecifier = (node2) => {
14110
- const identifiers = node2.namedChildren.filter((child) => child.type === "identifier" || child.type === "type_identifier").map((child) => child.text);
14111
- if (identifiers.length === 0)
14112
- return null;
14113
- const localName = identifiers[0];
14114
- const exportedName = identifiers[1] ?? localName;
14115
- return { localName, exportedName };
14116
- };
14117
- var parseImportSpecifier = (node2) => {
14118
- const identifiers = node2.namedChildren.filter((child) => child.type === "identifier" || child.type === "type_identifier").map((child) => child.text);
14119
- if (identifiers.length === 0)
14120
- return null;
14121
- const importedName = identifiers[0];
14122
- const localName = identifiers[1] ?? importedName;
14123
- return { importedName, localName };
14124
- };
14125
- var collectImportBindings = (root) => {
14126
- const bindings = new Map;
14127
- for (const node2 of root.namedChildren) {
14128
- if (node2.type !== "import_statement")
14129
- continue;
14130
- const stringNode = node2.namedChildren.find((child) => child.type === "string");
14131
- if (!stringNode)
14132
- continue;
14133
- const source = stripQuotes(stringNode.text);
14134
- const clause = node2.namedChildren.find((child) => child.type === "import_clause");
14135
- for (const part of clause?.namedChildren ?? []) {
14136
- if (part.type === "identifier") {
14137
- bindings.set(part.text, { source, importedName: "default" });
14138
- continue;
14139
- }
14140
- if (part.type !== "named_imports")
14672
+ const direct = requireCall(declaration.initializer);
14673
+ const source = direct ? staticStringValue(direct.arguments[0]) : null;
14674
+ if (!source || !ts7.isObjectBindingPattern(declaration.name))
14141
14675
  continue;
14142
- for (const specifier of part.namedChildren.filter((child) => child.type === "import_specifier")) {
14143
- const parsed = parseImportSpecifier(specifier);
14144
- if (parsed) {
14145
- bindings.set(parsed.localName, { source, importedName: parsed.importedName });
14146
- }
14676
+ for (const element of declaration.name.elements) {
14677
+ if (!ts7.isIdentifier(element.name))
14678
+ continue;
14679
+ const importedName = element.propertyName?.getText(sourceFile) ?? element.name.text;
14680
+ bindings.push({ localName: element.name.text, source, importedName, line });
14147
14681
  }
14148
14682
  }
14149
14683
  }
14150
14684
  return bindings;
14151
14685
  };
14152
- var uniqueExports = (exportsList) => {
14153
- const seen = new Set;
14154
- return exportsList.filter((item) => {
14155
- const key = `${item.declarationFile}::${item.localName}::${item.exportedName}`;
14156
- if (seen.has(key))
14157
- return false;
14158
- seen.add(key);
14159
- return true;
14160
- });
14161
- };
14162
- var traceImportedBinding = async (filePath, binding, exportedName, fs, state) => {
14163
- const targetPath = await resolveImportSourcePath(filePath, binding.source, fs, state.resolver);
14164
- if (!targetPath)
14165
- return [];
14166
- const traced = await traceFile(targetPath, fs, state);
14167
- const match = traced.find((item) => item.exportedName === binding.importedName || binding.importedName === "default" && item.exportedName === item.localName);
14168
- if (!match)
14169
- return [];
14170
- return [{
14171
- exportedName,
14172
- localName: match.localName,
14173
- declarationFile: match.declarationFile
14174
- }];
14175
- };
14176
- var traceFile = async (filePath, fs, state) => {
14177
- const cached = state.cache.get(filePath);
14178
- if (cached)
14179
- return cached;
14180
- if (state.inFlight.has(filePath))
14181
- return [];
14182
- const promise = (async () => {
14183
- state.inFlight.add(filePath);
14184
- state.files.add(filePath);
14185
- const source = await fs.readFile(filePath);
14186
- const commonJs = analyzeCommonJsModule(source, filePath);
14187
- if (commonJs.diagnostics.length > 0)
14188
- return [];
14189
- const jsxLike = isJsxLikePath(filePath);
14190
- const parserSource = jsxLike ? treeSitterCompatibleJsxSource(createEcmaScriptSourceFile(source, filePath), source) : source;
14191
- const tree = await parseFile(parserSource, jsxLike);
14192
- if (!tree)
14193
- return [];
14194
- const root = tree.rootNode;
14195
- const localDeclarations = collectLocalDeclarations(root);
14196
- const importBindings = collectImportBindings(root);
14197
- for (const declaration of commonJs.syntheticDeclarations) {
14198
- localDeclarations.set(declaration.name, declaration.name);
14686
+ var collectDynamicDiagnostics = (sourceFile) => {
14687
+ const diagnostics = [];
14688
+ const visit2 = (node2) => {
14689
+ if (ts7.isCallExpression(node2) && ts7.isIdentifier(node2.expression) && node2.expression.text === "require") {
14690
+ if (staticStringValue(node2.arguments[0]) === null) {
14691
+ const location = nodeLocation(sourceFile, node2);
14692
+ diagnostics.push({
14693
+ code: "dynamic-commonjs-require",
14694
+ severity: "error",
14695
+ file: sourceFile.fileName,
14696
+ line: location.line,
14697
+ column: location.column
14698
+ });
14699
+ }
14199
14700
  }
14200
- for (const binding of commonJs.bindings) {
14201
- importBindings.set(binding.localName, {
14202
- source: binding.source,
14203
- importedName: binding.importedName
14701
+ if (ts7.isCallExpression(node2) && isUnsupportedExportMutationCall(node2)) {
14702
+ const location = nodeLocation(sourceFile, node2);
14703
+ diagnostics.push({
14704
+ code: "unsupported-commonjs-export-form",
14705
+ severity: "error",
14706
+ file: sourceFile.fileName,
14707
+ line: location.line,
14708
+ column: location.column
14204
14709
  });
14205
14710
  }
14206
- const exportsList = [];
14207
- for (const node2 of root.namedChildren) {
14208
- if (node2.type !== "export_statement")
14209
- continue;
14210
- const stringNode = node2.namedChildren.find((child) => child.type === "string");
14211
- const exportClause = node2.namedChildren.find((child) => child.type === "export_clause");
14212
- const declaration = node2.namedChildren.find((child) => DECLARATION_TYPES.has(child.type));
14213
- if (declaration) {
14214
- for (const name of getDeclarationName(declaration)) {
14215
- exportsList.push({ exportedName: name, localName: name, declarationFile: filePath });
14216
- }
14217
- continue;
14218
- }
14219
- if (node2.text.startsWith("export default ")) {
14220
- const identifier = node2.namedChildren.find((child) => child.type === "identifier" || child.type === "type_identifier");
14221
- if (identifier && localDeclarations.has(identifier.text)) {
14222
- exportsList.push({
14223
- exportedName: identifier.text,
14224
- localName: identifier.text,
14225
- declarationFile: filePath
14711
+ if (ts7.isBinaryExpression(node2) && node2.operatorToken.kind === ts7.SyntaxKind.EqualsToken) {
14712
+ if (ts7.isElementAccessExpression(node2.left)) {
14713
+ const isCommonJsTarget = ts7.isIdentifier(node2.left.expression) && node2.left.expression.text === "exports" || isModuleExports(node2.left.expression) || isModuleExports(node2.left);
14714
+ if (isCommonJsTarget && commonJsExportTarget(node2.left) === null) {
14715
+ const location = nodeLocation(sourceFile, node2.left);
14716
+ diagnostics.push({
14717
+ code: "dynamic-commonjs-export",
14718
+ severity: "error",
14719
+ file: sourceFile.fileName,
14720
+ line: location.line,
14721
+ column: location.column
14226
14722
  });
14227
14723
  }
14228
- continue;
14229
14724
  }
14230
- if (!exportClause) {
14231
- if (stringNode && node2.text.startsWith("export *")) {
14232
- const targetPath2 = await resolveImportSourcePath(filePath, stripQuotes(stringNode.text), fs, state.resolver);
14233
- if (targetPath2) {
14234
- exportsList.push(...await traceFile(targetPath2, fs, state));
14235
- }
14236
- }
14237
- continue;
14725
+ }
14726
+ ts7.forEachChild(node2, visit2);
14727
+ };
14728
+ visit2(sourceFile);
14729
+ return diagnostics;
14730
+ };
14731
+ var analyzeCommonJsModule = (source, filePath) => {
14732
+ const sourceFile = createEcmaScriptSourceFile(source, filePath);
14733
+ const bindings = collectBindings(sourceFile);
14734
+ const bindingMap = new Map(bindings.map((binding) => [binding.localName, binding]));
14735
+ const result = {
14736
+ bindings,
14737
+ exports: [],
14738
+ wildcardSources: [],
14739
+ syntheticDeclarations: [],
14740
+ diagnostics: collectDynamicDiagnostics(sourceFile)
14741
+ };
14742
+ for (const statement of sourceFile.statements) {
14743
+ if (!ts7.isExpressionStatement(statement) || !ts7.isBinaryExpression(statement.expression))
14744
+ continue;
14745
+ const assignment = statement.expression;
14746
+ if (assignment.operatorToken.kind !== ts7.SyntaxKind.EqualsToken)
14747
+ continue;
14748
+ const target = commonJsExportTarget(assignment.left);
14749
+ if (!target)
14750
+ continue;
14751
+ const line = nodeLocation(sourceFile, assignment).line;
14752
+ if (target.kind === "named") {
14753
+ if (!pushExport(result, target.exportedName, assignment.right, line, bindingMap, sourceFile)) {
14754
+ appendUnsupportedExportDiagnostic(result, sourceFile, assignment.right);
14238
14755
  }
14239
- if (!stringNode) {
14240
- for (const specifier of exportClause.namedChildren.filter((child) => child.type === "export_specifier")) {
14241
- const parsed = parseExportSpecifier(specifier);
14242
- if (!parsed)
14243
- continue;
14244
- if (localDeclarations.has(parsed.localName)) {
14245
- exportsList.push({
14246
- exportedName: parsed.exportedName,
14247
- localName: parsed.localName,
14248
- declarationFile: filePath
14249
- });
14250
- continue;
14251
- }
14252
- const importBinding = importBindings.get(parsed.localName);
14253
- if (importBinding) {
14254
- exportsList.push(...await traceImportedBinding(filePath, importBinding, parsed.exportedName, fs, state));
14255
- }
14756
+ continue;
14757
+ }
14758
+ const directRequire = requireReference(assignment.right);
14759
+ if (directRequire?.importedName === "*") {
14760
+ result.wildcardSources.push(directRequire.source);
14761
+ continue;
14762
+ }
14763
+ if (ts7.isObjectLiteralExpression(assignment.right)) {
14764
+ for (const property of assignment.right.properties) {
14765
+ if (ts7.isShorthandPropertyAssignment(property)) {
14766
+ pushExport(result, property.name.text, property.name, line, bindingMap, sourceFile);
14767
+ continue;
14256
14768
  }
14257
- continue;
14258
- }
14259
- const targetPath = await resolveImportSourcePath(filePath, stripQuotes(stringNode.text), fs, state.resolver);
14260
- if (!targetPath)
14261
- continue;
14262
- const traced = await traceFile(targetPath, fs, state);
14263
- for (const specifier of exportClause.namedChildren.filter((child) => child.type === "export_specifier")) {
14264
- const parsed = parseExportSpecifier(specifier);
14265
- if (!parsed)
14769
+ if (ts7.isPropertyAssignment(property)) {
14770
+ const name = property.name && (ts7.isIdentifier(property.name) || ts7.isStringLiteral(property.name)) ? property.name.text : null;
14771
+ if (name) {
14772
+ if (!pushExport(result, name, property.initializer, line, bindingMap, sourceFile)) {
14773
+ appendUnsupportedExportDiagnostic(result, sourceFile, property.initializer);
14774
+ }
14775
+ } else {
14776
+ appendUnsupportedExportDiagnostic(result, sourceFile, property);
14777
+ }
14266
14778
  continue;
14267
- const match = traced.find((item) => item.exportedName === parsed.localName);
14268
- if (!match)
14779
+ }
14780
+ if (ts7.isMethodDeclaration(property) && property.name && ts7.isIdentifier(property.name)) {
14781
+ const location = nodeLocation(sourceFile, property);
14782
+ result.syntheticDeclarations.push({
14783
+ name: property.name.text,
14784
+ kind: "function",
14785
+ line: location.line,
14786
+ endLine: location.endLine,
14787
+ params: property.parameters.map((parameter) => parameter.name.getText(sourceFile))
14788
+ });
14789
+ result.exports.push({
14790
+ exportedName: property.name.text,
14791
+ localName: property.name.text,
14792
+ line
14793
+ });
14269
14794
  continue;
14270
- exportsList.push({
14271
- exportedName: parsed.exportedName,
14272
- localName: match.localName,
14273
- declarationFile: match.declarationFile
14274
- });
14795
+ }
14796
+ appendUnsupportedExportDiagnostic(result, sourceFile, property);
14275
14797
  }
14798
+ continue;
14276
14799
  }
14277
- exportsList.push(...await traceCommonJsExports({
14278
- analysis: commonJs,
14279
- filePath,
14280
- localDeclarations,
14281
- traceImported: (source2, importedName, exportedName) => traceImportedBinding(filePath, { source: source2, importedName }, exportedName, fs, state),
14282
- traceWildcard: async (source2) => {
14283
- const targetPath = await resolveImportSourcePath(filePath, source2, fs, state.resolver);
14284
- return targetPath ? traceFile(targetPath, fs, state) : [];
14800
+ if (ts7.isIdentifier(assignment.right)) {
14801
+ const binding = bindingMap.get(assignment.right.text);
14802
+ if (binding?.importedName === "*") {
14803
+ result.wildcardSources.push(binding.source);
14804
+ continue;
14285
14805
  }
14286
- }));
14287
- state.inFlight.delete(filePath);
14288
- return uniqueExports(exportsList);
14289
- })();
14290
- state.cache.set(filePath, promise);
14291
- return promise;
14292
- };
14293
- var traceExports = async (entryPath, fs, resolver = { mappings: [] }) => {
14294
- const state = {
14295
- files: new Set,
14296
- cache: new Map,
14297
- inFlight: new Set,
14298
- resolver
14299
- };
14300
- const exportsList = await traceFile(entryPath, fs, state);
14301
- return {
14302
- exports: uniqueExports(exportsList),
14303
- files: [...state.files].sort()
14304
- };
14806
+ if (!pushExport(result, assignment.right.text, assignment.right, line, bindingMap, sourceFile)) {
14807
+ appendUnsupportedExportDiagnostic(result, sourceFile, assignment.right);
14808
+ }
14809
+ continue;
14810
+ }
14811
+ if (!pushExport(result, "default", assignment.right, line, bindingMap, sourceFile)) {
14812
+ appendUnsupportedExportDiagnostic(result, sourceFile, assignment.right);
14813
+ }
14814
+ }
14815
+ result.bindings.sort((left, right) => left.localName.localeCompare(right.localName));
14816
+ result.exports.sort((left, right) => left.exportedName.localeCompare(right.exportedName) || left.line - right.line);
14817
+ result.wildcardSources = [...new Set(result.wildcardSources)].sort();
14818
+ result.syntheticDeclarations.sort((left, right) => left.name.localeCompare(right.name));
14819
+ result.diagnostics.sort((left, right) => left.line - right.line || left.column - right.column);
14820
+ return result;
14305
14821
  };
14306
14822
 
14307
- // src/symbolExtractorAst.ts
14823
+ // src/commonJsExportTrace.ts
14824
+ var traceCommonJsExports = async (input) => {
14825
+ const traced = [];
14826
+ for (const item of input.analysis.exports) {
14827
+ if (item.localName && input.localDeclarations.has(item.localName)) {
14828
+ traced.push({
14829
+ exportedName: item.exportedName,
14830
+ localName: item.localName,
14831
+ declarationFile: input.filePath
14832
+ });
14833
+ continue;
14834
+ }
14835
+ if (item.source && item.importedName) {
14836
+ traced.push(...await input.traceImported(item.source, item.importedName, item.exportedName));
14837
+ }
14838
+ }
14839
+ for (const source of input.analysis.wildcardSources) {
14840
+ traced.push(...await input.traceWildcard(source));
14841
+ }
14842
+ return traced;
14843
+ };
14844
+
14845
+ // src/exportTracer.ts
14308
14846
  var DECLARATION_TYPES2 = new Set([
14309
14847
  "function_declaration",
14310
14848
  "class_declaration",
@@ -14313,296 +14851,243 @@ var DECLARATION_TYPES2 = new Set([
14313
14851
  "enum_declaration",
14314
14852
  "lexical_declaration"
14315
14853
  ]);
14316
- var BUILTIN_TYPES = new Set([
14317
- "Array",
14318
- "Boolean",
14319
- "Date",
14320
- "Error",
14321
- "Map",
14322
- "Number",
14323
- "Object",
14324
- "Promise",
14325
- "ReadonlyArray",
14326
- "Record",
14327
- "Set",
14328
- "String",
14329
- "unknown",
14330
- "void",
14331
- "string",
14332
- "number",
14333
- "boolean",
14334
- "null",
14335
- "undefined",
14336
- "never",
14337
- "any"
14338
- ]);
14339
- var countLines = (source) => {
14340
- if (!source)
14341
- return 0;
14342
- return source.split(/\r\n|\r|\n/).filter((line) => line.trim().length > 0).length;
14343
- };
14344
- var createRelation = (type, from, to, isExternal, line) => ({
14345
- type,
14346
- from,
14347
- to,
14348
- isExternal,
14349
- grounding: "code" /* Code */,
14350
- confidence: 1,
14351
- source: "ast" /* Ast */,
14352
- ...line ? { line } : {}
14353
- });
14354
- var getLine = (node2) => node2.startPosition.row + 1;
14355
- var getEndLine = (node2) => node2.endPosition.row + 1;
14356
- var extractJSDoc = (node2) => {
14357
- const prev = node2.previousNamedSibling ?? node2.parent?.previousNamedSibling;
14358
- if (!prev || prev.type !== "comment")
14359
- return;
14360
- const text = prev.text;
14361
- if (!text.startsWith("/**"))
14362
- return;
14363
- const cleaned = text.replace(/^\/\*\*\s*/, "").replace(/\s*\*\/$/, "").replace(/^\s*\* ?/gm, "").trim();
14364
- return cleaned || undefined;
14365
- };
14366
- var extractTypeAnnotation = (node2) => {
14367
- if (!node2)
14368
- return null;
14369
- return node2.text.replace(/^:\s*/, "").trim() || null;
14370
- };
14371
- var getNameNodeText = (node2) => node2?.text?.trim() ? node2.text.trim() : null;
14372
- var getReturnType = (node2) => {
14373
- const returnNode = node2.childForFieldName("return_type") ?? node2.namedChildren.find((child) => child.type === "type_annotation") ?? null;
14374
- return extractTypeAnnotation(returnNode);
14375
- };
14376
- var getInitializer = (node2) => node2.childForFieldName("value") ?? node2.namedChildren.find((child) => child.type === "arrow_function" || child.type === "function" || child.type === "call_expression") ?? null;
14377
- var getCallableFromInitializer = (node2) => {
14378
- if (!node2)
14379
- return null;
14380
- if (node2.type === "arrow_function" || node2.type === "function")
14381
- return node2;
14382
- if (node2.type === "call_expression") {
14383
- return node2.namedChildren.find((child) => child.type === "arrow_function" || child.type === "function") ?? null;
14384
- }
14385
- return null;
14386
- };
14387
- var getInitializerTypeAnnotation = (node2) => {
14388
- if (!node2 || node2.type !== "call_expression")
14389
- return null;
14390
- const typeArguments = node2.namedChildren.find((child) => child.type === "type_arguments") ?? null;
14391
- if (!typeArguments)
14392
- return null;
14393
- const callee = node2.namedChildren.find((child) => child.type !== "type_arguments" && child.type !== "arguments") ?? null;
14394
- const calleeText = callee?.text?.trim();
14395
- return calleeText ? `${calleeText}${typeArguments.text}` : typeArguments.text;
14396
- };
14397
- var getInitializerText = (node2, options = {}) => {
14398
- if (!node2)
14399
- return null;
14400
- if ((node2.type === "arrow_function" || node2.type === "function") && !options.includeCallable)
14401
- return null;
14402
- const text = node2.text.trim();
14403
- if ((node2.type === "arrow_function" || node2.type === "function") && text.length > 600)
14404
- return null;
14405
- return text.length > 0 ? text : null;
14406
- };
14407
- var inferReturnType = (node2) => {
14408
- if (!node2)
14409
- return null;
14410
- return containsJsx(node2) ? "JSX.Element" : null;
14411
- };
14412
- var containsJsx = (node2) => {
14413
- if (node2.type.startsWith("jsx_"))
14414
- return true;
14415
- return node2.namedChildren.some(containsJsx);
14416
- };
14417
- var getTypeNames = (typeText) => {
14418
- if (!typeText)
14419
- return [];
14420
- const matches = typeText.match(/\b[A-Z][A-Za-z0-9_]*(?:\.[A-Z][A-Za-z0-9_]*)*\b/g) ?? [];
14421
- return [...new Set(matches)].filter((match) => !BUILTIN_TYPES.has(match));
14422
- };
14423
- var resolveTypeBinding = (typeName, importBindings, declarations) => {
14424
- const localName = typeName.split(".")[0] ?? typeName;
14425
- const importBinding = importBindings.get(localName);
14426
- if (importBinding)
14427
- return importBinding.isExternal;
14428
- if (declarations.has(localName))
14429
- return false;
14430
- return false;
14431
- };
14432
- var appendTypeRelations = (relations, relationType, from, typeText, importBindings, declarations, line) => {
14433
- for (const typeName of getTypeNames(typeText)) {
14434
- relations.push(createRelation(relationType, from, typeName, resolveTypeBinding(typeName, importBindings, declarations), line));
14435
- }
14436
- };
14437
- var classifyVariable = (name, filePath) => {
14438
- if ((filePath.endsWith(".tsx") || filePath.endsWith(".jsx")) && /^[A-Z]/.test(name)) {
14439
- return "component" /* Component */;
14854
+ var stripQuotes = (value) => value.replace(/^['"]/, "").replace(/['"]$/, "");
14855
+ var getDeclarationName = (node2) => {
14856
+ if (node2.type === "lexical_declaration") {
14857
+ return node2.namedChildren.filter((child) => child.type === "variable_declarator").map((child) => child.childForFieldName("name")?.text ?? child.namedChildren[0]?.text ?? "").filter(Boolean);
14440
14858
  }
14441
- return "variable" /* Variable */;
14442
- };
14443
- var collectParams = (node2) => {
14444
- if (!node2)
14445
- return [];
14446
- return node2.namedChildren.map((child) => {
14447
- const wrapper = child;
14448
- const target = child.type === "required_parameter" || child.type === "optional_parameter" ? child.namedChildren[0] ?? child : child;
14449
- const nameNode = target.childForFieldName("name") ?? target.namedChildren.find((candidate) => candidate.type === "identifier" || candidate.type === "property_identifier") ?? target.namedChildren[0] ?? target;
14450
- const typeNode = wrapper.childForFieldName("type") ?? wrapper.namedChildren.find((candidate) => candidate.type === "type_annotation") ?? target.childForFieldName("type") ?? target.namedChildren.find((candidate) => candidate.type === "type_annotation") ?? null;
14451
- return {
14452
- name: nameNode.text,
14453
- type: extractTypeAnnotation(typeNode)
14454
- };
14455
- });
14859
+ const nameNode = node2.childForFieldName("name") ?? node2.namedChildren.find((child) => child.type === "identifier" || child.type === "type_identifier");
14860
+ return nameNode?.text ? [nameNode.text] : [];
14456
14861
  };
14457
- var collectMembers = (node2, declarations, importBindings, ownerName, relations) => {
14458
- if (!node2)
14459
- return;
14460
- const members = [];
14461
- for (const child of node2.namedChildren) {
14462
- if (child.type === "public_field_definition" || child.type === "property_signature") {
14463
- const nameNode = child.childForFieldName("name") ?? child.namedChildren.find((candidate) => candidate.type === "property_identifier" || candidate.type === "identifier");
14464
- if (!nameNode)
14465
- continue;
14466
- const typeNode = child.childForFieldName("type") ?? child.namedChildren.find((candidate) => candidate.type === "type_annotation") ?? null;
14467
- const typeAnnotation = extractTypeAnnotation(typeNode);
14468
- const propDoc = extractJSDoc(child);
14469
- members.push({
14470
- name: nameNode.text,
14471
- kind: "prop" /* Prop */,
14472
- visibility: "internal" /* Internal */,
14473
- file: "",
14474
- line: getLine(child),
14475
- endLine: getEndLine(child),
14476
- ...typeAnnotation ? { typeAnnotation } : {},
14477
- ...propDoc ? { doc: propDoc } : {}
14478
- });
14479
- appendTypeRelations(relations, "of_type" /* OfType */, ownerName, typeAnnotation, importBindings, declarations, getLine(child));
14480
- continue;
14481
- }
14482
- const indexMember = indexSignatureMember(child);
14483
- if (indexMember) {
14484
- members.push(indexMember.info);
14485
- appendTypeRelations(relations, "of_type" /* OfType */, ownerName, indexMember.typeAnnotation, importBindings, declarations, getLine(child));
14486
- continue;
14487
- }
14488
- if (child.type === "method_definition" || child.type === "method_signature") {
14489
- const nameNode = child.childForFieldName("name") ?? child.namedChildren.find((candidate) => candidate.type === "property_identifier" || candidate.type === "identifier");
14490
- if (!nameNode)
14491
- continue;
14492
- const paramsNode = child.childForFieldName("parameters") ?? child.namedChildren.find((candidate) => candidate.type === "formal_parameters") ?? null;
14493
- const params = collectParams(paramsNode);
14494
- const returnType = getReturnType(child);
14495
- const methodDoc = extractJSDoc(child);
14496
- members.push({
14497
- name: nameNode.text,
14498
- kind: "method" /* Method */,
14499
- visibility: "internal" /* Internal */,
14500
- file: "",
14501
- line: getLine(child),
14502
- endLine: getEndLine(child),
14503
- ...params.length > 0 ? { params } : {},
14504
- ...returnType ? { returnType } : {},
14505
- ...methodDoc ? { doc: methodDoc } : {}
14506
- });
14507
- for (const param of params) {
14508
- appendTypeRelations(relations, "param_type" /* ParamType */, ownerName, param.type, importBindings, declarations, getLine(child));
14862
+ var collectLocalDeclarations = (root) => {
14863
+ const declarations = new Map;
14864
+ const register = (node2) => {
14865
+ for (const name of getDeclarationName(node2)) {
14866
+ if (!declarations.has(name)) {
14867
+ declarations.set(name, name);
14509
14868
  }
14510
- appendTypeRelations(relations, "return_type" /* ReturnType */, ownerName, returnType, importBindings, declarations, getLine(child));
14511
14869
  }
14512
- }
14513
- return members.length > 0 ? members : undefined;
14514
- };
14515
- var indexSignatureMember = (node2) => {
14516
- if (node2.type !== "index_signature")
14517
- return null;
14518
- const match = /^\s*(\[[^\]]+\])\s*:?\s*([^;]+)?;?\s*$/u.exec(node2.text);
14519
- const name = match?.[1]?.trim();
14520
- const typeAnnotation = match?.[2]?.trim();
14521
- if (!name)
14522
- return null;
14523
- const propDoc = extractJSDoc(node2);
14524
- return {
14525
- info: {
14526
- name,
14527
- kind: "prop" /* Prop */,
14528
- visibility: "internal" /* Internal */,
14529
- file: "",
14530
- line: getLine(node2),
14531
- endLine: getEndLine(node2),
14532
- ...typeAnnotation ? { typeAnnotation } : {},
14533
- ...propDoc ? { doc: propDoc } : {}
14534
- },
14535
- typeAnnotation
14536
14870
  };
14537
- };
14538
- var collectEnumValues = (node2) => {
14539
- const body = node2.namedChildren.find((child) => child.type === "enum_body") ?? null;
14540
- if (!body)
14541
- return;
14542
- const values = [];
14543
- for (const member of body.namedChildren.filter((child) => child.type === "enum_assignment" || child.type === "property_identifier")) {
14544
- if (member.type === "property_identifier") {
14545
- values.push(member.text);
14871
+ for (const child of root.namedChildren) {
14872
+ if (DECLARATION_TYPES2.has(child.type)) {
14873
+ register(child);
14546
14874
  continue;
14547
14875
  }
14548
- const name = member.childForFieldName("name")?.text ?? member.namedChildren[0]?.text;
14549
- if (!name)
14876
+ if (child.type !== "export_statement")
14550
14877
  continue;
14551
- const valueNode = member.childForFieldName("value") ?? member.namedChildren.find((child) => child !== member.childForFieldName("name")) ?? null;
14552
- const rawValue = valueNode?.text.replace(/^['"]|['"]$/gu, "");
14553
- values.push(rawValue ? `${name} = ${rawValue}` : name);
14878
+ const declaration = child.namedChildren.find((node2) => DECLARATION_TYPES2.has(node2.type));
14879
+ if (declaration) {
14880
+ register(declaration);
14881
+ }
14554
14882
  }
14555
- return values.length > 0 ? values : undefined;
14883
+ return declarations;
14556
14884
  };
14557
- var extractUnionLiteralValues = (typeNode) => {
14558
- if (!typeNode)
14559
- return;
14560
- if (typeNode.type === "literal_type") {
14561
- const text = typeNode.text.replace(/^['"]|['"]$/g, "");
14562
- return text ? [text] : undefined;
14563
- }
14564
- if (typeNode.type === "union_type") {
14565
- const values = [];
14566
- for (const child of typeNode.namedChildren) {
14567
- if (child.type === "literal_type") {
14568
- const text = child.text.replace(/^['"]|['"]$/g, "");
14569
- if (text)
14570
- values.push(text);
14571
- } else if (child.type === "union_type") {
14572
- const nested = extractUnionLiteralValues(child);
14573
- if (!nested)
14574
- return;
14575
- values.push(...nested);
14576
- } else {
14577
- return;
14885
+ var parseExportSpecifier = (node2) => {
14886
+ const identifiers = node2.namedChildren.filter((child) => child.type === "identifier" || child.type === "type_identifier").map((child) => child.text);
14887
+ if (identifiers.length === 0)
14888
+ return null;
14889
+ const localName = identifiers[0];
14890
+ const exportedName = identifiers[1] ?? localName;
14891
+ return { localName, exportedName };
14892
+ };
14893
+ var parseImportSpecifier = (node2) => {
14894
+ const identifiers = node2.namedChildren.filter((child) => child.type === "identifier" || child.type === "type_identifier").map((child) => child.text);
14895
+ if (identifiers.length === 0)
14896
+ return null;
14897
+ const importedName = identifiers[0];
14898
+ const localName = identifiers[1] ?? importedName;
14899
+ return { importedName, localName };
14900
+ };
14901
+ var collectImportBindings = (root) => {
14902
+ const bindings = new Map;
14903
+ for (const node2 of root.namedChildren) {
14904
+ if (node2.type !== "import_statement")
14905
+ continue;
14906
+ const stringNode = node2.namedChildren.find((child) => child.type === "string");
14907
+ if (!stringNode)
14908
+ continue;
14909
+ const source = stripQuotes(stringNode.text);
14910
+ const clause = node2.namedChildren.find((child) => child.type === "import_clause");
14911
+ for (const part of clause?.namedChildren ?? []) {
14912
+ if (part.type === "identifier") {
14913
+ bindings.set(part.text, { source, importedName: "default" });
14914
+ continue;
14915
+ }
14916
+ if (part.type !== "named_imports")
14917
+ continue;
14918
+ for (const specifier of part.namedChildren.filter((child) => child.type === "import_specifier")) {
14919
+ const parsed = parseImportSpecifier(specifier);
14920
+ if (parsed) {
14921
+ bindings.set(parsed.localName, { source, importedName: parsed.importedName });
14922
+ }
14578
14923
  }
14579
14924
  }
14580
- return values.length > 0 ? values : undefined;
14581
14925
  }
14582
- return;
14926
+ return bindings;
14583
14927
  };
14584
- var findObjectTypeNodes = (node2) => {
14585
- if (!node2)
14928
+ var uniqueExports = (exportsList) => {
14929
+ const seen = new Set;
14930
+ return exportsList.filter((item) => {
14931
+ const key = `${item.declarationFile}::${item.localName}::${item.exportedName}`;
14932
+ if (seen.has(key))
14933
+ return false;
14934
+ seen.add(key);
14935
+ return true;
14936
+ });
14937
+ };
14938
+ var traceImportedBinding = async (filePath, binding, exportedName, fs, state) => {
14939
+ const targetPath = await resolveImportSourcePath(filePath, binding.source, fs, state.resolver);
14940
+ if (!targetPath)
14586
14941
  return [];
14587
- if (node2.type === "object_type")
14588
- return [node2];
14589
- if (node2.type === "intersection_type" || node2.type === "union_type") {
14590
- return node2.namedChildren.flatMap(findObjectTypeNodes);
14591
- }
14592
- if (node2.type === "parenthesized_type" && node2.namedChildCount > 0) {
14593
- return findObjectTypeNodes(node2.namedChildren[0]);
14594
- }
14595
- return [];
14942
+ const traced = await traceFile(targetPath, fs, state);
14943
+ const match = traced.find((item) => item.exportedName === binding.importedName || binding.importedName === "default" && item.exportedName === item.localName);
14944
+ if (!match)
14945
+ return [];
14946
+ return [{
14947
+ exportedName,
14948
+ localName: match.localName,
14949
+ declarationFile: match.declarationFile
14950
+ }];
14951
+ };
14952
+ var traceFile = async (filePath, fs, state) => {
14953
+ const cached = state.cache.get(filePath);
14954
+ if (cached)
14955
+ return cached;
14956
+ if (state.inFlight.has(filePath))
14957
+ return [];
14958
+ const promise = (async () => {
14959
+ state.inFlight.add(filePath);
14960
+ state.files.add(filePath);
14961
+ const source = await fs.readFile(filePath);
14962
+ const commonJs = analyzeCommonJsModule(source, filePath);
14963
+ if (commonJs.diagnostics.length > 0)
14964
+ return [];
14965
+ const jsxLike = isJsxLikePath(filePath);
14966
+ const parserSource = jsxLike ? treeSitterCompatibleJsxSource(createEcmaScriptSourceFile(source, filePath), source) : source;
14967
+ const tree = await parseFile(parserSource, jsxLike);
14968
+ if (!tree)
14969
+ return [];
14970
+ const root = tree.rootNode;
14971
+ const localDeclarations = collectLocalDeclarations(root);
14972
+ const importBindings = collectImportBindings(root);
14973
+ for (const declaration of commonJs.syntheticDeclarations) {
14974
+ localDeclarations.set(declaration.name, declaration.name);
14975
+ }
14976
+ for (const binding of commonJs.bindings) {
14977
+ importBindings.set(binding.localName, {
14978
+ source: binding.source,
14979
+ importedName: binding.importedName
14980
+ });
14981
+ }
14982
+ const exportsList = [];
14983
+ for (const node2 of root.namedChildren) {
14984
+ if (node2.type !== "export_statement")
14985
+ continue;
14986
+ const stringNode = node2.namedChildren.find((child) => child.type === "string");
14987
+ const exportClause = node2.namedChildren.find((child) => child.type === "export_clause");
14988
+ const declaration = node2.namedChildren.find((child) => DECLARATION_TYPES2.has(child.type));
14989
+ if (declaration) {
14990
+ for (const name of getDeclarationName(declaration)) {
14991
+ exportsList.push({ exportedName: name, localName: name, declarationFile: filePath });
14992
+ }
14993
+ continue;
14994
+ }
14995
+ if (node2.text.startsWith("export default ")) {
14996
+ const identifier = node2.namedChildren.find((child) => child.type === "identifier" || child.type === "type_identifier");
14997
+ if (identifier && localDeclarations.has(identifier.text)) {
14998
+ exportsList.push({
14999
+ exportedName: identifier.text,
15000
+ localName: identifier.text,
15001
+ declarationFile: filePath
15002
+ });
15003
+ }
15004
+ continue;
15005
+ }
15006
+ if (!exportClause) {
15007
+ if (stringNode && node2.text.startsWith("export *")) {
15008
+ const targetPath2 = await resolveImportSourcePath(filePath, stripQuotes(stringNode.text), fs, state.resolver);
15009
+ if (targetPath2) {
15010
+ exportsList.push(...await traceFile(targetPath2, fs, state));
15011
+ }
15012
+ }
15013
+ continue;
15014
+ }
15015
+ if (!stringNode) {
15016
+ for (const specifier of exportClause.namedChildren.filter((child) => child.type === "export_specifier")) {
15017
+ const parsed = parseExportSpecifier(specifier);
15018
+ if (!parsed)
15019
+ continue;
15020
+ if (localDeclarations.has(parsed.localName)) {
15021
+ exportsList.push({
15022
+ exportedName: parsed.exportedName,
15023
+ localName: parsed.localName,
15024
+ declarationFile: filePath
15025
+ });
15026
+ continue;
15027
+ }
15028
+ const importBinding = importBindings.get(parsed.localName);
15029
+ if (importBinding) {
15030
+ exportsList.push(...await traceImportedBinding(filePath, importBinding, parsed.exportedName, fs, state));
15031
+ }
15032
+ }
15033
+ continue;
15034
+ }
15035
+ const targetPath = await resolveImportSourcePath(filePath, stripQuotes(stringNode.text), fs, state.resolver);
15036
+ if (!targetPath)
15037
+ continue;
15038
+ const traced = await traceFile(targetPath, fs, state);
15039
+ for (const specifier of exportClause.namedChildren.filter((child) => child.type === "export_specifier")) {
15040
+ const parsed = parseExportSpecifier(specifier);
15041
+ if (!parsed)
15042
+ continue;
15043
+ const match = traced.find((item) => item.exportedName === parsed.localName);
15044
+ if (!match)
15045
+ continue;
15046
+ exportsList.push({
15047
+ exportedName: parsed.exportedName,
15048
+ localName: match.localName,
15049
+ declarationFile: match.declarationFile
15050
+ });
15051
+ }
15052
+ }
15053
+ exportsList.push(...await traceCommonJsExports({
15054
+ analysis: commonJs,
15055
+ filePath,
15056
+ localDeclarations,
15057
+ traceImported: (source2, importedName, exportedName) => traceImportedBinding(filePath, { source: source2, importedName }, exportedName, fs, state),
15058
+ traceWildcard: async (source2) => {
15059
+ const targetPath = await resolveImportSourcePath(filePath, source2, fs, state.resolver);
15060
+ return targetPath ? traceFile(targetPath, fs, state) : [];
15061
+ }
15062
+ }));
15063
+ state.inFlight.delete(filePath);
15064
+ return uniqueExports(exportsList);
15065
+ })();
15066
+ state.cache.set(filePath, promise);
15067
+ return promise;
15068
+ };
15069
+ var traceExports = async (entryPath, fs, resolver = { mappings: [] }) => {
15070
+ const state = {
15071
+ files: new Set,
15072
+ cache: new Map,
15073
+ inFlight: new Set,
15074
+ resolver
15075
+ };
15076
+ const exportsList = await traceFile(entryPath, fs, state);
15077
+ return {
15078
+ exports: uniqueExports(exportsList),
15079
+ files: [...state.files].sort()
15080
+ };
14596
15081
  };
14597
15082
 
14598
15083
  // src/staticCallRelations.ts
14599
- import ts3 from "typescript";
15084
+ import ts8 from "typescript";
14600
15085
  var callTarget = (expression, sourceFile) => {
14601
- if (ts3.isIdentifier(expression))
15086
+ if (ts8.isIdentifier(expression))
14602
15087
  return expression.text === "require" ? null : expression.text;
14603
- if (ts3.isPropertyAccessExpression(expression))
15088
+ if (ts8.isPropertyAccessExpression(expression))
14604
15089
  return expression.getText(sourceFile).replace(/\s+/gu, "");
14605
- if (ts3.isElementAccessExpression(expression)) {
15090
+ if (ts8.isElementAccessExpression(expression)) {
14606
15091
  const property = staticStringValue(expression.argumentExpression);
14607
15092
  return property ? `${expression.expression.getText(sourceFile).replace(/\s+/gu, "")}.${property}` : null;
14608
15093
  }
@@ -14610,21 +15095,21 @@ var callTarget = (expression, sourceFile) => {
14610
15095
  };
14611
15096
  var rootIdentifier = (expression) => {
14612
15097
  let current = expression;
14613
- while (ts3.isPropertyAccessExpression(current) || ts3.isElementAccessExpression(current)) {
15098
+ while (ts8.isPropertyAccessExpression(current) || ts8.isElementAccessExpression(current)) {
14614
15099
  current = current.expression;
14615
15100
  }
14616
- return ts3.isIdentifier(current) ? current.text : null;
15101
+ return ts8.isIdentifier(current) ? current.text : null;
14617
15102
  };
14618
15103
  var declarationName = (node2, sourceFile) => {
14619
- if (ts3.isFunctionDeclaration(node2) && node2.name)
15104
+ if (ts8.isFunctionDeclaration(node2) && node2.name)
14620
15105
  return node2.name.text;
14621
- if (ts3.isClassDeclaration(node2) && node2.name)
15106
+ if (ts8.isClassDeclaration(node2) && node2.name)
14622
15107
  return node2.name.text;
14623
- if (ts3.isVariableDeclaration(node2) && ts3.isIdentifier(node2.name))
15108
+ if (ts8.isVariableDeclaration(node2) && ts8.isIdentifier(node2.name))
14624
15109
  return node2.name.text;
14625
- if (ts3.isMethodDeclaration(node2) || ts3.isGetAccessorDeclaration(node2) || ts3.isSetAccessorDeclaration(node2)) {
15110
+ if (ts8.isMethodDeclaration(node2) || ts8.isGetAccessorDeclaration(node2) || ts8.isSetAccessorDeclaration(node2)) {
14626
15111
  const parent = node2.parent;
14627
- if (parent && ts3.isClassDeclaration(parent) && parent.name)
15112
+ if (parent && ts8.isClassDeclaration(parent) && parent.name)
14628
15113
  return parent.name.text;
14629
15114
  return node2.name?.getText(sourceFile) ?? null;
14630
15115
  }
@@ -14635,7 +15120,7 @@ var collectStaticCallRelations = (source, filePath, importBindings) => {
14635
15120
  const relations = [];
14636
15121
  const visit2 = (node2, owner) => {
14637
15122
  const namedOwner = declarationName(node2, sourceFile) ?? owner;
14638
- if (ts3.isCallExpression(node2) || ts3.isNewExpression(node2)) {
15123
+ if (ts8.isCallExpression(node2) || ts8.isNewExpression(node2)) {
14639
15124
  const target = callTarget(node2.expression, sourceFile);
14640
15125
  if (target) {
14641
15126
  const root = rootIdentifier(node2.expression);
@@ -14643,7 +15128,7 @@ var collectStaticCallRelations = (source, filePath, importBindings) => {
14643
15128
  relations.push(createRelation("calls" /* Calls */, namedOwner, target, isExternal, nodeLocation(sourceFile, node2).line));
14644
15129
  }
14645
15130
  }
14646
- ts3.forEachChild(node2, (child) => visit2(child, namedOwner));
15131
+ ts8.forEachChild(node2, (child) => visit2(child, namedOwner));
14647
15132
  };
14648
15133
  visit2(sourceFile, filePath);
14649
15134
  const seen = new Set;
@@ -14778,10 +15263,10 @@ var analyzeLexicalDeclaration = (node2, filePath, declarations, importBindings,
14778
15263
  continue;
14779
15264
  const typeNode = declarator.childForFieldName("type") ?? declarator.namedChildren.find((child) => child.type === "type_annotation") ?? null;
14780
15265
  const initializer = getInitializer(declarator);
14781
- const callable = getCallableFromInitializer(initializer);
14782
- const paramsNode = callable?.childForFieldName("parameters") ?? callable?.namedChildren.find((child) => child.type === "formal_parameters") ?? null;
15266
+ const callable2 = getCallableFromInitializer(initializer);
15267
+ const paramsNode = callable2?.childForFieldName("parameters") ?? callable2?.namedChildren.find((child) => child.type === "formal_parameters") ?? null;
14783
15268
  const params = collectParams(paramsNode);
14784
- const returnType = callable ? getReturnType(callable) ?? inferReturnType(callable) : null;
15269
+ const returnType = callable2 ? getReturnType(callable2) ?? inferReturnType(callable2) : null;
14785
15270
  const initializerTypeAnnotation = getInitializerTypeAnnotation(initializer);
14786
15271
  const typeAnnotation = extractTypeAnnotation(typeNode) ?? initializerTypeAnnotation;
14787
15272
  const initializerText = getInitializerText(initializer, {
@@ -14807,7 +15292,7 @@ var analyzeLexicalDeclaration = (node2, filePath, declarations, importBindings,
14807
15292
  appendTypeRelations(relations, "param_type" /* ParamType */, nameNode.text, param.type, importBindings, declarations, getLine(declarator));
14808
15293
  }
14809
15294
  appendTypeRelations(relations, "return_type" /* ReturnType */, nameNode.text, returnType, importBindings, declarations, getLine(declarator));
14810
- appendTypeRelations(relations, "of_type" /* OfType */, nameNode.text, typeAnnotation, importBindings, declarations, getLine(declarator));
15295
+ appendTypeRelations(relations, "of_type" /* OfType */, nameNode.text, extractTypeAnnotation(typeNode) ?? getInitializerTypeAnnotation(initializer, { referencesOnly: true }), importBindings, declarations, getLine(declarator));
14811
15296
  }
14812
15297
  };
14813
15298
  var analyzeFunctionDeclaration = (node2, name, filePath, declarations, importBindings, relations) => {
@@ -14815,7 +15300,8 @@ var analyzeFunctionDeclaration = (node2, name, filePath, declarations, importBin
14815
15300
  const params = collectParams(paramsNode);
14816
15301
  const returnType = getReturnType(node2);
14817
15302
  const funcDoc = extractJSDoc(node2);
14818
- const signature = `${name}(${params.map((param) => `${param.name}${param.type ? `: ${param.type}` : ""}`).join(", ")})`;
15303
+ const body = node2.childForFieldName("body");
15304
+ const signature = body === null ? node2.text : node2.text.slice(0, body.startIndex - node2.startIndex).trimEnd();
14819
15305
  declarations.set(name, {
14820
15306
  info: {
14821
15307
  name,
@@ -14990,13 +15476,13 @@ var analyzeFile = async (filePath, fs, resolver = { mappings: [] }) => {
14990
15476
  }
14991
15477
  }
14992
15478
  for (const child of root.namedChildren) {
14993
- if (DECLARATION_TYPES2.has(child.type)) {
15479
+ if (DECLARATION_TYPES.has(child.type)) {
14994
15480
  analyzeDeclaration(child, filePath, declarations, importBindings, relations);
14995
15481
  continue;
14996
15482
  }
14997
15483
  if (child.type !== "export_statement")
14998
15484
  continue;
14999
- const declaration = child.namedChildren.find((node2) => DECLARATION_TYPES2.has(node2.type));
15485
+ const declaration = child.namedChildren.find((node2) => DECLARATION_TYPES.has(node2.type));
15000
15486
  if (declaration) {
15001
15487
  analyzeDeclaration(declaration, filePath, declarations, importBindings, relations);
15002
15488
  }
@@ -15006,7 +15492,7 @@ var analyzeFile = async (filePath, fs, resolver = { mappings: [] }) => {
15006
15492
  return {
15007
15493
  declarations,
15008
15494
  importBindings,
15009
- relations,
15495
+ relations: relations.map((relation) => ({ ...relation, file: filePath })),
15010
15496
  lines: countLines(source),
15011
15497
  disposition: "analyzed",
15012
15498
  diagnostics: []
@@ -15022,6 +15508,7 @@ var relationIdentity = (relation) => JSON.stringify([
15022
15508
  relation.grounding,
15023
15509
  relation.confidence,
15024
15510
  relation.source,
15511
+ relation.file ?? null,
15025
15512
  relation.line ?? null
15026
15513
  ]);
15027
15514
  var uniqueRelations = (relations) => {
@@ -15061,14 +15548,19 @@ var extractSymbols = async (entries, fs, options) => {
15061
15548
  continue;
15062
15549
  const declKey = `${tracedExport.declarationFile}::${tracedExport.localName}`;
15063
15550
  const exportKey = `${declKey}::${tracedExport.exportedName}`;
15064
- if (exportedDeclarationKeys.has(exportKey))
15551
+ if (exportedDeclarationKeys.has(exportKey)) {
15552
+ const existing = exportedSymbols.find((symbol) => symbol.file === tracedExport.declarationFile && symbol.name === tracedExport.exportedName);
15553
+ if (existing !== undefined)
15554
+ existing.publicEntrypoints = [...new Set([...existing.publicEntrypoints, entry.path])].sort();
15065
15555
  continue;
15556
+ }
15066
15557
  exportedDeclarationKeys.add(declKey);
15067
15558
  exportedDeclarationKeys.add(exportKey);
15068
15559
  exportedSymbols.push({
15069
15560
  ...declaration.info,
15070
15561
  name: tracedExport.exportedName,
15071
- visibility: "exported" /* Exported */
15562
+ visibility: "exported" /* Exported */,
15563
+ publicEntrypoints: [entry.path]
15072
15564
  });
15073
15565
  }
15074
15566
  }
@@ -15090,34 +15582,7 @@ var extractSymbols = async (entries, fs, options) => {
15090
15582
  }
15091
15583
  }
15092
15584
  const symbols = [...exportedSymbols, ...internalSymbols];
15093
- const typeDeclarations = new Map;
15094
- for (const analysis of analyses.values()) {
15095
- for (const [name, decl] of analysis.declarations) {
15096
- if (decl.info.kind === "interface" || decl.info.kind === "type") {
15097
- typeDeclarations.set(name, decl.info.file);
15098
- }
15099
- }
15100
- }
15101
- for (const sym of symbols) {
15102
- if (sym.kind !== "component")
15103
- continue;
15104
- let propsTypeName;
15105
- if (sym.typeAnnotation) {
15106
- const genericBody = /<(.+)>/u.exec(sym.typeAnnotation)?.[1];
15107
- const genericNames = genericBody?.match(/\b[A-Z][A-Za-z0-9_]*\b/gu) ?? [];
15108
- propsTypeName = genericNames.filter((name) => typeDeclarations.has(name)).at(-1);
15109
- }
15110
- if (!propsTypeName) {
15111
- const conventionName = `${sym.name}Props`;
15112
- if (typeDeclarations.has(conventionName)) {
15113
- propsTypeName = conventionName;
15114
- }
15115
- }
15116
- if (propsTypeName) {
15117
- sym.propsType = propsTypeName;
15118
- relations.push(createRelation("of_type" /* OfType */, sym.name, propsTypeName, false, sym.line));
15119
- }
15120
- }
15585
+ await enrichPublicContracts({ symbols, paths: [...analyses.keys()], fs, resolver, relations });
15121
15586
  const deduplicatedRelations = uniqueRelations(relations);
15122
15587
  const files = [...filePaths].sort().map((filePath) => ({
15123
15588
  path: filePath,
@@ -15195,10 +15660,15 @@ class TypeScriptPlugin {
15195
15660
  }
15196
15661
  }
15197
15662
  async extractSymbolsInScope(entries, analysisPaths, fs) {
15198
- const packageInfo = this.#lastDetection?.package;
15199
- if (!packageInfo) {
15200
- throw new Error("TypeScriptPlugin.extractSymbolsInScope requires detectEntries to run first");
15201
- }
15663
+ const detectedPackage = this.#lastDetection?.package;
15664
+ if (!detectedPackage && entries.length > 0) {
15665
+ throw new Error("TypeScriptPlugin.extractSymbolsInScope requires detectEntries before using package entries");
15666
+ }
15667
+ const packageInfo = detectedPackage ?? {
15668
+ name: "unknown-package",
15669
+ kind: "lib" /* Lib */,
15670
+ language: packageLanguage(analysisPaths)
15671
+ };
15202
15672
  try {
15203
15673
  return await extractSymbols(entries, fs, {
15204
15674
  packageInfo,
@@ -15211,20 +15681,20 @@ class TypeScriptPlugin {
15211
15681
  }
15212
15682
  }
15213
15683
  // src/reactRouter.ts
15214
- import * as ts4 from "typescript";
15684
+ import * as ts9 from "typescript";
15215
15685
  function compact(value) {
15216
15686
  return value.replace(/\s+/gu, " ").trim();
15217
15687
  }
15218
15688
  function scalarValue(node2) {
15219
15689
  if (!node2)
15220
15690
  return;
15221
- if (ts4.isStringLiteralLike(node2) || ts4.isNoSubstitutionTemplateLiteral(node2))
15691
+ if (ts9.isStringLiteralLike(node2) || ts9.isNoSubstitutionTemplateLiteral(node2))
15222
15692
  return node2.text;
15223
- if (ts4.isNumericLiteral(node2))
15693
+ if (ts9.isNumericLiteral(node2))
15224
15694
  return Number(node2.text);
15225
- if (node2.kind === ts4.SyntaxKind.TrueKeyword)
15695
+ if (node2.kind === ts9.SyntaxKind.TrueKeyword)
15226
15696
  return true;
15227
- if (node2.kind === ts4.SyntaxKind.FalseKeyword)
15697
+ if (node2.kind === ts9.SyntaxKind.FalseKeyword)
15228
15698
  return false;
15229
15699
  return;
15230
15700
  }
@@ -15233,37 +15703,37 @@ function findDynamicImport(node2) {
15233
15703
  const visit2 = (child) => {
15234
15704
  if (result)
15235
15705
  return;
15236
- if (ts4.isCallExpression(child) && child.expression.kind === ts4.SyntaxKind.ImportKeyword && child.arguments[0] && ts4.isStringLiteralLike(child.arguments[0])) {
15706
+ if (ts9.isCallExpression(child) && child.expression.kind === ts9.SyntaxKind.ImportKeyword && child.arguments[0] && ts9.isStringLiteralLike(child.arguments[0])) {
15237
15707
  result = child.arguments[0].text;
15238
15708
  return;
15239
15709
  }
15240
- ts4.forEachChild(child, visit2);
15710
+ ts9.forEachChild(child, visit2);
15241
15711
  };
15242
15712
  visit2(node2);
15243
15713
  return result;
15244
15714
  }
15245
15715
  function parseSource(source, filePath) {
15246
- const sourceFile = ts4.createSourceFile(filePath, source, ts4.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts4.ScriptKind.TSX : ts4.ScriptKind.TS);
15716
+ const sourceFile = ts9.createSourceFile(filePath, source, ts9.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts9.ScriptKind.TSX : ts9.ScriptKind.TS);
15247
15717
  const imports = new Map;
15248
15718
  const constants2 = new Map;
15249
15719
  for (const statement of sourceFile.statements) {
15250
- if (ts4.isImportDeclaration(statement) && ts4.isStringLiteral(statement.moduleSpecifier)) {
15720
+ if (ts9.isImportDeclaration(statement) && ts9.isStringLiteral(statement.moduleSpecifier)) {
15251
15721
  const moduleSource = statement.moduleSpecifier.text;
15252
15722
  const clause = statement.importClause;
15253
15723
  if (clause?.name)
15254
15724
  imports.set(clause.name.text, moduleSource);
15255
15725
  const bindings = clause?.namedBindings;
15256
- if (bindings && ts4.isNamedImports(bindings)) {
15726
+ if (bindings && ts9.isNamedImports(bindings)) {
15257
15727
  for (const element of bindings.elements)
15258
15728
  imports.set(element.name.text, moduleSource);
15259
15729
  }
15260
- if (bindings && ts4.isNamespaceImport(bindings))
15730
+ if (bindings && ts9.isNamespaceImport(bindings))
15261
15731
  imports.set(bindings.name.text, moduleSource);
15262
15732
  }
15263
- if (!ts4.isVariableStatement(statement))
15733
+ if (!ts9.isVariableStatement(statement))
15264
15734
  continue;
15265
15735
  for (const declaration of statement.declarationList.declarations) {
15266
- if (!ts4.isIdentifier(declaration.name) || !declaration.initializer)
15736
+ if (!ts9.isIdentifier(declaration.name) || !declaration.initializer)
15267
15737
  continue;
15268
15738
  const scalar = scalarValue(declaration.initializer);
15269
15739
  if (scalar !== undefined)
@@ -15292,13 +15762,13 @@ function routeConditions(node2, sourceFile) {
15292
15762
  let current = node2;
15293
15763
  while (current?.parent) {
15294
15764
  const parent = current.parent;
15295
- if (ts4.isConditionalExpression(parent)) {
15765
+ if (ts9.isConditionalExpression(parent)) {
15296
15766
  const condition = compact(parent.condition.getText(sourceFile));
15297
15767
  conditions.push(current === parent.whenTrue ? condition : `!(${condition})`);
15298
- } else if (ts4.isBinaryExpression(parent) && parent.operatorToken.kind === ts4.SyntaxKind.AmpersandAmpersandToken && current === parent.right) {
15768
+ } else if (ts9.isBinaryExpression(parent) && parent.operatorToken.kind === ts9.SyntaxKind.AmpersandAmpersandToken && current === parent.right) {
15299
15769
  conditions.push(compact(parent.left.getText(sourceFile)));
15300
15770
  }
15301
- if (ts4.isFunctionLike(parent))
15771
+ if (ts9.isFunctionLike(parent))
15302
15772
  break;
15303
15773
  current = parent;
15304
15774
  }
@@ -15307,36 +15777,36 @@ function routeConditions(node2, sourceFile) {
15307
15777
  function jsxAttributes(node2) {
15308
15778
  const result = new Map;
15309
15779
  for (const property of node2.attributes.properties)
15310
- if (ts4.isJsxAttribute(property))
15780
+ if (ts9.isJsxAttribute(property))
15311
15781
  result.set(property.name.getText(), property);
15312
15782
  return result;
15313
15783
  }
15314
15784
  function jsxExpression(attribute) {
15315
15785
  const initializer = attribute?.initializer;
15316
- return initializer && ts4.isJsxExpression(initializer) ? initializer.expression : undefined;
15786
+ return initializer && ts9.isJsxExpression(initializer) ? initializer.expression : undefined;
15317
15787
  }
15318
15788
  function jsxScalar(attribute, constants2) {
15319
15789
  if (!attribute)
15320
15790
  return;
15321
15791
  if (!attribute.initializer)
15322
15792
  return true;
15323
- if (ts4.isStringLiteral(attribute.initializer))
15793
+ if (ts9.isStringLiteral(attribute.initializer))
15324
15794
  return attribute.initializer.text;
15325
15795
  const expression = jsxExpression(attribute);
15326
- return scalarValue(expression) ?? (expression && ts4.isIdentifier(expression) ? constants2.get(expression.text) : undefined);
15796
+ return scalarValue(expression) ?? (expression && ts9.isIdentifier(expression) ? constants2.get(expression.text) : undefined);
15327
15797
  }
15328
15798
  function descendantTags(node2) {
15329
15799
  const tags = new Set;
15330
15800
  const visit2 = (child) => {
15331
- if (ts4.isJsxElement(child) || ts4.isJsxSelfClosingElement(child)) {
15332
- const opening = ts4.isJsxElement(child) ? child.openingElement : child;
15801
+ if (ts9.isJsxElement(child) || ts9.isJsxSelfClosingElement(child)) {
15802
+ const opening = ts9.isJsxElement(child) ? child.openingElement : child;
15333
15803
  const tag = opening.tagName.getText();
15334
15804
  if (child !== node2 && tag === "Route")
15335
15805
  return;
15336
15806
  if (!["Route", "Routes", "Suspense", "Fragment", "React.Fragment", "Navigate"].includes(tag))
15337
15807
  tags.add(tag);
15338
15808
  }
15339
- ts4.forEachChild(child, visit2);
15809
+ ts9.forEachChild(child, visit2);
15340
15810
  };
15341
15811
  visit2(node2);
15342
15812
  return [...tags];
@@ -15346,8 +15816,8 @@ function navigateTarget(node2, sourceFile) {
15346
15816
  const visit2 = (child) => {
15347
15817
  if (target)
15348
15818
  return;
15349
- if (ts4.isJsxElement(child) || ts4.isJsxSelfClosingElement(child)) {
15350
- const opening = ts4.isJsxElement(child) ? child.openingElement : child;
15819
+ if (ts9.isJsxElement(child) || ts9.isJsxSelfClosingElement(child)) {
15820
+ const opening = ts9.isJsxElement(child) ? child.openingElement : child;
15351
15821
  if (child !== node2 && opening.tagName.getText() === "Route")
15352
15822
  return;
15353
15823
  if (opening.tagName.getText() === "Navigate") {
@@ -15362,7 +15832,7 @@ function navigateTarget(node2, sourceFile) {
15362
15832
  }
15363
15833
  }
15364
15834
  }
15365
- ts4.forEachChild(child, visit2);
15835
+ ts9.forEachChild(child, visit2);
15366
15836
  };
15367
15837
  visit2(node2);
15368
15838
  return target;
@@ -15379,12 +15849,12 @@ function componentSource(component, imports) {
15379
15849
  }
15380
15850
  function objectProperty(object2, name) {
15381
15851
  for (const property of object2.properties) {
15382
- if (!ts4.isPropertyAssignment(property) && !ts4.isShorthandPropertyAssignment(property))
15852
+ if (!ts9.isPropertyAssignment(property) && !ts9.isShorthandPropertyAssignment(property))
15383
15853
  continue;
15384
- const key = property.name && (ts4.isIdentifier(property.name) || ts4.isStringLiteralLike(property.name)) ? property.name.text : undefined;
15854
+ const key = property.name && (ts9.isIdentifier(property.name) || ts9.isStringLiteralLike(property.name)) ? property.name.text : undefined;
15385
15855
  if (key !== name)
15386
15856
  continue;
15387
- return ts4.isPropertyAssignment(property) ? property.initializer : property.name;
15857
+ return ts9.isPropertyAssignment(property) ? property.initializer : property.name;
15388
15858
  }
15389
15859
  return;
15390
15860
  }
@@ -15426,7 +15896,7 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15426
15896
  };
15427
15897
  const visitRouteObjects = (array, parentPath) => {
15428
15898
  for (const element of array.elements) {
15429
- if (!ts4.isObjectLiteralExpression(element))
15899
+ if (!ts9.isObjectLiteralExpression(element))
15430
15900
  continue;
15431
15901
  const index = scalarValue(objectProperty(element, "index")) === true;
15432
15902
  const pathValue = scalarValue(objectProperty(element, "path"));
@@ -15442,13 +15912,13 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15442
15912
  index,
15443
15913
  ...component ? { component } : {},
15444
15914
  ...typeof redirect === "string" ? { redirectTo: redirect } : {},
15445
- ...children && ts4.isArrayLiteralExpression(children) ? { children } : {}
15915
+ ...children && ts9.isArrayLiteralExpression(children) ? { children } : {}
15446
15916
  });
15447
15917
  }
15448
15918
  };
15449
15919
  const visit2 = (node2, parentPath) => {
15450
- if (ts4.isJsxElement(node2) || ts4.isJsxSelfClosingElement(node2)) {
15451
- const opening = ts4.isJsxElement(node2) ? node2.openingElement : node2;
15920
+ if (ts9.isJsxElement(node2) || ts9.isJsxSelfClosingElement(node2)) {
15921
+ const opening = ts9.isJsxElement(node2) ? node2.openingElement : node2;
15452
15922
  if (opening.tagName.getText() === "Route") {
15453
15923
  const attributes = jsxAttributes(opening);
15454
15924
  const index = jsxScalar(attributes.get("index"), parsed.constants) === true;
@@ -15461,30 +15931,30 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15461
15931
  const fullPath = joinRoutePath(parentPath, typeof pathValue === "string" ? pathValue : "", index);
15462
15932
  const redirectTo = navigateTarget(candidateNode, parsed.sourceFile);
15463
15933
  pushRoute({ node: node2, parentPath, path: typeof pathValue === "string" ? pathValue : "", index, ...component ? { component } : {}, candidates, ...redirectTo ? { redirectTo } : {} });
15464
- if (ts4.isJsxElement(node2))
15934
+ if (ts9.isJsxElement(node2))
15465
15935
  for (const child of node2.children)
15466
15936
  visit2(child, fullPath);
15467
15937
  return;
15468
15938
  }
15469
15939
  }
15470
- if (ts4.isCallExpression(node2)) {
15940
+ if (ts9.isCallExpression(node2)) {
15471
15941
  const callee = node2.expression.getText(parsed.sourceFile);
15472
- if ((callee === "createBrowserRouter" || callee === "createHashRouter" || callee === "useRoutes") && node2.arguments[0] && ts4.isArrayLiteralExpression(node2.arguments[0])) {
15942
+ if ((callee === "createBrowserRouter" || callee === "createHashRouter" || callee === "useRoutes") && node2.arguments[0] && ts9.isArrayLiteralExpression(node2.arguments[0])) {
15473
15943
  visitRouteObjects(node2.arguments[0], mountPath);
15474
15944
  }
15475
15945
  }
15476
- ts4.forEachChild(node2, (child) => visit2(child, parentPath));
15946
+ ts9.forEachChild(node2, (child) => visit2(child, parentPath));
15477
15947
  };
15478
15948
  visit2(parsed.sourceFile, mountPath);
15479
15949
  return routes.sort((left, right) => left.fullPath.localeCompare(right.fullPath) || left.location.startLine - right.location.startLine || left.location.startColumn - right.location.startColumn);
15480
15950
  }
15481
15951
  // src/moduleExports.ts
15482
- import * as ts5 from "typescript";
15952
+ import * as ts10 from "typescript";
15483
15953
  function exportedDeclarationName(statement) {
15484
- const exported = ts5.canHaveModifiers(statement) && ts5.getModifiers(statement)?.some((modifier) => modifier.kind === ts5.SyntaxKind.ExportKeyword);
15954
+ const exported = ts10.canHaveModifiers(statement) && ts10.getModifiers(statement)?.some((modifier) => modifier.kind === ts10.SyntaxKind.ExportKeyword);
15485
15955
  if (!exported)
15486
15956
  return;
15487
- if ((ts5.isFunctionDeclaration(statement) || ts5.isClassDeclaration(statement) || ts5.isInterfaceDeclaration(statement) || ts5.isTypeAliasDeclaration(statement) || ts5.isEnumDeclaration(statement)) && statement.name) {
15957
+ if ((ts10.isFunctionDeclaration(statement) || ts10.isClassDeclaration(statement) || ts10.isInterfaceDeclaration(statement) || ts10.isTypeAliasDeclaration(statement) || ts10.isEnumDeclaration(statement)) && statement.name) {
15488
15958
  return statement.name.text;
15489
15959
  }
15490
15960
  return;
@@ -15495,17 +15965,17 @@ function extractTypeScriptModuleExports(source, filePath = "module.ts") {
15495
15965
  const wildcard = new Set;
15496
15966
  const targets = new Set;
15497
15967
  for (const statement of sourceFile.statements) {
15498
- if (ts5.isExportDeclaration(statement)) {
15499
- const target = statement.moduleSpecifier && ts5.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : undefined;
15968
+ if (ts10.isExportDeclaration(statement)) {
15969
+ const target = statement.moduleSpecifier && ts10.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : undefined;
15500
15970
  if (target)
15501
15971
  targets.add(target);
15502
15972
  if (!statement.exportClause) {
15503
15973
  if (target)
15504
15974
  wildcard.add(target);
15505
- } else if (ts5.isNamedExports(statement.exportClause)) {
15975
+ } else if (ts10.isNamedExports(statement.exportClause)) {
15506
15976
  for (const element of statement.exportClause.elements)
15507
15977
  named.add(element.name.text);
15508
- } else if (ts5.isNamespaceExport(statement.exportClause)) {
15978
+ } else if (ts10.isNamespaceExport(statement.exportClause)) {
15509
15979
  named.add(statement.exportClause.name.text);
15510
15980
  }
15511
15981
  continue;
@@ -15513,9 +15983,9 @@ function extractTypeScriptModuleExports(source, filePath = "module.ts") {
15513
15983
  const declarationName2 = exportedDeclarationName(statement);
15514
15984
  if (declarationName2)
15515
15985
  named.add(declarationName2);
15516
- if (ts5.isVariableStatement(statement) && ts5.getModifiers(statement)?.some((modifier) => modifier.kind === ts5.SyntaxKind.ExportKeyword)) {
15986
+ if (ts10.isVariableStatement(statement) && ts10.getModifiers(statement)?.some((modifier) => modifier.kind === ts10.SyntaxKind.ExportKeyword)) {
15517
15987
  for (const declaration of statement.declarationList.declarations) {
15518
- if (ts5.isIdentifier(declaration.name))
15988
+ if (ts10.isIdentifier(declaration.name))
15519
15989
  named.add(declaration.name.text);
15520
15990
  }
15521
15991
  }
@@ -15580,6 +16050,8 @@ export {
15580
16050
  extractReactRouterRoutes,
15581
16051
  extractEcmaScriptModuleExports,
15582
16052
  ecmaScriptLanguage,
16053
+ componentPropsName,
16054
+ componentBindingDefaults,
15583
16055
  TypeScriptPlugin,
15584
16056
  EXTRACT_TS_COVERAGE_TIER,
15585
16057
  EXTRACT_TS_CAPABILITIES