@generaltranslation/vue-extractor 0.0.0 → 0.1.0-iris.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE.md +18 -102
  2. package/dist/detect.d.ts +8 -0
  3. package/dist/detect.js +2 -0
  4. package/dist/index.d.ts +3 -1
  5. package/dist/index.js +2 -1
  6. package/dist/inspect.d.ts +9 -0
  7. package/dist/inspect.js +2 -0
  8. package/dist/integration.d.ts +69 -0
  9. package/dist/integration.js +162 -0
  10. package/dist/integration.js.map +1 -0
  11. package/dist/internal/config/configFiles.d.ts +6 -0
  12. package/dist/internal/config/configFiles.js +34 -0
  13. package/dist/internal/config/configFiles.js.map +1 -0
  14. package/dist/internal/config/resolveVueCompilerOptions.d.ts +6 -0
  15. package/dist/internal/config/resolveVueCompilerOptions.js +74 -56
  16. package/dist/internal/config/resolveVueCompilerOptions.js.map +1 -1
  17. package/dist/internal/extractFromVueSource.d.ts +4 -3
  18. package/dist/internal/extractFromVueSource.js +255 -12
  19. package/dist/internal/extractFromVueSource.js.map +1 -1
  20. package/dist/internal/project/consumerUsage.d.ts +34 -0
  21. package/dist/internal/project/consumerUsage.js +1220 -0
  22. package/dist/internal/project/consumerUsage.js.map +1 -0
  23. package/dist/internal/project/detectVueProject.d.ts +13 -0
  24. package/dist/internal/project/detectVueProject.js +65 -0
  25. package/dist/internal/project/detectVueProject.js.map +1 -0
  26. package/dist/internal/project/extractFromVueProject.d.ts +10 -0
  27. package/dist/internal/project/extractFromVueProject.js +579 -0
  28. package/dist/internal/project/extractFromVueProject.js.map +1 -0
  29. package/dist/internal/project/inspectVueProject.d.ts +48 -0
  30. package/dist/internal/project/inspectVueProject.js +143 -0
  31. package/dist/internal/project/inspectVueProject.js.map +1 -0
  32. package/dist/internal/project/manifest.d.ts +64 -0
  33. package/dist/internal/project/manifest.js +270 -0
  34. package/dist/internal/project/manifest.js.map +1 -0
  35. package/dist/internal/project/mergeVueProjectExtraction.d.ts +18 -0
  36. package/dist/internal/project/mergeVueProjectExtraction.js +79 -0
  37. package/dist/internal/project/mergeVueProjectExtraction.js.map +1 -0
  38. package/dist/internal/project/moduleResolver.d.ts +18 -0
  39. package/dist/internal/project/moduleResolver.js +325 -0
  40. package/dist/internal/project/moduleResolver.js.map +1 -0
  41. package/dist/internal/project/scopes.d.ts +31 -0
  42. package/dist/internal/project/scopes.js +182 -0
  43. package/dist/internal/project/scopes.js.map +1 -0
  44. package/dist/internal/project/sourcePatterns.d.ts +4 -0
  45. package/dist/internal/project/sourcePatterns.js +32 -0
  46. package/dist/internal/project/sourcePatterns.js.map +1 -0
  47. package/dist/internal/project/viteAliases.d.ts +42 -0
  48. package/dist/internal/project/viteAliases.js +1020 -0
  49. package/dist/internal/project/viteAliases.js.map +1 -0
  50. package/dist/internal/project/vueSourceClassification.d.ts +13 -0
  51. package/dist/internal/project/vueSourceClassification.js +146 -0
  52. package/dist/internal/project/vueSourceClassification.js.map +1 -0
  53. package/dist/internal/project/workspaces.d.ts +31 -0
  54. package/dist/internal/project/workspaces.js +326 -0
  55. package/dist/internal/project/workspaces.js.map +1 -0
  56. package/dist/internal/project/wrapperProvenance.d.ts +21 -0
  57. package/dist/internal/project/wrapperProvenance.js +287 -0
  58. package/dist/internal/project/wrapperProvenance.js.map +1 -0
  59. package/dist/internal/script/analyze.js +252 -85
  60. package/dist/internal/script/analyze.js.map +1 -1
  61. package/dist/internal/script/jsx.d.ts +7 -4
  62. package/dist/internal/script/jsx.js +351 -79
  63. package/dist/internal/script/jsx.js.map +1 -1
  64. package/dist/internal/script/localModules.d.ts +23 -2
  65. package/dist/internal/script/localModules.js +533 -20
  66. package/dist/internal/script/localModules.js.map +1 -1
  67. package/dist/internal/script/model.d.ts +9 -2
  68. package/dist/internal/script/parser.js +2 -1
  69. package/dist/internal/script/parser.js.map +1 -1
  70. package/dist/internal/script/runtimeModules.d.ts +10 -0
  71. package/dist/internal/script/runtimeModules.js +27 -0
  72. package/dist/internal/script/runtimeModules.js.map +1 -0
  73. package/dist/internal/stringCalls.js +1 -1
  74. package/dist/internal/stringCalls.js.map +1 -1
  75. package/dist/internal/template.js +263 -141
  76. package/dist/internal/template.js.map +1 -1
  77. package/dist/internal/types.d.ts +4 -1
  78. package/dist/internal/utils.d.ts +14 -3
  79. package/dist/internal/utils.js +63 -3
  80. package/dist/internal/utils.js.map +1 -1
  81. package/dist/internal/vueCompiler.d.ts +9 -1
  82. package/dist/internal/vueCompiler.js +37 -14
  83. package/dist/internal/vueCompiler.js.map +1 -1
  84. package/dist/project.d.ts +11 -0
  85. package/dist/project.js +3 -0
  86. package/dist/types.d.ts +95 -4
  87. package/package.json +30 -4
@@ -1,7 +1,9 @@
1
1
  import { parseScriptAst } from "./parser.js";
2
+ import { isKnownNonVueGTRuntime } from "./runtimeModules.js";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import traverseModule from "@babel/traverse";
6
+ import { initSync, parse } from "es-module-lexer";
5
7
  //#region src/internal/script/localModules.ts
6
8
  const traverse = traverseModule.default || traverseModule;
7
9
  const SOURCE_EXTENSIONS = [
@@ -27,6 +29,13 @@ const GT_EXPORT_NAMES = [
27
29
  "useGT",
28
30
  "useMessages"
29
31
  ];
32
+ /** Complete public value surface currently exported by the gt-vue runtime. */
33
+ const GT_RUNTIME_EXPORT_NAMES = [
34
+ ...GT_EXPORT_NAMES,
35
+ "createGT",
36
+ "useLocale",
37
+ "useSetLocale"
38
+ ];
30
39
  const VUE_EXPORT_NAMES = [
31
40
  "Suspense",
32
41
  "computed",
@@ -51,9 +60,14 @@ const VUE_EXPORT_NAMES = [
51
60
  * The resolver reads and parses source text but never imports or executes it.
52
61
  * Bare aliases are accepted only through the caller's explicit resolver hook.
53
62
  */
54
- function createLocalModuleResolver(resolveModuleOption) {
63
+ function createLocalModuleResolver(resolveModuleOption, options = {}) {
55
64
  const records = /* @__PURE__ */ new Map();
65
+ const recoveredRecords = /* @__PURE__ */ new Map();
56
66
  const resolutions = /* @__PURE__ */ new Map();
67
+ const recordPaths = /* @__PURE__ */ new WeakMap();
68
+ const isProjectModule = (filePath) => {
69
+ return !readRealPath(path.resolve(filePath)).split(path.sep).includes("node_modules");
70
+ };
57
71
  const resolveModule = (importer, specifier) => {
58
72
  if (specifier === "gt-vue" || specifier === "vue") return void 0;
59
73
  let requested;
@@ -66,6 +80,7 @@ function createLocalModuleResolver(resolveModuleOption) {
66
80
  };
67
81
  const getRecord = (filePath) => {
68
82
  const normalized = path.resolve(filePath);
83
+ if (!isProjectModule(normalized)) return void 0;
69
84
  const cached = records.get(normalized);
70
85
  if (cached !== void 0) return cached ?? void 0;
71
86
  records.set(normalized, null);
@@ -73,33 +88,375 @@ function createLocalModuleResolver(resolveModuleOption) {
73
88
  records.set(normalized, parsed ?? null);
74
89
  return parsed;
75
90
  };
91
+ const getRecoveredRecord = (filePath) => {
92
+ const normalized = path.resolve(filePath);
93
+ if (!isProjectModule(normalized)) return void 0;
94
+ const cached = recoveredRecords.get(normalized);
95
+ if (cached !== void 0) return cached ?? void 0;
96
+ const recovered = recoverMalformedModuleExports(normalized);
97
+ recoveredRecords.set(normalized, recovered ?? null);
98
+ return recovered;
99
+ };
76
100
  const resolveExportInternal = (filePath, exportName, seen) => {
77
101
  const normalized = path.resolve(filePath);
102
+ if (!isProjectModule(normalized)) return {
103
+ status: "resolved",
104
+ target: {
105
+ originKey: `${normalized}#${exportName}`,
106
+ type: "ordinary-external"
107
+ }
108
+ };
78
109
  const cycleKey = `${normalized}\0${exportName}`;
79
110
  if (seen.has(cycleKey)) return { status: "absent" };
80
- const record = getRecord(normalized);
81
- if (!record) return { status: "invalid" };
82
111
  const nextSeen = new Set(seen).add(cycleKey);
112
+ const record = getRecord(normalized);
113
+ if (!record) {
114
+ const recovered = getRecoveredRecord(normalized);
115
+ return recovered ? resolveRecoveredExport(recovered, exportName, nextSeen) : { status: "invalid" };
116
+ }
83
117
  const explicit = record.explicitExports.get(exportName);
84
118
  if (explicit === "ambiguous") return { status: "ambiguous" };
85
119
  if (explicit) return resolveDeclaredExport(record, exportName, explicit, nextSeen);
86
120
  if (exportName === "default") return { status: "absent" };
87
121
  const candidates = [];
122
+ let ambiguous = false;
88
123
  let invalid = false;
124
+ let invalidGTExportName;
125
+ let invalidGTSourceReference = false;
126
+ let recoveredTargets = [];
89
127
  for (const source of record.starExports) {
90
128
  const candidate = resolveFromSource(record, source, exportName, nextSeen);
91
- if (candidate.status === "resolved") candidates.push(candidate.target);
92
- if (candidate.status === "ambiguous") return candidate;
93
- if (candidate.status === "invalid") invalid = true;
129
+ if (candidate.status === "absent") continue;
130
+ const candidateGTExportName = readGTExportName(candidate, nextSeen);
131
+ invalidGTSourceReference ||= candidateGTExportName !== void 0;
132
+ invalidGTExportName ??= candidateGTExportName;
133
+ if (candidate.status === "resolved") {
134
+ candidates.push(candidate.target);
135
+ recoveredTargets?.push(candidate.target);
136
+ }
137
+ if (candidate.status === "ambiguous") {
138
+ ambiguous = true;
139
+ recoveredTargets = void 0;
140
+ }
141
+ if (candidate.status === "invalid") {
142
+ invalid = true;
143
+ invalidGTSourceReference ||= candidate.hasGTSourceReference === true;
144
+ invalidGTExportName ??= candidate.gtExportName;
145
+ if (recoveredTargets && candidate.recoveredTargets) recoveredTargets.push(...candidate.recoveredTargets);
146
+ else recoveredTargets = void 0;
147
+ }
94
148
  }
95
- if (candidates.length === 0) return { status: invalid ? "invalid" : "absent" };
96
- return new Set(candidates.map(({ originKey }) => originKey)).size === 1 ? {
149
+ if (new Set(candidates.map(({ originKey }) => originKey)).size > 1) {
150
+ ambiguous = true;
151
+ recoveredTargets = void 0;
152
+ }
153
+ if (recoveredTargets && new Set(recoveredTargets.map(({ originKey }) => originKey)).size > 1) {
154
+ ambiguous = true;
155
+ recoveredTargets = void 0;
156
+ }
157
+ if (invalid) return {
158
+ ...invalidGTSourceReference && { hasGTSourceReference: true },
159
+ ...invalidGTExportName && { gtExportName: invalidGTExportName },
160
+ ...recoveredTargets?.length && { recoveredTargets: uniqueRecoveredTargets(recoveredTargets) },
161
+ status: "invalid"
162
+ };
163
+ if (ambiguous) return { status: "ambiguous" };
164
+ return candidates.length === 0 ? { status: "absent" } : {
97
165
  status: "resolved",
98
166
  target: candidates[0]
99
- } : { status: "ambiguous" };
167
+ };
168
+ };
169
+ const resolveRecoveredExport = (record, exportName, seen) => {
170
+ const explicit = record.explicitExports.get(exportName);
171
+ if (explicit === "ambiguous") return { status: "ambiguous" };
172
+ if (explicit) return invalidateRecoveredResolution(explicit.type === "reexport" ? resolveFromSource(record, explicit.source, explicit.importedName, seen) : resolveRecoveredNamespace(record, explicit.source), seen);
173
+ if (exportName === "default") return { status: "invalid" };
174
+ let gtExportName;
175
+ let recoveredTargets = [];
176
+ for (const source of record.starExports) {
177
+ const candidate = resolveFromSource(record, source, exportName, seen);
178
+ if (candidate.status === "absent") continue;
179
+ gtExportName ??= readGTExportName(candidate, seen);
180
+ if (recoveredTargets && candidate.status === "resolved") recoveredTargets.push(candidate.target);
181
+ else if (recoveredTargets && candidate.status === "invalid" && candidate.recoveredTargets) recoveredTargets.push(...candidate.recoveredTargets);
182
+ else recoveredTargets = void 0;
183
+ }
184
+ if (recoveredTargets && new Set(recoveredTargets.map(({ originKey }) => originKey)).size > 1) recoveredTargets = void 0;
185
+ return {
186
+ ...gtExportName && {
187
+ gtExportName,
188
+ hasGTSourceReference: true
189
+ },
190
+ ...recoveredTargets?.length && { recoveredTargets: uniqueRecoveredTargets(recoveredTargets) },
191
+ status: "invalid"
192
+ };
193
+ };
194
+ const resolveRecoveredNamespace = (record, source) => {
195
+ if (isKnownNonVueGTRuntime(source)) return {
196
+ status: "resolved",
197
+ target: {
198
+ originKey: `${source}#namespace`,
199
+ type: "ordinary-external"
200
+ }
201
+ };
202
+ if (isExternalModule(source)) return {
203
+ status: "resolved",
204
+ target: {
205
+ originKey: `${source}#namespace`,
206
+ source,
207
+ type: "external-namespace"
208
+ }
209
+ };
210
+ const modulePath = resolveModule(record.filePath, source);
211
+ if (!modulePath) return { status: "invalid" };
212
+ if (!isProjectModule(modulePath)) return {
213
+ status: "resolved",
214
+ target: {
215
+ originKey: `${modulePath}#namespace`,
216
+ type: "ordinary-external"
217
+ }
218
+ };
219
+ return {
220
+ status: "resolved",
221
+ target: {
222
+ modulePath,
223
+ originKey: `${modulePath}#namespace`,
224
+ type: "namespace"
225
+ }
226
+ };
227
+ };
228
+ const invalidateRecoveredResolution = (resolution, seen) => {
229
+ const gtExportName = readGTExportName(resolution, seen);
230
+ return {
231
+ ...gtExportName && {
232
+ gtExportName,
233
+ hasGTSourceReference: true
234
+ },
235
+ ...resolution.status === "resolved" ? { recoveredTargets: [resolution.target] } : resolution.status === "invalid" && resolution.recoveredTargets ? { recoveredTargets: resolution.recoveredTargets } : {},
236
+ status: "invalid"
237
+ };
238
+ };
239
+ const readGTExportName = (resolution, seen, allowNamespaceContainers = true) => {
240
+ if (resolution.status === "invalid") return allowNamespaceContainers || resolution.gtExportName !== "*" ? resolution.gtExportName : void 0;
241
+ if (resolution.status !== "resolved") return void 0;
242
+ const { target } = resolution;
243
+ if (target.type === "external") return target.source === "gt-vue" ? target.exportName : void 0;
244
+ if (target.type === "external-namespace") return allowNamespaceContainers && target.source === "gt-vue" ? "*" : void 0;
245
+ if (target.type === "namespace") {
246
+ if (!allowNamespaceContainers) return void 0;
247
+ return (options.recognizeAllGTRuntimeExports ? [...GT_RUNTIME_EXPORT_NAMES] : [...GT_EXPORT_NAMES]).some((name) => Boolean(readGTExportName(resolveExportInternal(target.modulePath, name, seen), seen, allowNamespaceContainers))) ? "*" : void 0;
248
+ }
249
+ if (target.type === "ordinary-external") return void 0;
250
+ const state = {
251
+ bindings: /* @__PURE__ */ new Set(),
252
+ nodes: /* @__PURE__ */ new Set(),
253
+ record: target.record,
254
+ resolutions: seen,
255
+ allowNamespaceContainers
256
+ };
257
+ if (target.type === "expression") return readDerivedGT(target.node, state);
258
+ const binding = target.record.programScope.getBinding(target.exportName);
259
+ return binding ? readDerivedGTBinding(binding, state) : void 0;
260
+ };
261
+ /** Lazily indexes lexical paths only when package provenance needs them. */
262
+ const readNodePath = (record, node) => {
263
+ let paths = recordPaths.get(record);
264
+ if (!paths) {
265
+ paths = /* @__PURE__ */ new WeakMap();
266
+ traverse(record.ast, { enter(nodePath) {
267
+ paths.set(nodePath.node, nodePath);
268
+ } });
269
+ recordPaths.set(record, paths);
270
+ }
271
+ return paths.get(node);
272
+ };
273
+ /** Rejects a namespace member whose value is overwritten in this module. */
274
+ const namespaceMemberIsWritten = (binding, exportName) => {
275
+ return binding.referencePaths.some((reference) => {
276
+ const member = reference.parentPath;
277
+ if (!member?.isMemberExpression() && !member?.isOptionalMemberExpression() || member.node.object !== reference.node || readStaticMemberName(member.node) !== exportName) return false;
278
+ const parent = member.parentPath?.node;
279
+ return Boolean(parent?.type === "AssignmentExpression" && parent.left === member.node || parent?.type === "UpdateExpression" && parent.argument === member.node || parent?.type === "UnaryExpression" && parent.operator === "delete" && parent.argument === member.node || (parent?.type === "ForInStatement" || parent?.type === "ForOfStatement") && parent.left === member.node);
280
+ });
281
+ };
282
+ /** Follows immutable aliases while rejecting mutation and lexical shadows. */
283
+ const readDerivedGTBinding = (binding, state) => {
284
+ if (!binding.constant || state.bindings.has(binding)) return void 0;
285
+ const next = {
286
+ ...state,
287
+ bindings: new Set(state.bindings).add(binding)
288
+ };
289
+ if (binding.kind === "module") {
290
+ const imported = state.record.imports.get(binding.identifier.name);
291
+ if (!imported) return void 0;
292
+ if (imported.importedName === "*") return state.allowNamespaceContainers && imported.source === "gt-vue" ? "*" : void 0;
293
+ return readGTExportName(resolveFromSource(state.record, imported.source, imported.importedName, state.resolutions), state.resolutions, state.allowNamespaceContainers);
294
+ }
295
+ const declaration = binding.path.node;
296
+ if (declaration.type === "VariableDeclarator") {
297
+ if (declaration.id.type === "Identifier") return readDerivedGT(declaration.init, next);
298
+ return readDestructuredGTBinding(binding, declaration, next);
299
+ }
300
+ return declaration.type === "FunctionDeclaration" ? readDerivedGT(declaration, next) : void 0;
301
+ };
302
+ /** Resolves one exact leaf destructured from a direct gt-vue namespace. */
303
+ const readDestructuredGTBinding = (binding, declaration, state) => {
304
+ if (declaration.id.type !== "ObjectPattern" || declaration.id.properties.some((property) => property.type === "RestElement")) return;
305
+ const property = declaration.id.properties.find((candidate) => candidate.type === "ObjectProperty" && !candidate.computed && candidate.value.type === "Identifier" && candidate.value === binding.identifier);
306
+ const exportName = property ? readStaticObjectKey(property) : void 0;
307
+ if (!exportName || !knownExternalExport("gt-vue", exportName, options.recognizeAllGTRuntimeExports === true)) return;
308
+ const namespace = unwrapLocalExpression(declaration.init);
309
+ if (!namespace || namespace.type !== "Identifier") return void 0;
310
+ const namespaceBinding = readNodePath(state.record, namespace)?.scope.getBinding(namespace.name);
311
+ const imported = namespaceBinding ? state.record.imports.get(namespaceBinding.identifier.name) : void 0;
312
+ return namespaceBinding?.kind === "module" && namespaceBinding.constant && imported?.source === "gt-vue" && imported.importedName === "*" && !namespaceMemberIsWritten(namespaceBinding, exportName) ? exportName : void 0;
313
+ };
314
+ /** Resolves a direct gt-vue value, including immutable local aliases. */
315
+ const readDirectGT = (node, state) => {
316
+ const expression = unwrapLocalExpression(node);
317
+ if (!expression || state.nodes.has(expression)) return void 0;
318
+ const next = {
319
+ ...state,
320
+ nodes: new Set(state.nodes).add(expression)
321
+ };
322
+ if (expression.type === "Identifier") {
323
+ const binding = readNodePath(state.record, expression)?.scope.getBinding(expression.name);
324
+ return binding ? readDerivedGTBinding(binding, next) : void 0;
325
+ }
326
+ if (expression.type !== "MemberExpression" && expression.type !== "OptionalMemberExpression") return;
327
+ const property = readStaticMemberName(expression);
328
+ const object = unwrapLocalExpression(expression.object);
329
+ if (!property || object?.type !== "Identifier") return void 0;
330
+ const binding = readNodePath(state.record, object)?.scope.getBinding(object.name);
331
+ if (!binding || binding.kind !== "module" || !binding.constant) return;
332
+ const imported = state.record.imports.get(binding.identifier.name);
333
+ if (!imported || imported.importedName !== "*") return void 0;
334
+ if (namespaceMemberIsWritten(binding, property)) return void 0;
335
+ if (imported.source === "gt-vue") return knownExternalExport(imported.source, property, options.recognizeAllGTRuntimeExports === true) ? property : void 0;
336
+ const modulePath = resolveModule(state.record.filePath, imported.source);
337
+ return modulePath && isProjectModule(modulePath) ? readGTExportName(resolveExportInternal(modulePath, property, state.resolutions), state.resolutions, state.allowNamespaceContainers) : void 0;
338
+ };
339
+ /** Recognizes only explicit aliases and Vue component wrapper forms. */
340
+ const readDerivedGT = (node, state) => {
341
+ const direct = readDirectGT(node, state);
342
+ if (direct) return direct;
343
+ const expression = unwrapLocalExpression(node);
344
+ if (!expression || state.nodes.has(expression)) return void 0;
345
+ const next = {
346
+ ...state,
347
+ nodes: new Set(state.nodes).add(expression)
348
+ };
349
+ if (expression.type === "ArrowFunctionExpression" || expression.type === "FunctionExpression" || expression.type === "FunctionDeclaration" || expression.type === "ObjectMethod") return readFunctionRenderedGT(expression, next);
350
+ if (expression.type === "ObjectExpression") return readComponentObjectGT(expression, next);
351
+ if ((expression.type === "CallExpression" || expression.type === "OptionalCallExpression") && isVueHelper(expression.callee, state, "defineComponent")) {
352
+ const component = expression.arguments[0];
353
+ return component && component.type !== "SpreadElement" && component.type !== "ArgumentPlaceholder" ? readDerivedGT(component, next) : void 0;
354
+ }
355
+ return readRenderedGT(expression, state);
356
+ };
357
+ /** Checks only return values owned by the wrapper function itself. */
358
+ const readFunctionRenderedGT = (fn, state) => {
359
+ if (fn.type === "ArrowFunctionExpression" && fn.body.type !== "BlockStatement") return readRenderedGT(fn.body, state);
360
+ const functionPath = readNodePath(state.record, fn);
361
+ if (!functionPath) return void 0;
362
+ let result;
363
+ functionPath.traverse({ ReturnStatement(returnPath) {
364
+ if (result || returnPath.getFunctionParent()?.node !== fn) return;
365
+ result = readRenderedGT(returnPath.node.argument, state);
366
+ } });
367
+ return result;
368
+ };
369
+ /** Checks the two component options that can directly produce rendered output. */
370
+ const readComponentObjectGT = (object, state) => {
371
+ for (const property of object.properties) {
372
+ if (property.type === "SpreadElement") continue;
373
+ const name = readStaticObjectKey(property);
374
+ if (name !== "render" && name !== "setup") continue;
375
+ const result = readDerivedGT(property.type === "ObjectProperty" ? property.value : property, state);
376
+ if (result) return result;
377
+ }
378
+ };
379
+ /** Recognizes GT only in returned JSX or the h/createVNode component slot. */
380
+ const readRenderedGT = (node, state) => {
381
+ const expression = unwrapLocalExpression(node);
382
+ if (!expression || state.nodes.has(expression)) return void 0;
383
+ const next = {
384
+ ...state,
385
+ nodes: new Set(state.nodes).add(expression)
386
+ };
387
+ if (expression.type === "ArrowFunctionExpression" || expression.type === "FunctionExpression") return readFunctionRenderedGT(expression, next);
388
+ if (expression.type === "JSXElement") {
389
+ const component = readJSXComponentGT(expression.openingElement.name, next);
390
+ if (component) return component;
391
+ for (const child of expression.children) {
392
+ const result = readRenderedGT(child.type === "JSXExpressionContainer" ? child.expression.type === "JSXEmptyExpression" ? void 0 : child.expression : child, next);
393
+ if (result) return result;
394
+ }
395
+ return;
396
+ }
397
+ if (expression.type === "JSXFragment") {
398
+ for (const child of expression.children) {
399
+ const result = readRenderedGT(child.type === "JSXExpressionContainer" ? child.expression.type === "JSXEmptyExpression" ? void 0 : child.expression : child, next);
400
+ if (result) return result;
401
+ }
402
+ return;
403
+ }
404
+ if (expression.type === "ConditionalExpression") return readRenderedGT(expression.consequent, next) ?? readRenderedGT(expression.alternate, next);
405
+ if (expression.type === "LogicalExpression") return readRenderedGT(expression.left, next) ?? readRenderedGT(expression.right, next);
406
+ if (expression.type !== "CallExpression" && expression.type !== "OptionalCallExpression" || !isVueHelper(expression.callee, state, "h") && !isVueHelper(expression.callee, state, "createVNode")) return;
407
+ const component = expression.arguments[0];
408
+ return component && component.type !== "SpreadElement" && component.type !== "ArgumentPlaceholder" ? readDirectGT(component, next) : void 0;
409
+ };
410
+ /** Resolves an imported GT component used as a JSX element name. */
411
+ const readJSXComponentGT = (name, state) => {
412
+ if (name.type === "JSXMemberExpression") {
413
+ if (name.object.type !== "JSXIdentifier") return void 0;
414
+ const binding = readNodePath(state.record, name.object)?.scope.getBinding(name.object.name);
415
+ if (!binding || binding.kind !== "module" || !binding.constant) return;
416
+ const imported = state.record.imports.get(binding.identifier.name);
417
+ if (!imported || imported.importedName !== "*") return void 0;
418
+ const property = name.property.name;
419
+ if (namespaceMemberIsWritten(binding, property)) return void 0;
420
+ if (imported.source === "gt-vue") return knownExternalExport(imported.source, property, options.recognizeAllGTRuntimeExports === true) ? property : void 0;
421
+ const modulePath = resolveModule(state.record.filePath, imported.source);
422
+ return modulePath && isProjectModule(modulePath) ? readGTExportName(resolveExportInternal(modulePath, property, state.resolutions), state.resolutions, state.allowNamespaceContainers) : void 0;
423
+ }
424
+ if (name.type !== "JSXIdentifier" || /^[a-z]/.test(name.name)) return;
425
+ const binding = readNodePath(state.record, name)?.scope.getBinding(name.name);
426
+ return binding ? readDerivedGTBinding(binding, state) : void 0;
427
+ };
428
+ /** Matches a direct or namespace ESM import from Vue without evaluating calls. */
429
+ const isVueHelper = (node, state, exportName) => {
430
+ const expression = unwrapLocalExpression(node);
431
+ if (!expression) return false;
432
+ const identifier = expression.type === "Identifier" ? expression : (expression.type === "MemberExpression" || expression.type === "OptionalMemberExpression") && readStaticMemberName(expression) === exportName ? unwrapLocalExpression(expression.object) : void 0;
433
+ if (!identifier || identifier.type !== "Identifier") return false;
434
+ const binding = readNodePath(state.record, identifier)?.scope.getBinding(identifier.name);
435
+ const imported = binding?.kind === "module" ? state.record.imports.get(binding.identifier.name) : void 0;
436
+ const expectedImport = expression.type === "Identifier" ? exportName : "*";
437
+ return binding?.constant === true && imported?.source === "vue" && imported.importedName === expectedImport && (expectedImport !== "*" || !namespaceMemberIsWritten(binding, exportName));
438
+ };
439
+ const readStaticMemberName = (member) => {
440
+ if (!member.computed && member.property.type === "Identifier") return member.property.name;
441
+ return member.computed && member.property.type === "StringLiteral" ? member.property.value : void 0;
442
+ };
443
+ const readStaticObjectKey = (property) => {
444
+ if (!property.key) return void 0;
445
+ if (!property.computed && property.key.type === "Identifier") return property.key.name;
446
+ return property.key.type === "StringLiteral" ? property.key.value : void 0;
447
+ };
448
+ const resolutionReferencesGT = (resolution, seen) => {
449
+ return readGTExportName(resolution, seen) !== void 0;
100
450
  };
101
451
  const resolveFromSource = (record, source, exportName, seen) => {
102
- if (isExternalModule(source)) return knownExternalExport(source, exportName) ? {
452
+ if (isKnownNonVueGTRuntime(source)) return {
453
+ status: "resolved",
454
+ target: {
455
+ originKey: `${source}#${exportName}`,
456
+ type: "ordinary-external"
457
+ }
458
+ };
459
+ if (isExternalModule(source)) return knownExternalExport(source, exportName, options.recognizeAllGTRuntimeExports === true) ? {
103
460
  status: "resolved",
104
461
  target: {
105
462
  exportName,
@@ -109,11 +466,26 @@ function createLocalModuleResolver(resolveModuleOption) {
109
466
  }
110
467
  } : { status: "absent" };
111
468
  const modulePath = resolveModule(record.filePath, source);
112
- return modulePath ? resolveExportInternal(modulePath, exportName, seen) : { status: "invalid" };
469
+ if (!modulePath) return { status: "invalid" };
470
+ if (!isProjectModule(modulePath)) return {
471
+ status: "resolved",
472
+ target: {
473
+ originKey: `${modulePath}#${exportName}`,
474
+ type: "ordinary-external"
475
+ }
476
+ };
477
+ return resolveExportInternal(modulePath, exportName, seen);
113
478
  };
114
479
  const resolveDeclaredExport = (record, exportName, declared, seen) => {
115
480
  if (declared.type === "reexport") return resolveFromSource(record, declared.source, declared.importedName, seen);
116
481
  if (declared.type === "namespace") {
482
+ if (isKnownNonVueGTRuntime(declared.source)) return {
483
+ status: "resolved",
484
+ target: {
485
+ originKey: `${declared.source}#namespace`,
486
+ type: "ordinary-external"
487
+ }
488
+ };
117
489
  if (isExternalModule(declared.source)) return {
118
490
  status: "resolved",
119
491
  target: {
@@ -123,6 +495,13 @@ function createLocalModuleResolver(resolveModuleOption) {
123
495
  }
124
496
  };
125
497
  const modulePath = resolveModule(record.filePath, declared.source);
498
+ if (modulePath && !isProjectModule(modulePath)) return {
499
+ status: "resolved",
500
+ target: {
501
+ originKey: `${modulePath}#namespace`,
502
+ type: "ordinary-external"
503
+ }
504
+ };
126
505
  return modulePath ? {
127
506
  status: "resolved",
128
507
  target: {
@@ -136,6 +515,13 @@ function createLocalModuleResolver(resolveModuleOption) {
136
515
  const imported = record.imports.get(declared.name);
137
516
  if (imported) {
138
517
  if (imported.importedName === "*") {
518
+ if (isKnownNonVueGTRuntime(imported.source)) return {
519
+ status: "resolved",
520
+ target: {
521
+ originKey: `${imported.source}#namespace`,
522
+ type: "ordinary-external"
523
+ }
524
+ };
139
525
  if (isExternalModule(imported.source)) return {
140
526
  status: "resolved",
141
527
  target: {
@@ -145,6 +531,13 @@ function createLocalModuleResolver(resolveModuleOption) {
145
531
  }
146
532
  };
147
533
  const modulePath = resolveModule(record.filePath, imported.source);
534
+ if (modulePath && !isProjectModule(modulePath)) return {
535
+ status: "resolved",
536
+ target: {
537
+ originKey: `${modulePath}#namespace`,
538
+ type: "ordinary-external"
539
+ }
540
+ };
148
541
  return modulePath ? {
149
542
  status: "resolved",
150
543
  target: {
@@ -191,26 +584,49 @@ function createLocalModuleResolver(resolveModuleOption) {
191
584
  const normalized = path.resolve(filePath);
192
585
  if (seen.has(normalized)) return /* @__PURE__ */ new Set();
193
586
  const record = getRecord(normalized);
194
- if (!record) return /* @__PURE__ */ new Set();
587
+ const recovered = record ? void 0 : getRecoveredRecord(normalized);
588
+ if (!record && !recovered) return /* @__PURE__ */ new Set();
589
+ const moduleRecord = record ?? recovered;
195
590
  const nextSeen = new Set(seen).add(normalized);
196
- const names = new Set(record.explicitExports.keys());
197
- for (const source of record.starExports) if (source === "gt-vue") for (const name of GT_EXPORT_NAMES) names.add(name);
591
+ const names = new Set(moduleRecord.explicitExports.keys());
592
+ for (const source of moduleRecord.starExports) if (source === "gt-vue") for (const name of GT_EXPORT_NAMES) names.add(name);
198
593
  else if (source === "vue") for (const name of VUE_EXPORT_NAMES) names.add(name);
594
+ else if (isKnownNonVueGTRuntime(source)) continue;
199
595
  else {
200
- const modulePath = resolveModule(record.filePath, source);
201
- if (!modulePath) continue;
596
+ const modulePath = resolveModule(moduleRecord.filePath, source);
597
+ if (!modulePath || !isProjectModule(modulePath)) continue;
202
598
  for (const name of collectExportNames(modulePath, nextSeen)) if (name !== "default") names.add(name);
203
599
  }
204
600
  return names;
205
601
  };
602
+ const hasGTExportReference = (filePath, exportName) => {
603
+ return resolutionReferencesGT(resolveExportInternal(filePath, exportName, /* @__PURE__ */ new Set()), /* @__PURE__ */ new Set());
604
+ };
605
+ const getGTExportName = (filePath, exportName) => {
606
+ const resolution = resolveExportInternal(filePath, exportName, /* @__PURE__ */ new Set());
607
+ return resolution.status === "resolved" ? readGTExportName(resolution, /* @__PURE__ */ new Set(), false) : void 0;
608
+ };
206
609
  return {
207
610
  getRecord,
611
+ getGTExportName,
208
612
  hasCustomResolver: resolveModuleOption !== void 0,
613
+ hasGTExportReference,
614
+ isProjectModule,
209
615
  listExportNames,
210
616
  resolveExport,
211
617
  resolveModule
212
618
  };
213
619
  }
620
+ /** Removes syntax-only wrappers without importing the compiler-facing utilities. */
621
+ function unwrapLocalExpression(input) {
622
+ let current = input ?? void 0;
623
+ while (current && (current.type === "TSAsExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSInstantiationExpression" || current.type === "TypeCastExpression" || current.type === "ParenthesizedExpression")) current = current.expression;
624
+ return current;
625
+ }
626
+ /** Deduplicates recovered graph targets without discarding their identities. */
627
+ function uniqueRecoveredTargets(targets) {
628
+ return [...new Map(targets.map((target) => [target.originKey, target])).values()];
629
+ }
214
630
  function resolveSourceFile(requested) {
215
631
  const candidates = [requested];
216
632
  const extension = path.extname(requested).toLowerCase();
@@ -234,6 +650,14 @@ function isReadableFile(filePath) {
234
650
  return false;
235
651
  }
236
652
  }
653
+ /** Resolves symlinks when possible while retaining missing-path diagnostics. */
654
+ function readRealPath(filePath) {
655
+ try {
656
+ return fs.realpathSync.native(filePath);
657
+ } catch {
658
+ return filePath;
659
+ }
660
+ }
237
661
  function parseLocalModule(filePath) {
238
662
  let source;
239
663
  try {
@@ -276,11 +700,95 @@ function parseLocalModule(filePath) {
276
700
  collectExports(record);
277
701
  return record;
278
702
  }
703
+ let moduleLexerInitialized = false;
704
+ /**
705
+ * Recovers only source-bound runtime exports from an otherwise invalid module.
706
+ *
707
+ * The recovered declarations establish provenance, but never become executable
708
+ * analyzer input. Their resolutions remain invalid so consumers fail closed
709
+ * while type-only and unrelated module references stay invisible.
710
+ */
711
+ function recoverMalformedModuleExports(filePath) {
712
+ const extension = path.extname(filePath).toLowerCase();
713
+ if (extension === ".cjs" || extension === ".cts" || extension === ".vue") return;
714
+ let source;
715
+ try {
716
+ source = fs.readFileSync(filePath, "utf8");
717
+ } catch {
718
+ return;
719
+ }
720
+ if (!moduleLexerInitialized) {
721
+ initSync();
722
+ moduleLexerInitialized = true;
723
+ }
724
+ let moduleImports;
725
+ try {
726
+ [moduleImports] = parse(source);
727
+ } catch {
728
+ return;
729
+ }
730
+ const record = {
731
+ explicitExports: /* @__PURE__ */ new Map(),
732
+ filePath,
733
+ starExports: []
734
+ };
735
+ const statements = /* @__PURE__ */ new Set();
736
+ for (const moduleImport of moduleImports) {
737
+ if (moduleImport.d !== -1 || moduleImport.ss < 0 || moduleImport.se <= moduleImport.ss) continue;
738
+ statements.add(source.slice(moduleImport.ss, moduleImport.se));
739
+ }
740
+ for (const statementSource of statements) {
741
+ const statement = parseRecoveredModuleStatement(statementSource, extension);
742
+ if (!statement) continue;
743
+ collectRecoveredExport(record, statement);
744
+ }
745
+ return record.explicitExports.size > 0 || record.starExports.length > 0 ? record : void 0;
746
+ }
747
+ /** Parses one lexed declaration under the source file's supported grammars. */
748
+ function parseRecoveredModuleStatement(source, extension) {
749
+ const declaredLanguage = extension === ".mjs" ? "js" : extension === ".mts" ? "ts" : extension.slice(1);
750
+ const languages = new Set([declaredLanguage]);
751
+ if (declaredLanguage === "js" || declaredLanguage === "jsx") languages.add("flow");
752
+ languages.add("tsx");
753
+ for (const language of languages) try {
754
+ const ast = parseScriptAst(source, language);
755
+ if (ast.program.body.length === 1) return ast.program.body[0];
756
+ } catch {}
757
+ }
758
+ /** Adds runtime re-exports without trusting declarations around the syntax error. */
759
+ function collectRecoveredExport(record, statement) {
760
+ if (statement.type === "ExportAllDeclaration") {
761
+ if (statement.exportKind !== "type") record.starExports.push(statement.source.value);
762
+ return;
763
+ }
764
+ if (statement.type !== "ExportNamedDeclaration" || statement.exportKind === "type" || !statement.source) return;
765
+ for (const specifier of statement.specifiers) {
766
+ if (specifier.type === "ExportSpecifier" && specifier.exportKind === "type") continue;
767
+ const exportedName = specifier.exported.type === "Identifier" ? specifier.exported.name : specifier.exported.value;
768
+ if (specifier.type === "ExportNamespaceSpecifier") {
769
+ addRecoveredExplicitExport(record, exportedName, {
770
+ source: statement.source.value,
771
+ type: "namespace"
772
+ });
773
+ continue;
774
+ }
775
+ if (specifier.type !== "ExportSpecifier") continue;
776
+ addRecoveredExplicitExport(record, exportedName, {
777
+ importedName: specifier.local.name,
778
+ source: statement.source.value,
779
+ type: "reexport"
780
+ });
781
+ }
782
+ }
783
+ /** Preserves ambiguity instead of selecting an arbitrary recovered identity. */
784
+ function addRecoveredExplicitExport(record, name, value) {
785
+ record.explicitExports.set(name, record.explicitExports.has(name) ? "ambiguous" : value);
786
+ }
279
787
  function collectImportedBindings(ast) {
280
788
  const imports = /* @__PURE__ */ new Map();
281
789
  for (const statement of ast.program.body) {
282
- if (statement.type !== "ImportDeclaration" || statement.importKind === "type") continue;
283
- for (const specifier of statement.specifiers) if (specifier.type === "ImportSpecifier" && specifier.importKind !== "type") imports.set(specifier.local.name, {
790
+ if (statement.type !== "ImportDeclaration" || isTypeOnlyImportKind(statement.importKind)) continue;
791
+ for (const specifier of statement.specifiers) if (specifier.type === "ImportSpecifier" && !isTypeOnlyImportKind(specifier.importKind)) imports.set(specifier.local.name, {
284
792
  importedName: specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value,
285
793
  source: statement.source.value
286
794
  });
@@ -295,6 +803,10 @@ function collectImportedBindings(ast) {
295
803
  }
296
804
  return imports;
297
805
  }
806
+ /** Returns whether Babel classified an ESM binding as type-only. */
807
+ function isTypeOnlyImportKind(kind) {
808
+ return kind === "type" || kind === "typeof";
809
+ }
298
810
  function collectExports(record) {
299
811
  for (const statement of record.ast.program.body) {
300
812
  if (statement.type === "ExportAllDeclaration") {
@@ -355,8 +867,9 @@ function patternNames(pattern) {
355
867
  function isExternalModule(source) {
356
868
  return source === "gt-vue" || source === "vue";
357
869
  }
358
- function knownExternalExport(source, exportName) {
359
- return source === "gt-vue" ? GT_EXPORT_NAMES.includes(exportName) : VUE_EXPORT_NAMES.includes(exportName);
870
+ function knownExternalExport(source, exportName, recognizeAllGTRuntimeExports) {
871
+ if (source === "vue") return VUE_EXPORT_NAMES.includes(exportName);
872
+ return (recognizeAllGTRuntimeExports ? GT_RUNTIME_EXPORT_NAMES : GT_EXPORT_NAMES).includes(exportName);
360
873
  }
361
874
  //#endregion
362
875
  export { createLocalModuleResolver };