@c4a/extract-ts 0.7.1 → 0.7.5

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 +325 -39
  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,
@@ -12854,6 +12872,13 @@ function relationSourceFile(relation, symbols, filePaths) {
12854
12872
  }
12855
12873
  return null;
12856
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
+ }
12857
12882
  function diagnosticPayload(diagnostic) {
12858
12883
  return {
12859
12884
  code: diagnostic.code,
@@ -12916,6 +12941,10 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12916
12941
  }
12917
12942
  const facts = [];
12918
12943
  if (coverageFile.disposition === "analyzed" && fileInfo) {
12944
+ const source = invocation.source_files?.[normalizedPath2];
12945
+ if (invocation.source_files !== undefined && source === undefined) {
12946
+ throw new TypeError(`Analyzed file ${normalizedPath2} has no scoped source text`);
12947
+ }
12919
12948
  facts.push(fact2({
12920
12949
  sourceRef: invocation.authorized_scope.source_ref,
12921
12950
  moduleRef: invocation.module_ref,
@@ -12923,7 +12952,11 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12923
12952
  qualifiedItemPath: "file",
12924
12953
  kind: "source-file",
12925
12954
  signature: { path: normalizedPath2, language: fileInfo.language },
12926
- payload: fileInfo,
12955
+ payload: source === undefined ? fileInfo : {
12956
+ ...fileInfo,
12957
+ line: 1,
12958
+ endLine: source.split(/\r\n|\r|\n/u).length
12959
+ },
12927
12960
  denominator: ownsDenominators ? "eligible-file" : "none"
12928
12961
  }));
12929
12962
  facts.push(fact2({
@@ -12960,7 +12993,7 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12960
12993
  sourceRef: invocation.authorized_scope.source_ref,
12961
12994
  moduleRef: invocation.module_ref,
12962
12995
  normalizedPath: normalizedPath2,
12963
- qualifiedItemPath: `relation:${relation.type}:${relation.from}->${relation.to}@${relation.line ?? 0}`,
12996
+ qualifiedItemPath: relationQualifiedItemPath(relation),
12964
12997
  kind: "code-relation",
12965
12998
  signature: relation,
12966
12999
  payload: relation,
@@ -12976,7 +13009,7 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
12976
13009
  role,
12977
13010
  coverage_tier: coverage.tier,
12978
13011
  disposition: coverageFile.disposition,
12979
- facts
13012
+ facts: uniqueFacts(facts)
12980
13013
  };
12981
13014
  });
12982
13015
  const diagnostics = [
@@ -13017,6 +13050,184 @@ function extractionResultToEvidenceAdapterResult(extraction, invocation) {
13017
13050
  }]
13018
13051
  });
13019
13052
  }
13053
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
13054
+ var CharacterCodes;
13055
+ (function(CharacterCodes2) {
13056
+ CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
13057
+ CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
13058
+ CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
13059
+ CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
13060
+ CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
13061
+ CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
13062
+ CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
13063
+ CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
13064
+ CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
13065
+ CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
13066
+ CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
13067
+ CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
13068
+ CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
13069
+ CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
13070
+ CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
13071
+ CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
13072
+ CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
13073
+ CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
13074
+ CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
13075
+ CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
13076
+ CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
13077
+ CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
13078
+ CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
13079
+ CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
13080
+ CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
13081
+ CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
13082
+ CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
13083
+ CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
13084
+ CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
13085
+ CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
13086
+ CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
13087
+ CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
13088
+ CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
13089
+ CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
13090
+ CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
13091
+ CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
13092
+ CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
13093
+ CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
13094
+ CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
13095
+ CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
13096
+ CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
13097
+ CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
13098
+ CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
13099
+ CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
13100
+ CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
13101
+ CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
13102
+ CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
13103
+ CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
13104
+ CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
13105
+ CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
13106
+ CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
13107
+ CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
13108
+ CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
13109
+ CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
13110
+ CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
13111
+ CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
13112
+ CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
13113
+ CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
13114
+ CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
13115
+ CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
13116
+ CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
13117
+ CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
13118
+ CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
13119
+ CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
13120
+ CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
13121
+ CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
13122
+ CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
13123
+ CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
13124
+ CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
13125
+ CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
13126
+ CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
13127
+ CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
13128
+ CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
13129
+ CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
13130
+ CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
13131
+ CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
13132
+ CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
13133
+ CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
13134
+ CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
13135
+ CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
13136
+ })(CharacterCodes || (CharacterCodes = {}));
13137
+
13138
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/string-intern.js
13139
+ var cachedSpaces = new Array(20).fill(0).map((_, index) => {
13140
+ return " ".repeat(index);
13141
+ });
13142
+ var maxCachedValues = 200;
13143
+ var cachedBreakLinesWithSpaces = {
13144
+ " ": {
13145
+ "\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13146
+ return `
13147
+ ` + " ".repeat(index);
13148
+ }),
13149
+ "\r": new Array(maxCachedValues).fill(0).map((_, index) => {
13150
+ return "\r" + " ".repeat(index);
13151
+ }),
13152
+ "\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13153
+ return `\r
13154
+ ` + " ".repeat(index);
13155
+ })
13156
+ },
13157
+ "\t": {
13158
+ "\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13159
+ return `
13160
+ ` + "\t".repeat(index);
13161
+ }),
13162
+ "\r": new Array(maxCachedValues).fill(0).map((_, index) => {
13163
+ return "\r" + "\t".repeat(index);
13164
+ }),
13165
+ "\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
13166
+ return `\r
13167
+ ` + "\t".repeat(index);
13168
+ })
13169
+ }
13170
+ };
13171
+
13172
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js
13173
+ var ParseOptions;
13174
+ (function(ParseOptions2) {
13175
+ ParseOptions2.DEFAULT = {
13176
+ allowTrailingComma: false
13177
+ };
13178
+ })(ParseOptions || (ParseOptions = {}));
13179
+
13180
+ // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js
13181
+ var ScanError;
13182
+ (function(ScanError2) {
13183
+ ScanError2[ScanError2["None"] = 0] = "None";
13184
+ ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
13185
+ ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
13186
+ ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
13187
+ ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
13188
+ ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
13189
+ ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
13190
+ })(ScanError || (ScanError = {}));
13191
+ var SyntaxKind;
13192
+ (function(SyntaxKind2) {
13193
+ SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
13194
+ SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
13195
+ SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
13196
+ SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
13197
+ SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
13198
+ SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
13199
+ SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
13200
+ SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
13201
+ SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
13202
+ SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
13203
+ SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
13204
+ SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
13205
+ SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
13206
+ SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
13207
+ SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
13208
+ SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
13209
+ SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
13210
+ })(SyntaxKind || (SyntaxKind = {}));
13211
+ var ParseErrorCode;
13212
+ (function(ParseErrorCode2) {
13213
+ ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
13214
+ ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
13215
+ ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
13216
+ ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
13217
+ ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
13218
+ ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
13219
+ ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
13220
+ ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
13221
+ ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
13222
+ ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
13223
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
13224
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
13225
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
13226
+ ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
13227
+ ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
13228
+ ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
13229
+ })(ParseErrorCode || (ParseErrorCode = {}));
13230
+
13020
13231
  // ../../node_modules/.bun/eslint-visitor-keys@5.0.1/node_modules/eslint-visitor-keys/lib/visitor-keys.js
13021
13232
  var KEYS = {
13022
13233
  ArrayExpression: ["elements"],
@@ -13505,6 +13716,24 @@ var scriptKind = (filePath) => {
13505
13716
  return ts.ScriptKind.TS;
13506
13717
  };
13507
13718
  var createEcmaScriptSourceFile = (source, filePath) => ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, scriptKind(filePath));
13719
+ var treeSitterCompatibleJsxSource = (sourceFile, source) => {
13720
+ const characters = source.split("");
13721
+ let changed = false;
13722
+ const visit2 = (node2) => {
13723
+ const jsxPresentationLiteral = ts.isJsxText(node2) || ts.isStringLiteral(node2) && ts.isJsxAttribute(node2.parent);
13724
+ if (jsxPresentationLiteral) {
13725
+ for (let index = node2.getStart(sourceFile);index < node2.getEnd(); index += 1) {
13726
+ if (characters[index] === "&") {
13727
+ characters[index] = " ";
13728
+ changed = true;
13729
+ }
13730
+ }
13731
+ }
13732
+ ts.forEachChild(node2, visit2);
13733
+ };
13734
+ visit2(sourceFile);
13735
+ return changed ? characters.join("") : source;
13736
+ };
13508
13737
  var syntaxDiagnostics = (sourceFile) => {
13509
13738
  const diagnostics = sourceFile.parseDiagnostics ?? [];
13510
13739
  return diagnostics.map((diagnostic) => {
@@ -13688,7 +13917,7 @@ var collectBindings = (sourceFile) => {
13688
13917
  };
13689
13918
  var collectDynamicDiagnostics = (sourceFile) => {
13690
13919
  const diagnostics = [];
13691
- const visit = (node2) => {
13920
+ const visit2 = (node2) => {
13692
13921
  if (ts2.isCallExpression(node2) && ts2.isIdentifier(node2.expression) && node2.expression.text === "require") {
13693
13922
  if (staticStringValue(node2.arguments[0]) === null) {
13694
13923
  const location = nodeLocation(sourceFile, node2);
@@ -13726,9 +13955,9 @@ var collectDynamicDiagnostics = (sourceFile) => {
13726
13955
  }
13727
13956
  }
13728
13957
  }
13729
- ts2.forEachChild(node2, visit);
13958
+ ts2.forEachChild(node2, visit2);
13730
13959
  };
13731
- visit(sourceFile);
13960
+ visit2(sourceFile);
13732
13961
  return diagnostics;
13733
13962
  };
13734
13963
  var analyzeCommonJsModule = (source, filePath) => {
@@ -13965,7 +14194,9 @@ var traceFile = async (filePath, fs, state) => {
13965
14194
  const commonJs = analyzeCommonJsModule(source, filePath);
13966
14195
  if (commonJs.diagnostics.length > 0)
13967
14196
  return [];
13968
- const tree = await parseFile(source, isJsxLikePath(filePath));
14197
+ const jsxLike = isJsxLikePath(filePath);
14198
+ const parserSource = jsxLike ? treeSitterCompatibleJsxSource(createEcmaScriptSourceFile(source, filePath), source) : source;
14199
+ const tree = await parseFile(parserSource, jsxLike);
13969
14200
  if (!tree)
13970
14201
  return [];
13971
14202
  const root = tree.rootNode;
@@ -14410,7 +14641,7 @@ var declarationName = (node2, sourceFile) => {
14410
14641
  var collectStaticCallRelations = (source, filePath, importBindings) => {
14411
14642
  const sourceFile = createEcmaScriptSourceFile(source, filePath);
14412
14643
  const relations = [];
14413
- const visit = (node2, owner) => {
14644
+ const visit2 = (node2, owner) => {
14414
14645
  const namedOwner = declarationName(node2, sourceFile) ?? owner;
14415
14646
  if (ts3.isCallExpression(node2) || ts3.isNewExpression(node2)) {
14416
14647
  const target = callTarget(node2.expression, sourceFile);
@@ -14420,9 +14651,9 @@ var collectStaticCallRelations = (source, filePath, importBindings) => {
14420
14651
  relations.push(createRelation("calls" /* Calls */, namedOwner, target, isExternal, nodeLocation(sourceFile, node2).line));
14421
14652
  }
14422
14653
  }
14423
- ts3.forEachChild(node2, (child) => visit(child, namedOwner));
14654
+ ts3.forEachChild(node2, (child) => visit2(child, namedOwner));
14424
14655
  };
14425
- visit(sourceFile, filePath);
14656
+ visit2(sourceFile, filePath);
14426
14657
  const seen = new Set;
14427
14658
  return relations.sort((left, right) => (left.line ?? 0) - (right.line ?? 0) || left.from.localeCompare(right.from) || left.to.localeCompare(right.to)).filter((relation) => {
14428
14659
  const key = `${relation.from}\x00${relation.to}\x00${relation.line ?? 0}`;
@@ -14724,7 +14955,9 @@ var analyzeFile = async (filePath, fs, resolver = { mappings: [] }) => {
14724
14955
  const source = await fs.readFile(filePath);
14725
14956
  const sourceFile = createEcmaScriptSourceFile(source, filePath);
14726
14957
  const commonJs = analyzeCommonJsModule(source, filePath);
14727
- const tree = await parseFile(source, isJsxLikePath(filePath));
14958
+ const jsxLike = isJsxLikePath(filePath);
14959
+ const parserSource = jsxLike ? treeSitterCompatibleJsxSource(sourceFile, source) : source;
14960
+ const tree = await parseFile(parserSource, jsxLike);
14728
14961
  if (!tree) {
14729
14962
  const diagnostics = syntaxDiagnostics(sourceFile);
14730
14963
  if (diagnostics.length === 0) {
@@ -14789,6 +15022,26 @@ var analyzeFile = async (filePath, fs, resolver = { mappings: [] }) => {
14789
15022
  };
14790
15023
 
14791
15024
  // src/symbolExtractor.ts
15025
+ var relationIdentity = (relation) => JSON.stringify([
15026
+ relation.type,
15027
+ relation.from,
15028
+ relation.to,
15029
+ relation.isExternal,
15030
+ relation.grounding,
15031
+ relation.confidence,
15032
+ relation.source,
15033
+ relation.line ?? null
15034
+ ]);
15035
+ var uniqueRelations = (relations) => {
15036
+ const seen = new Set;
15037
+ return relations.filter((relation) => {
15038
+ const identity = relationIdentity(relation);
15039
+ if (seen.has(identity))
15040
+ return false;
15041
+ seen.add(identity);
15042
+ return true;
15043
+ });
15044
+ };
14792
15045
  var extractSymbols = async (entries, fs, options) => {
14793
15046
  const resolver = await loadTsConfigPathResolver(fs);
14794
15047
  const exportedSymbols = [];
@@ -14797,15 +15050,19 @@ var extractSymbols = async (entries, fs, options) => {
14797
15050
  const filePaths = new Set;
14798
15051
  const exportedDeclarationKeys = new Set;
14799
15052
  const analyses = new Map;
15053
+ const analysisScope = options.analysisPaths === undefined ? null : new Set(options.analysisPaths);
15054
+ const isInScope = (path2) => analysisScope === null || analysisScope.has(path2);
14800
15055
  for (const entry of entries) {
14801
15056
  const traced = await traceExports(entry.path, fs, resolver);
14802
- traced.files.forEach((filePath) => filePaths.add(filePath));
14803
- for (const filePath of traced.files) {
15057
+ traced.files.filter(isInScope).forEach((filePath) => filePaths.add(filePath));
15058
+ for (const filePath of traced.files.filter(isInScope)) {
14804
15059
  if (!analyses.has(filePath)) {
14805
15060
  analyses.set(filePath, await analyzeFile(filePath, fs, resolver));
14806
15061
  }
14807
15062
  }
14808
15063
  for (const tracedExport of traced.exports) {
15064
+ if (!isInScope(tracedExport.declarationFile))
15065
+ continue;
14809
15066
  const analysis = analyses.get(tracedExport.declarationFile);
14810
15067
  const declaration = analysis?.declarations.get(tracedExport.localName);
14811
15068
  if (!declaration)
@@ -14823,6 +15080,12 @@ var extractSymbols = async (entries, fs, options) => {
14823
15080
  });
14824
15081
  }
14825
15082
  }
15083
+ for (const filePath of [...analysisScope ?? []].sort()) {
15084
+ filePaths.add(filePath);
15085
+ if (!analyses.has(filePath)) {
15086
+ analyses.set(filePath, await analyzeFile(filePath, fs, resolver));
15087
+ }
15088
+ }
14826
15089
  for (const [filePath, analysis] of analyses) {
14827
15090
  relations.push(...analysis.relations);
14828
15091
  for (const [name, declaration] of analysis.declarations) {
@@ -14863,6 +15126,7 @@ var extractSymbols = async (entries, fs, options) => {
14863
15126
  relations.push(createRelation("of_type" /* OfType */, sym.name, propsTypeName, false, sym.line));
14864
15127
  }
14865
15128
  }
15129
+ const deduplicatedRelations = uniqueRelations(relations);
14866
15130
  const files = [...filePaths].sort().map((filePath) => ({
14867
15131
  path: filePath,
14868
15132
  language: ecmaScriptLanguage(filePath),
@@ -14890,7 +15154,7 @@ var extractSymbols = async (entries, fs, options) => {
14890
15154
  package: options.packageInfo,
14891
15155
  files,
14892
15156
  symbols,
14893
- relations,
15157
+ relations: deduplicatedRelations,
14894
15158
  coverage: {
14895
15159
  tier: EXTRACT_TS_COVERAGE_TIER,
14896
15160
  capabilities: [...EXTRACT_TS_CAPABILITIES],
@@ -14902,7 +15166,7 @@ var extractSymbols = async (entries, fs, options) => {
14902
15166
  lines: files.reduce((sum, file) => sum + file.lines, 0),
14903
15167
  exportedSymbols: exportedSymbols.length,
14904
15168
  internalSymbols: internalSymbols.length,
14905
- relations: relations.length
15169
+ relations: deduplicatedRelations.length
14906
15170
  }
14907
15171
  };
14908
15172
  };
@@ -14929,12 +15193,34 @@ class TypeScriptPlugin {
14929
15193
  if (!packageInfo) {
14930
15194
  throw new Error("TypeScriptPlugin.extractSymbols requires detectEntries to run first");
14931
15195
  }
14932
- const result = await extractSymbols(entries, fs, {
14933
- packageInfo,
14934
- pluginId: this.id
14935
- });
14936
- this.#lastDetection = null;
14937
- return result;
15196
+ try {
15197
+ return await extractSymbols(entries, fs, {
15198
+ packageInfo,
15199
+ pluginId: this.id
15200
+ });
15201
+ } finally {
15202
+ this.#lastDetection = null;
15203
+ }
15204
+ }
15205
+ async extractSymbolsInScope(entries, analysisPaths, fs) {
15206
+ const detectedPackage = this.#lastDetection?.package;
15207
+ if (!detectedPackage && entries.length > 0) {
15208
+ throw new Error("TypeScriptPlugin.extractSymbolsInScope requires detectEntries before using package entries");
15209
+ }
15210
+ const packageInfo = detectedPackage ?? {
15211
+ name: "unknown-package",
15212
+ kind: "lib" /* Lib */,
15213
+ language: packageLanguage(analysisPaths)
15214
+ };
15215
+ try {
15216
+ return await extractSymbols(entries, fs, {
15217
+ packageInfo,
15218
+ pluginId: this.id,
15219
+ analysisPaths
15220
+ });
15221
+ } finally {
15222
+ this.#lastDetection = null;
15223
+ }
14938
15224
  }
14939
15225
  }
14940
15226
  // src/reactRouter.ts
@@ -14957,16 +15243,16 @@ function scalarValue(node2) {
14957
15243
  }
14958
15244
  function findDynamicImport(node2) {
14959
15245
  let result;
14960
- const visit = (child) => {
15246
+ const visit2 = (child) => {
14961
15247
  if (result)
14962
15248
  return;
14963
15249
  if (ts4.isCallExpression(child) && child.expression.kind === ts4.SyntaxKind.ImportKeyword && child.arguments[0] && ts4.isStringLiteralLike(child.arguments[0])) {
14964
15250
  result = child.arguments[0].text;
14965
15251
  return;
14966
15252
  }
14967
- ts4.forEachChild(child, visit);
15253
+ ts4.forEachChild(child, visit2);
14968
15254
  };
14969
- visit(node2);
15255
+ visit2(node2);
14970
15256
  return result;
14971
15257
  }
14972
15258
  function parseSource(source, filePath) {
@@ -15054,7 +15340,7 @@ function jsxScalar(attribute, constants2) {
15054
15340
  }
15055
15341
  function descendantTags(node2) {
15056
15342
  const tags = new Set;
15057
- const visit = (child) => {
15343
+ const visit2 = (child) => {
15058
15344
  if (ts4.isJsxElement(child) || ts4.isJsxSelfClosingElement(child)) {
15059
15345
  const opening = ts4.isJsxElement(child) ? child.openingElement : child;
15060
15346
  const tag = opening.tagName.getText();
@@ -15063,14 +15349,14 @@ function descendantTags(node2) {
15063
15349
  if (!["Route", "Routes", "Suspense", "Fragment", "React.Fragment", "Navigate"].includes(tag))
15064
15350
  tags.add(tag);
15065
15351
  }
15066
- ts4.forEachChild(child, visit);
15352
+ ts4.forEachChild(child, visit2);
15067
15353
  };
15068
- visit(node2);
15354
+ visit2(node2);
15069
15355
  return [...tags];
15070
15356
  }
15071
15357
  function navigateTarget(node2, sourceFile) {
15072
15358
  let target;
15073
- const visit = (child) => {
15359
+ const visit2 = (child) => {
15074
15360
  if (target)
15075
15361
  return;
15076
15362
  if (ts4.isJsxElement(child) || ts4.isJsxSelfClosingElement(child)) {
@@ -15089,9 +15375,9 @@ function navigateTarget(node2, sourceFile) {
15089
15375
  }
15090
15376
  }
15091
15377
  }
15092
- ts4.forEachChild(child, visit);
15378
+ ts4.forEachChild(child, visit2);
15093
15379
  };
15094
- visit(node2);
15380
+ visit2(node2);
15095
15381
  return target;
15096
15382
  }
15097
15383
  function leadingNote(node2, sourceFile) {
@@ -15173,7 +15459,7 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15173
15459
  });
15174
15460
  }
15175
15461
  };
15176
- const visit = (node2, parentPath) => {
15462
+ const visit2 = (node2, parentPath) => {
15177
15463
  if (ts4.isJsxElement(node2) || ts4.isJsxSelfClosingElement(node2)) {
15178
15464
  const opening = ts4.isJsxElement(node2) ? node2.openingElement : node2;
15179
15465
  if (opening.tagName.getText() === "Route") {
@@ -15190,7 +15476,7 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15190
15476
  pushRoute({ node: node2, parentPath, path: typeof pathValue === "string" ? pathValue : "", index, ...component ? { component } : {}, candidates, ...redirectTo ? { redirectTo } : {} });
15191
15477
  if (ts4.isJsxElement(node2))
15192
15478
  for (const child of node2.children)
15193
- visit(child, fullPath);
15479
+ visit2(child, fullPath);
15194
15480
  return;
15195
15481
  }
15196
15482
  }
@@ -15200,9 +15486,9 @@ function extractReactRouterRoutes(source, filePath, options = {}) {
15200
15486
  visitRouteObjects(node2.arguments[0], mountPath);
15201
15487
  }
15202
15488
  }
15203
- ts4.forEachChild(node2, (child) => visit(child, parentPath));
15489
+ ts4.forEachChild(node2, (child) => visit2(child, parentPath));
15204
15490
  };
15205
- visit(parsed.sourceFile, mountPath);
15491
+ visit2(parsed.sourceFile, mountPath);
15206
15492
  return routes.sort((left, right) => left.fullPath.localeCompare(right.fullPath) || left.location.startLine - right.location.startLine || left.location.startColumn - right.location.startColumn);
15207
15493
  }
15208
15494
  // src/moduleExports.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract-ts",
3
- "version": "0.7.1",
3
+ "version": "0.7.5",
4
4
  "type": "module",
5
5
  "description": "TypeScript and JavaScript extraction plugin for the Context ExtractionResult v2 contract",
6
6
  "license": "MIT",