@gtkx/cli 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/README.md +5 -4
  2. package/dist/builder.d.ts +1 -1
  3. package/dist/builder.d.ts.map +1 -1
  4. package/dist/builder.js +6 -6
  5. package/dist/builder.js.map +1 -1
  6. package/dist/codegen/run-codegen.d.ts +3 -2
  7. package/dist/codegen/run-codegen.d.ts.map +1 -1
  8. package/dist/codegen/run-codegen.js +41 -12
  9. package/dist/codegen/run-codegen.js.map +1 -1
  10. package/dist/commands/build.d.ts +0 -4
  11. package/dist/commands/build.d.ts.map +1 -1
  12. package/dist/commands/build.js +0 -5
  13. package/dist/commands/build.js.map +1 -1
  14. package/dist/commands/codegen.d.ts.map +1 -1
  15. package/dist/commands/codegen.js +2 -4
  16. package/dist/commands/codegen.js.map +1 -1
  17. package/dist/deploy/depends.d.ts +2 -2
  18. package/dist/deploy/depends.d.ts.map +1 -1
  19. package/dist/deploy/depends.js +30 -15
  20. package/dist/deploy/depends.js.map +1 -1
  21. package/dist/deploy/freedesktop/localize.d.ts +6 -0
  22. package/dist/deploy/freedesktop/localize.d.ts.map +1 -0
  23. package/dist/deploy/freedesktop/localize.js +107 -0
  24. package/dist/deploy/freedesktop/localize.js.map +1 -0
  25. package/dist/deploy/install-hints.d.ts.map +1 -1
  26. package/dist/deploy/install-hints.js +5 -0
  27. package/dist/deploy/install-hints.js.map +1 -1
  28. package/dist/deploy/nfpm/config.js +1 -1
  29. package/dist/deploy/nfpm/config.js.map +1 -1
  30. package/dist/deploy/node-runtime/elf.d.ts +1 -1
  31. package/dist/deploy/node-runtime/elf.d.ts.map +1 -1
  32. package/dist/deploy/node-runtime/elf.js +2 -2
  33. package/dist/deploy/node-runtime/elf.js.map +1 -1
  34. package/dist/deploy/node-runtime/index.js +2 -2
  35. package/dist/deploy/node-runtime/index.js.map +1 -1
  36. package/dist/deploy/notices/collect.d.ts +3 -1
  37. package/dist/deploy/notices/collect.d.ts.map +1 -1
  38. package/dist/deploy/notices/collect.js +2 -2
  39. package/dist/deploy/notices/collect.js.map +1 -1
  40. package/dist/deploy/notices/packages.d.ts +2 -1
  41. package/dist/deploy/notices/packages.d.ts.map +1 -1
  42. package/dist/deploy/notices/packages.js +4 -27
  43. package/dist/deploy/notices/packages.js.map +1 -1
  44. package/dist/deploy/payload/icons.d.ts +7 -3
  45. package/dist/deploy/payload/icons.d.ts.map +1 -1
  46. package/dist/deploy/payload/icons.js +46 -28
  47. package/dist/deploy/payload/icons.js.map +1 -1
  48. package/dist/deploy/payload/launcher.d.ts.map +1 -1
  49. package/dist/deploy/payload/launcher.js +2 -0
  50. package/dist/deploy/payload/launcher.js.map +1 -1
  51. package/dist/deploy/payload/stage.d.ts +1 -1
  52. package/dist/deploy/payload/stage.d.ts.map +1 -1
  53. package/dist/deploy/payload/stage.js +23 -13
  54. package/dist/deploy/payload/stage.js.map +1 -1
  55. package/dist/deploy/run-deploy.d.ts.map +1 -1
  56. package/dist/deploy/run-deploy.js +149 -25
  57. package/dist/deploy/run-deploy.js.map +1 -1
  58. package/dist/deploy/settings/build-manifest.d.ts +9 -0
  59. package/dist/deploy/settings/build-manifest.d.ts.map +1 -0
  60. package/dist/deploy/settings/build-manifest.js +80 -0
  61. package/dist/deploy/settings/build-manifest.js.map +1 -0
  62. package/dist/deploy/settings/index.d.ts.map +1 -1
  63. package/dist/deploy/settings/index.js +9 -3
  64. package/dist/deploy/settings/index.js.map +1 -1
  65. package/dist/deploy/settings/libraries.d.ts +8 -0
  66. package/dist/deploy/settings/libraries.d.ts.map +1 -0
  67. package/dist/deploy/settings/libraries.js +39 -0
  68. package/dist/deploy/settings/libraries.js.map +1 -0
  69. package/dist/deploy/settings/paths.d.ts +3 -0
  70. package/dist/deploy/settings/paths.d.ts.map +1 -1
  71. package/dist/deploy/settings/paths.js +6 -32
  72. package/dist/deploy/settings/paths.js.map +1 -1
  73. package/dist/deploy/targets/appimage.d.ts.map +1 -1
  74. package/dist/deploy/targets/appimage.js +19 -13
  75. package/dist/deploy/targets/appimage.js.map +1 -1
  76. package/dist/deploy/targets/flatpak-manifest.d.ts +2 -1
  77. package/dist/deploy/targets/flatpak-manifest.d.ts.map +1 -1
  78. package/dist/deploy/targets/flatpak-manifest.js +5 -1
  79. package/dist/deploy/targets/flatpak-manifest.js.map +1 -1
  80. package/dist/deploy/targets/flatpak-source.d.ts.map +1 -1
  81. package/dist/deploy/targets/flatpak-source.js +30 -16
  82. package/dist/deploy/targets/flatpak-source.js.map +1 -1
  83. package/dist/deploy/tools.d.ts +6 -1
  84. package/dist/deploy/tools.d.ts.map +1 -1
  85. package/dist/deploy/tools.js +26 -1
  86. package/dist/deploy/tools.js.map +1 -1
  87. package/dist/deploy/types.d.ts +4 -4
  88. package/dist/deploy/types.d.ts.map +1 -1
  89. package/dist/deploy/types.js.map +1 -1
  90. package/dist/dev/icon-dir.d.ts +1 -1
  91. package/dist/dev/icon-dir.d.ts.map +1 -1
  92. package/dist/dev/icon-dir.js +20 -7
  93. package/dist/dev/icon-dir.js.map +1 -1
  94. package/dist/dev/locale-dir.d.ts +3 -0
  95. package/dist/dev/locale-dir.d.ts.map +1 -0
  96. package/dist/dev/locale-dir.js +17 -0
  97. package/dist/dev/locale-dir.js.map +1 -0
  98. package/dist/dev/runner-deps.d.ts.map +1 -1
  99. package/dist/dev/runner-deps.js +5 -1
  100. package/dist/dev/runner-deps.js.map +1 -1
  101. package/dist/dev/runner-main.d.ts.map +1 -1
  102. package/dist/dev/runner-main.js +6 -4
  103. package/dist/dev/runner-main.js.map +1 -1
  104. package/dist/dev/runner.d.ts +1 -1
  105. package/dist/dev/runner.d.ts.map +1 -1
  106. package/dist/dev/runner.js +7 -1
  107. package/dist/dev/runner.js.map +1 -1
  108. package/dist/dev/schema-dir.d.ts +1 -1
  109. package/dist/dev/schema-dir.d.ts.map +1 -1
  110. package/dist/dev/schema-dir.js +3 -1
  111. package/dist/dev/schema-dir.js.map +1 -1
  112. package/dist/dev/vite-dev-server.d.ts +1 -0
  113. package/dist/dev/vite-dev-server.d.ts.map +1 -1
  114. package/dist/dev/vite-dev-server.js.map +1 -1
  115. package/dist/i18n/binding-extractor.d.ts +30 -0
  116. package/dist/i18n/binding-extractor.d.ts.map +1 -0
  117. package/dist/i18n/binding-extractor.js +1324 -0
  118. package/dist/i18n/binding-extractor.js.map +1 -0
  119. package/dist/i18n/catalog-template.d.ts +3 -0
  120. package/dist/i18n/catalog-template.d.ts.map +1 -0
  121. package/dist/i18n/catalog-template.js +18 -0
  122. package/dist/i18n/catalog-template.js.map +1 -0
  123. package/dist/i18n/catalogs.d.ts +21 -0
  124. package/dist/i18n/catalogs.d.ts.map +1 -0
  125. package/dist/i18n/catalogs.js +139 -0
  126. package/dist/i18n/catalogs.js.map +1 -0
  127. package/dist/i18n/extractor-plugin.d.ts +8 -0
  128. package/dist/i18n/extractor-plugin.d.ts.map +1 -0
  129. package/dist/i18n/extractor-plugin.js +247 -0
  130. package/dist/i18n/extractor-plugin.js.map +1 -0
  131. package/dist/i18n/metadata-templates.d.ts +11 -0
  132. package/dist/i18n/metadata-templates.d.ts.map +1 -0
  133. package/dist/i18n/metadata-templates.js +11 -0
  134. package/dist/i18n/metadata-templates.js.map +1 -0
  135. package/dist/i18n/source-messages.d.ts +23 -0
  136. package/dist/i18n/source-messages.d.ts.map +1 -0
  137. package/dist/i18n/source-messages.js +403 -0
  138. package/dist/i18n/source-messages.js.map +1 -0
  139. package/dist/i18n/types.d.ts +10 -0
  140. package/dist/i18n/types.d.ts.map +1 -0
  141. package/dist/i18n/types.js +108 -0
  142. package/dist/i18n/types.js.map +1 -0
  143. package/dist/internal/build-manifest.d.ts +20 -0
  144. package/dist/internal/build-manifest.d.ts.map +1 -0
  145. package/dist/internal/build-manifest.js +6 -0
  146. package/dist/internal/build-manifest.js.map +1 -0
  147. package/dist/internal/icon-path.d.ts +13 -0
  148. package/dist/internal/icon-path.d.ts.map +1 -0
  149. package/dist/internal/icon-path.js +86 -0
  150. package/dist/internal/icon-path.js.map +1 -0
  151. package/dist/internal/source-imports.d.ts +12 -0
  152. package/dist/internal/source-imports.d.ts.map +1 -0
  153. package/dist/internal/source-imports.js +123 -0
  154. package/dist/internal/source-imports.js.map +1 -0
  155. package/dist/mcp/client.d.ts +0 -1
  156. package/dist/mcp/client.d.ts.map +1 -1
  157. package/dist/mcp/client.js +11 -39
  158. package/dist/mcp/client.js.map +1 -1
  159. package/dist/mcp/handlers.d.ts +2 -1
  160. package/dist/mcp/handlers.d.ts.map +1 -1
  161. package/dist/mcp/handlers.js.map +1 -1
  162. package/dist/mcp/widget-properties.d.ts.map +1 -1
  163. package/dist/mcp/widget-properties.js +3 -12
  164. package/dist/mcp/widget-properties.js.map +1 -1
  165. package/dist/settings/render.d.ts +10 -1
  166. package/dist/settings/render.d.ts.map +1 -1
  167. package/dist/settings/render.js +78 -20
  168. package/dist/settings/render.js.map +1 -1
  169. package/dist/settings/schema.d.ts +4 -3
  170. package/dist/settings/schema.d.ts.map +1 -1
  171. package/dist/settings/schema.js +124 -15
  172. package/dist/settings/schema.js.map +1 -1
  173. package/dist/vite-plugins/asset-emitter.d.ts +1 -1
  174. package/dist/vite-plugins/asset-emitter.d.ts.map +1 -1
  175. package/dist/vite-plugins/asset-emitter.js.map +1 -1
  176. package/dist/vite-plugins/asset-extensions.d.ts.map +1 -1
  177. package/dist/vite-plugins/asset-extensions.js +1 -0
  178. package/dist/vite-plugins/asset-extensions.js.map +1 -1
  179. package/dist/vite-plugins/asset-imports.d.ts +2 -1
  180. package/dist/vite-plugins/asset-imports.d.ts.map +1 -1
  181. package/dist/vite-plugins/asset-imports.js +39 -28
  182. package/dist/vite-plugins/asset-imports.js.map +1 -1
  183. package/dist/vite-plugins/asset-specifier.d.ts +13 -1
  184. package/dist/vite-plugins/asset-specifier.d.ts.map +1 -1
  185. package/dist/vite-plugins/asset-specifier.js +39 -1
  186. package/dist/vite-plugins/asset-specifier.js.map +1 -1
  187. package/dist/vite-plugins/build-manifest.d.ts +5 -0
  188. package/dist/vite-plugins/build-manifest.d.ts.map +1 -0
  189. package/dist/vite-plugins/{bundled-packages.js → build-manifest.js} +20 -14
  190. package/dist/vite-plugins/build-manifest.js.map +1 -0
  191. package/dist/vite-plugins/built-url.d.ts +1 -1
  192. package/dist/vite-plugins/built-url.d.ts.map +1 -1
  193. package/dist/vite-plugins/built-url.js +37 -24
  194. package/dist/vite-plugins/built-url.js.map +1 -1
  195. package/dist/vite-plugins/i18n.d.ts +5 -0
  196. package/dist/vite-plugins/i18n.d.ts.map +1 -0
  197. package/dist/vite-plugins/i18n.js +88 -0
  198. package/dist/vite-plugins/i18n.js.map +1 -0
  199. package/dist/vite-plugins/icons.d.ts +2 -1
  200. package/dist/vite-plugins/icons.d.ts.map +1 -1
  201. package/dist/vite-plugins/icons.js +25 -12
  202. package/dist/vite-plugins/icons.js.map +1 -1
  203. package/dist/vite-plugins/index.d.ts +2 -1
  204. package/dist/vite-plugins/index.d.ts.map +1 -1
  205. package/dist/vite-plugins/index.js +9 -5
  206. package/dist/vite-plugins/index.js.map +1 -1
  207. package/dist/vite-plugins/native.d.ts.map +1 -1
  208. package/dist/vite-plugins/native.js +23 -4
  209. package/dist/vite-plugins/native.js.map +1 -1
  210. package/dist/vite-plugins/resource-init-module.d.ts +7 -3
  211. package/dist/vite-plugins/resource-init-module.d.ts.map +1 -1
  212. package/dist/vite-plugins/resource-init-module.js +39 -14
  213. package/dist/vite-plugins/resource-init-module.js.map +1 -1
  214. package/dist/vite-plugins/resource-shared.d.ts +3 -1
  215. package/dist/vite-plugins/resource-shared.d.ts.map +1 -1
  216. package/dist/vite-plugins/resource-shared.js +3 -1
  217. package/dist/vite-plugins/resource-shared.js.map +1 -1
  218. package/dist/vite-plugins/resources.d.ts +1 -1
  219. package/dist/vite-plugins/resources.d.ts.map +1 -1
  220. package/dist/vite-plugins/resources.js +877 -86
  221. package/dist/vite-plugins/resources.js.map +1 -1
  222. package/dist/vite-plugins/self-contained.d.ts.map +1 -1
  223. package/dist/vite-plugins/self-contained.js +128 -135
  224. package/dist/vite-plugins/self-contained.js.map +1 -1
  225. package/dist/vite-plugins/settings-worker-env.d.ts.map +1 -1
  226. package/dist/vite-plugins/settings-worker-env.js +6 -3
  227. package/dist/vite-plugins/settings-worker-env.js.map +1 -1
  228. package/dist/vite-plugins/settings.d.ts +3 -1
  229. package/dist/vite-plugins/settings.d.ts.map +1 -1
  230. package/dist/vite-plugins/settings.js +63 -23
  231. package/dist/vite-plugins/settings.js.map +1 -1
  232. package/env.d.ts +11 -192
  233. package/package.json +11 -10
  234. package/src/builder.ts +7 -7
  235. package/src/codegen/run-codegen.ts +64 -15
  236. package/src/commands/build.ts +0 -5
  237. package/src/commands/codegen.ts +2 -4
  238. package/src/deploy/depends.ts +47 -18
  239. package/src/deploy/freedesktop/localize.ts +144 -0
  240. package/src/deploy/install-hints.ts +5 -0
  241. package/src/deploy/nfpm/config.ts +1 -1
  242. package/src/deploy/node-runtime/elf.ts +3 -3
  243. package/src/deploy/node-runtime/index.ts +2 -2
  244. package/src/deploy/notices/collect.ts +4 -2
  245. package/src/deploy/notices/packages.ts +5 -43
  246. package/src/deploy/payload/icons.ts +64 -34
  247. package/src/deploy/payload/launcher.ts +2 -0
  248. package/src/deploy/payload/stage.ts +40 -12
  249. package/src/deploy/run-deploy.ts +214 -24
  250. package/src/deploy/settings/build-manifest.ts +122 -0
  251. package/src/deploy/settings/index.ts +9 -4
  252. package/src/deploy/settings/libraries.ts +57 -0
  253. package/src/deploy/settings/paths.ts +10 -47
  254. package/src/deploy/targets/appimage.ts +32 -15
  255. package/src/deploy/targets/flatpak-manifest.ts +7 -1
  256. package/src/deploy/targets/flatpak-source.ts +42 -20
  257. package/src/deploy/tools.ts +35 -0
  258. package/src/deploy/types.ts +4 -4
  259. package/src/dev/icon-dir.ts +31 -7
  260. package/src/dev/locale-dir.ts +22 -0
  261. package/src/dev/runner-deps.ts +5 -1
  262. package/src/dev/runner-main.ts +6 -4
  263. package/src/dev/runner.ts +10 -2
  264. package/src/dev/schema-dir.ts +3 -1
  265. package/src/dev/vite-dev-server.ts +1 -0
  266. package/src/i18n/binding-extractor.ts +1969 -0
  267. package/src/i18n/catalog-template.ts +24 -0
  268. package/src/i18n/catalogs.ts +216 -0
  269. package/src/i18n/extractor-plugin.ts +413 -0
  270. package/src/i18n/metadata-templates.ts +29 -0
  271. package/src/i18n/source-messages.ts +608 -0
  272. package/src/i18n/types.ts +154 -0
  273. package/src/internal/build-manifest.ts +32 -0
  274. package/src/internal/icon-path.ts +127 -0
  275. package/src/internal/source-imports.ts +171 -0
  276. package/src/mcp/client.ts +17 -44
  277. package/src/mcp/handlers.ts +7 -6
  278. package/src/mcp/widget-properties.ts +3 -14
  279. package/src/settings/render.ts +113 -21
  280. package/src/settings/schema.ts +192 -17
  281. package/src/vite-plugins/asset-emitter.ts +1 -1
  282. package/src/vite-plugins/asset-extensions.ts +1 -0
  283. package/src/vite-plugins/asset-imports.ts +62 -33
  284. package/src/vite-plugins/asset-specifier.ts +73 -1
  285. package/src/vite-plugins/{bundled-packages.ts → build-manifest.ts} +30 -19
  286. package/src/vite-plugins/built-url.ts +49 -28
  287. package/src/vite-plugins/i18n.ts +146 -0
  288. package/src/vite-plugins/icons.ts +33 -14
  289. package/src/vite-plugins/index.ts +15 -5
  290. package/src/vite-plugins/native.ts +31 -4
  291. package/src/vite-plugins/resource-init-module.ts +44 -15
  292. package/src/vite-plugins/resource-shared.ts +4 -0
  293. package/src/vite-plugins/resources.ts +1397 -100
  294. package/src/vite-plugins/self-contained.ts +150 -169
  295. package/src/vite-plugins/settings-worker-env.ts +7 -3
  296. package/src/vite-plugins/settings.ts +89 -21
  297. package/dist/vite-plugins/bundled-packages.d.ts +0 -5
  298. package/dist/vite-plugins/bundled-packages.d.ts.map +0 -1
  299. package/dist/vite-plugins/bundled-packages.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { existsSync, mkdirSync, rmSync, statSync } from "node:fs";
2
- import { join } from "node:path";
2
+ import { basename, join } from "node:path";
3
3
  import type {
4
4
  DeployArtifact,
5
5
  DeployManifest,
@@ -10,18 +10,21 @@ import type {
10
10
  } from "../types.js";
11
11
  import { runCliTool } from "../../internal/run-cli-tool.js";
12
12
  import { copyInto, copyTree, EXECUTABLE_MODE, writeInto } from "../payload/copy-tree.js";
13
- import { getIconSize } from "../payload/icons.js";
13
+ import { type ApplicationIconVariant, classifyApplicationIcon } from "../payload/icons.js";
14
14
  import { FILE_TOOL } from "../tools.js";
15
15
  import { resolveAppimageTooling } from "../vendored/appimagetool.js";
16
16
 
17
+ type RankedIcon = {
18
+ file: StagedFile;
19
+ variant: ApplicationIconVariant;
20
+ };
21
+
17
22
  const PREFIX = "/usr";
18
23
  const TARGET_DIR = "appimage";
19
24
  const APPRUN_FILENAME = "AppRun";
20
25
  const APPDIR_NAME = "AppDir";
21
26
  const USR_DIR = "usr";
22
- const ICON_EXTENSIONS = [".svg", ".png", ".xpm"];
23
27
  const EXTRACT_AND_RUN = "APPIMAGE_EXTRACT_AND_RUN";
24
- const SCALABLE_RANK = Number.MAX_SAFE_INTEGER;
25
28
 
26
29
  const appimageTarget: DeployTarget = {
27
30
  name: "appimage",
@@ -50,31 +53,45 @@ const renderManifests = (payload: DeployPayload): DeployManifest[] => [
50
53
  { path: appRunPathFor(payload.settings), contents: renderAppRun(payload.settings) },
51
54
  ];
52
55
 
53
- const iconRank = (file: StagedFile): number =>
54
- file.rel.endsWith(".svg") ? SCALABLE_RANK : (getIconSize(file.rel) ?? 0);
56
+ const rankedIcon = (applicationId: string, file: StagedFile): RankedIcon | null => {
57
+ const variant = classifyApplicationIcon(applicationId, file.rel);
58
+
59
+ return variant === null ? null : { file, variant };
60
+ };
61
+
62
+ const isLargerIcon = (candidate: RankedIcon, best: RankedIcon): boolean =>
63
+ candidate.variant.scalable === best.variant.scalable
64
+ ? candidate.variant.effectivePixels > best.variant.effectivePixels
65
+ : candidate.variant.scalable;
66
+
67
+ const largerIcon = (best: RankedIcon | undefined, candidate: RankedIcon): RankedIcon =>
68
+ best === undefined || isLargerIcon(candidate, best) ? candidate : best;
55
69
 
56
- const largestIcon = (icons: StagedFile[]): StagedFile | undefined => {
57
- let best: StagedFile | undefined;
70
+ const largestIcon = (applicationId: string, files: StagedFile[]): StagedFile | undefined => {
71
+ let best: RankedIcon | undefined;
58
72
 
59
- for (const file of icons) {
60
- if (best === undefined || iconRank(file) > iconRank(best)) {
61
- best = file;
73
+ for (const file of files) {
74
+ const candidate = rankedIcon(applicationId, file);
75
+
76
+ if (candidate === null) {
77
+ continue;
62
78
  }
79
+
80
+ best = largerIcon(best, candidate);
63
81
  }
64
82
 
65
- return best;
83
+ return best?.file;
66
84
  };
67
85
 
68
86
  const rootIconFor = (payload: DeployPayload): { rel: string; abs: string } => {
69
87
  const { applicationId } = payload.settings;
70
- const names = new Set(ICON_EXTENSIONS.map((extension) => `${applicationId}${extension}`));
71
- const icon = largestIcon(payload.stage.filter((file) => names.has(file.rel.split("/").at(-1) ?? "")));
88
+ const icon = largestIcon(applicationId, payload.stage);
72
89
 
73
90
  if (icon === undefined) {
74
91
  throw new Error(`Cannot build an AppImage without a ${applicationId} icon in the staged icon tree`);
75
92
  }
76
93
 
77
- return { rel: icon.rel.split("/").at(-1) ?? "", abs: icon.abs };
94
+ return { rel: basename(icon.rel), abs: icon.abs };
78
95
  };
79
96
 
80
97
  const buildAppDir = (payload: DeployPayload): string => {
@@ -110,6 +110,12 @@ const runtimeKeys = (settings: DeploySettings): FlatpakManifest => {
110
110
  };
111
111
  };
112
112
 
113
+ const runtimeLabelFor = (settings: DeploySettings): string => {
114
+ const flatpak = settings.deploy.flatpak ?? {};
115
+
116
+ return `${flatpak.runtime ?? DEFAULT_RUNTIME}//${flatpak.runtimeVersion ?? DEFAULT_RUNTIME_VERSION}`;
117
+ };
118
+
113
119
  const renderFlatpakManifest = (payload: DeployPayload): FlatpakManifest => {
114
120
  const settings = payload.settings;
115
121
 
@@ -123,4 +129,4 @@ const renderFlatpakManifest = (payload: DeployPayload): FlatpakManifest => {
123
129
  };
124
130
  };
125
131
 
126
- export { branchFor, finishArgsFor, hasDisplaySocket, renderFlatpakManifest };
132
+ export { branchFor, finishArgsFor, hasDisplaySocket, renderFlatpakManifest, runtimeLabelFor };
@@ -1,12 +1,10 @@
1
- import { existsSync, realpathSync } from "node:fs";
1
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
2
2
  import { posix, relative, resolve } from "node:path";
3
3
  import type { DeployPayload, DeploySettings } from "../types.js";
4
+ import { LOCALE_DIRNAME } from "../../i18n/catalogs.js";
4
5
  import { listFilesRecursive } from "../../internal/list-files.js";
5
6
  import { BUNDLE_FILENAME } from "../../vite-plugins/esm-extension.js";
6
7
  import { renderDbusService } from "../freedesktop/dbus-service.js";
7
- import { renderDesktopEntry } from "../freedesktop/desktop-entry.js";
8
- import { renderMetainfo } from "../freedesktop/metainfo.js";
9
- import { renderMimePackage } from "../freedesktop/mime-package.js";
10
8
  import { optional } from "../nfpm/optional.js";
11
9
  import { renderNotices } from "../notices/render.js";
12
10
  import { executableModeFor } from "../payload/copy-tree.js";
@@ -60,6 +58,7 @@ const installCommand = (source: string, destination: string, mode: string): stri
60
58
 
61
59
  const runtimeInstallCommands = (settings: DeploySettings, nodeExtensionPath: string): string[] => {
62
60
  const lib = `${DESTINATION}/lib/${settings.binaryName}`;
61
+ const locale = `${DESTINATION}/share/${LOCALE_DIRNAME}`;
63
62
 
64
63
  return [
65
64
  installCommand(`${nodeExtensionPath}/bin/node`, `${lib}/node`, "m755"),
@@ -69,6 +68,7 @@ const runtimeInstallCommands = (settings: DeploySettings, nodeExtensionPath: str
69
68
  "test ! -f dist/gschemas.compiled || " +
70
69
  installCommand("dist/gschemas.compiled", `${lib}/gschemas.compiled`, "m644"),
71
70
  `test ! -d dist/assets || cp -a dist/assets ${lib}/assets`,
71
+ `test ! -d dist/${LOCALE_DIRNAME} || { mkdir -p ${locale} && cp -a dist/${LOCALE_DIRNAME}/. ${locale}/; }`,
72
72
  installCommand(LAUNCHER_FILENAME, `${DESTINATION}/bin/${settings.binaryName}`, "m755"),
73
73
  ];
74
74
  };
@@ -87,10 +87,35 @@ const activationInstallCommands = (settings: DeploySettings): string[] =>
87
87
  )]
88
88
  : [];
89
89
 
90
- const mimeSources = (settings: DeploySettings): FlatpakModule[] => {
91
- const contents = renderMimePackage(settings);
90
+ const stagedContents = (payload: DeployPayload, destination: string): string => {
91
+ const file = payload.stage.find((candidate) => candidate.rel === destination);
92
92
 
93
- return contents === null ? [] : [inlineSource(`${settings.applicationId}.xml`, contents)];
93
+ if (file === undefined) {
94
+ throw new Error(`Cannot render the source Flatpak: ${destination} was not staged`);
95
+ }
96
+
97
+ return readFileSync(file.abs, "utf8");
98
+ };
99
+
100
+ const stagedMetadataSources = (payload: DeployPayload): FlatpakModule[] => {
101
+ const settings = payload.settings;
102
+
103
+ return [
104
+ inlineSource(
105
+ `${settings.applicationId}.desktop`,
106
+ stagedContents(payload, posix.join("share", "applications", `${settings.applicationId}.desktop`)),
107
+ ),
108
+ inlineSource(
109
+ `${settings.applicationId}.metainfo.xml`,
110
+ stagedContents(payload, posix.join("share", "metainfo", `${settings.applicationId}.metainfo.xml`)),
111
+ ),
112
+ ...(settings.fileAssociations.length === 0
113
+ ? []
114
+ : [inlineSource(
115
+ `${settings.applicationId}.xml`,
116
+ stagedContents(payload, posix.join("share", "mime", "packages", `${settings.applicationId}.xml`)),
117
+ )]),
118
+ ];
94
119
  };
95
120
 
96
121
  const mimeInstallCommands = (settings: DeploySettings): string[] =>
@@ -120,12 +145,11 @@ const metadataInstallCommands = (settings: DeploySettings): string[] => [
120
145
  const schemaInstallCommands = (settings: DeploySettings): string[] =>
121
146
  settings.paths.schemaFiles.map((file) => {
122
147
  const name = posix.basename(file);
148
+ const source = projectRelative(settings, file);
149
+ const destination = `${DESTINATION}/share/glib-2.0/schemas/${shellArgument(name)}`;
150
+ assertInsideProject(settings, { destination, source, resolved: file });
123
151
 
124
- return installCommand(
125
- projectRelative(settings, file),
126
- `${DESTINATION}/share/glib-2.0/schemas/${shellArgument(name)}`,
127
- "m644",
128
- );
152
+ return installCommand(source, destination, "m644");
129
153
  });
130
154
 
131
155
  const iconInstallCommand = (settings: DeploySettings, source: string, rel: string): string =>
@@ -136,17 +160,17 @@ const iconInstallCommand = (settings: DeploySettings, source: string, rel: strin
136
160
  );
137
161
 
138
162
  const iconInstallCommands = (settings: DeploySettings): string[] => {
139
- const { iconsDir, iconFile } = settings.paths;
163
+ const source = settings.paths.applicationIcon;
140
164
 
141
- if (iconFile !== null) {
142
- return [iconInstallCommand(settings, iconFile, iconPathFor(settings, iconFile))];
165
+ if (source.kind === "file") {
166
+ return [iconInstallCommand(settings, source.path, iconPathFor(settings, source.path))];
143
167
  }
144
168
 
145
- if (iconsDir === null) {
169
+ if (source.kind === "none") {
146
170
  return [];
147
171
  }
148
172
 
149
- return listFilesRecursive(iconsDir).map((icon) => iconInstallCommand(settings, icon.absPath, icon.rel));
173
+ return listFilesRecursive(source.path).map((icon) => iconInstallCommand(settings, icon.absPath, icon.rel));
150
174
  };
151
175
 
152
176
  const assertInsideProject = (settings: DeploySettings, installed: InstalledFile): void => {
@@ -240,9 +264,7 @@ const flatpakSourceModule = (payload: DeployPayload): FlatpakModule => {
240
264
  resolveGitSource(settings),
241
265
  ...(pin === null ? [] : pnpmSources(pin, moduleDirFor(settings))),
242
266
  GENERATED_SOURCES,
243
- inlineSource(`${settings.applicationId}.desktop`, renderDesktopEntry(settings)),
244
- inlineSource(`${settings.applicationId}.metainfo.xml`, renderMetainfo(settings)),
245
- ...mimeSources(settings),
267
+ ...stagedMetadataSources(payload),
246
268
  inlineSource(LAUNCHER_FILENAME, renderLauncher(settings)),
247
269
  inlineSource(NOTICES_FILENAME, renderNotices(settings, payload.notices)),
248
270
  ...activationSource(settings),
@@ -56,6 +56,36 @@ const FLATPAK_NODE_GENERATOR_PNPM: DeployTool = {
56
56
  isPresent: () => hasGeneratorPnpmSupport(),
57
57
  };
58
58
 
59
+ const MSGFMT: DeployTool = {
60
+ command: "msgfmt",
61
+ purpose: "compiles the gettext catalogs and localized metadata",
62
+ isOptional: false,
63
+ };
64
+
65
+ const MSGGREP: DeployTool = {
66
+ command: "msggrep",
67
+ purpose: "retains generated metadata while refreshing the catalog template",
68
+ isOptional: false,
69
+ };
70
+
71
+ const MSGINIT: DeployTool = {
72
+ command: "msginit",
73
+ purpose: "initializes newly listed gettext catalogs",
74
+ isOptional: false,
75
+ };
76
+
77
+ const MSGMERGE: DeployTool = {
78
+ command: "msgmerge",
79
+ purpose: "synchronizes translations with the catalog template",
80
+ isOptional: false,
81
+ };
82
+
83
+ const XGETTEXT: DeployTool = {
84
+ command: "xgettext",
85
+ purpose: "extracts the gettext catalog template",
86
+ isOptional: false,
87
+ };
88
+
59
89
  const STRIP: DeployTool = {
60
90
  command: "strip",
61
91
  purpose: "would shrink the bundled Node.js by removing its symbols",
@@ -149,8 +179,13 @@ export {
149
179
  FILE_TOOL,
150
180
  FLATPAK,
151
181
  FLATPAK_BUILDER,
182
+ MSGFMT,
183
+ MSGGREP,
184
+ MSGINIT,
185
+ MSGMERGE,
152
186
  probeTools,
153
187
  STRIP,
154
188
  TAR,
155
189
  warnMissingOptional,
190
+ XGETTEXT,
156
191
  };
@@ -1,4 +1,5 @@
1
1
  import type { Config } from "@gtkx/config";
2
+ import type { ResolvedApplicationIcon } from "../internal/icon-path.js";
2
3
 
3
4
  type DeployConfig = NonNullable<Config["deploy"]>;
4
5
  type DeployTargetName = NonNullable<DeployConfig["targets"]>[number];
@@ -21,7 +22,7 @@ type NodeRuntime = {
21
22
  path: string;
22
23
  licenseFile: string | null;
23
24
  version: string;
24
- glibcFloor: string | null;
25
+ glibcMinimum: string | null;
25
26
  isStripped: boolean;
26
27
  };
27
28
 
@@ -106,9 +107,7 @@ type DeployPaths = {
106
107
  overlay: string;
107
108
  targets: string;
108
109
  output: string;
109
- dataDir: string | null;
110
- iconsDir: string | null;
111
- iconFile: string | null;
110
+ applicationIcon: ResolvedApplicationIcon;
112
111
  licenseFile: string | null;
113
112
  schemaFiles: string[];
114
113
  };
@@ -145,6 +144,7 @@ type DeploySettings = {
145
144
  arch: DeployArch;
146
145
  paths: DeployPaths;
147
146
  libraries: string[];
147
+ minimumLibraryVersions: Record<string, string>;
148
148
  deploy: DeployConfig;
149
149
  };
150
150
 
@@ -1,18 +1,42 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
1
+ import { mkdirSync, symlinkSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import {
4
+ relativeIconPath,
5
+ resolveApplicationIcon,
6
+ type ResolvedApplicationIcon,
7
+ } from "../internal/icon-path.js";
8
+ import { createRetainedStagingDir } from "../internal/staging-dir.js";
3
9
  import { prependXdgDataDir } from "../internal/xdg-data-dirs.js";
4
10
 
5
- const prepareDevIconDir = (root: string, dataDir: string | null): string | null => {
6
- if (dataDir === null) {
7
- return null;
11
+ const stageIconSource = (shareDir: string, applicationId: string, source: ResolvedApplicationIcon): void => {
12
+ if (source.kind === "theme") {
13
+ symlinkSync(source.path, join(shareDir, "icons"), "dir");
14
+
15
+ return;
16
+ }
17
+
18
+ if (source.kind === "none") {
19
+ return;
8
20
  }
9
21
 
10
- const shareDir = join(root, dataDir);
22
+ const target = join(shareDir, "icons", relativeIconPath(applicationId, source.path));
23
+ mkdirSync(dirname(target), { recursive: true });
24
+ symlinkSync(source.path, target, "file");
25
+ };
26
+
27
+ const prepareDevIconDir = (
28
+ root: string,
29
+ applicationId: string,
30
+ configured: string | undefined,
31
+ ): string | null => {
32
+ const source = resolveApplicationIcon(root, applicationId, configured);
11
33
 
12
- if (!existsSync(join(shareDir, "icons"))) {
34
+ if (source.kind === "none") {
13
35
  return null;
14
36
  }
15
37
 
38
+ const shareDir = createRetainedStagingDir("icons").retain();
39
+ stageIconSource(shareDir, applicationId, source);
16
40
  process.env.XDG_DATA_DIRS = prependXdgDataDir(shareDir, process.env.XDG_DATA_DIRS);
17
41
 
18
42
  return shareDir;
@@ -0,0 +1,22 @@
1
+ import { compileCatalogs, resolveCatalogProject, synchronizeCatalogs } from "../i18n/catalogs.js";
2
+ import { createRetainedStagingDir } from "../internal/staging-dir.js";
3
+
4
+ const LOCALE_DIR_ENV = "GTKX_LOCALE_DIR";
5
+ const localeDir = createRetainedStagingDir("locale");
6
+
7
+ const prepareDevLocaleDir = (root: string, domain: string): string | null => {
8
+ const project = resolveCatalogProject(root, domain);
9
+
10
+ if (project === null) {
11
+ return null;
12
+ }
13
+
14
+ const outputDir = localeDir.retain();
15
+ synchronizeCatalogs(project);
16
+ compileCatalogs(project, outputDir);
17
+ process.env[LOCALE_DIR_ENV] = outputDir;
18
+
19
+ return outputDir;
20
+ };
21
+
22
+ export { prepareDevLocaleDir };
@@ -86,7 +86,11 @@ const defaultDevRunnerDeps = (): DevRunnerDeps => ({
86
86
  isRefreshBoundary,
87
87
  staleExportName,
88
88
  readFileRevision,
89
- plugins: () => [...gtkxVitePlugins(DEV_MODE), ...gtkxFastRefresh(), gtkxReactDomPrebundle()],
89
+ plugins: (entryPath) => [
90
+ ...gtkxVitePlugins(DEV_MODE, entryPath),
91
+ ...gtkxFastRefresh(),
92
+ gtkxReactDomPrebundle(),
93
+ ],
90
94
  log: info,
91
95
  exit: (code: number): never => process.exit(code),
92
96
  });
@@ -1,8 +1,9 @@
1
+ import { loadConfig } from "@gtkx/config";
1
2
  import { error } from "@gtkx/utils";
2
3
  import { resolve } from "node:path";
3
- import { resolveDataDir } from "../internal/data-dir.js";
4
4
  import { DEV_ENTRY_ENV } from "./entry-env.js";
5
5
  import { prepareDevIconDir } from "./icon-dir.js";
6
+ import { prepareDevLocaleDir } from "./locale-dir.js";
6
7
  import { createDevRunner } from "./runner.js";
7
8
  import { prepareDevSchemaDir } from "./schema-dir.js";
8
9
 
@@ -21,9 +22,10 @@ const main = async (): Promise<void> => {
21
22
  process.exit(1);
22
23
  }
23
24
 
24
- const dataDir = resolveDataDir(cwd);
25
- prepareDevSchemaDir(cwd, dataDir);
26
- prepareDevIconDir(cwd, dataDir);
25
+ const { config, root } = await loadConfig(cwd, { mode: "development" });
26
+ prepareDevLocaleDir(root, config.applicationId);
27
+ prepareDevSchemaDir(root, config.future?.v2ResourceImports === true);
28
+ prepareDevIconDir(root, config.applicationId, config.applicationIcon);
27
29
  const entryPath = resolve(cwd, entryArg);
28
30
  const { defaultDevRunnerDeps } = await import("./runner-deps.js");
29
31
  const runner = createDevRunner(defaultDevRunnerDeps());
package/src/dev/runner.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { ApplicationInstance } from "@gtkx/runtime/internal";
2
2
  import type { InlineConfig, Plugin } from "vite";
3
3
  import { error, warn } from "@gtkx/utils";
4
+ import { isCatalogSource } from "../i18n/catalogs.js";
4
5
  import { loadModuleExclusively, withExclusiveLoad } from "../internal/module-loads.js";
5
6
  import { createChangeQueue, type WatchedChange } from "./change-queue.js";
6
7
  import { createFailureTracker, type FailureTracker } from "./failure-tracker.js";
@@ -32,7 +33,7 @@ type DevRunnerDeps = {
32
33
  isRefreshBoundary(module: Record<string, unknown>): boolean;
33
34
  staleExportName(previous: Record<string, unknown>, current: Record<string, unknown>): string | null;
34
35
  readFileRevision(path: string): Promise<string>;
35
- plugins(): Plugin[];
36
+ plugins(entryPath: string): Plugin[];
36
37
  log(message: string): void;
37
38
  exit(code: number): never;
38
39
  };
@@ -374,6 +375,13 @@ const applyChange = async (session: DevSession, change: WatchedChange): Promise<
374
375
  return;
375
376
  }
376
377
 
378
+ if (isCatalogSource(session.server.config.root, change.path)) {
379
+ session.deps.log(`Translation catalog changed: ${change.path}`);
380
+ await requestRestart(session);
381
+
382
+ return;
383
+ }
384
+
377
385
  if (isServerConfigFile(session.server.config, change.path)) {
378
386
  await restartForServerConfig(session, change.path);
379
387
 
@@ -602,7 +610,7 @@ const createSession = (server: DevServer, deps: DevRunnerDeps): DevSession => {
602
610
 
603
611
  const createDevRunner = (deps: DevRunnerDeps): DevRunner => ({
604
612
  async run(entryPath: string): Promise<void> {
605
- const server = await deps.createServer(createDevServerConfig(process.cwd(), deps.plugins()));
613
+ const server = await deps.createServer(createDevServerConfig(process.cwd(), deps.plugins(entryPath)));
606
614
  const session = createSession(server, deps);
607
615
  deps.installShutdownHandlers(onShutdownSignal(session));
608
616
 
@@ -1,6 +1,8 @@
1
+ import { resolveDataDir } from "../internal/data-dir.js";
1
2
  import { prependSchemaDir, stageAndCompileProjectSchemas } from "../settings/schema.js";
2
3
 
3
- const prepareDevSchemaDir = (root: string, dataDir: string | null): string | null => {
4
+ const prepareDevSchemaDir = (root: string, isV2ResourceImports: boolean): string | null => {
5
+ const dataDir = isV2ResourceImports ? null : resolveDataDir(root);
4
6
  const dir = stageAndCompileProjectSchemas(root, dataDir);
5
7
 
6
8
  if (dir === null) {
@@ -20,6 +20,7 @@ type DevServerConfig = {
20
20
  configFileDependencies: string[];
21
21
  envDir: string | false;
22
22
  mode: string;
23
+ root: string;
23
24
  };
24
25
 
25
26
  type DevServer = {