@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,36 +1,11 @@
1
+ import { NUXT_CONFIG_FILES, VITE_CONFIG_EXTENSIONS, VITE_CONFIG_FILES } from "./configFiles.js";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import { parse } from "@babel/parser";
4
5
  import traverseModule from "@babel/traverse";
5
- import { createDiagnosticMessage } from "generaltranslation/internal";
6
+ import { createDiagnosticMessage, formatDiagnosticErrorDetails } from "generaltranslation/internal";
6
7
  //#region src/internal/config/resolveVueCompilerOptions.ts
7
8
  const traverse = traverseModule.default || traverseModule;
8
- const VITE_CONFIG_FILES = [
9
- "vite.config.js",
10
- "vite.config.mjs",
11
- "vite.config.ts",
12
- "vite.config.cjs",
13
- "vite.config.mts",
14
- "vite.config.cts"
15
- ];
16
- const NUXT_CONFIG_FILES = [
17
- "nuxt.config.js",
18
- "nuxt.config.ts",
19
- "nuxt.config.mjs",
20
- "nuxt.config.cjs",
21
- "nuxt.config.mts",
22
- "nuxt.config.cts"
23
- ];
24
- const CUSTOM_VITE_CONFIG_EXTENSIONS = new Set([
25
- ".js",
26
- ".jsx",
27
- ".mjs",
28
- ".cjs",
29
- ".ts",
30
- ".tsx",
31
- ".mts",
32
- ".cts"
33
- ]);
34
9
  /**
35
10
  * Resolves hash-affecting Vue template compiler options without executing
36
11
  * project configuration files.
@@ -49,14 +24,14 @@ function resolveVueCompilerOptions(cwd, explicitOptions, resolverOptions = {}) {
49
24
  readExplicitOptions(explicitOptions, state, errors);
50
25
  if (resolverOptions.viteConfigPath !== void 0) {
51
26
  const file = resolveCustomViteConfig(cwd, resolverOptions.viteConfigPath, errors);
52
- if (file) readViteConfig(file, state, errors);
27
+ if (file) readViteConfig(file, state, errors, true);
53
28
  return {
54
29
  compilerOptions: state.options,
55
30
  errors
56
31
  };
57
32
  }
58
- const nuxtConfig = findFirstConfig(cwd, NUXT_CONFIG_FILES);
59
- const viteConfig = findFirstConfig(cwd, VITE_CONFIG_FILES);
33
+ const nuxtConfig = findFirstConfig(cwd, NUXT_CONFIG_FILES, errors);
34
+ const viteConfig = findFirstConfig(cwd, VITE_CONFIG_FILES, errors);
60
35
  if (nuxtConfig && viteConfig) {
61
36
  errors.push(optionError("Found both Nuxt and Vite project config files", "For direct Vite builds, set files.gt.parsingFlags.viteConfigPath to the active Vite config. For Nuxt builds, remove or relocate the inactive Vite config so the compiler configuration is unambiguous"));
62
37
  return {
@@ -65,23 +40,24 @@ function resolveVueCompilerOptions(cwd, explicitOptions, resolverOptions = {}) {
65
40
  };
66
41
  }
67
42
  if (nuxtConfig) {
68
- readNuxtConfig(nuxtConfig, state, errors);
43
+ readNuxtConfig(nuxtConfig, state, errors, resolverOptions.sourceDiscoveryIsExplicit ?? false);
69
44
  return {
70
45
  compilerOptions: state.options,
71
46
  errors
72
47
  };
73
48
  }
74
- if (viteConfig) readViteConfig(viteConfig, state, errors);
49
+ if (viteConfig) readViteConfig(viteConfig, state, errors, resolverOptions.sourceDiscoveryIsExplicit ?? false);
75
50
  return {
76
51
  compilerOptions: state.options,
77
52
  errors
78
53
  };
79
54
  }
80
55
  /** Selects the first config file in the framework's documented lookup order. */
81
- function findFirstConfig(cwd, filenames) {
56
+ function findFirstConfig(cwd, filenames, errors) {
82
57
  for (const filename of filenames) {
83
- const file = path.resolve(cwd, filename);
84
- if (fs.existsSync(file)) return file;
58
+ const resolution = inspectConfigFile(path.resolve(cwd), path.resolve(cwd, filename), false, errors);
59
+ if (resolution.kind === "file") return resolution.file;
60
+ if (resolution.kind === "invalid") return void 0;
85
61
  }
86
62
  }
87
63
  /** Validates an explicit Vite config without searching or executing files. */
@@ -97,22 +73,44 @@ function resolveCustomViteConfig(cwd, configuredPath, errors) {
97
73
  errors.push(optionError("Found a Vite config path outside the project source boundary", "Choose a Vite config file inside the project root and outside node_modules"));
98
74
  return;
99
75
  }
100
- if (!CUSTOM_VITE_CONFIG_EXTENSIONS.has(path.extname(candidate).toLowerCase())) {
76
+ if (!VITE_CONFIG_EXTENSIONS.has(path.extname(candidate).toLowerCase())) {
101
77
  errors.push(optionError("Found an unsupported Vite config file extension", "Use a JavaScript or TypeScript Vite config file"));
102
78
  return;
103
79
  }
104
- if (!fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
105
- errors.push(optionError("Could not find the configured Vite config file", "Set files.gt.parsingFlags.viteConfigPath to an existing file inside the project root"));
106
- return;
107
- }
108
- const realRoot = fs.realpathSync(root);
109
- const realCandidate = fs.realpathSync(candidate);
110
- const realRelative = path.relative(realRoot, realCandidate);
111
- if (realRelative.startsWith(`..${path.sep}`) || realRelative === ".." || path.isAbsolute(realRelative) || realRelative.split(path.sep).includes("node_modules")) {
112
- errors.push(optionError("Found a Vite config path outside the project source boundary", "Choose a Vite config file inside the project root and outside node_modules"));
113
- return;
80
+ const resolution = inspectConfigFile(root, candidate, true, errors);
81
+ return resolution.kind === "file" ? resolution.file : void 0;
82
+ }
83
+ /** Validates one config candidate without letting filesystem races escape. */
84
+ function inspectConfigFile(root, candidate, missingIsError, errors) {
85
+ let candidateWasFound = false;
86
+ try {
87
+ const stats = fs.statSync(candidate);
88
+ candidateWasFound = true;
89
+ if (!stats.isFile()) {
90
+ errors.push(configFileDiagnostic("Found a Vue project config path that is not a regular file", "Replace it with a readable JavaScript or TypeScript config file", candidate));
91
+ return { kind: "invalid" };
92
+ }
93
+ fs.accessSync(candidate, fs.constants.R_OK);
94
+ const realRoot = fs.realpathSync(root);
95
+ const realCandidate = fs.realpathSync(candidate);
96
+ const realRelative = path.relative(realRoot, realCandidate);
97
+ if (realRelative.startsWith(`..${path.sep}`) || realRelative === ".." || path.isAbsolute(realRelative) || realRelative.split(path.sep).includes("node_modules")) {
98
+ errors.push(optionError("Found a Vue project config path outside the project source boundary", "Choose a project config file inside the project root and outside node_modules"));
99
+ return { kind: "invalid" };
100
+ }
101
+ return {
102
+ kind: "file",
103
+ file: realCandidate
104
+ };
105
+ } catch (error) {
106
+ if (isMissingPathError(error) && !missingIsError && !candidateWasFound) return { kind: "missing" };
107
+ if (isMissingPathError(error) && missingIsError && !candidateWasFound) errors.push(configFileDiagnostic("Could not find the configured Vite config file", "Set files.gt.parsingFlags.viteConfigPath to an existing file inside the project root", candidate, error));
108
+ else errors.push(configFileDiagnostic("Could not read the Vue project config file", "Restore read access to the config file and try extraction again", candidate, error));
109
+ return { kind: "invalid" };
114
110
  }
115
- return realCandidate;
111
+ }
112
+ function isMissingPathError(error) {
113
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
116
114
  }
117
115
  function readExplicitOptions(input, state, errors) {
118
116
  if (input === void 0) return;
@@ -126,8 +124,8 @@ function readExplicitOptions(input, state, errors) {
126
124
  if (input.delimiters !== void 0) if (!isDelimiterPair(input.delimiters)) errors.push(optionError("Found invalid Vue interpolation delimiters in gt.config.json", "Set delimiters to exactly two non-empty strings, such as [\"[[\", \"]]\"]"));
127
125
  else mergeOption(state, "delimiters", input.delimiters, { file: "gt.config.json" }, errors);
128
126
  }
129
- function readViteConfig(file, state, errors) {
130
- const ast = parseConfig(file, errors);
127
+ function readViteConfig(file, state, errors, reportAllSyntaxErrors) {
128
+ const ast = parseConfig(file, errors, reportAllSyntaxErrors);
131
129
  if (!ast) return;
132
130
  const pluginBindings = /* @__PURE__ */ new Set();
133
131
  const namespaceBindings = /* @__PURE__ */ new Set();
@@ -329,8 +327,8 @@ function rejectCustomVueCompiler(root, scope, file, errors) {
329
327
  if (!compiler) return;
330
328
  errors.push(locatedOptionError(file, compiler.node, "Found a custom Vue compiler instance in the Vite plugin", "Remove the compiler override so extraction and Vite both use the app's vue/compiler-sfc version"));
331
329
  }
332
- function readNuxtConfig(file, state, errors) {
333
- const ast = parseConfig(file, errors);
330
+ function readNuxtConfig(file, state, errors, sourceDiscoveryIsExplicit) {
331
+ const ast = parseConfig(file, errors, sourceDiscoveryIsExplicit);
334
332
  if (!ast) return;
335
333
  const defineNuxtConfigBindings = /* @__PURE__ */ new Set();
336
334
  traverse(ast, { ImportDeclaration(importPath) {
@@ -359,7 +357,7 @@ function readNuxtConfig(file, state, errors) {
359
357
  errors.push(locatedOptionError(file, extendsEntry.node, "Found Nuxt layer inheritance that could change Vue compiler options", "Run extraction from a Nuxt configuration without inherited layers until gt-vue can resolve the complete layer chain safely"));
360
358
  return;
361
359
  }
362
- const unsupportedSourceLayout = findUnsupportedNuxtSourceLayout(configObject.value);
360
+ const unsupportedSourceLayout = sourceDiscoveryIsExplicit ? void 0 : findUnsupportedNuxtSourceLayout(configObject.value);
363
361
  if (unsupportedSourceLayout) {
364
362
  errors.push(locatedOptionError(file, unsupportedSourceLayout, "Found custom Nuxt source directories that default Vue discovery cannot scan safely", "Use Nuxt source directories covered by the default app, src, pages, layouts, plugins, and related globs until custom directory discovery is supported"));
365
363
  return;
@@ -917,18 +915,29 @@ function resolveKnownConfigConsumer(input, scope, seen) {
917
915
  }
918
916
  return (node.type === "MemberExpression" || node.type === "OptionalMemberExpression") && isDefaultMember(node) && (getPluginVueRequireKind(node, "@vitejs/plugin-vue") === "default" || getPluginVueRequireKind(node, "@vitejs/plugin-vue-jsx") === "default");
919
917
  }
920
- function parseConfig(file, errors) {
921
- const source = fs.readFileSync(file, "utf8");
918
+ /**
919
+ * Parses one project config without executing it. Automatic discovery keeps
920
+ * ignoring malformed configs that contain no Vue-relevant setting, while an
921
+ * explicit config or source scope reports every syntax error.
922
+ */
923
+ function parseConfig(file, errors, reportAllSyntaxErrors) {
924
+ let source;
925
+ try {
926
+ source = fs.readFileSync(file, "utf8");
927
+ } catch (error) {
928
+ errors.push(configFileDiagnostic("Could not read the Vue project config file", "Restore the config file and its read permissions, then try extraction again", file, error));
929
+ return;
930
+ }
922
931
  try {
923
932
  return parse(source, {
924
933
  sourceType: "unambiguous",
925
934
  plugins: parserPlugins(file)
926
935
  });
927
936
  } catch (error) {
928
- if (!/compilerOptions|whitespace|delimiters|@vitejs\/plugin-vue-jsx|babelPlugins|pragma/.test(source)) return;
937
+ if (!reportAllSyntaxErrors && !/compilerOptions|whitespace|delimiters|@vitejs\/plugin-vue-jsx|babelPlugins|pragma/.test(source)) return;
929
938
  const syntaxError = error;
930
939
  errors.push(withLocation(file, createDiagnosticMessage({
931
- whatHappened: "Could not parse a project configuration containing Vue compiler options",
940
+ whatHappened: reportAllSyntaxErrors ? "Could not parse the Vue project config file" : "Could not parse a project configuration containing Vue compiler options",
932
941
  details: syntaxError.message,
933
942
  fix: "Use a statically analyzable Vite or Nuxt configuration, or configure files.gt.parsingFlags.vueCompilerOptions explicitly"
934
943
  }), syntaxError.loc ? `${syntaxError.loc.line}:${syntaxError.loc.column + 1}` : void 0));
@@ -978,6 +987,15 @@ function optionError(whatHappened, fix) {
978
987
  fix
979
988
  });
980
989
  }
990
+ /** Formats a filesystem-backed config diagnostic without leaking an exception. */
991
+ function configFileDiagnostic(whatHappened, fix, file, error) {
992
+ const errorDetails = error === void 0 ? void 0 : formatDiagnosticErrorDetails(error);
993
+ return createDiagnosticMessage({
994
+ whatHappened,
995
+ fix,
996
+ details: [file, ...errorDetails === void 0 ? [] : [errorDetails]]
997
+ });
998
+ }
981
999
  function withLocation(file, message, location) {
982
1000
  return `${file}${location ? ` (${location})` : ""}: ${message}`;
983
1001
  }