@c4a/extract-ts 0.7.0 → 0.7.4

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 (4) hide show
  1. package/README.md +16 -36
  2. package/README.zh-CN.md +11 -28
  3. package/index.js +316 -40
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -4,14 +4,13 @@
4
4
 
5
5
  `@c4a/extract-ts` turns TypeScript, JavaScript, TSX, and JSX structure into deterministic code
6
6
  evidence for Context knowledge production. It implements the
7
- `ExtractionPlugin` protocol from `@c4a/extract` and is the default plugin used
8
- by the SDK `extractTs({ source, collection: "codegraph" })` phase for npm-style
9
- packages.
7
+ `ExtractionPlugin` protocol from `@c4a/extract` and is the community Code
8
+ Indexer Provider's ECMAScript parser for npm-style packages.
10
9
 
11
10
  It extracts code facts; it does not decide product meaning, write approved
12
11
  Markdown, or choose the user's source boundary. Knowledge-workspace users reach
13
- it through the Context Agent entry and a confirmed extraction phase. The direct
14
- APIs below are for reusable structural analysis and project-owned adapters.
12
+ it through the selected Code Indexer Provider. The direct APIs below are for
13
+ Provider authors and reusable structural analysis.
15
14
 
16
15
  ## Package Role
17
16
 
@@ -24,12 +23,12 @@ confirmed TypeScript/JavaScript boundary
24
23
 
25
24
  entry detection + export tracing + AST facts
26
25
 
27
- raw code snapshot review candidates → approved knowledge
26
+ Indexer factsreader-oriented Candidates → approved knowledge
28
27
  ```
29
28
 
30
29
  ## React Router structural facts
31
30
 
32
- Projects that use `extractCustom()` can reuse `extractReactRouterRoutes()` to
31
+ Indexer Providers can reuse `extractReactRouterRoutes()` to
33
32
  index JSX `<Route>` declarations and route-object arrays. It reports paths,
34
33
  components, redirects, conditions, import sources, notes, and source locations
35
34
  without classifying product meaning:
@@ -83,10 +82,9 @@ const moduleFacts = extractEcmaScriptModuleExports(source, "src/index.cjs");
83
82
  - package version propagation into `ExtractionResult.package.version`
84
83
  - authored `.js`, `.jsx`, `.mjs`, and `.cjs` entry files without remapping them to TypeScript
85
84
 
86
- The Context project may override auto-detection with source-relative
87
- `extractTs.entries`, or use `mode: "scan"` to make every `include`-matched file
88
- an extraction root. These settings live in the Context workspace; consumers do
89
- not need to modify the analyzed package solely to declare extraction entries.
85
+ The Code Indexer Provider may override auto-detection with source-relative
86
+ entries, or use scan mode to make every include-matched file an extraction
87
+ root. Consumers do not modify the analyzed package solely to configure parsing.
90
88
 
91
89
  Entry files are returned as module-relative paths. The repository runner later prefixes them to repo-relative paths in raw snapshots.
92
90
 
@@ -160,9 +158,8 @@ identities, per-file owner/disposition, explicit denominators, diagnostics, and
160
158
  the ordered parser receipt through `context.indexer.evidence-adapter-result/v1`.
161
159
  `ExtractionResult` remains available for the existing raw snapshot runner.
162
160
 
163
- The Context CLI consumes those rows during `context run extract:<source>:codegraph`
164
- to build review candidates for package/category/symbol knowledge Nodes. The
165
- important projection inputs are:
161
+ The Code Indexer Provider consumes those facts while producing the current
162
+ Indexer result. Important authoring inputs include:
166
163
 
167
164
  - stable package names and versions
168
165
  - stable exported symbol names
@@ -187,33 +184,16 @@ const registry = new ExtractionPluginRegistry();
187
184
  registry.register(new TypeScriptPlugin());
188
185
  ```
189
186
 
190
- Workspace usage normally goes through a declared project phase:
191
-
192
- ```ts
193
- import { defineProject, extractTs, reviewValidity, source } from "@c4a/context";
194
-
195
- const componentLib = source("component-lib");
196
-
197
- export default defineProject({
198
- sources: [componentLib],
199
- phases: [
200
- extractTs({ source: componentLib, collection: "codegraph" }),
201
- reviewValidity({ collection: "codegraph" }),
202
- ],
203
- packages: [],
204
- });
205
- ```
206
-
207
- The source boundary is registered first, then the phase is previewed or run:
187
+ Workspace usage registers the source boundary, then selects the Code Indexer
188
+ Provider through `src/indexers.yaml`:
208
189
 
209
190
  ```bash
210
191
  context source add repo component-lib --local ../packages/component-lib
211
- context run extract:component-lib:codegraph --dry-run
212
- context run extract:component-lib:codegraph
192
+ context status --format json
213
193
  ```
214
194
 
215
- Agents should not hand-build runner input or raw snapshots for normal Context
216
- workspace operation.
195
+ Agents should not hand-build parser input, raw snapshots, or Candidate files
196
+ for normal Context workspace operation.
217
197
 
218
198
  ## Development
219
199
 
package/README.zh-CN.md CHANGED
@@ -3,12 +3,12 @@
3
3
  [English](./README.md)
4
4
 
5
5
  `@c4a/extract-ts` 将 TypeScript、JavaScript、TSX 和 JSX 结构转化为 Context 知识生产可使用的确定性
6
- 代码证据。它实现 `@c4a/extract` 的 `ExtractionPlugin` 协议,也是 npm-style
7
- package 使用 `extractTs({ source, collection: "codegraph" })` 阶段时的默认插件。
6
+ 代码证据。它实现 `@c4a/extract` 的 `ExtractionPlugin` 协议,也是社区 Code
7
+ Indexer Provider 面向 npm-style package 使用的 ECMAScript 解析器。
8
8
 
9
9
  它只提取代码事实,不判断产品含义、不写正式 Markdown,也不替用户选择来源边界。
10
- 知识工作区用户通过 Context Agent 入口和已确认的提取阶段使用它;直接 API 面向
11
- 可复用结构分析和项目自有 Adapter。
10
+ 知识工作区用户通过选中的 Code Indexer Provider 使用它;直接 API 面向 Provider
11
+ 作者和可复用结构分析。
12
12
 
13
13
  ## 在知识生产链中的职责
14
14
 
@@ -17,7 +17,7 @@ package 使用 `extractTs({ source, collection: "codegraph" })` 阶段时的默
17
17
 
18
18
  入口检测 + 导出追踪 + AST 事实
19
19
 
20
- 原始代码快照审核候选 → 正式知识
20
+ Indexer 事实 面向读者的 Candidate → 正式知识
21
21
  ```
22
22
 
23
23
  `@c4a/extract-ts` 负责 npm package 入口检测和 ECMAScript-family AST 提取。它不直接写工作区;
@@ -29,7 +29,7 @@ package 使用 `extractTs({ source, collection: "codegraph" })` 阶段时的默
29
29
 
30
30
  ### React Router 结构事实
31
31
 
32
- 使用 `extractCustom()` 的项目可以复用 `extractReactRouterRoutes()`,索引 JSX
32
+ Indexer Provider 可以复用 `extractReactRouterRoutes()`,索引 JSX
33
33
  `<Route>` 声明和 route-object 数组:
34
34
 
35
35
  ```ts
@@ -83,9 +83,8 @@ const moduleFacts = extractEcmaScriptModuleExports(source, "src/index.cjs");
83
83
  - 将 package version 写入 `ExtractionResult.package.version`。
84
84
  - 直接识别源码目录中的 `.js`、`.jsx`、`.mjs` 和 `.cjs`,不会误映射为 TypeScript。
85
85
 
86
- Context 项目可以使用 source-relative `extractTs.entries` 覆盖自动检测,或用
87
- `mode: "scan"` 把所有 `include` 命中的文件作为提取根。这些设置属于知识工作区,
88
- 无需修改被分析 package。
86
+ Code Indexer Provider 可以使用 source-relative entries 覆盖自动检测,或用 scan
87
+ 模式把所有命中 include 的文件作为解析根;无需修改被分析 package。
89
88
 
90
89
  入口文件以 module-relative 路径返回,Repository Runner 再为原始快照补充
91
90
  repo-relative 前缀。
@@ -162,25 +161,9 @@ const registry = new ExtractionPluginRegistry();
162
161
  registry.register(new TypeScriptPlugin());
163
162
  ```
164
163
 
165
- 正常工作区在 `src/index.ts` 声明项目阶段:
166
-
167
- ```ts
168
- import { defineProject, extractTs, reviewValidity, source } from "@c4a/context";
169
-
170
- const componentLib = source("component-lib");
171
-
172
- export default defineProject({
173
- sources: [componentLib],
174
- phases: [
175
- extractTs({ source: componentLib, collection: "codegraph" }),
176
- reviewValidity({ collection: "codegraph" }),
177
- ],
178
- packages: [],
179
- });
180
- ```
181
-
182
- 实际提取由当前 Context Route 驱动。Agent 不应在正常知识生产中手工构造 Runner
183
- 输入或原始快照。
164
+ 正常工作区先登记来源,再由 `src/indexers.yaml` 选择 Code Indexer Provider。
165
+ 实际解析由当前 Context Route 驱动。Agent 不应在正常知识生产中手工构造 Runner
166
+ 输入、原始快照或 Candidate 文件。
184
167
 
185
168
  ## 开发
186
169
 
package/index.js CHANGED
@@ -11404,6 +11404,8 @@ function keyTokens(key) {
11404
11404
  return key.replace(/([a-z0-9])([A-Z])/gu, "$1-$2").replace(/[^A-Za-z0-9]+/gu, "-").toLowerCase().split("-").filter(Boolean);
11405
11405
  }
11406
11406
  function sensitiveKey(key, value) {
11407
+ if (value === INDEXER_OUTPUT_REDACTION_MARKER)
11408
+ return false;
11407
11409
  const tokens = keyTokens(key);
11408
11410
  if (tokens.length === 0)
11409
11411
  return false;
@@ -11445,12 +11447,12 @@ function replaceWithCount(value, pattern, replacement, count) {
11445
11447
  function redactKnownText(value, count) {
11446
11448
  let output = value;
11447
11449
  output = replaceWithCount(output, /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/gu, INDEXER_OUTPUT_REDACTION_MARKER, count);
11448
- output = replaceWithCount(output, /(\bauthorization\s*:\s*(?:bearer|basic)\s+)[^\s,;]+/giu, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11450
+ output = replaceWithCount(output, new RegExp(`(\\bauthorization\\s*:\\s*(?:bearer|basic)\\s+)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^\\s,;]+`, "giu"), (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11449
11451
  output = replaceWithCount(output, /([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/giu, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}@`, count);
11450
- output = replaceWithCount(output, /([?&](?:access_token|refresh_token|api_key|password|secret)=)[^&#\s]+/giu, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11452
+ output = replaceWithCount(output, new RegExp(`([?&](?:access_token|refresh_token|api_key|password|secret)=)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^&#\\s]+`, "giu"), (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11451
11453
  const key = "(?:[A-Za-z0-9_.-]*(?:password|passwd|pwd|secret|token|credential|cookie)[A-Za-z0-9_.-]*|api[-_]?key|access[-_]?(?:key|token)|private[-_]?key|client[-_]?secret|authorization)";
11452
11454
  const assignment = `(?:=\\s*|:\\s+(?=\\S)|:\\s*(?=["']))`;
11453
- output = replaceWithCount(output, new RegExp(`((?:["']?${key}["']?)\\s*${assignment})(?:"(?:\\\\.|[^"])*"|'(?:\\\\.|[^'])*'|[^\\s,;}\\]]+)`, "giu"), (_match, prefix) => `${prefix}"${INDEXER_OUTPUT_REDACTION_MARKER}"`, count);
11455
+ output = replaceWithCount(output, new RegExp(`((?:["']?${key}["']?)\\s*${assignment})` + `(?!["']?${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})` + `(?:"(?:\\\\.|[^"])*"|'(?:\\\\.|[^'])*'|[^\\s,;}\\]]+)`, "giu"), (_match, prefix) => `${prefix}"${INDEXER_OUTPUT_REDACTION_MARKER}"`, count);
11454
11456
  return output;
11455
11457
  }
11456
11458
  function redactBlockedText(value, blocked, count) {
@@ -12312,6 +12314,7 @@ var buildToSourcePaths = (withoutExtension) => {
12312
12314
  }
12313
12315
  const fullRest = rest.join("/");
12314
12316
  results.push(`src/${fullRest}`);
12317
+ results.push(fullRest);
12315
12318
  return unique(results);
12316
12319
  };
12317
12320
  var createCandidatePaths = (value, options = {}) => {
@@ -12463,7 +12466,7 @@ var expandWorkspacePattern = async (rootDir, pattern, fs) => {
12463
12466
  if (pattern.endsWith("/*")) {
12464
12467
  const prefix = pattern.slice(0, -2);
12465
12468
  const baseDir = prefix ? `${rootDir}/${prefix}` : rootDir;
12466
- const entries = await fs.readdir(baseDir);
12469
+ const entries = (await fs.readdir(baseDir)).sort();
12467
12470
  return entries.map((entry) => `${baseDir}/${entry}`.replace(/^\.\//, ""));
12468
12471
  }
12469
12472
  return [`${rootDir}/${pattern}`.replace(/^\.\//, "")];
@@ -12814,6 +12817,10 @@ var codeExtractRunnerInputSchema = exports_external.object({
12814
12817
  });
12815
12818
  // ../extract/src/evidenceAdapter.ts
12816
12819
  function fact2(input) {
12820
+ const payload = redactIndexerOutput({
12821
+ channel: "success-payload",
12822
+ value: input.payload
12823
+ }).value;
12817
12824
  return createIndexerEvidenceAdapterFact({
12818
12825
  source_ref: input.sourceRef,
12819
12826
  module_ref: input.moduleRef,
@@ -12821,10 +12828,21 @@ function fact2(input) {
12821
12828
  qualified_item_path: input.qualifiedItemPath,
12822
12829
  kind: input.kind,
12823
12830
  signature: input.signature,
12824
- payload: input.payload,
12831
+ payload,
12825
12832
  denominator: input.denominator
12826
12833
  });
12827
12834
  }
12835
+ function uniqueFacts(facts) {
12836
+ const byRef = new Map;
12837
+ for (const value of facts) {
12838
+ const previous = byRef.get(value.fact_ref);
12839
+ if (previous !== undefined && indexerEvidenceAdapterProtocolDigest(previous) !== indexerEvidenceAdapterProtocolDigest(value)) {
12840
+ throw new TypeError(`ExtractionResult emits conflicting facts for ${value.fact_ref}`);
12841
+ }
12842
+ byRef.set(value.fact_ref, previous ?? value);
12843
+ }
12844
+ return [...byRef.values()];
12845
+ }
12828
12846
  function semanticExtractionPayload(extraction) {
12829
12847
  return {
12830
12848
  version: extraction.version,
@@ -12841,7 +12859,9 @@ function semanticExtractionPayload(extraction) {
12841
12859
  stats: extraction.stats
12842
12860
  };
12843
12861
  }
12844
- function relationSourceFile(relation, symbols) {
12862
+ function relationSourceFile(relation, symbols, filePaths) {
12863
+ if (filePaths.has(relation.from))
12864
+ return relation.from;
12845
12865
  const candidates = symbols.filter((symbol) => symbol.name === relation.from);
12846
12866
  if (candidates.length === 1)
12847
12867
  return candidates[0].file;
@@ -12852,6 +12872,13 @@ function relationSourceFile(relation, symbols) {
12852
12872
  }
12853
12873
  return null;
12854
12874
  }
12875
+ function relationQualifiedItemPath(relation) {
12876
+ const identityDigest = indexerEvidenceAdapterProtocolDigest({
12877
+ from: relation.from,
12878
+ to: relation.to
12879
+ });
12880
+ return `relation:${relation.type}@${relation.line ?? 0}#${identityDigest}`;
12881
+ }
12855
12882
  function diagnosticPayload(diagnostic) {
12856
12883
  return {
12857
12884
  code: diagnostic.code,
@@ -12871,6 +12898,7 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12871
12898
  }
12872
12899
  const coverageByPath = new Map(coverage.files.map((file) => [file.path, file]));
12873
12900
  const fileInfoByPath = new Map(extraction.files.map((file) => [file.path, file]));
12901
+ const filePaths = new Set([...coverageByPath.keys(), ...fileInfoByPath.keys()]);
12874
12902
  for (const file of extraction.files) {
12875
12903
  if (!coverageByPath.has(file.path)) {
12876
12904
  throw new TypeError(`ExtractionResult file ${file.path} has no coverage disposition`);
@@ -12887,7 +12915,7 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12887
12915
  const generatedDiagnostics = [];
12888
12916
  const relationsByFile = new Map;
12889
12917
  for (const relation of extraction.relations) {
12890
- const file = relationSourceFile(relation, extraction.symbols);
12918
+ const file = relationSourceFile(relation, extraction.symbols, filePaths);
12891
12919
  if (file === null || coverageByPath.get(file)?.disposition !== "analyzed") {
12892
12920
  generatedDiagnostics.push({
12893
12921
  code: "relation-locator-unresolved",
@@ -12957,7 +12985,7 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12957
12985
  sourceRef: invocation.authorized_scope.source_ref,
12958
12986
  moduleRef: invocation.module_ref,
12959
12987
  normalizedPath: normalizedPath2,
12960
- qualifiedItemPath: `relation:${relation.type}:${relation.from}->${relation.to}@${relation.line ?? 0}`,
12988
+ qualifiedItemPath: relationQualifiedItemPath(relation),
12961
12989
  kind: "code-relation",
12962
12990
  signature: relation,
12963
12991
  payload: relation,
@@ -12973,7 +13001,7 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12973
13001
  role,
12974
13002
  coverage_tier: coverage.tier,
12975
13003
  disposition: coverageFile.disposition,
12976
- facts
13004
+ facts: uniqueFacts(facts)
12977
13005
  };
12978
13006
  });
12979
13007
  const diagnostics = [
@@ -13014,6 +13042,184 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
13014
13042
  }]
13015
13043
  });
13016
13044
  }
13045
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
13046
+ var CharacterCodes;
13047
+ (function(CharacterCodes2) {
13048
+ CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
13049
+ CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
13050
+ CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
13051
+ CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
13052
+ CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
13053
+ CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
13054
+ CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
13055
+ CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
13056
+ CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
13057
+ CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
13058
+ CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
13059
+ CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
13060
+ CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
13061
+ CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
13062
+ CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
13063
+ CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
13064
+ CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
13065
+ CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
13066
+ CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
13067
+ CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
13068
+ CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
13069
+ CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
13070
+ CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
13071
+ CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
13072
+ CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
13073
+ CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
13074
+ CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
13075
+ CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
13076
+ CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
13077
+ CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
13078
+ CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
13079
+ CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
13080
+ CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
13081
+ CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
13082
+ CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
13083
+ CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
13084
+ CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
13085
+ CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
13086
+ CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
13087
+ CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
13088
+ CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
13089
+ CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
13090
+ CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
13091
+ CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
13092
+ CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
13093
+ CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
13094
+ CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
13095
+ CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
13096
+ CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
13097
+ CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
13098
+ CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
13099
+ CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
13100
+ CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
13101
+ CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
13102
+ CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
13103
+ CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
13104
+ CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
13105
+ CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
13106
+ CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
13107
+ CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
13108
+ CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
13109
+ CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
13110
+ CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
13111
+ CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
13112
+ CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
13113
+ CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
13114
+ CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
13115
+ CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
13116
+ CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
13117
+ CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
13118
+ CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
13119
+ CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
13120
+ CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
13121
+ CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
13122
+ CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
13123
+ CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
13124
+ CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
13125
+ CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
13126
+ CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
13127
+ CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
13128
+ })(CharacterCodes || (CharacterCodes = {}));
13129
+
13130
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/string-intern.js
13131
+ var cachedSpaces = new Array(20).fill(0).map((_, index) => {
13132
+ return " ".repeat(index);
13133
+ });
13134
+ var maxCachedValues = 200;
13135
+ var cachedBreakLinesWithSpaces = {
13136
+ " ": {
13137
+ "\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13138
+ return `
13139
+ ` + " ".repeat(index);
13140
+ }),
13141
+ "\r": new Array(maxCachedValues).fill(0).map((_, index) => {
13142
+ return "\r" + " ".repeat(index);
13143
+ }),
13144
+ "\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13145
+ return `\r
13146
+ ` + " ".repeat(index);
13147
+ })
13148
+ },
13149
+ "\t": {
13150
+ "\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13151
+ return `
13152
+ ` + "\t".repeat(index);
13153
+ }),
13154
+ "\r": new Array(maxCachedValues).fill(0).map((_, index) => {
13155
+ return "\r" + "\t".repeat(index);
13156
+ }),
13157
+ "\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13158
+ return `\r
13159
+ ` + "\t".repeat(index);
13160
+ })
13161
+ }
13162
+ };
13163
+
13164
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js
13165
+ var ParseOptions;
13166
+ (function(ParseOptions2) {
13167
+ ParseOptions2.DEFAULT = {
13168
+ allowTrailingComma: false
13169
+ };
13170
+ })(ParseOptions || (ParseOptions = {}));
13171
+
13172
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js
13173
+ var ScanError;
13174
+ (function(ScanError2) {
13175
+ ScanError2[ScanError2["None"] = 0] = "None";
13176
+ ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
13177
+ ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
13178
+ ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
13179
+ ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
13180
+ ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
13181
+ ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
13182
+ })(ScanError || (ScanError = {}));
13183
+ var SyntaxKind;
13184
+ (function(SyntaxKind2) {
13185
+ SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
13186
+ SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
13187
+ SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
13188
+ SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
13189
+ SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
13190
+ SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
13191
+ SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
13192
+ SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
13193
+ SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
13194
+ SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
13195
+ SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
13196
+ SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
13197
+ SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
13198
+ SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
13199
+ SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
13200
+ SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
13201
+ SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
13202
+ })(SyntaxKind || (SyntaxKind = {}));
13203
+ var ParseErrorCode;
13204
+ (function(ParseErrorCode2) {
13205
+ ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
13206
+ ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
13207
+ ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
13208
+ ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
13209
+ ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
13210
+ ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
13211
+ ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
13212
+ ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
13213
+ ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
13214
+ ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
13215
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
13216
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
13217
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
13218
+ ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
13219
+ ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
13220
+ ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
13221
+ })(ParseErrorCode || (ParseErrorCode = {}));
13222
+
13017
13223
  // ../../node_modules/.bun/eslint-visitor-keys@5.0.1/node_modules/eslint-visitor-keys/lib/visitor-keys.js
13018
13224
  var KEYS = {
13019
13225
  ArrayExpression: ["elements"],
@@ -13502,6 +13708,24 @@ var scriptKind = (filePath) => {
13502
13708
  return ts.ScriptKind.TS;
13503
13709
  };
13504
13710
  var createEcmaScriptSourceFile = (source, filePath) => ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, scriptKind(filePath));
13711
+ var treeSitterCompatibleJsxSource = (sourceFile, source) => {
13712
+ const characters = source.split("");
13713
+ let changed = false;
13714
+ const visit2 = (node2) => {
13715
+ const jsxPresentationLiteral = ts.isJsxText(node2) || ts.isStringLiteral(node2) && ts.isJsxAttribute(node2.parent);
13716
+ if (jsxPresentationLiteral) {
13717
+ for (let index = node2.getStart(sourceFile);index < node2.getEnd(); index += 1) {
13718
+ if (characters[index] === "&") {
13719
+ characters[index] = " ";
13720
+ changed = true;
13721
+ }
13722
+ }
13723
+ }
13724
+ ts.forEachChild(node2, visit2);
13725
+ };
13726
+ visit2(sourceFile);
13727
+ return changed ? characters.join("") : source;
13728
+ };
13505
13729
  var syntaxDiagnostics = (sourceFile) => {
13506
13730
  const diagnostics = sourceFile.parseDiagnostics ?? [];
13507
13731
  return diagnostics.map((diagnostic) => {
@@ -13685,7 +13909,7 @@ var collectBindings = (sourceFile) => {
13685
13909
  };
13686
13910
  var collectDynamicDiagnostics = (sourceFile) => {
13687
13911
  const diagnostics = [];
13688
- const visit = (node2) => {
13912
+ const visit2 = (node2) => {
13689
13913
  if (ts2.isCallExpression(node2) && ts2.isIdentifier(node2.expression) && node2.expression.text === "require") {
13690
13914
  if (staticStringValue(node2.arguments[0]) === null) {
13691
13915
  const location = nodeLocation(sourceFile, node2);
@@ -13723,9 +13947,9 @@ var collectDynamicDiagnostics = (sourceFile) => {
13723
13947
  }
13724
13948
  }
13725
13949
  }
13726
- ts2.forEachChild(node2, visit);
13950
+ ts2.forEachChild(node2, visit2);
13727
13951
  };
13728
- visit(sourceFile);
13952
+ visit2(sourceFile);
13729
13953
  return diagnostics;
13730
13954
  };
13731
13955
  var analyzeCommonJsModule = (source, filePath) => {
@@ -13962,7 +14186,9 @@ var traceFile = async (filePath, fs, state) => {
13962
14186
  const commonJs = analyzeCommonJsModule(source, filePath);
13963
14187
  if (commonJs.diagnostics.length > 0)
13964
14188
  return [];
13965
- const tree = await parseFile(source, isJsxLikePath(filePath));
14189
+ const jsxLike = isJsxLikePath(filePath);
14190
+ const parserSource = jsxLike ? treeSitterCompatibleJsxSource(createEcmaScriptSourceFile(source, filePath), source) : source;
14191
+ const tree = await parseFile(parserSource, jsxLike);
13966
14192
  if (!tree)
13967
14193
  return [];
13968
14194
  const root = tree.rootNode;
@@ -14407,7 +14633,7 @@ var declarationName = (node2, sourceFile) => {
14407
14633
  var collectStaticCallRelations = (source, filePath, importBindings) => {
14408
14634
  const sourceFile = createEcmaScriptSourceFile(source, filePath);
14409
14635
  const relations = [];
14410
- const visit = (node2, owner) => {
14636
+ const visit2 = (node2, owner) => {
14411
14637
  const namedOwner = declarationName(node2, sourceFile) ?? owner;
14412
14638
  if (ts3.isCallExpression(node2) || ts3.isNewExpression(node2)) {
14413
14639
  const target = callTarget(node2.expression, sourceFile);
@@ -14417,9 +14643,9 @@ var collectStaticCallRelations = (source, filePath, importBindings) => {
14417
14643
  relations.push(createRelation("calls" /* Calls */, namedOwner, target, isExternal, nodeLocation(sourceFile, node2).line));
14418
14644
  }
14419
14645
  }
14420
- ts3.forEachChild(node2, (child) => visit(child, namedOwner));
14646
+ ts3.forEachChild(node2, (child) => visit2(child, namedOwner));
14421
14647
  };
14422
- visit(sourceFile, filePath);
14648
+ visit2(sourceFile, filePath);
14423
14649
  const seen = new Set;
14424
14650
  return relations.sort((left, right) => (left.line ?? 0) - (right.line ?? 0) || left.from.localeCompare(right.from) || left.to.localeCompare(right.to)).filter((relation) => {
14425
14651
  const key = `${relation.from}\x00${relation.to}\x00${relation.line ?? 0}`;
@@ -14721,7 +14947,9 @@ var analyzeFile = async (filePath, fs, resolver = { mappings: [] }) => {
14721
14947
  const source = await fs.readFile(filePath);
14722
14948
  const sourceFile = createEcmaScriptSourceFile(source, filePath);
14723
14949
  const commonJs = analyzeCommonJsModule(source, filePath);
14724
- const tree = await parseFile(source, isJsxLikePath(filePath));
14950
+ const jsxLike = isJsxLikePath(filePath);
14951
+ const parserSource = jsxLike ? treeSitterCompatibleJsxSource(sourceFile, source) : source;
14952
+ const tree = await parseFile(parserSource, jsxLike);
14725
14953
  if (!tree) {
14726
14954
  const diagnostics = syntaxDiagnostics(sourceFile);
14727
14955
  if (diagnostics.length === 0) {
@@ -14786,6 +15014,26 @@ var analyzeFile = async (filePath, fs, resolver = { mappings: [] }) => {
14786
15014
  };
14787
15015
 
14788
15016
  // src/symbolExtractor.ts
15017
+ var relationIdentity = (relation) => JSON.stringify([
15018
+ relation.type,
15019
+ relation.from,
15020
+ relation.to,
15021
+ relation.isExternal,
15022
+ relation.grounding,
15023
+ relation.confidence,
15024
+ relation.source,
15025
+ relation.line ?? null
15026
+ ]);
15027
+ var uniqueRelations = (relations) => {
15028
+ const seen = new Set;
15029
+ return relations.filter((relation) => {
15030
+ const identity = relationIdentity(relation);
15031
+ if (seen.has(identity))
15032
+ return false;
15033
+ seen.add(identity);
15034
+ return true;
15035
+ });
15036
+ };
14789
15037
  var extractSymbols = async (entries, fs, options) => {
14790
15038
  const resolver = await loadTsConfigPathResolver(fs);
14791
15039
  const exportedSymbols = [];
@@ -14794,15 +15042,19 @@ var extractSymbols = async (entries, fs, options) => {
14794
15042
  const filePaths = new Set;
14795
15043
  const exportedDeclarationKeys = new Set;
14796
15044
  const analyses = new Map;
15045
+ const analysisScope = options.analysisPaths === undefined ? null : new Set(options.analysisPaths);
15046
+ const isInScope = (path2) => analysisScope === null || analysisScope.has(path2);
14797
15047
  for (const entry of entries) {
14798
15048
  const traced = await traceExports(entry.path, fs, resolver);
14799
- traced.files.forEach((filePath) => filePaths.add(filePath));
14800
- for (const filePath of traced.files) {
15049
+ traced.files.filter(isInScope).forEach((filePath) => filePaths.add(filePath));
15050
+ for (const filePath of traced.files.filter(isInScope)) {
14801
15051
  if (!analyses.has(filePath)) {
14802
15052
  analyses.set(filePath, await analyzeFile(filePath, fs, resolver));
14803
15053
  }
14804
15054
  }
14805
15055
  for (const tracedExport of traced.exports) {
15056
+ if (!isInScope(tracedExport.declarationFile))
15057
+ continue;
14806
15058
  const analysis = analyses.get(tracedExport.declarationFile);
14807
15059
  const declaration = analysis?.declarations.get(tracedExport.localName);
14808
15060
  if (!declaration)
@@ -14820,6 +15072,12 @@ var extractSymbols = async (entries, fs, options) => {
14820
15072
  });
14821
15073
  }
14822
15074
  }
15075
+ for (const filePath of [...analysisScope ?? []].sort()) {
15076
+ filePaths.add(filePath);
15077
+ if (!analyses.has(filePath)) {
15078
+ analyses.set(filePath, await analyzeFile(filePath, fs, resolver));
15079
+ }
15080
+ }
14823
15081
  for (const [filePath, analysis] of analyses) {
14824
15082
  relations.push(...analysis.relations);
14825
15083
  for (const [name, declaration] of analysis.declarations) {
@@ -14860,6 +15118,7 @@ var extractSymbols = async (entries, fs, options) => {
14860
15118
  relations.push(createRelation("of_type" /* OfType */, sym.name, propsTypeName, false, sym.line));
14861
15119
  }
14862
15120
  }
15121
+ const deduplicatedRelations = uniqueRelations(relations);
14863
15122
  const files = [...filePaths].sort().map((filePath) => ({
14864
15123
  path: filePath,
14865
15124
  language: ecmaScriptLanguage(filePath),
@@ -14887,7 +15146,7 @@ var extractSymbols = async (entries, fs, options) => {
14887
15146
  package: options.packageInfo,
14888
15147
  files,
14889
15148
  symbols,
14890
- relations,
15149
+ relations: deduplicatedRelations,
14891
15150
  coverage: {
14892
15151
  tier: EXTRACT_TS_COVERAGE_TIER,
14893
15152
  capabilities: [...EXTRACT_TS_CAPABILITIES],
@@ -14899,7 +15158,7 @@ var extractSymbols = async (entries, fs, options) => {
14899
15158
  lines: files.reduce((sum, file) => sum + file.lines, 0),
14900
15159
  exportedSymbols: exportedSymbols.length,
14901
15160
  internalSymbols: internalSymbols.length,
14902
- relations: relations.length
15161
+ relations: deduplicatedRelations.length
14903
15162
  }
14904
15163
  };
14905
15164
  };
@@ -14926,12 +15185,29 @@ class TypeScriptPlugin {
14926
15185
  if (!packageInfo) {
14927
15186
  throw new Error("TypeScriptPlugin.extractSymbols requires detectEntries to run first");
14928
15187
  }
14929
- const result = await extractSymbols(entries, fs, {
14930
- packageInfo,
14931
- pluginId: this.id
14932
- });
14933
- this.#lastDetection = null;
14934
- return result;
15188
+ try {
15189
+ return await extractSymbols(entries, fs, {
15190
+ packageInfo,
15191
+ pluginId: this.id
15192
+ });
15193
+ } finally {
15194
+ this.#lastDetection = null;
15195
+ }
15196
+ }
15197
+ 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
+ }
15202
+ try {
15203
+ return await extractSymbols(entries, fs, {
15204
+ packageInfo,
15205
+ pluginId: this.id,
15206
+ analysisPaths
15207
+ });
15208
+ } finally {
15209
+ this.#lastDetection = null;
15210
+ }
14935
15211
  }
14936
15212
  }
14937
15213
  // src/reactRouter.ts
@@ -14954,16 +15230,16 @@ function scalarValue(node2) {
14954
15230
  }
14955
15231
  function findDynamicImport(node2) {
14956
15232
  let result;
14957
- const visit = (child) => {
15233
+ const visit2 = (child) => {
14958
15234
  if (result)
14959
15235
  return;
14960
15236
  if (ts4.isCallExpression(child) && child.expression.kind === ts4.SyntaxKind.ImportKeyword && child.arguments[0] && ts4.isStringLiteralLike(child.arguments[0])) {
14961
15237
  result = child.arguments[0].text;
14962
15238
  return;
14963
15239
  }
14964
- ts4.forEachChild(child, visit);
15240
+ ts4.forEachChild(child, visit2);
14965
15241
  };
14966
- visit(node2);
15242
+ visit2(node2);
14967
15243
  return result;
14968
15244
  }
14969
15245
  function parseSource(source, filePath) {
@@ -15051,7 +15327,7 @@ function jsxScalar(attribute, constants2) {
15051
15327
  }
15052
15328
  function descendantTags(node2) {
15053
15329
  const tags = new Set;
15054
- const visit = (child) => {
15330
+ const visit2 = (child) => {
15055
15331
  if (ts4.isJsxElement(child) || ts4.isJsxSelfClosingElement(child)) {
15056
15332
  const opening = ts4.isJsxElement(child) ? child.openingElement : child;
15057
15333
  const tag = opening.tagName.getText();
@@ -15060,14 +15336,14 @@ function descendantTags(node2) {
15060
15336
  if (!["Route", "Routes", "Suspense", "Fragment", "React.Fragment", "Navigate"].includes(tag))
15061
15337
  tags.add(tag);
15062
15338
  }
15063
- ts4.forEachChild(child, visit);
15339
+ ts4.forEachChild(child, visit2);
15064
15340
  };
15065
- visit(node2);
15341
+ visit2(node2);
15066
15342
  return [...tags];
15067
15343
  }
15068
15344
  function navigateTarget(node2, sourceFile) {
15069
15345
  let target;
15070
- const visit = (child) => {
15346
+ const visit2 = (child) => {
15071
15347
  if (target)
15072
15348
  return;
15073
15349
  if (ts4.isJsxElement(child) || ts4.isJsxSelfClosingElement(child)) {
@@ -15086,9 +15362,9 @@ function navigateTarget(node2, sourceFile) {
15086
15362
  }
15087
15363
  }
15088
15364
  }
15089
- ts4.forEachChild(child, visit);
15365
+ ts4.forEachChild(child, visit2);
15090
15366
  };
15091
- visit(node2);
15367
+ visit2(node2);
15092
15368
  return target;
15093
15369
  }
15094
15370
  function leadingNote(node2, sourceFile) {
@@ -15170,7 +15446,7 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15170
15446
  });
15171
15447
  }
15172
15448
  };
15173
- const visit = (node2, parentPath) => {
15449
+ const visit2 = (node2, parentPath) => {
15174
15450
  if (ts4.isJsxElement(node2) || ts4.isJsxSelfClosingElement(node2)) {
15175
15451
  const opening = ts4.isJsxElement(node2) ? node2.openingElement : node2;
15176
15452
  if (opening.tagName.getText() === "Route") {
@@ -15187,7 +15463,7 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15187
15463
  pushRoute({ node: node2, parentPath, path: typeof pathValue === "string" ? pathValue : "", index, ...component ? { component } : {}, candidates, ...redirectTo ? { redirectTo } : {} });
15188
15464
  if (ts4.isJsxElement(node2))
15189
15465
  for (const child of node2.children)
15190
- visit(child, fullPath);
15466
+ visit2(child, fullPath);
15191
15467
  return;
15192
15468
  }
15193
15469
  }
@@ -15197,9 +15473,9 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15197
15473
  visitRouteObjects(node2.arguments[0], mountPath);
15198
15474
  }
15199
15475
  }
15200
- ts4.forEachChild(node2, (child) => visit(child, parentPath));
15476
+ ts4.forEachChild(node2, (child) => visit2(child, parentPath));
15201
15477
  };
15202
- visit(parsed.sourceFile, mountPath);
15478
+ visit2(parsed.sourceFile, mountPath);
15203
15479
  return routes.sort((left, right) => left.fullPath.localeCompare(right.fullPath) || left.location.startLine - right.location.startLine || left.location.startColumn - right.location.startColumn);
15204
15480
  }
15205
15481
  // src/moduleExports.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract-ts",
3
- "version": "0.7.0",
3
+ "version": "0.7.4",
4
4
  "type": "module",
5
5
  "description": "TypeScript and JavaScript extraction plugin for the Context ExtractionResult v2 contract",
6
6
  "license": "MIT",