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

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