@gtkx/cli 2.0.0-beta.3 → 2.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/cli.js +4 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/codegen/config-dependencies.d.ts +3 -0
  4. package/dist/codegen/config-dependencies.d.ts.map +1 -0
  5. package/dist/codegen/config-dependencies.js +355 -0
  6. package/dist/codegen/config-dependencies.js.map +1 -0
  7. package/dist/codegen/run-codegen.d.ts +3 -2
  8. package/dist/codegen/run-codegen.d.ts.map +1 -1
  9. package/dist/codegen/run-codegen.js +31 -6
  10. package/dist/codegen/run-codegen.js.map +1 -1
  11. package/dist/codegen/store-resolver.d.ts +1 -0
  12. package/dist/codegen/store-resolver.d.ts.map +1 -1
  13. package/dist/codegen/store-resolver.js +4 -2
  14. package/dist/codegen/store-resolver.js.map +1 -1
  15. package/dist/commands/cleanup.d.ts +9 -0
  16. package/dist/commands/cleanup.d.ts.map +1 -0
  17. package/dist/commands/cleanup.js +31 -0
  18. package/dist/commands/cleanup.js.map +1 -0
  19. package/dist/commands/dev.d.ts.map +1 -1
  20. package/dist/commands/dev.js +4 -2
  21. package/dist/commands/dev.js.map +1 -1
  22. package/dist/deploy/freedesktop/validate.d.ts.map +1 -1
  23. package/dist/deploy/freedesktop/validate.js +45 -12
  24. package/dist/deploy/freedesktop/validate.js.map +1 -1
  25. package/dist/deploy/payload/stage.d.ts.map +1 -1
  26. package/dist/deploy/payload/stage.js +24 -3
  27. package/dist/deploy/payload/stage.js.map +1 -1
  28. package/dist/deploy/settings/extra-files.d.ts.map +1 -1
  29. package/dist/deploy/settings/extra-files.js +4 -3
  30. package/dist/deploy/settings/extra-files.js.map +1 -1
  31. package/dist/dev/catalog-writes.d.ts +8 -0
  32. package/dist/dev/catalog-writes.d.ts.map +1 -0
  33. package/dist/dev/catalog-writes.js +26 -0
  34. package/dist/dev/catalog-writes.js.map +1 -0
  35. package/dist/dev/runner-deps.d.ts.map +1 -1
  36. package/dist/dev/runner-deps.js +10 -6
  37. package/dist/dev/runner-deps.js.map +1 -1
  38. package/dist/dev/runner.d.ts +1 -0
  39. package/dist/dev/runner.d.ts.map +1 -1
  40. package/dist/dev/runner.js +8 -2
  41. package/dist/dev/runner.js.map +1 -1
  42. package/dist/dev/supervisor.d.ts +2 -1
  43. package/dist/dev/supervisor.d.ts.map +1 -1
  44. package/dist/dev/supervisor.js +128 -26
  45. package/dist/dev/supervisor.js.map +1 -1
  46. package/dist/i18n/catalogs.d.ts +6 -2
  47. package/dist/i18n/catalogs.d.ts.map +1 -1
  48. package/dist/i18n/catalogs.js +9 -7
  49. package/dist/i18n/catalogs.js.map +1 -1
  50. package/dist/i18n/source-messages.d.ts +3 -1
  51. package/dist/i18n/source-messages.d.ts.map +1 -1
  52. package/dist/i18n/source-messages.js +14 -2
  53. package/dist/i18n/source-messages.js.map +1 -1
  54. package/dist/internal/build-output.d.ts.map +1 -1
  55. package/dist/internal/build-output.js +45 -8
  56. package/dist/internal/build-output.js.map +1 -1
  57. package/dist/internal/prepare-project.d.ts +1 -0
  58. package/dist/internal/prepare-project.d.ts.map +1 -1
  59. package/dist/internal/prepare-project.js +8 -2
  60. package/dist/internal/prepare-project.js.map +1 -1
  61. package/dist/vite-plugins/i18n.d.ts +11 -2
  62. package/dist/vite-plugins/i18n.d.ts.map +1 -1
  63. package/dist/vite-plugins/i18n.js +20 -6
  64. package/dist/vite-plugins/i18n.js.map +1 -1
  65. package/dist/vite-plugins/index.d.ts +2 -0
  66. package/dist/vite-plugins/index.d.ts.map +1 -1
  67. package/dist/vite-plugins/index.js +10 -2
  68. package/dist/vite-plugins/index.js.map +1 -1
  69. package/package.json +12 -10
  70. package/src/cli.ts +5 -0
  71. package/src/codegen/config-dependencies.ts +470 -0
  72. package/src/codegen/run-codegen.ts +37 -5
  73. package/src/codegen/store-resolver.ts +5 -2
  74. package/src/commands/cleanup.ts +36 -0
  75. package/src/commands/dev.ts +9 -2
  76. package/src/deploy/freedesktop/validate.ts +63 -13
  77. package/src/deploy/payload/stage.ts +42 -3
  78. package/src/deploy/settings/extra-files.ts +5 -3
  79. package/src/dev/catalog-writes.ts +35 -0
  80. package/src/dev/runner-deps.ts +14 -6
  81. package/src/dev/runner.ts +11 -2
  82. package/src/dev/supervisor.ts +177 -29
  83. package/src/i18n/catalogs.ts +20 -8
  84. package/src/i18n/source-messages.ts +19 -3
  85. package/src/internal/build-output.ts +67 -9
  86. package/src/internal/prepare-project.ts +9 -3
  87. package/src/vite-plugins/i18n.ts +42 -9
  88. package/src/vite-plugins/index.ts +19 -3
@@ -33,28 +33,65 @@ const isReusableBuildDirectory = (path) => {
33
33
  }
34
34
  return stats.isDirectory() && (readdirSync(path).length === 0 || isGtkxBuildDirectory(path));
35
35
  };
36
- const buildOutputError = (root) => new Error(`Build output must be an empty directory or an earlier GTKX build below the project root ${root}`);
37
- const hasGtkxBuildAncestor = (root, outDir) => {
36
+ const outputName = (root, path) => relative(root, path) || ".";
37
+ const gtkxBuildAncestor = (root, outDir) => {
38
38
  let ancestor = dirname(outDir);
39
39
  while (isPathInside(root, ancestor)) {
40
40
  if (isGtkxBuildDirectory(ancestor)) {
41
- return true;
41
+ return ancestor;
42
42
  }
43
43
  ancestor = dirname(ancestor);
44
44
  }
45
- return false;
45
+ return null;
46
+ };
47
+ const childDirectories = (parent) => readdirSync(parent, { withFileTypes: true })
48
+ .filter((entry) => entry.isDirectory())
49
+ .map((entry) => join(parent, entry.name));
50
+ const gtkxBuildDescendant = (root) => {
51
+ const pending = childDirectories(root);
52
+ while (pending.length > 0) {
53
+ const path = pending.pop();
54
+ if (path === undefined) {
55
+ return null;
56
+ }
57
+ if (isGtkxBuildDirectory(path)) {
58
+ return path;
59
+ }
60
+ pending.push(...childDirectories(path));
61
+ }
62
+ return null;
46
63
  };
47
64
  const assertSafeBuildLocation = (root, outDir) => {
48
- if (!isPathInside(root, outDir) || hasSymlinkComponent(root, outDir) || hasGtkxBuildAncestor(root, outDir)) {
49
- throw buildOutputError(root);
65
+ if (!isPathInside(root, outDir)) {
66
+ throw new Error(`Build output ${outDir} must be below the project root ${root}`);
67
+ }
68
+ if (hasSymlinkComponent(root, outDir)) {
69
+ throw new Error(`Build output ${outputName(root, outDir)} passes through a symbolic link`);
70
+ }
71
+ const ancestor = gtkxBuildAncestor(root, outDir);
72
+ if (ancestor !== null) {
73
+ throw new Error(`Build output ${outputName(root, outDir)} is nested inside the earlier GTKX build ` +
74
+ outputName(root, ancestor));
75
+ }
76
+ };
77
+ const nonReusableBuildOutputError = (root, outDir) => {
78
+ const stats = lstatSync(outDir, { throwIfNoEntry: false });
79
+ if (stats?.isDirectory() !== true) {
80
+ return new Error(`Build output ${outputName(root, outDir)} exists and is not a directory`);
81
+ }
82
+ const descendant = gtkxBuildDescendant(outDir);
83
+ if (descendant !== null) {
84
+ return new Error(`Build output ${outputName(root, outDir)} contains the earlier GTKX build ` +
85
+ outputName(root, descendant));
50
86
  }
87
+ return new Error(`Build output ${outputName(root, outDir)} is nonempty and is not an earlier GTKX build`);
51
88
  };
52
89
  const resolveBuildOutDir = (root, configured) => {
53
90
  const selected = configured ?? DEFAULT_BUILD_OUT_DIR;
54
91
  const outDir = resolve(root, selected);
55
92
  assertSafeBuildLocation(root, outDir);
56
93
  if (!isReusableBuildDirectory(outDir)) {
57
- throw buildOutputError(root);
94
+ throw nonReusableBuildOutputError(root, outDir);
58
95
  }
59
96
  return outDir;
60
97
  };
@@ -62,7 +99,7 @@ const prepareBuildOutDir = (root, outDir) => {
62
99
  assertSafeBuildLocation(root, outDir);
63
100
  const prepared = prepareOutputDirectory(root, outDir, isReusableBuildDirectory);
64
101
  if (prepared.status === "unsafe") {
65
- throw buildOutputError(root);
102
+ throw new Error(`Build output ${outputName(root, outDir)} became unsafe while preparing it`);
66
103
  }
67
104
  const transaction = prepared.transaction;
68
105
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"build-output.js","sourceRoot":"","sources":["../../src/internal/build-output.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPathInside, isRecord } from \"@gtkx/utils\";\nimport { lstatSync, readdirSync } from \"node:fs\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport {\n BUILD_MANIFEST_FILENAME,\n BUILD_MANIFEST_GENERATOR,\n} from \"./build-manifest.js\";\nimport {\n type OutputDirectoryTransaction,\n prepareOutputDirectory,\n readRegularFile,\n} from \"./output-directory.js\";\n\nconst DEFAULT_BUILD_OUT_DIR = \"dist\";\nconst PRESERVED_BUILD_ENTRIES: ReadonlySet<string> = new Set([\".git\"]);\n\ntype PreparedBuildOutDir = Disposable & { commit: () => void; path: string };\n\nconst hasSymlinkComponent = (root: string, target: string): boolean => {\n let current = root;\n\n for (const segment of relative(root, target).split(sep)) {\n current = join(current, segment);\n\n if (lstatSync(current, { throwIfNoEntry: false })?.isSymbolicLink() === true) {\n return true;\n }\n }\n\n return false;\n};\n\nconst isGtkxBuildDirectory = (path: string): boolean => {\n const manifest = join(path, BUILD_MANIFEST_FILENAME);\n const contents = readRegularFile(manifest);\n\n try {\n const parsed: unknown = contents === null ? null : JSON.parse(contents);\n\n return isRecord(parsed) && parsed.generator === BUILD_MANIFEST_GENERATOR;\n } catch {\n return false;\n }\n};\n\nconst isReusableBuildDirectory = (path: string): boolean => {\n const stats = lstatSync(path, { throwIfNoEntry: false });\n\n if (stats === undefined) {\n return true;\n }\n\n return stats.isDirectory() && (readdirSync(path).length === 0 || isGtkxBuildDirectory(path));\n};\n\nconst buildOutputError = (root: string): Error =>\n new Error(`Build output must be an empty directory or an earlier GTKX build below the project root ${root}`);\n\nconst hasGtkxBuildAncestor = (root: string, outDir: string): boolean => {\n let ancestor = dirname(outDir);\n\n while (isPathInside(root, ancestor)) {\n if (isGtkxBuildDirectory(ancestor)) {\n return true;\n }\n\n ancestor = dirname(ancestor);\n }\n\n return false;\n};\n\nconst assertSafeBuildLocation = (root: string, outDir: string): void => {\n if (!isPathInside(root, outDir) || hasSymlinkComponent(root, outDir) || hasGtkxBuildAncestor(root, outDir)) {\n throw buildOutputError(root);\n }\n};\n\nconst resolveBuildOutDir = (root: string, configured?: string): string => {\n const selected = configured ?? DEFAULT_BUILD_OUT_DIR;\n const outDir = resolve(root, selected);\n\n assertSafeBuildLocation(root, outDir);\n\n if (!isReusableBuildDirectory(outDir)) {\n throw buildOutputError(root);\n }\n\n return outDir;\n};\n\nconst prepareBuildOutDir = (root: string, outDir: string): PreparedBuildOutDir => {\n assertSafeBuildLocation(root, outDir);\n const prepared = prepareOutputDirectory(root, outDir, isReusableBuildDirectory);\n\n if (prepared.status === \"unsafe\") {\n throw buildOutputError(root);\n }\n\n const transaction: OutputDirectoryTransaction = prepared.transaction;\n\n return {\n path: transaction.path,\n commit: () => {\n transaction.commit(PRESERVED_BUILD_ENTRIES, isGtkxBuildDirectory);\n },\n [Symbol.dispose]: () => {\n transaction[Symbol.dispose]();\n },\n };\n};\n\nexport { prepareBuildOutDir, resolveBuildOutDir };\n"]}
1
+ {"version":3,"file":"build-output.js","sourceRoot":"","sources":["../../src/internal/build-output.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPathInside, isRecord } from \"@gtkx/utils\";\nimport { lstatSync, readdirSync } from \"node:fs\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport {\n BUILD_MANIFEST_FILENAME,\n BUILD_MANIFEST_GENERATOR,\n} from \"./build-manifest.js\";\nimport {\n type OutputDirectoryTransaction,\n prepareOutputDirectory,\n readRegularFile,\n} from \"./output-directory.js\";\n\nconst DEFAULT_BUILD_OUT_DIR = \"dist\";\nconst PRESERVED_BUILD_ENTRIES: ReadonlySet<string> = new Set([\".git\"]);\n\ntype PreparedBuildOutDir = Disposable & { commit: () => void; path: string };\n\nconst hasSymlinkComponent = (root: string, target: string): boolean => {\n let current = root;\n\n for (const segment of relative(root, target).split(sep)) {\n current = join(current, segment);\n\n if (lstatSync(current, { throwIfNoEntry: false })?.isSymbolicLink() === true) {\n return true;\n }\n }\n\n return false;\n};\n\nconst isGtkxBuildDirectory = (path: string): boolean => {\n const manifest = join(path, BUILD_MANIFEST_FILENAME);\n const contents = readRegularFile(manifest);\n\n try {\n const parsed: unknown = contents === null ? null : JSON.parse(contents);\n\n return isRecord(parsed) && parsed.generator === BUILD_MANIFEST_GENERATOR;\n } catch {\n return false;\n }\n};\n\nconst isReusableBuildDirectory = (path: string): boolean => {\n const stats = lstatSync(path, { throwIfNoEntry: false });\n\n if (stats === undefined) {\n return true;\n }\n\n return stats.isDirectory() && (readdirSync(path).length === 0 || isGtkxBuildDirectory(path));\n};\n\nconst outputName = (root: string, path: string): string => relative(root, path) || \".\";\n\nconst gtkxBuildAncestor = (root: string, outDir: string): string | null => {\n let ancestor = dirname(outDir);\n\n while (isPathInside(root, ancestor)) {\n if (isGtkxBuildDirectory(ancestor)) {\n return ancestor;\n }\n\n ancestor = dirname(ancestor);\n }\n\n return null;\n};\n\nconst childDirectories = (parent: string): string[] =>\n readdirSync(parent, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(parent, entry.name));\n\nconst gtkxBuildDescendant = (root: string): string | null => {\n const pending = childDirectories(root);\n\n while (pending.length > 0) {\n const path = pending.pop();\n\n if (path === undefined) {\n return null;\n }\n\n if (isGtkxBuildDirectory(path)) {\n return path;\n }\n\n pending.push(...childDirectories(path));\n }\n\n return null;\n};\n\nconst assertSafeBuildLocation = (root: string, outDir: string): void => {\n if (!isPathInside(root, outDir)) {\n throw new Error(`Build output ${outDir} must be below the project root ${root}`);\n }\n\n if (hasSymlinkComponent(root, outDir)) {\n throw new Error(`Build output ${outputName(root, outDir)} passes through a symbolic link`);\n }\n\n const ancestor = gtkxBuildAncestor(root, outDir);\n\n if (ancestor !== null) {\n throw new Error(\n `Build output ${outputName(root, outDir)} is nested inside the earlier GTKX build ` +\n outputName(root, ancestor),\n );\n }\n};\n\nconst nonReusableBuildOutputError = (root: string, outDir: string): Error => {\n const stats = lstatSync(outDir, { throwIfNoEntry: false });\n\n if (stats?.isDirectory() !== true) {\n return new Error(`Build output ${outputName(root, outDir)} exists and is not a directory`);\n }\n\n const descendant = gtkxBuildDescendant(outDir);\n\n if (descendant !== null) {\n return new Error(\n `Build output ${outputName(root, outDir)} contains the earlier GTKX build ` +\n outputName(root, descendant),\n );\n }\n\n return new Error(\n `Build output ${outputName(root, outDir)} is nonempty and is not an earlier GTKX build`,\n );\n};\n\nconst resolveBuildOutDir = (root: string, configured?: string): string => {\n const selected = configured ?? DEFAULT_BUILD_OUT_DIR;\n const outDir = resolve(root, selected);\n\n assertSafeBuildLocation(root, outDir);\n\n if (!isReusableBuildDirectory(outDir)) {\n throw nonReusableBuildOutputError(root, outDir);\n }\n\n return outDir;\n};\n\nconst prepareBuildOutDir = (root: string, outDir: string): PreparedBuildOutDir => {\n assertSafeBuildLocation(root, outDir);\n const prepared = prepareOutputDirectory(root, outDir, isReusableBuildDirectory);\n\n if (prepared.status === \"unsafe\") {\n throw new Error(`Build output ${outputName(root, outDir)} became unsafe while preparing it`);\n }\n\n const transaction: OutputDirectoryTransaction = prepared.transaction;\n\n return {\n path: transaction.path,\n commit: () => {\n transaction.commit(PRESERVED_BUILD_ENTRIES, isGtkxBuildDirectory);\n },\n [Symbol.dispose]: () => {\n transaction[Symbol.dispose]();\n },\n };\n};\n\nexport { prepareBuildOutDir, resolveBuildOutDir };\n"]}
@@ -8,6 +8,7 @@ type PreparedProject = {
8
8
  cwd: string;
9
9
  entry: string;
10
10
  configFile: string;
11
+ configDependencies: string[];
11
12
  };
12
13
  type ResolvedProject = PreparedProject & {
13
14
  context: CodegenContext;
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-project.d.ts","sourceRoot":"","sources":["../../src/internal/prepare-project.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAyB,MAAM,8BAA8B,CAAC;AAG1F,KAAK,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACrE,KAAK,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAC1E,KAAK,eAAe,GAAG,eAAe,GAAG;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC;AAErE,QAAA,MAAM,cAAc,GAAU,MAAM,WAAW,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,eAAe,CAKtF,CAAC;AAEF,QAAA,MAAM,cAAc,GAAU,MAAM,WAAW,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,eAAe,CAKtF,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"prepare-project.d.ts","sourceRoot":"","sources":["../../src/internal/prepare-project.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAyB,MAAM,8BAA8B,CAAC;AAG1F,KAAK,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACrE,KAAK,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AACxG,KAAK,eAAe,GAAG,eAAe,GAAG;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC;AAErE,QAAA,MAAM,cAAc,GAAU,MAAM,WAAW,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,eAAe,CAWtF,CAAC;AAEF,QAAA,MAAM,cAAc,GAAU,MAAM,WAAW,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,eAAe,CAKtF,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC"}
@@ -4,12 +4,18 @@ import { resolveCwd, resolveEntry } from "./entry-arg.js";
4
4
  const resolveProject = async (args, mode) => {
5
5
  const cwd = resolveCwd(args);
6
6
  const context = await resolveCodegenContext(cwd, mode, args.config);
7
- return { cwd, entry: resolveEntry(cwd, args.entry), configFile: context.configFile, context };
7
+ return {
8
+ cwd,
9
+ entry: resolveEntry(cwd, args.entry),
10
+ configFile: context.configFile,
11
+ configDependencies: context.configDependencies,
12
+ context,
13
+ };
8
14
  };
9
15
  const prepareProject = async (args, mode) => {
10
16
  const { cwd, entry, context } = await resolveProject(args, mode);
11
17
  await ensureGeneratedIn(context, { shouldAnnounce: true, mode });
12
- return { cwd, entry, configFile: context.configFile };
18
+ return { cwd, entry, configFile: context.configFile, configDependencies: context.configDependencies };
13
19
  };
14
20
  export { prepareProject, resolveProject };
15
21
  //# sourceMappingURL=prepare-project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-project.js","sourceRoot":"","sources":["../../src/internal/prepare-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAuB,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM1D,MAAM,cAAc,GAAG,KAAK,EAAE,IAAiB,EAAE,IAAY,EAA4B,EAAE;IACvF,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEpE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;AAClG,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAAE,IAAiB,EAAE,IAAY,EAA4B,EAAE;IACvF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjE,MAAM,iBAAiB,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;AAC1D,CAAC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC","sourcesContent":["import { ensureGeneratedIn } from \"../codegen/run-codegen.js\";\nimport { type CodegenContext, resolveCodegenContext } from \"../codegen/store-resolver.js\";\nimport { resolveCwd, resolveEntry } from \"./entry-arg.js\";\n\ntype ProjectArgs = { entry?: string; cwd?: string; config?: string };\ntype PreparedProject = { cwd: string; entry: string; configFile: string };\ntype ResolvedProject = PreparedProject & { context: CodegenContext };\n\nconst resolveProject = async (args: ProjectArgs, mode: string): Promise<ResolvedProject> => {\n const cwd = resolveCwd(args);\n const context = await resolveCodegenContext(cwd, mode, args.config);\n\n return { cwd, entry: resolveEntry(cwd, args.entry), configFile: context.configFile, context };\n};\n\nconst prepareProject = async (args: ProjectArgs, mode: string): Promise<PreparedProject> => {\n const { cwd, entry, context } = await resolveProject(args, mode);\n await ensureGeneratedIn(context, { shouldAnnounce: true, mode });\n\n return { cwd, entry, configFile: context.configFile };\n};\n\nexport { prepareProject, resolveProject };\n"]}
1
+ {"version":3,"file":"prepare-project.js","sourceRoot":"","sources":["../../src/internal/prepare-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAuB,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM1D,MAAM,cAAc,GAAG,KAAK,EAAE,IAAiB,EAAE,IAAY,EAA4B,EAAE;IACvF,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEpE,OAAO;QACH,GAAG;QACH,KAAK,EAAE,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC;QACpC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,OAAO;KACV,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAAE,IAAiB,EAAE,IAAY,EAA4B,EAAE;IACvF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjE,MAAM,iBAAiB,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,EAAE,CAAC;AAC1G,CAAC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC","sourcesContent":["import { ensureGeneratedIn } from \"../codegen/run-codegen.js\";\nimport { type CodegenContext, resolveCodegenContext } from \"../codegen/store-resolver.js\";\nimport { resolveCwd, resolveEntry } from \"./entry-arg.js\";\n\ntype ProjectArgs = { entry?: string; cwd?: string; config?: string };\ntype PreparedProject = { cwd: string; entry: string; configFile: string; configDependencies: string[] };\ntype ResolvedProject = PreparedProject & { context: CodegenContext };\n\nconst resolveProject = async (args: ProjectArgs, mode: string): Promise<ResolvedProject> => {\n const cwd = resolveCwd(args);\n const context = await resolveCodegenContext(cwd, mode, args.config);\n\n return {\n cwd,\n entry: resolveEntry(cwd, args.entry),\n configFile: context.configFile,\n configDependencies: context.configDependencies,\n context,\n };\n};\n\nconst prepareProject = async (args: ProjectArgs, mode: string): Promise<PreparedProject> => {\n const { cwd, entry, context } = await resolveProject(args, mode);\n await ensureGeneratedIn(context, { shouldAnnounce: true, mode });\n\n return { cwd, entry, configFile: context.configFile, configDependencies: context.configDependencies };\n};\n\nexport { prepareProject, resolveProject };\n"]}
@@ -1,5 +1,14 @@
1
1
  import type { ConfigLoader } from "@gtkx/config";
2
2
  import type { Plugin } from "vite";
3
- declare const gtkxI18n: (entryPath: string, loadConfig?: ConfigLoader, shouldPreserveMetadataMessages?: boolean) => Plugin;
4
- export { gtkxI18n };
3
+ import { type WrittenCatalog } from "../i18n/catalogs.js";
4
+ type CatalogWriteListener = (catalogs: WrittenCatalog[]) => void;
5
+ type I18nPluginOptions = {
6
+ entryPath: string;
7
+ loadConfig?: ConfigLoader | undefined;
8
+ onCatalogsWritten?: CatalogWriteListener | undefined;
9
+ shouldPreserveMetadataMessages?: boolean | undefined;
10
+ shouldRecoverExtractionErrors?: boolean | undefined;
11
+ };
12
+ declare const gtkxI18n: ({ entryPath, loadConfig, onCatalogsWritten, shouldPreserveMetadataMessages, shouldRecoverExtractionErrors, }: I18nPluginOptions) => Plugin;
13
+ export { type CatalogWriteListener, gtkxI18n };
5
14
  //# sourceMappingURL=i18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/vite-plugins/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAyKnD,QAAA,MAAM,QAAQ,GACV,WAAW,MAAM,EACjB,aAAY,YAAmC,EAC/C,wCAAqC,KACtC,MAgDF,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/vite-plugins/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAMnD,OAAO,EAMH,KAAK,cAAc,EACtB,MAAM,qBAAqB,CAAC;AAM7B,KAAK,oBAAoB,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;AAEjE,KAAK,iBAAiB,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACtC,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACrD,8BAA8B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrD,6BAA6B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvD,CAAC;AA0KF,QAAA,MAAM,QAAQ,GAAI,8GAMf,iBAAiB,KAAG,MAmDtB,CAAC;AAEF,OAAO,EAAE,KAAK,oBAAoB,EAAE,QAAQ,EAAE,CAAC"}
@@ -4,7 +4,7 @@ import { existsSync, mkdirSync } from "node:fs";
4
4
  import { createRequire } from "node:module";
5
5
  import { dirname, join, posix, relative, resolve } from "node:path";
6
6
  import { compileCatalogs, LOCALE_DIRNAME, resolveCatalogProject, synchronizeCatalogs, } from "../i18n/catalogs.js";
7
- import { extractSourceCatalog } from "../i18n/source-messages.js";
7
+ import { extractSourceCatalog, SourceExtractionError } from "../i18n/source-messages.js";
8
8
  import { emitI18nTypes } from "../i18n/types.js";
9
9
  import { discoverSourceFiles, sourceLanguage } from "../internal/source-imports.js";
10
10
  import { stripQuery } from "./strip-query.js";
@@ -61,7 +61,7 @@ const extractProjectMessages = async (state, shouldPreserveMetadataMessages, sho
61
61
  const sourceFiles = discoverSourceFiles(existsSync(srcDir) ? srcDir : project.root);
62
62
  await extractSourceCatalog(project, sourceFiles, shouldPreserveMetadataMessages);
63
63
  if (shouldSynchronizeCatalogs) {
64
- synchronizeCatalogs(project);
64
+ state.onCatalogsWritten(synchronizeCatalogs(project));
65
65
  }
66
66
  await emitI18nTypes(project.root);
67
67
  };
@@ -91,15 +91,26 @@ const isProjectSource = (state, path) => {
91
91
  const sourceRoot = existsSync(srcDir) ? srcDir : project.root;
92
92
  return isPathWithin(sourceRoot, path);
93
93
  };
94
- const refreshProjectMessages = async (state, shouldPreserveMetadataMessages) => {
94
+ const refreshProjectMessages = async (state, shouldPreserveMetadataMessages, shouldSynchronizeCatalogs = false) => {
95
95
  try {
96
- await queueExtraction(state, shouldPreserveMetadataMessages, false);
96
+ await queueExtraction(state, shouldPreserveMetadataMessages, shouldSynchronizeCatalogs);
97
97
  }
98
98
  catch (error) {
99
99
  logger.error(error instanceof Error ? error.message : String(error));
100
100
  }
101
101
  };
102
- const gtkxI18n = (entryPath, loadConfig = createConfigLoader(), shouldPreserveMetadataMessages = true) => {
102
+ const recoverInitialSourceExtraction = async (state, shouldPreserveMetadataMessages) => {
103
+ try {
104
+ await queueExtraction(state, shouldPreserveMetadataMessages, true);
105
+ }
106
+ catch (error) {
107
+ if (!(error instanceof SourceExtractionError)) {
108
+ throw error;
109
+ }
110
+ logger.error(error.message);
111
+ }
112
+ };
113
+ const gtkxI18n = ({ entryPath, loadConfig = createConfigLoader(), onCatalogsWritten = () => undefined, shouldPreserveMetadataMessages = true, shouldRecoverExtractionErrors = false, }) => {
103
114
  const state = {
104
115
  entryPath,
105
116
  extraction: Promise.resolve(),
@@ -107,12 +118,15 @@ const gtkxI18n = (entryPath, loadConfig = createConfigLoader(), shouldPreserveMe
107
118
  i18nRoot: "",
108
119
  outDir: "",
109
120
  project: null,
121
+ onCatalogsWritten,
110
122
  };
111
123
  return {
112
124
  name: "gtkx:i18n",
113
125
  enforce: "pre",
114
126
  configResolved: (config) => applyResolvedConfig(state, config, loadConfig),
115
- buildStart: () => queueExtraction(state, shouldPreserveMetadataMessages, true),
127
+ buildStart: () => shouldRecoverExtractionErrors
128
+ ? recoverInitialSourceExtraction(state, shouldPreserveMetadataMessages)
129
+ : queueExtraction(state, shouldPreserveMetadataMessages, true),
116
130
  hotUpdate(options) {
117
131
  if (!isProjectSource(state, options.file) || state.hotUpdateTimestamp === options.timestamp) {
118
132
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/vite-plugins/i18n.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConfigLoader } from \"@gtkx/config\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\nimport { createConfigLoader } from \"@gtkx/config/internal\";\nimport { isPathWithin, logger, toPosixPath } from \"@gtkx/utils\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, posix, relative, resolve } from \"node:path\";\nimport {\n type CatalogProject,\n compileCatalogs,\n LOCALE_DIRNAME,\n resolveCatalogProject,\n synchronizeCatalogs,\n} from \"../i18n/catalogs.js\";\nimport { extractSourceCatalog } from \"../i18n/source-messages.js\";\nimport { emitI18nTypes } from \"../i18n/types.js\";\nimport { discoverSourceFiles, sourceLanguage } from \"../internal/source-imports.js\";\nimport { stripQuery } from \"./strip-query.js\";\n\ntype I18nState = {\n entryPath: string;\n i18nRoot: string;\n outDir: string;\n project: CatalogProject | null;\n extraction: Promise<void>;\n hotUpdateTimestamp: number | null;\n};\n\nconst BOOTSTRAP_SPECIFIER = \"@gtkx/i18n/bootstrap\";\nconst LOCALE_URL_PLACEHOLDER = \"__GTKX_BUNDLE_LOCALE_DIR__\";\nconst LOCALE_MODULE_PATHS = new Set([\"dist/locale.js\", \"src/locale.ts\"]);\nconst LOCALE_URL_PATTERN = /new URL\\(([\"'])locale\\1,\\s*import\\.meta\\.url\\)/;\n\nconst isI18nLocaleModule = (state: I18nState, id: string): boolean => {\n if (state.i18nRoot.length === 0) {\n return false;\n }\n\n const path = toPosixPath(relative(state.i18nRoot, stripQuery(id)));\n\n return LOCALE_MODULE_PATHS.has(path);\n};\n\nconst markLocaleUrl = (code: string): string =>\n code.replace(\n LOCALE_URL_PATTERN,\n () => `new URL(${JSON.stringify(LOCALE_URL_PLACEHOLDER)}, import.meta.url)`,\n );\n\nconst localeUrlForChunk = (fileName: string): string => {\n const path = posix.relative(posix.dirname(fileName), LOCALE_DIRNAME);\n\n return path.length === 0 ? \".\" : path;\n};\n\nconst rebaseLocaleUrl = (state: I18nState, code: string, fileName: string, moduleIds: string[]): string | null => {\n if (moduleIds.every((id) => !isI18nLocaleModule(state, id))) {\n return null;\n }\n\n const placeholder = JSON.stringify(LOCALE_URL_PLACEHOLDER);\n\n if (!code.includes(placeholder)) {\n throw new Error(`Unable to locate the @gtkx/i18n locale fallback in ${fileName}`);\n }\n\n return code.replace(placeholder, () => JSON.stringify(localeUrlForChunk(fileName)));\n};\n\nconst applyResolvedConfig = async (\n state: I18nState,\n config: ResolvedConfig,\n loadConfig: ConfigLoader,\n): Promise<void> => {\n state.entryPath = resolve(config.root, state.entryPath);\n state.outDir = resolve(config.root, config.build.outDir);\n const application = await loadConfig.resolve(config.root);\n state.project = resolveCatalogProject(config.root, application.applicationId);\n\n if (state.project !== null) {\n const projectRequire = createRequire(resolve(config.root, \"package.json\"));\n state.i18nRoot = dirname(projectRequire.resolve(\"@gtkx/i18n/package.json\"));\n }\n};\n\nconst buildCatalogs = (state: I18nState): void => {\n const project = state.project;\n\n if (project === null) {\n return;\n }\n\n mkdirSync(state.outDir, { recursive: true });\n compileCatalogs(project, resolve(state.outDir, LOCALE_DIRNAME));\n};\n\nconst extractProjectMessages = async (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n shouldSynchronizeCatalogs: boolean,\n): Promise<void> => {\n const project = state.project;\n\n if (project === null) {\n return;\n }\n\n const srcDir = join(project.root, \"src\");\n const sourceFiles = discoverSourceFiles(existsSync(srcDir) ? srcDir : project.root);\n await extractSourceCatalog(project, sourceFiles, shouldPreserveMetadataMessages);\n\n if (shouldSynchronizeCatalogs) {\n synchronizeCatalogs(project);\n }\n\n await emitI18nTypes(project.root);\n};\n\nconst settleExtraction = async (pending: Promise<void>): Promise<void> => {\n try {\n await pending;\n } catch {\n return;\n }\n};\n\nconst queueExtraction = (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n shouldSynchronizeCatalogs: boolean,\n): Promise<void> => {\n const prior = state.extraction;\n const pending = (async (): Promise<void> => {\n await settleExtraction(prior);\n await extractProjectMessages(\n state,\n shouldPreserveMetadataMessages,\n shouldSynchronizeCatalogs,\n );\n })();\n\n state.extraction = pending;\n\n return pending;\n};\n\nconst isProjectSource = (state: I18nState, path: string): boolean => {\n const project = state.project;\n\n if (project === null || sourceLanguage(path) === undefined) {\n return false;\n }\n\n const srcDir = join(project.root, \"src\");\n const sourceRoot = existsSync(srcDir) ? srcDir : project.root;\n\n return isPathWithin(sourceRoot, path);\n};\n\nconst refreshProjectMessages = async (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n): Promise<void> => {\n try {\n await queueExtraction(state, shouldPreserveMetadataMessages, false);\n } catch (error) {\n logger.error(error instanceof Error ? error.message : String(error));\n }\n};\n\nconst gtkxI18n = (\n entryPath: string,\n loadConfig: ConfigLoader = createConfigLoader(),\n shouldPreserveMetadataMessages = true,\n): Plugin => {\n const state: I18nState = {\n entryPath,\n extraction: Promise.resolve(),\n hotUpdateTimestamp: null,\n i18nRoot: \"\",\n outDir: \"\",\n project: null,\n };\n\n return {\n name: \"gtkx:i18n\",\n enforce: \"pre\",\n\n configResolved: (config) => applyResolvedConfig(state, config, loadConfig),\n\n buildStart: () => queueExtraction(state, shouldPreserveMetadataMessages, true),\n\n hotUpdate(options) {\n if (!isProjectSource(state, options.file) || state.hotUpdateTimestamp === options.timestamp) {\n return;\n }\n\n state.hotUpdateTimestamp = options.timestamp;\n\n return refreshProjectMessages(state, shouldPreserveMetadataMessages);\n },\n\n transform(code, id) {\n if (isI18nLocaleModule(state, id)) {\n return markLocaleUrl(code);\n }\n\n if (state.project === null || resolve(stripQuery(id)) !== state.entryPath) {\n return;\n }\n\n return `import ${JSON.stringify(BOOTSTRAP_SPECIFIER)};\\n${code}`;\n },\n\n renderChunk(code, chunk) {\n return rebaseLocaleUrl(state, code, chunk.fileName, chunk.moduleIds);\n },\n\n generateBundle() {\n buildCatalogs(state);\n },\n };\n};\n\nexport { gtkxI18n };\n"]}
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/vite-plugins/i18n.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAEH,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,mBAAmB,GAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAsB9C,MAAM,mBAAmB,GAAG,sBAAsB,CAAC;AACnD,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AAC5D,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAC;AACzE,MAAM,kBAAkB,GAAG,gDAAgD,CAAC;AAE5E,MAAM,kBAAkB,GAAG,CAAC,KAAgB,EAAE,EAAU,EAAW,EAAE;IACjE,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEnE,OAAO,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,IAAY,EAAU,EAAE,CAC3C,IAAI,CAAC,OAAO,CACR,kBAAkB,EAClB,GAAG,EAAE,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,oBAAoB,CAC9E,CAAC;AAEN,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACnD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAC;IAErE,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,KAAgB,EAAE,IAAY,EAAE,QAAgB,EAAE,SAAmB,EAAiB,EAAE;IAC7G,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAE3D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sDAAsD,QAAQ,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxF,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,EAC7B,KAAgB,EAChB,MAAsB,EACtB,UAAwB,EACX,EAAE;IACf,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACxD,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1D,KAAK,CAAC,OAAO,GAAG,qBAAqB,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IAE9E,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;QAC3E,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAChF,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,KAAgB,EAAQ,EAAE;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IAED,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAChC,KAAgB,EAChB,8BAAuC,EACvC,yBAAkC,EACrB,EAAE;IACf,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,MAAM,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,8BAA8B,CAAC,CAAC;IAEjF,IAAI,yBAAyB,EAAE,CAAC;QAC5B,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAsB,EAAiB,EAAE;IACrE,IAAI,CAAC;QACD,MAAM,OAAO,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO;IACX,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CACpB,KAAgB,EAChB,8BAAuC,EACvC,yBAAkC,EACrB,EAAE;IACf,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;IAC/B,MAAM,OAAO,GAAG,CAAC,KAAK,IAAmB,EAAE;QACvC,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,sBAAsB,CACxB,KAAK,EACL,8BAA8B,EAC9B,yBAAyB,CAC5B,CAAC;IACN,CAAC,CAAC,EAAE,CAAC;IAEL,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC;IAE3B,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,KAAgB,EAAE,IAAY,EAAW,EAAE;IAChE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,IAAI,OAAO,KAAK,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IAE9D,OAAO,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAChC,KAAgB,EAChB,8BAAuC,EACvC,yBAAyB,GAAG,KAAK,EACpB,EAAE;IACf,IAAI,CAAC;QACD,MAAM,eAAe,CAAC,KAAK,EAAE,8BAA8B,EAAE,yBAAyB,CAAC,CAAC;IAC5F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzE,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,8BAA8B,GAAG,KAAK,EACxC,KAAgB,EAChB,8BAAuC,EAC1B,EAAE;IACf,IAAI,CAAC;QACD,MAAM,eAAe,CAAC,KAAK,EAAE,8BAA8B,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,KAAK,YAAY,qBAAqB,CAAC,EAAE,CAAC;YAC5C,MAAM,KAAK,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,EACd,SAAS,EACT,UAAU,GAAG,kBAAkB,EAAE,EACjC,iBAAiB,GAAG,GAAS,EAAE,CAAC,SAAS,EACzC,8BAA8B,GAAG,IAAI,EACrC,6BAA6B,GAAG,KAAK,GACrB,EAAU,EAAE;IAC5B,MAAM,KAAK,GAAc;QACrB,SAAS;QACT,UAAU,EAAE,OAAO,CAAC,OAAO,EAAE;QAC7B,kBAAkB,EAAE,IAAI;QACxB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,IAAI;QACb,iBAAiB;KACpB,CAAC;IAEF,OAAO;QACH,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,KAAK;QAEd,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC;QAE1E,UAAU,EAAE,GAAG,EAAE,CAAC,6BAA6B;YAC3C,CAAC,CAAC,8BAA8B,CAAC,KAAK,EAAE,8BAA8B,CAAC;YACvE,CAAC,CAAC,eAAe,CAAC,KAAK,EAAE,8BAA8B,EAAE,IAAI,CAAC;QAElE,SAAS,CAAC,OAAO;YACb,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,kBAAkB,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;gBAC1F,OAAO;YACX,CAAC;YAED,KAAK,CAAC,kBAAkB,GAAG,OAAO,CAAC,SAAS,CAAC;YAE7C,OAAO,sBAAsB,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAAC;QACzE,CAAC;QAED,SAAS,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;gBAChC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;gBACxE,OAAO;YACX,CAAC;YAED,OAAO,UAAU,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,MAAM,IAAI,EAAE,CAAC;QACrE,CAAC;QAED,WAAW,CAAC,IAAI,EAAE,KAAK;YACnB,OAAO,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACzE,CAAC;QAED,cAAc;YACV,aAAa,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAA6B,QAAQ,EAAE,CAAC","sourcesContent":["import type { ConfigLoader } from \"@gtkx/config\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\nimport { createConfigLoader } from \"@gtkx/config/internal\";\nimport { isPathWithin, logger, toPosixPath } from \"@gtkx/utils\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, posix, relative, resolve } from \"node:path\";\nimport {\n type CatalogProject,\n compileCatalogs,\n LOCALE_DIRNAME,\n resolveCatalogProject,\n synchronizeCatalogs,\n type WrittenCatalog,\n} from \"../i18n/catalogs.js\";\nimport { extractSourceCatalog, SourceExtractionError } from \"../i18n/source-messages.js\";\nimport { emitI18nTypes } from \"../i18n/types.js\";\nimport { discoverSourceFiles, sourceLanguage } from \"../internal/source-imports.js\";\nimport { stripQuery } from \"./strip-query.js\";\n\ntype CatalogWriteListener = (catalogs: WrittenCatalog[]) => void;\n\ntype I18nPluginOptions = {\n entryPath: string;\n loadConfig?: ConfigLoader | undefined;\n onCatalogsWritten?: CatalogWriteListener | undefined;\n shouldPreserveMetadataMessages?: boolean | undefined;\n shouldRecoverExtractionErrors?: boolean | undefined;\n};\n\ntype I18nState = {\n entryPath: string;\n i18nRoot: string;\n outDir: string;\n project: CatalogProject | null;\n extraction: Promise<void>;\n hotUpdateTimestamp: number | null;\n onCatalogsWritten: CatalogWriteListener;\n};\n\nconst BOOTSTRAP_SPECIFIER = \"@gtkx/i18n/bootstrap\";\nconst LOCALE_URL_PLACEHOLDER = \"__GTKX_BUNDLE_LOCALE_DIR__\";\nconst LOCALE_MODULE_PATHS = new Set([\"dist/locale.js\", \"src/locale.ts\"]);\nconst LOCALE_URL_PATTERN = /new URL\\(([\"'])locale\\1,\\s*import\\.meta\\.url\\)/;\n\nconst isI18nLocaleModule = (state: I18nState, id: string): boolean => {\n if (state.i18nRoot.length === 0) {\n return false;\n }\n\n const path = toPosixPath(relative(state.i18nRoot, stripQuery(id)));\n\n return LOCALE_MODULE_PATHS.has(path);\n};\n\nconst markLocaleUrl = (code: string): string =>\n code.replace(\n LOCALE_URL_PATTERN,\n () => `new URL(${JSON.stringify(LOCALE_URL_PLACEHOLDER)}, import.meta.url)`,\n );\n\nconst localeUrlForChunk = (fileName: string): string => {\n const path = posix.relative(posix.dirname(fileName), LOCALE_DIRNAME);\n\n return path.length === 0 ? \".\" : path;\n};\n\nconst rebaseLocaleUrl = (state: I18nState, code: string, fileName: string, moduleIds: string[]): string | null => {\n if (moduleIds.every((id) => !isI18nLocaleModule(state, id))) {\n return null;\n }\n\n const placeholder = JSON.stringify(LOCALE_URL_PLACEHOLDER);\n\n if (!code.includes(placeholder)) {\n throw new Error(`Unable to locate the @gtkx/i18n locale fallback in ${fileName}`);\n }\n\n return code.replace(placeholder, () => JSON.stringify(localeUrlForChunk(fileName)));\n};\n\nconst applyResolvedConfig = async (\n state: I18nState,\n config: ResolvedConfig,\n loadConfig: ConfigLoader,\n): Promise<void> => {\n state.entryPath = resolve(config.root, state.entryPath);\n state.outDir = resolve(config.root, config.build.outDir);\n const application = await loadConfig.resolve(config.root);\n state.project = resolveCatalogProject(config.root, application.applicationId);\n\n if (state.project !== null) {\n const projectRequire = createRequire(resolve(config.root, \"package.json\"));\n state.i18nRoot = dirname(projectRequire.resolve(\"@gtkx/i18n/package.json\"));\n }\n};\n\nconst buildCatalogs = (state: I18nState): void => {\n const project = state.project;\n\n if (project === null) {\n return;\n }\n\n mkdirSync(state.outDir, { recursive: true });\n compileCatalogs(project, resolve(state.outDir, LOCALE_DIRNAME));\n};\n\nconst extractProjectMessages = async (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n shouldSynchronizeCatalogs: boolean,\n): Promise<void> => {\n const project = state.project;\n\n if (project === null) {\n return;\n }\n\n const srcDir = join(project.root, \"src\");\n const sourceFiles = discoverSourceFiles(existsSync(srcDir) ? srcDir : project.root);\n await extractSourceCatalog(project, sourceFiles, shouldPreserveMetadataMessages);\n\n if (shouldSynchronizeCatalogs) {\n state.onCatalogsWritten(synchronizeCatalogs(project));\n }\n\n await emitI18nTypes(project.root);\n};\n\nconst settleExtraction = async (pending: Promise<void>): Promise<void> => {\n try {\n await pending;\n } catch {\n return;\n }\n};\n\nconst queueExtraction = (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n shouldSynchronizeCatalogs: boolean,\n): Promise<void> => {\n const prior = state.extraction;\n const pending = (async (): Promise<void> => {\n await settleExtraction(prior);\n await extractProjectMessages(\n state,\n shouldPreserveMetadataMessages,\n shouldSynchronizeCatalogs,\n );\n })();\n\n state.extraction = pending;\n\n return pending;\n};\n\nconst isProjectSource = (state: I18nState, path: string): boolean => {\n const project = state.project;\n\n if (project === null || sourceLanguage(path) === undefined) {\n return false;\n }\n\n const srcDir = join(project.root, \"src\");\n const sourceRoot = existsSync(srcDir) ? srcDir : project.root;\n\n return isPathWithin(sourceRoot, path);\n};\n\nconst refreshProjectMessages = async (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n shouldSynchronizeCatalogs = false,\n): Promise<void> => {\n try {\n await queueExtraction(state, shouldPreserveMetadataMessages, shouldSynchronizeCatalogs);\n } catch (error) {\n logger.error(error instanceof Error ? error.message : String(error));\n }\n};\n\nconst recoverInitialSourceExtraction = async (\n state: I18nState,\n shouldPreserveMetadataMessages: boolean,\n): Promise<void> => {\n try {\n await queueExtraction(state, shouldPreserveMetadataMessages, true);\n } catch (error) {\n if (!(error instanceof SourceExtractionError)) {\n throw error;\n }\n\n logger.error(error.message);\n }\n};\n\nconst gtkxI18n = ({\n entryPath,\n loadConfig = createConfigLoader(),\n onCatalogsWritten = (): void => undefined,\n shouldPreserveMetadataMessages = true,\n shouldRecoverExtractionErrors = false,\n}: I18nPluginOptions): Plugin => {\n const state: I18nState = {\n entryPath,\n extraction: Promise.resolve(),\n hotUpdateTimestamp: null,\n i18nRoot: \"\",\n outDir: \"\",\n project: null,\n onCatalogsWritten,\n };\n\n return {\n name: \"gtkx:i18n\",\n enforce: \"pre\",\n\n configResolved: (config) => applyResolvedConfig(state, config, loadConfig),\n\n buildStart: () => shouldRecoverExtractionErrors\n ? recoverInitialSourceExtraction(state, shouldPreserveMetadataMessages)\n : queueExtraction(state, shouldPreserveMetadataMessages, true),\n\n hotUpdate(options) {\n if (!isProjectSource(state, options.file) || state.hotUpdateTimestamp === options.timestamp) {\n return;\n }\n\n state.hotUpdateTimestamp = options.timestamp;\n\n return refreshProjectMessages(state, shouldPreserveMetadataMessages);\n },\n\n transform(code, id) {\n if (isI18nLocaleModule(state, id)) {\n return markLocaleUrl(code);\n }\n\n if (state.project === null || resolve(stripQuery(id)) !== state.entryPath) {\n return;\n }\n\n return `import ${JSON.stringify(BOOTSTRAP_SPECIFIER)};\\n${code}`;\n },\n\n renderChunk(code, chunk) {\n return rebaseLocaleUrl(state, code, chunk.fileName, chunk.moduleIds);\n },\n\n generateBundle() {\n buildCatalogs(state);\n },\n };\n};\n\nexport { type CatalogWriteListener, gtkxI18n };\n"]}
@@ -1,10 +1,12 @@
1
1
  import type { Plugin } from "vite";
2
2
  import type { BuildManifestCollector } from "../internal/build-manifest.js";
3
+ import { type CatalogWriteListener } from "./i18n.js";
3
4
  type GtkxVitePluginOptions = {
4
5
  buildManifest?: BuildManifestCollector | undefined;
5
6
  configFile?: string | undefined;
6
7
  entryPath?: string | undefined;
7
8
  mode?: string | undefined;
9
+ onCatalogsWritten?: CatalogWriteListener | undefined;
8
10
  shouldPreserveI18nMetadata?: boolean | undefined;
9
11
  };
10
12
  declare const gtkxVitePlugins: (options?: GtkxVitePluginOptions) => Plugin[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite-plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAY5E,KAAK,qBAAqB,GAAG;IACzB,aAAa,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,UAAS,qBAA0B,KAAG,MAAM,EAoBpE,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite-plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAI5E,OAAO,EAAE,KAAK,oBAAoB,EAAY,MAAM,WAAW,CAAC;AAQhE,KAAK,qBAAqB,GAAG;IACzB,aAAa,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACrD,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,UAAS,qBAA0B,KAAG,MAAM,EAmCpE,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -11,14 +11,22 @@ import { gtkxSettings } from "./settings.js";
11
11
  import { gtkxStoreLinks } from "./store-links.js";
12
12
  import { gtkxUndeclaredLibrary } from "./undeclared-library.js";
13
13
  const gtkxVitePlugins = (options = {}) => {
14
- const { buildManifest, configFile, entryPath, mode, shouldPreserveI18nMetadata = true } = options;
14
+ const { buildManifest, configFile, entryPath, mode, onCatalogsWritten, shouldPreserveI18nMetadata = true, } = options;
15
15
  const loadConfig = createConfigLoader({
16
16
  ...(mode !== undefined && { mode }),
17
17
  ...(configFile !== undefined && { configFile }),
18
18
  });
19
19
  return [
20
20
  createConfigPlugin({ name: "gtkx:config", loadConfig }),
21
- ...(entryPath === undefined ? [] : [gtkxI18n(entryPath, loadConfig, shouldPreserveI18nMetadata)]),
21
+ ...(entryPath === undefined
22
+ ? []
23
+ : [gtkxI18n({
24
+ entryPath,
25
+ loadConfig,
26
+ onCatalogsWritten,
27
+ shouldPreserveMetadataMessages: shouldPreserveI18nMetadata,
28
+ shouldRecoverExtractionErrors: mode === "development",
29
+ })]),
22
30
  gtkxStoreLinks(),
23
31
  gtkxUndeclaredLibrary(loadConfig),
24
32
  gtkxSettings(buildManifest),
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite-plugins/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAUhE,MAAM,eAAe,GAAG,CAAC,UAAiC,EAAE,EAAY,EAAE;IACtE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,0BAA0B,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAClG,MAAM,UAAU,GAAG,kBAAkB,CAAC;QAClC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;QACnC,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,OAAO;QACH,kBAAkB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;QACvD,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC,CAAC;QACjG,cAAc,EAAE;QAChB,qBAAqB,CAAC,UAAU,CAAC;QACjC,YAAY,CAAC,aAAa,CAAC;QAC3B,SAAS,CAAC,UAAU,CAAC;QACrB,gBAAgB,EAAE;QAClB,YAAY,EAAE;QACd,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC;QACpC,OAAO,EAAE;QACT,iBAAiB,CAAC,UAAU,CAAC;KAChC,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import type { Plugin } from \"vite\";\nimport { createConfigLoader } from \"@gtkx/config/internal\";\nimport createConfigPlugin from \"@gtkx/config/vite-plugin\";\nimport type { BuildManifestCollector } from \"../internal/build-manifest.js\";\nimport { gtkxAssetImports } from \"./asset-imports.js\";\nimport { gtkxBuiltUrl } from \"./built-url.js\";\nimport { gtkxCss } from \"./css.js\";\nimport { gtkxI18n } from \"./i18n.js\";\nimport { gtkxIcons } from \"./icons.js\";\nimport { gtkxReactCompiler } from \"./react-compiler.js\";\nimport { gtkxResources } from \"./resources.js\";\nimport { gtkxSettings } from \"./settings.js\";\nimport { gtkxStoreLinks } from \"./store-links.js\";\nimport { gtkxUndeclaredLibrary } from \"./undeclared-library.js\";\n\ntype GtkxVitePluginOptions = {\n buildManifest?: BuildManifestCollector | undefined;\n configFile?: string | undefined;\n entryPath?: string | undefined;\n mode?: string | undefined;\n shouldPreserveI18nMetadata?: boolean | undefined;\n};\n\nconst gtkxVitePlugins = (options: GtkxVitePluginOptions = {}): Plugin[] => {\n const { buildManifest, configFile, entryPath, mode, shouldPreserveI18nMetadata = true } = options;\n const loadConfig = createConfigLoader({\n ...(mode !== undefined && { mode }),\n ...(configFile !== undefined && { configFile }),\n });\n\n return [\n createConfigPlugin({ name: \"gtkx:config\", loadConfig }),\n ...(entryPath === undefined ? [] : [gtkxI18n(entryPath, loadConfig, shouldPreserveI18nMetadata)]),\n gtkxStoreLinks(),\n gtkxUndeclaredLibrary(loadConfig),\n gtkxSettings(buildManifest),\n gtkxIcons(loadConfig),\n gtkxAssetImports(),\n gtkxBuiltUrl(),\n gtkxResources(loadConfig, entryPath),\n gtkxCss(),\n gtkxReactCompiler(loadConfig),\n ];\n};\n\nexport { gtkxVitePlugins };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite-plugins/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAA6B,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAWhE,MAAM,eAAe,GAAG,CAAC,UAAiC,EAAE,EAAY,EAAE;IACtE,MAAM,EACF,aAAa,EACb,UAAU,EACV,SAAS,EACT,IAAI,EACJ,iBAAiB,EACjB,0BAA0B,GAAG,IAAI,GACpC,GAAG,OAAO,CAAC;IACZ,MAAM,UAAU,GAAG,kBAAkB,CAAC;QAClC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;QACnC,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,OAAO;QACH,kBAAkB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;QACvD,GAAG,CAAC,SAAS,KAAK,SAAS;YACvB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,QAAQ,CAAC;oBACJ,SAAS;oBACT,UAAU;oBACV,iBAAiB;oBACjB,8BAA8B,EAAE,0BAA0B;oBAC1D,6BAA6B,EAAE,IAAI,KAAK,aAAa;iBACxD,CAAC,CAAC,CAAC;QACZ,cAAc,EAAE;QAChB,qBAAqB,CAAC,UAAU,CAAC;QACjC,YAAY,CAAC,aAAa,CAAC;QAC3B,SAAS,CAAC,UAAU,CAAC;QACrB,gBAAgB,EAAE;QAClB,YAAY,EAAE;QACd,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC;QACpC,OAAO,EAAE;QACT,iBAAiB,CAAC,UAAU,CAAC;KAChC,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import type { Plugin } from \"vite\";\nimport { createConfigLoader } from \"@gtkx/config/internal\";\nimport createConfigPlugin from \"@gtkx/config/vite-plugin\";\nimport type { BuildManifestCollector } from \"../internal/build-manifest.js\";\nimport { gtkxAssetImports } from \"./asset-imports.js\";\nimport { gtkxBuiltUrl } from \"./built-url.js\";\nimport { gtkxCss } from \"./css.js\";\nimport { type CatalogWriteListener, gtkxI18n } from \"./i18n.js\";\nimport { gtkxIcons } from \"./icons.js\";\nimport { gtkxReactCompiler } from \"./react-compiler.js\";\nimport { gtkxResources } from \"./resources.js\";\nimport { gtkxSettings } from \"./settings.js\";\nimport { gtkxStoreLinks } from \"./store-links.js\";\nimport { gtkxUndeclaredLibrary } from \"./undeclared-library.js\";\n\ntype GtkxVitePluginOptions = {\n buildManifest?: BuildManifestCollector | undefined;\n configFile?: string | undefined;\n entryPath?: string | undefined;\n mode?: string | undefined;\n onCatalogsWritten?: CatalogWriteListener | undefined;\n shouldPreserveI18nMetadata?: boolean | undefined;\n};\n\nconst gtkxVitePlugins = (options: GtkxVitePluginOptions = {}): Plugin[] => {\n const {\n buildManifest,\n configFile,\n entryPath,\n mode,\n onCatalogsWritten,\n shouldPreserveI18nMetadata = true,\n } = options;\n const loadConfig = createConfigLoader({\n ...(mode !== undefined && { mode }),\n ...(configFile !== undefined && { configFile }),\n });\n\n return [\n createConfigPlugin({ name: \"gtkx:config\", loadConfig }),\n ...(entryPath === undefined\n ? []\n : [gtkxI18n({\n entryPath,\n loadConfig,\n onCatalogsWritten,\n shouldPreserveMetadataMessages: shouldPreserveI18nMetadata,\n shouldRecoverExtractionErrors: mode === \"development\",\n })]),\n gtkxStoreLinks(),\n gtkxUndeclaredLibrary(loadConfig),\n gtkxSettings(buildManifest),\n gtkxIcons(loadConfig),\n gtkxAssetImports(),\n gtkxBuiltUrl(),\n gtkxResources(loadConfig, entryPath),\n gtkxCss(),\n gtkxReactCompiler(loadConfig),\n ];\n};\n\nexport { gtkxVitePlugins };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/cli",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.5",
4
4
  "description": "GTK app toolchain for React: scaffold, dev server, build, docs.",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -70,27 +70,29 @@
70
70
  "dependencies": {
71
71
  "@babel/core": "^8.0.1",
72
72
  "@babel/preset-typescript": "^8.0.1",
73
- "@gtkx/codegen": "2.0.0-beta.3",
74
- "@gtkx/config": "2.0.0-beta.3",
75
- "@gtkx/mcp": "2.0.0-beta.3",
76
- "@gtkx/native": "2.0.0-beta.3",
77
- "@gtkx/runtime": "2.0.0-beta.3",
78
- "@gtkx/utils": "2.0.0-beta.3",
79
- "@gtkx/vitest": "2.0.0-beta.3",
73
+ "@gtkx/codegen": "2.0.0-beta.5",
74
+ "@gtkx/config": "2.0.0-beta.5",
75
+ "@gtkx/mcp": "2.0.0-beta.5",
76
+ "@gtkx/native": "2.0.0-beta.5",
77
+ "@gtkx/runtime": "2.0.0-beta.5",
78
+ "@gtkx/utils": "2.0.0-beta.5",
79
+ "@gtkx/vitest": "2.0.0-beta.5",
80
80
  "@swc/core": "^1.16.1",
81
81
  "babel-plugin-react-compiler": "^1.0.0",
82
82
  "citty": "^0.2.2",
83
- "create-gtkx": "2.0.0-beta.3",
83
+ "confbox": "^0.2.4",
84
+ "create-gtkx": "2.0.0-beta.5",
84
85
  "fast-xml-builder": "^1.3.1",
85
86
  "fast-xml-parser": "^5.11.1",
86
87
  "hosted-git-info": "^10.1.1",
87
88
  "i18next-cli": "1.72.1",
89
+ "jiti": "^2.7.0",
88
90
  "react-refresh": "^0.18.0",
89
91
  "vite": "^8.2.2",
90
92
  "yaml": "^2.9.0"
91
93
  },
92
94
  "devDependencies": {
93
- "@gtkx/testing": "2.0.0-beta.3",
95
+ "@gtkx/testing": "2.0.0-beta.5",
94
96
  "@types/babel__core": "^7.20.5",
95
97
  "@types/hosted-git-info": "^3.0.5",
96
98
  "@types/react-refresh": "^0.14.7",
package/src/cli.ts CHANGED
@@ -56,6 +56,11 @@ const main = defineCommand({
56
56
 
57
57
  return withErrorBoundary(scaffoldCommand);
58
58
  },
59
+ cleanup: async () => {
60
+ const { cleanup } = await import("./commands/cleanup.js");
61
+
62
+ return withErrorBoundary(cleanup);
63
+ },
59
64
  },
60
65
  });
61
66