@gtkx/cli 2.0.0-beta.4 → 2.0.0-beta.6

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 (62) hide show
  1. package/dist/builder.d.ts.map +1 -1
  2. package/dist/builder.js +28 -8
  3. package/dist/builder.js.map +1 -1
  4. package/dist/commands/dev.js +2 -2
  5. package/dist/commands/dev.js.map +1 -1
  6. package/dist/deploy/freedesktop/validate.d.ts.map +1 -1
  7. package/dist/deploy/freedesktop/validate.js +50 -13
  8. package/dist/deploy/freedesktop/validate.js.map +1 -1
  9. package/dist/dev/catalog-writes.d.ts +8 -0
  10. package/dist/dev/catalog-writes.d.ts.map +1 -0
  11. package/dist/dev/catalog-writes.js +26 -0
  12. package/dist/dev/catalog-writes.js.map +1 -0
  13. package/dist/dev/runner-deps.d.ts.map +1 -1
  14. package/dist/dev/runner-deps.js +10 -6
  15. package/dist/dev/runner-deps.js.map +1 -1
  16. package/dist/dev/runner.d.ts +1 -0
  17. package/dist/dev/runner.d.ts.map +1 -1
  18. package/dist/dev/runner.js +8 -2
  19. package/dist/dev/runner.js.map +1 -1
  20. package/dist/dev/supervisor.d.ts.map +1 -1
  21. package/dist/dev/supervisor.js +26 -20
  22. package/dist/dev/supervisor.js.map +1 -1
  23. package/dist/i18n/catalogs.d.ts +6 -2
  24. package/dist/i18n/catalogs.d.ts.map +1 -1
  25. package/dist/i18n/catalogs.js +9 -7
  26. package/dist/i18n/catalogs.js.map +1 -1
  27. package/dist/internal/agent-rules.d.ts.map +1 -1
  28. package/dist/internal/agent-rules.js +1 -0
  29. package/dist/internal/agent-rules.js.map +1 -1
  30. package/dist/internal/banner.d.ts +4 -2
  31. package/dist/internal/banner.d.ts.map +1 -1
  32. package/dist/internal/banner.js +16 -5
  33. package/dist/internal/banner.js.map +1 -1
  34. package/dist/vite-plugins/i18n.d.ts +11 -2
  35. package/dist/vite-plugins/i18n.d.ts.map +1 -1
  36. package/dist/vite-plugins/i18n.js +3 -2
  37. package/dist/vite-plugins/i18n.js.map +1 -1
  38. package/dist/vite-plugins/icons.d.ts.map +1 -1
  39. package/dist/vite-plugins/icons.js +6 -6
  40. package/dist/vite-plugins/icons.js.map +1 -1
  41. package/dist/vite-plugins/index.d.ts +2 -0
  42. package/dist/vite-plugins/index.d.ts.map +1 -1
  43. package/dist/vite-plugins/index.js +8 -2
  44. package/dist/vite-plugins/index.js.map +1 -1
  45. package/dist/vite-plugins/settings.d.ts.map +1 -1
  46. package/dist/vite-plugins/settings.js +6 -6
  47. package/dist/vite-plugins/settings.js.map +1 -1
  48. package/package.json +10 -10
  49. package/src/builder.ts +28 -8
  50. package/src/commands/dev.ts +2 -2
  51. package/src/deploy/freedesktop/validate.ts +70 -14
  52. package/src/dev/catalog-writes.ts +35 -0
  53. package/src/dev/runner-deps.ts +14 -6
  54. package/src/dev/runner.ts +11 -2
  55. package/src/dev/supervisor.ts +38 -21
  56. package/src/i18n/catalogs.ts +20 -8
  57. package/src/internal/agent-rules.ts +1 -0
  58. package/src/internal/banner.ts +23 -6
  59. package/src/vite-plugins/i18n.ts +20 -6
  60. package/src/vite-plugins/icons.ts +7 -7
  61. package/src/vite-plugins/index.ts +15 -6
  62. package/src/vite-plugins/settings.ts +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAmC,MAAM,MAAM,CAAC;AAS1E,KAAK,YAAY,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC,CAAC;AAoBF,QAAA,MAAM,KAAK,GAAU,SAAS,YAAY,KAAG,OAAO,CAAC,MAAM,CA0C1D,CAAC;AAEF,OAAO,EAAE,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAmC,MAAM,MAAM,CAAC;AAS1E,KAAK,YAAY,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC,CAAC;AAqEF,QAAA,MAAM,KAAK,GAAU,SAAS,YAAY,KAAG,OAAO,CAAC,MAAM,CAa1D,CAAC;AAEF,OAAO,EAAE,KAAK,EAAE,CAAC"}
package/dist/builder.js CHANGED
@@ -20,21 +20,20 @@ const buildDefaults = {
20
20
  minify: true,
21
21
  cssMinify: false,
22
22
  },
23
- define: {
24
- "process.env.NODE_ENV": JSON.stringify(BUILD_MODE),
25
- },
26
23
  };
27
- const build = async (options) => {
28
- const { entry, shouldPreserveI18nMetadata = true, vite: viteConfig } = options;
29
- const root = resolve(viteConfig?.root ?? process.cwd());
30
- const assetsDir = viteConfig?.build?.assetsDir ?? DEFAULT_ASSETS_DIR;
24
+ const forcedConfig = async (options, root, assetsDir) => {
25
+ const { entry, shouldPreserveI18nMetadata = true } = options;
31
26
  const buildManifest = createBuildManifestCollector();
32
27
  const loadedConfig = await loadConfig(root, { mode: BUILD_MODE, configFile: options.configFile });
33
28
  const buildConfigIdentity = {
34
29
  configFile: posix.normalize(relative(root, loadedConfig.configFile).replaceAll("\\", "/")),
35
30
  configDigest: configDigest(loadedConfig.config),
36
31
  };
37
- const forced = {
32
+ return {
33
+ mode: BUILD_MODE,
34
+ define: {
35
+ "process.env.NODE_ENV": JSON.stringify(BUILD_MODE),
36
+ },
38
37
  plugins: [
39
38
  ...gtkxVitePlugins({
40
39
  mode: BUILD_MODE,
@@ -60,9 +59,30 @@ const build = async (options) => {
60
59
  },
61
60
  },
62
61
  };
62
+ };
63
+ const buildProduction = async (options) => {
64
+ const viteConfig = options.vite;
65
+ const root = resolve(viteConfig?.root ?? process.cwd());
66
+ const assetsDir = viteConfig?.build?.assetsDir ?? DEFAULT_ASSETS_DIR;
67
+ const forced = await forcedConfig(options, root, assetsDir);
63
68
  const merged = mergeConfig(mergeConfig(buildDefaults, viteConfig ?? {}), forced);
64
69
  await viteBuild({ ...merged, ssr: { ...merged.ssr, noExternal: true } });
65
70
  return join(merged.build?.outDir ?? DEFAULT_OUT_DIR, ENTRY_FILE_NAMES);
66
71
  };
72
+ const build = async (options) => {
73
+ const callerNodeEnv = process.env.NODE_ENV;
74
+ process.env.NODE_ENV = BUILD_MODE;
75
+ try {
76
+ return await buildProduction(options);
77
+ }
78
+ finally {
79
+ if (callerNodeEnv === undefined) {
80
+ delete process.env.NODE_ENV;
81
+ }
82
+ else {
83
+ process.env.NODE_ENV = callerNodeEnv;
84
+ }
85
+ }
86
+ };
67
87
  export { build };
68
88
  //# sourceMappingURL=builder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"builder.js","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { loadConfig } from \"@gtkx/config\";\nimport { join, posix, relative, resolve } from \"node:path\";\nimport { type InlineConfig, mergeConfig, build as viteBuild } from \"vite\";\nimport { configDigest, createBuildManifestCollector } from \"./internal/build-manifest.js\";\nimport { gtkxBuildManifest } from \"./vite-plugins/build-manifest.js\";\nimport { BUNDLE_FILENAME, ESM_EXTENSION } from \"./vite-plugins/esm-extension.js\";\nimport { gtkxVitePlugins } from \"./vite-plugins/index.js\";\nimport { gtkxNative } from \"./vite-plugins/native.js\";\nimport { gtkxSelfContained } from \"./vite-plugins/self-contained.js\";\nimport { gtkxWorker } from \"./vite-plugins/worker.js\";\n\ntype BuildOptions = {\n entry: string;\n configFile?: string | undefined;\n shouldPreserveI18nMetadata?: boolean | undefined;\n vite?: InlineConfig | undefined;\n};\n\nconst BUILD_MODE = \"production\";\nconst CHUNK_STEM = \"[name]-[hash]\";\nconst DEFAULT_OUT_DIR = \"dist\";\nconst DEFAULT_ASSETS_DIR = \"assets\";\nconst ENTRY_FILE_NAMES = BUNDLE_FILENAME;\n\nconst buildDefaults: InlineConfig = {\n build: {\n ssrEmitAssets: true,\n outDir: DEFAULT_OUT_DIR,\n minify: true,\n cssMinify: false,\n },\n define: {\n \"process.env.NODE_ENV\": JSON.stringify(BUILD_MODE),\n },\n};\n\nconst build = async (options: BuildOptions): Promise<string> => {\n const { entry, shouldPreserveI18nMetadata = true, vite: viteConfig } = options;\n const root = resolve(viteConfig?.root ?? process.cwd());\n const assetsDir = viteConfig?.build?.assetsDir ?? DEFAULT_ASSETS_DIR;\n const buildManifest = createBuildManifestCollector();\n const loadedConfig = await loadConfig(root, { mode: BUILD_MODE, configFile: options.configFile });\n const buildConfigIdentity = {\n configFile: posix.normalize(relative(root, loadedConfig.configFile).replaceAll(\"\\\\\", \"/\")),\n configDigest: configDigest(loadedConfig.config),\n };\n\n const forced: InlineConfig = {\n plugins: [\n ...gtkxVitePlugins({\n mode: BUILD_MODE,\n entryPath: entry,\n buildManifest,\n shouldPreserveI18nMetadata,\n configFile: options.configFile,\n }),\n gtkxWorker(),\n gtkxNative(root),\n gtkxBuildManifest(root, buildManifest, buildConfigIdentity),\n gtkxSelfContained(),\n ],\n build: {\n ssr: entry,\n assetsInlineLimit: 0,\n rolldownOptions: {\n output: {\n entryFileNames: ENTRY_FILE_NAMES,\n chunkFileNames: posix.join(assetsDir, CHUNK_STEM + ESM_EXTENSION),\n keepNames: true,\n },\n },\n },\n };\n\n const merged: InlineConfig = mergeConfig(mergeConfig(buildDefaults, viteConfig ?? {}), forced);\n await viteBuild({ ...merged, ssr: { ...merged.ssr, noExternal: true } });\n\n return join(merged.build?.outDir ?? DEFAULT_OUT_DIR, ENTRY_FILE_NAMES);\n};\n\nexport { build };\n"]}
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAqB,WAAW,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAStD,MAAM,UAAU,GAAG,YAAY,CAAC;AAChC,MAAM,UAAU,GAAG,eAAe,CAAC;AACnC,MAAM,eAAe,GAAG,MAAM,CAAC;AAC/B,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AACpC,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAEzC,MAAM,aAAa,GAAiB;IAChC,KAAK,EAAE;QACH,aAAa,EAAE,IAAI;QACnB,MAAM,EAAE,eAAe;QACvB,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,KAAK;KACnB;CACJ,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,EAAE,OAAqB,EAAE,IAAY,EAAE,SAAiB,EAAyB,EAAE;IACzG,MAAM,EAAE,KAAK,EAAE,0BAA0B,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAC7D,MAAM,aAAa,GAAG,4BAA4B,EAAE,CAAC;IACrD,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAClG,MAAM,mBAAmB,GAAG;QACxB,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC1F,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC;KAClD,CAAC;IAEF,OAAO;QACH,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE;YACJ,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;SACrD;QACD,OAAO,EAAE;YACL,GAAG,eAAe,CAAC;gBACf,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE,KAAK;gBAChB,aAAa;gBACb,0BAA0B;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;aACjC,CAAC;YACF,UAAU,EAAE;YACZ,UAAU,CAAC,IAAI,CAAC;YAChB,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,mBAAmB,CAAC;YAC3D,iBAAiB,EAAE;SACtB;QACD,KAAK,EAAE;YACH,GAAG,EAAE,KAAK;YACV,iBAAiB,EAAE,CAAC;YACpB,eAAe,EAAE;gBACb,MAAM,EAAE;oBACJ,cAAc,EAAE,gBAAgB;oBAChC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,aAAa,CAAC;oBACjE,SAAS,EAAE,IAAI;iBAClB;aACJ;SACJ;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,EAAE,OAAqB,EAAmB,EAAE;IACrE,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAChC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,UAAU,EAAE,KAAK,EAAE,SAAS,IAAI,kBAAkB,CAAC;IACrE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAiB,WAAW,CAAC,WAAW,CAAC,aAAa,EAAE,UAAU,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/F,MAAM,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAEzE,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,KAAK,EAAE,OAAqB,EAAmB,EAAE;IAC3D,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC;IAElC,IAAI,CAAC;QACD,OAAO,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;YAAS,CAAC;QACP,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAChC,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;QACzC,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,EAAE,KAAK,EAAE,CAAC","sourcesContent":["import { loadConfig } from \"@gtkx/config\";\nimport { join, posix, relative, resolve } from \"node:path\";\nimport { type InlineConfig, mergeConfig, build as viteBuild } from \"vite\";\nimport { configDigest, createBuildManifestCollector } from \"./internal/build-manifest.js\";\nimport { gtkxBuildManifest } from \"./vite-plugins/build-manifest.js\";\nimport { BUNDLE_FILENAME, ESM_EXTENSION } from \"./vite-plugins/esm-extension.js\";\nimport { gtkxVitePlugins } from \"./vite-plugins/index.js\";\nimport { gtkxNative } from \"./vite-plugins/native.js\";\nimport { gtkxSelfContained } from \"./vite-plugins/self-contained.js\";\nimport { gtkxWorker } from \"./vite-plugins/worker.js\";\n\ntype BuildOptions = {\n entry: string;\n configFile?: string | undefined;\n shouldPreserveI18nMetadata?: boolean | undefined;\n vite?: InlineConfig | undefined;\n};\n\nconst BUILD_MODE = \"production\";\nconst CHUNK_STEM = \"[name]-[hash]\";\nconst DEFAULT_OUT_DIR = \"dist\";\nconst DEFAULT_ASSETS_DIR = \"assets\";\nconst ENTRY_FILE_NAMES = BUNDLE_FILENAME;\n\nconst buildDefaults: InlineConfig = {\n build: {\n ssrEmitAssets: true,\n outDir: DEFAULT_OUT_DIR,\n minify: true,\n cssMinify: false,\n },\n};\n\nconst forcedConfig = async (options: BuildOptions, root: string, assetsDir: string): Promise<InlineConfig> => {\n const { entry, shouldPreserveI18nMetadata = true } = options;\n const buildManifest = createBuildManifestCollector();\n const loadedConfig = await loadConfig(root, { mode: BUILD_MODE, configFile: options.configFile });\n const buildConfigIdentity = {\n configFile: posix.normalize(relative(root, loadedConfig.configFile).replaceAll(\"\\\\\", \"/\")),\n configDigest: configDigest(loadedConfig.config),\n };\n\n return {\n mode: BUILD_MODE,\n define: {\n \"process.env.NODE_ENV\": JSON.stringify(BUILD_MODE),\n },\n plugins: [\n ...gtkxVitePlugins({\n mode: BUILD_MODE,\n entryPath: entry,\n buildManifest,\n shouldPreserveI18nMetadata,\n configFile: options.configFile,\n }),\n gtkxWorker(),\n gtkxNative(root),\n gtkxBuildManifest(root, buildManifest, buildConfigIdentity),\n gtkxSelfContained(),\n ],\n build: {\n ssr: entry,\n assetsInlineLimit: 0,\n rolldownOptions: {\n output: {\n entryFileNames: ENTRY_FILE_NAMES,\n chunkFileNames: posix.join(assetsDir, CHUNK_STEM + ESM_EXTENSION),\n keepNames: true,\n },\n },\n },\n };\n};\n\nconst buildProduction = async (options: BuildOptions): Promise<string> => {\n const viteConfig = options.vite;\n const root = resolve(viteConfig?.root ?? process.cwd());\n const assetsDir = viteConfig?.build?.assetsDir ?? DEFAULT_ASSETS_DIR;\n const forced = await forcedConfig(options, root, assetsDir);\n const merged: InlineConfig = mergeConfig(mergeConfig(buildDefaults, viteConfig ?? {}), forced);\n await viteBuild({ ...merged, ssr: { ...merged.ssr, noExternal: true } });\n\n return join(merged.build?.outDir ?? DEFAULT_OUT_DIR, ENTRY_FILE_NAMES);\n};\n\nconst build = async (options: BuildOptions): Promise<string> => {\n const callerNodeEnv = process.env.NODE_ENV;\n process.env.NODE_ENV = BUILD_MODE;\n\n try {\n return await buildProduction(options);\n } finally {\n if (callerNodeEnv === undefined) {\n delete process.env.NODE_ENV;\n } else {\n process.env.NODE_ENV = callerNodeEnv;\n }\n }\n};\n\nexport { build };\n"]}
@@ -1,5 +1,5 @@
1
1
  import { armParentDeath } from "@gtkx/native/internal";
2
- import { reapStaleHeadlessDisplays } from "@gtkx/vitest/headless";
2
+ import { reapStaleHeadlessDisplaysAtStartup } from "@gtkx/vitest/headless";
3
3
  import { defineCommand } from "citty";
4
4
  import { resolveConfigWatch } from "../codegen/run-codegen.js";
5
5
  import { startHeadlessDevDisplay } from "../dev/headless.js";
@@ -27,7 +27,7 @@ const dev = defineCommand({
27
27
  },
28
28
  },
29
29
  async run({ args }) {
30
- reapStaleHeadlessDisplays();
30
+ reapStaleHeadlessDisplaysAtStartup();
31
31
  const initialProcessGroupOwner = getInitialProcessGroupOwner();
32
32
  if (!armParentDeath(initialParentId, initialProcessGroupOwner?.pid, initialProcessGroupOwner?.startTime)) {
33
33
  throw new Error("The process that launched gtkx dev exited during startup");
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAiB,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,MAAM,QAAQ,GAAG,aAAa,CAAC;AAE/B,MAAM,GAAG,GAAG,aAAa,CAAC;IACtB,IAAI,EAAE;QACF,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,mCAAmC;KACnD;IACD,IAAI,EAAE;QACF,GAAG,QAAQ;QACX,GAAG,SAAS;QACZ,QAAQ,EAAE;YACN,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6CAA6C;SAC7D;QACD,IAAI,EAAE;YACF,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,uCAAuC;SACvD;KACJ;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QACd,yBAAyB,EAAE,CAAC;QAC5B,MAAM,wBAAwB,GAAG,2BAA2B,EAAE,CAAC;QAE/D,IACI,CAAC,cAAc,CACX,eAAe,EACf,wBAAwB,EAAE,GAAG,EAC7B,wBAAwB,EAAE,SAAS,CACtC,EACH,CAAC;YACC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvG,MAAM,KAAK,GAAyB,MAAM,kBAAkB,CACxD,GAAG,EACH,QAAQ,EACR,UAAU,EACV,kBAAkB,CACrB,CAAC;QACF,MAAM,EAAE,eAAe,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE1F,IAAI,CAAC;YACD,MAAM,gBAAgB,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;QACzF,CAAC;gBAAS,CAAC;YACP,YAAY,EAAE,EAAE,CAAC;QACrB,CAAC;IACL,CAAC;CACJ,CAAC,CAAC;AAEH,OAAO,EAAE,GAAG,EAAE,CAAC","sourcesContent":["import { armParentDeath } from \"@gtkx/native/internal\";\nimport { reapStaleHeadlessDisplays } from \"@gtkx/vitest/headless\";\nimport { defineCommand } from \"citty\";\nimport { resolveConfigWatch } from \"../codegen/run-codegen.js\";\nimport { startHeadlessDevDisplay } from \"../dev/headless.js\";\nimport { type DevWatch, runDevSupervisor } from \"../dev/supervisor.js\";\nimport { splitApplicationArgs } from \"../internal/application-args.js\";\nimport { configArg, entryArg } from \"../internal/entry-arg.js\";\nimport { getInitialProcessGroupOwner, initialParentId } from \"../internal/parent-process.js\";\nimport { prepareProject } from \"../internal/prepare-project.js\";\n\nconst DEV_MODE = \"development\";\n\nconst dev = defineCommand({\n meta: {\n name: \"dev\",\n description: \"Start development server with HMR\",\n },\n args: {\n ...entryArg,\n ...configArg,\n headless: {\n type: \"boolean\",\n description: \"Run on an isolated headless Wayland display\",\n },\n size: {\n type: \"string\",\n description: \"Headless display size as WIDTHxHEIGHT\",\n },\n },\n async run({ args }) {\n reapStaleHeadlessDisplays();\n const initialProcessGroupOwner = getInitialProcessGroupOwner();\n\n if (\n !armParentDeath(\n initialParentId,\n initialProcessGroupOwner?.pid,\n initialProcessGroupOwner?.startTime,\n )\n ) {\n throw new Error(\"The process that launched gtkx dev exited during startup\");\n }\n\n if (args.size !== undefined && !args.headless) {\n throw new Error(\"--size requires --headless\");\n }\n\n const { cwd, entry: entryPath, configFile, configDependencies } = await prepareProject(args, DEV_MODE);\n const watch: DevWatch | undefined = await resolveConfigWatch(\n cwd,\n DEV_MODE,\n configFile,\n configDependencies,\n );\n const { applicationArgs } = splitApplicationArgs(process.argv.slice(2));\n const stopHeadless = args.headless ? await startHeadlessDevDisplay(args.size) : undefined;\n\n try {\n await runDevSupervisor({ entryPath, cwd, configFile, args: applicationArgs, watch });\n } finally {\n stopHeadless?.();\n }\n },\n});\n\nexport { dev };\n"]}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAiB,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,MAAM,QAAQ,GAAG,aAAa,CAAC;AAE/B,MAAM,GAAG,GAAG,aAAa,CAAC;IACtB,IAAI,EAAE;QACF,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,mCAAmC;KACnD;IACD,IAAI,EAAE;QACF,GAAG,QAAQ;QACX,GAAG,SAAS;QACZ,QAAQ,EAAE;YACN,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6CAA6C;SAC7D;QACD,IAAI,EAAE;YACF,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,uCAAuC;SACvD;KACJ;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QACd,kCAAkC,EAAE,CAAC;QACrC,MAAM,wBAAwB,GAAG,2BAA2B,EAAE,CAAC;QAE/D,IACI,CAAC,cAAc,CACX,eAAe,EACf,wBAAwB,EAAE,GAAG,EAC7B,wBAAwB,EAAE,SAAS,CACtC,EACH,CAAC;YACC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvG,MAAM,KAAK,GAAyB,MAAM,kBAAkB,CACxD,GAAG,EACH,QAAQ,EACR,UAAU,EACV,kBAAkB,CACrB,CAAC;QACF,MAAM,EAAE,eAAe,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE1F,IAAI,CAAC;YACD,MAAM,gBAAgB,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;QACzF,CAAC;gBAAS,CAAC;YACP,YAAY,EAAE,EAAE,CAAC;QACrB,CAAC;IACL,CAAC;CACJ,CAAC,CAAC;AAEH,OAAO,EAAE,GAAG,EAAE,CAAC","sourcesContent":["import { armParentDeath } from \"@gtkx/native/internal\";\nimport { reapStaleHeadlessDisplaysAtStartup } from \"@gtkx/vitest/headless\";\nimport { defineCommand } from \"citty\";\nimport { resolveConfigWatch } from \"../codegen/run-codegen.js\";\nimport { startHeadlessDevDisplay } from \"../dev/headless.js\";\nimport { type DevWatch, runDevSupervisor } from \"../dev/supervisor.js\";\nimport { splitApplicationArgs } from \"../internal/application-args.js\";\nimport { configArg, entryArg } from \"../internal/entry-arg.js\";\nimport { getInitialProcessGroupOwner, initialParentId } from \"../internal/parent-process.js\";\nimport { prepareProject } from \"../internal/prepare-project.js\";\n\nconst DEV_MODE = \"development\";\n\nconst dev = defineCommand({\n meta: {\n name: \"dev\",\n description: \"Start development server with HMR\",\n },\n args: {\n ...entryArg,\n ...configArg,\n headless: {\n type: \"boolean\",\n description: \"Run on an isolated headless Wayland display\",\n },\n size: {\n type: \"string\",\n description: \"Headless display size as WIDTHxHEIGHT\",\n },\n },\n async run({ args }) {\n reapStaleHeadlessDisplaysAtStartup();\n const initialProcessGroupOwner = getInitialProcessGroupOwner();\n\n if (\n !armParentDeath(\n initialParentId,\n initialProcessGroupOwner?.pid,\n initialProcessGroupOwner?.startTime,\n )\n ) {\n throw new Error(\"The process that launched gtkx dev exited during startup\");\n }\n\n if (args.size !== undefined && !args.headless) {\n throw new Error(\"--size requires --headless\");\n }\n\n const { cwd, entry: entryPath, configFile, configDependencies } = await prepareProject(args, DEV_MODE);\n const watch: DevWatch | undefined = await resolveConfigWatch(\n cwd,\n DEV_MODE,\n configFile,\n configDependencies,\n );\n const { applicationArgs } = splitApplicationArgs(process.argv.slice(2));\n const stopHeadless = args.headless ? await startHeadlessDevDisplay(args.size) : undefined;\n\n try {\n await runDevSupervisor({ entryPath, cwd, configFile, args: applicationArgs, watch });\n } finally {\n stopHeadless?.();\n }\n },\n});\n\nexport { dev };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/deploy/freedesktop/validate.ts"],"names":[],"mappings":"AAuGA,QAAA,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,IAU5C,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,MAAM,MAAM,EAAE,kBAAkB,OAAO,KAAG,IAenE,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/deploy/freedesktop/validate.ts"],"names":[],"mappings":"AA8IA,QAAA,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,IAgB5C,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,MAAM,MAAM,EAAE,kBAAkB,OAAO,KAAG,IA0BnE,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1,10 +1,16 @@
1
1
  import { resolveExecutable, sortStrings, warn } from "@gtkx/utils";
2
2
  import { spawnSync } from "node:child_process";
3
- const DIAGNOSTIC = /^(?<severity>[EIPW]): \S+ (?<rule>[\w-]+)/;
3
+ const DIAGNOSTIC = /^(?<severity>[EIPW]): \S+ (?<rule>[\w-]+)(?: (?<detail>.*))?$/;
4
+ const SUCCESS_SUMMARY = /^\W*Validation was successful/u;
4
5
  const ERROR_SEVERITY = "E";
5
6
  const WARNING_SEVERITY = "W";
6
7
  const INFO_SEVERITY = "I";
7
8
  const FATAL_WARNING_RULES = new Set(["unknown-tag"]);
9
+ const DESKTOP_ERROR = /(?:^|:\s)error:/iu;
10
+ const FATAL_RULE_NOTES = {
11
+ "unknown-tag": (element) => "GTKX treats unknown-tag as fatal for every target, whatever severity appstreamcli assigns it; " +
12
+ `the unsupported element is <${element}>`,
13
+ };
8
14
  const REMEDY_FOR_RULE = {
9
15
  "component-summary-missing": "set `deploy.summary`",
10
16
  "description-first-para-too-short": "open `deploy.description` with a paragraph longer than 80 characters",
@@ -22,18 +28,34 @@ const runTool = ({ tool, args, subject }) => {
22
28
  }
23
29
  return { output: [result.stdout, result.stderr].join("\n").trim(), status: result.status ?? 0 };
24
30
  };
25
- const rulesIn = (output, severities) => output
31
+ const parseDiagnostics = (output) => output.split("\n").flatMap((line) => {
32
+ const groups = DIAGNOSTIC.exec(line)?.groups;
33
+ return groups === undefined
34
+ ? []
35
+ : [{ severity: groups.severity ?? "", rule: groups.rule ?? "", detail: (groups.detail ?? "").trim() }];
36
+ });
37
+ const rulesIn = (diagnostics, severities) => diagnostics.filter((diagnostic) => severities.includes(diagnostic.severity)).map((diagnostic) => diagnostic.rule);
38
+ const fatalNotes = (diagnostics) => diagnostics
39
+ .filter((diagnostic) => diagnostic.severity !== ERROR_SEVERITY && FATAL_WARNING_RULES.has(diagnostic.rule))
40
+ .map((diagnostic) => FATAL_RULE_NOTES[diagnostic.rule]?.(diagnostic.detail) ??
41
+ `GTKX treats ${diagnostic.rule} as fatal for every target`);
42
+ const withoutSuccessSummary = (output) => output
26
43
  .split("\n")
27
- .map((line) => DIAGNOSTIC.exec(line)?.groups)
28
- .filter((groups) => groups !== undefined && severities.includes(groups.severity ?? ""))
29
- .map((groups) => groups?.rule ?? "");
44
+ .filter((line) => !SUCCESS_SUMMARY.test(line))
45
+ .join("\n")
46
+ .trimEnd();
30
47
  const remedyLines = (rules) => {
31
48
  const remedies = sortStrings([...new Set(rules)])
32
49
  .filter((rule) => REMEDY_FOR_RULE[rule] !== undefined)
33
50
  .map((rule) => ` ${rule}: ${REMEDY_FOR_RULE[rule] ?? ""}`);
34
51
  return remedies.length === 0 ? [] : ["", "Fix it in gtkx.config.ts:", ...remedies];
35
52
  };
36
- const invalid = (subject, output, rules) => new Error([`${subject} is not valid:`, output.length > 0 ? output : "no output", ...remedyLines(rules)].join("\n"));
53
+ const invalid = (subject, output, rules, notes) => new Error([
54
+ `${subject} is not valid:`,
55
+ output.length > 0 ? output : "no output",
56
+ ...notes,
57
+ ...remedyLines(rules),
58
+ ].join("\n"));
37
59
  const isFatalResult = ({ status, errors, warnings, rules, areWarningsFatal }) => {
38
60
  if (errors.length > 0) {
39
61
  return true;
@@ -48,7 +70,7 @@ const isFatalResult = ({ status, errors, warnings, rules, areWarningsFatal }) =>
48
70
  };
49
71
  const assertNotFatal = (result) => {
50
72
  if (isFatalResult(result)) {
51
- throw invalid(result.subject, result.output, result.rules);
73
+ throw invalid(result.subject, result.output, result.rules, result.notes);
52
74
  }
53
75
  };
54
76
  const describeRule = (rule) => {
@@ -66,8 +88,12 @@ const validateDesktopEntry = (path) => {
66
88
  args: [path],
67
89
  subject: "The desktop entry",
68
90
  });
69
- if (status !== 0 || output.length > 0) {
70
- throw invalid("The desktop entry", output, []);
91
+ const diagnostics = output.split("\n").filter((line) => line.length > 0);
92
+ if (status !== 0 || diagnostics.some((line) => DESKTOP_ERROR.test(line))) {
93
+ throw invalid("The desktop entry", output, [], []);
94
+ }
95
+ for (const diagnostic of diagnostics) {
96
+ warn(diagnostic);
71
97
  }
72
98
  };
73
99
  const validateMetainfo = (path, areWarningsFatal) => {
@@ -77,11 +103,22 @@ const validateMetainfo = (path, areWarningsFatal) => {
77
103
  args: ["validate", "--no-net", "--explain", path],
78
104
  subject,
79
105
  });
80
- const errors = rulesIn(output, [ERROR_SEVERITY]);
81
- const warnings = rulesIn(output, [WARNING_SEVERITY]);
82
- const infos = rulesIn(output, [INFO_SEVERITY]);
106
+ const diagnostics = parseDiagnostics(output);
107
+ const errors = rulesIn(diagnostics, [ERROR_SEVERITY]);
108
+ const warnings = rulesIn(diagnostics, [WARNING_SEVERITY]);
109
+ const infos = rulesIn(diagnostics, [INFO_SEVERITY]);
83
110
  const rules = [...errors, ...warnings, ...infos];
84
- assertNotFatal({ subject, output, status, errors, warnings, rules, areWarningsFatal });
111
+ const notes = fatalNotes(diagnostics);
112
+ assertNotFatal({
113
+ subject,
114
+ output: withoutSuccessSummary(output),
115
+ status,
116
+ errors,
117
+ warnings,
118
+ rules,
119
+ notes,
120
+ areWarningsFatal,
121
+ });
85
122
  reportDiagnostics(subject, [...warnings, ...infos]);
86
123
  };
87
124
  export { validateDesktopEntry, validateMetainfo };
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/deploy/freedesktop/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveExecutable, sortStrings, warn } from \"@gtkx/utils\";\nimport { spawnSync } from \"node:child_process\";\n\ntype ToolResult = {\n output: string;\n status: number;\n};\n\ntype MetainfoResult = {\n subject: string;\n output: string;\n status: number;\n errors: string[];\n warnings: string[];\n rules: string[];\n areWarningsFatal: boolean;\n};\n\ntype ToolRequest = {\n tool: string;\n args: string[];\n subject: string;\n};\n\nconst DIAGNOSTIC = /^(?<severity>[EIPW]): \\S+ (?<rule>[\\w-]+)/;\nconst ERROR_SEVERITY = \"E\";\nconst WARNING_SEVERITY = \"W\";\nconst INFO_SEVERITY = \"I\";\nconst FATAL_WARNING_RULES: Set<string> = new Set([\"unknown-tag\"]);\n\nconst REMEDY_FOR_RULE: Record<string, string> = {\n \"component-summary-missing\": \"set `deploy.summary`\",\n \"description-first-para-too-short\": \"open `deploy.description` with a paragraph longer than 80 characters\",\n \"developer-info-missing\": \"set `deploy.developer.name`\",\n \"metainfo-legacy-path\": \"this file is generated; report it as a gtkx bug\",\n \"summary-has-dot-suffix\": \"drop the trailing period from `deploy.summary`\",\n \"summary-too-long\": \"shorten `deploy.summary`\",\n \"unknown-tag\": \"remove the unsupported `deploy.metainfoExtra` element or use a `<custom>` value\",\n \"url-homepage-missing\": \"set `deploy.homepage`, or `homepage` in package.json\",\n};\n\nconst runTool = ({ tool, args, subject }: ToolRequest): ToolResult => {\n const result = spawnSync(resolveExecutable(tool), args, { encoding: \"utf8\" });\n\n if (result.error !== undefined) {\n throw new Error(`${subject} could not be validated: ${result.error.message}`, { cause: result.error });\n }\n\n return { output: [result.stdout, result.stderr].join(\"\\n\").trim(), status: result.status ?? 0 };\n};\n\nconst rulesIn = (output: string, severities: string[]): string[] =>\n output\n .split(\"\\n\")\n .map((line) => DIAGNOSTIC.exec(line)?.groups)\n .filter((groups) => groups !== undefined && severities.includes(groups.severity ?? \"\"))\n .map((groups) => groups?.rule ?? \"\");\n\nconst remedyLines = (rules: string[]): string[] => {\n const remedies = sortStrings([...new Set(rules)])\n .filter((rule) => REMEDY_FOR_RULE[rule] !== undefined)\n .map((rule) => ` ${rule}: ${REMEDY_FOR_RULE[rule] ?? \"\"}`);\n\n return remedies.length === 0 ? [] : [\"\", \"Fix it in gtkx.config.ts:\", ...remedies];\n};\n\nconst invalid = (subject: string, output: string, rules: string[]): Error =>\n new Error([`${subject} is not valid:`, output.length > 0 ? output : \"no output\", ...remedyLines(rules)].join(\"\\n\"));\n\nconst isFatalResult = ({ status, errors, warnings, rules, areWarningsFatal }: MetainfoResult): boolean => {\n if (errors.length > 0) {\n return true;\n }\n\n if (rules.some((rule) => FATAL_WARNING_RULES.has(rule))) {\n return true;\n }\n\n if (areWarningsFatal && warnings.length > 0) {\n return true;\n }\n\n return status !== 0 && warnings.length === 0;\n};\n\nconst assertNotFatal = (result: MetainfoResult): void => {\n if (isFatalResult(result)) {\n throw invalid(result.subject, result.output, result.rules);\n }\n};\n\nconst describeRule = (rule: string): string => {\n const remedy = REMEDY_FOR_RULE[rule];\n\n return remedy === undefined ? rule : `${rule} — ${remedy}`;\n};\n\nconst reportDiagnostics = (subject: string, rules: string[]): void => {\n for (const rule of rules) {\n warn(`${subject}: ${describeRule(rule)}`);\n }\n};\n\nconst validateDesktopEntry = (path: string): void => {\n const { output, status } = runTool({\n tool: \"desktop-file-validate\",\n args: [path],\n subject: \"The desktop entry\",\n });\n\n if (status !== 0 || output.length > 0) {\n throw invalid(\"The desktop entry\", output, []);\n }\n};\n\nconst validateMetainfo = (path: string, areWarningsFatal: boolean): void => {\n const subject = \"The AppStream metainfo\";\n\n const { output, status } = runTool({\n tool: \"appstreamcli\",\n args: [\"validate\", \"--no-net\", \"--explain\", path],\n subject,\n });\n\n const errors = rulesIn(output, [ERROR_SEVERITY]);\n const warnings = rulesIn(output, [WARNING_SEVERITY]);\n const infos = rulesIn(output, [INFO_SEVERITY]);\n const rules = [...errors, ...warnings, ...infos];\n assertNotFatal({ subject, output, status, errors, warnings, rules, areWarningsFatal });\n reportDiagnostics(subject, [...warnings, ...infos]);\n};\n\nexport { validateDesktopEntry, validateMetainfo };\n"]}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/deploy/freedesktop/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveExecutable, sortStrings, warn } from \"@gtkx/utils\";\nimport { spawnSync } from \"node:child_process\";\n\ntype ToolResult = {\n output: string;\n status: number;\n};\n\ntype Diagnostic = {\n severity: string;\n rule: string;\n detail: string;\n};\n\ntype MetainfoResult = {\n subject: string;\n output: string;\n status: number;\n errors: string[];\n warnings: string[];\n rules: string[];\n notes: string[];\n areWarningsFatal: boolean;\n};\n\ntype ToolRequest = {\n tool: string;\n args: string[];\n subject: string;\n};\n\nconst DIAGNOSTIC = /^(?<severity>[EIPW]): \\S+ (?<rule>[\\w-]+)(?: (?<detail>.*))?$/;\nconst SUCCESS_SUMMARY = /^\\W*Validation was successful/u;\nconst ERROR_SEVERITY = \"E\";\nconst WARNING_SEVERITY = \"W\";\nconst INFO_SEVERITY = \"I\";\nconst FATAL_WARNING_RULES: Set<string> = new Set([\"unknown-tag\"]);\nconst DESKTOP_ERROR = /(?:^|:\\s)error:/iu;\n\nconst FATAL_RULE_NOTES: Record<string, (detail: string) => string> = {\n \"unknown-tag\": (element) =>\n \"GTKX treats unknown-tag as fatal for every target, whatever severity appstreamcli assigns it; \" +\n `the unsupported element is <${element}>`,\n};\n\nconst REMEDY_FOR_RULE: Record<string, string> = {\n \"component-summary-missing\": \"set `deploy.summary`\",\n \"description-first-para-too-short\": \"open `deploy.description` with a paragraph longer than 80 characters\",\n \"developer-info-missing\": \"set `deploy.developer.name`\",\n \"metainfo-legacy-path\": \"this file is generated; report it as a gtkx bug\",\n \"summary-has-dot-suffix\": \"drop the trailing period from `deploy.summary`\",\n \"summary-too-long\": \"shorten `deploy.summary`\",\n \"unknown-tag\": \"remove the unsupported `deploy.metainfoExtra` element or use a `<custom>` value\",\n \"url-homepage-missing\": \"set `deploy.homepage`, or `homepage` in package.json\",\n};\n\nconst runTool = ({ tool, args, subject }: ToolRequest): ToolResult => {\n const result = spawnSync(resolveExecutable(tool), args, { encoding: \"utf8\" });\n\n if (result.error !== undefined) {\n throw new Error(`${subject} could not be validated: ${result.error.message}`, { cause: result.error });\n }\n\n return { output: [result.stdout, result.stderr].join(\"\\n\").trim(), status: result.status ?? 0 };\n};\n\nconst parseDiagnostics = (output: string): Diagnostic[] =>\n output.split(\"\\n\").flatMap((line) => {\n const groups = DIAGNOSTIC.exec(line)?.groups;\n\n return groups === undefined\n ? []\n : [{ severity: groups.severity ?? \"\", rule: groups.rule ?? \"\", detail: (groups.detail ?? \"\").trim() }];\n });\n\nconst rulesIn = (diagnostics: Diagnostic[], severities: string[]): string[] =>\n diagnostics.filter((diagnostic) => severities.includes(diagnostic.severity)).map((diagnostic) => diagnostic.rule);\n\nconst fatalNotes = (diagnostics: Diagnostic[]): string[] =>\n diagnostics\n .filter((diagnostic) => diagnostic.severity !== ERROR_SEVERITY && FATAL_WARNING_RULES.has(diagnostic.rule))\n .map((diagnostic) =>\n FATAL_RULE_NOTES[diagnostic.rule]?.(diagnostic.detail) ??\n `GTKX treats ${diagnostic.rule} as fatal for every target`);\n\nconst withoutSuccessSummary = (output: string): string =>\n output\n .split(\"\\n\")\n .filter((line) => !SUCCESS_SUMMARY.test(line))\n .join(\"\\n\")\n .trimEnd();\n\nconst remedyLines = (rules: string[]): string[] => {\n const remedies = sortStrings([...new Set(rules)])\n .filter((rule) => REMEDY_FOR_RULE[rule] !== undefined)\n .map((rule) => ` ${rule}: ${REMEDY_FOR_RULE[rule] ?? \"\"}`);\n\n return remedies.length === 0 ? [] : [\"\", \"Fix it in gtkx.config.ts:\", ...remedies];\n};\n\nconst invalid = (subject: string, output: string, rules: string[], notes: string[]): Error =>\n new Error([\n `${subject} is not valid:`,\n output.length > 0 ? output : \"no output\",\n ...notes,\n ...remedyLines(rules),\n ].join(\"\\n\"));\n\nconst isFatalResult = ({ status, errors, warnings, rules, areWarningsFatal }: MetainfoResult): boolean => {\n if (errors.length > 0) {\n return true;\n }\n\n if (rules.some((rule) => FATAL_WARNING_RULES.has(rule))) {\n return true;\n }\n\n if (areWarningsFatal && warnings.length > 0) {\n return true;\n }\n\n return status !== 0 && warnings.length === 0;\n};\n\nconst assertNotFatal = (result: MetainfoResult): void => {\n if (isFatalResult(result)) {\n throw invalid(result.subject, result.output, result.rules, result.notes);\n }\n};\n\nconst describeRule = (rule: string): string => {\n const remedy = REMEDY_FOR_RULE[rule];\n\n return remedy === undefined ? rule : `${rule} — ${remedy}`;\n};\n\nconst reportDiagnostics = (subject: string, rules: string[]): void => {\n for (const rule of rules) {\n warn(`${subject}: ${describeRule(rule)}`);\n }\n};\n\nconst validateDesktopEntry = (path: string): void => {\n const { output, status } = runTool({\n tool: \"desktop-file-validate\",\n args: [path],\n subject: \"The desktop entry\",\n });\n\n const diagnostics = output.split(\"\\n\").filter((line) => line.length > 0);\n\n if (status !== 0 || diagnostics.some((line) => DESKTOP_ERROR.test(line))) {\n throw invalid(\"The desktop entry\", output, [], []);\n }\n\n for (const diagnostic of diagnostics) {\n warn(diagnostic);\n }\n};\n\nconst validateMetainfo = (path: string, areWarningsFatal: boolean): void => {\n const subject = \"The AppStream metainfo\";\n\n const { output, status } = runTool({\n tool: \"appstreamcli\",\n args: [\"validate\", \"--no-net\", \"--explain\", path],\n subject,\n });\n\n const diagnostics = parseDiagnostics(output);\n const errors = rulesIn(diagnostics, [ERROR_SEVERITY]);\n const warnings = rulesIn(diagnostics, [WARNING_SEVERITY]);\n const infos = rulesIn(diagnostics, [INFO_SEVERITY]);\n const rules = [...errors, ...warnings, ...infos];\n const notes = fatalNotes(diagnostics);\n assertNotFatal({\n subject,\n output: withoutSuccessSummary(output),\n status,\n errors,\n warnings,\n rules,\n notes,\n areWarningsFatal,\n });\n reportDiagnostics(subject, [...warnings, ...infos]);\n};\n\nexport { validateDesktopEntry, validateMetainfo };\n"]}
@@ -0,0 +1,8 @@
1
+ import type { WrittenCatalog } from "../i18n/catalogs.js";
2
+ type CatalogWrites = {
3
+ record: (catalogs: WrittenCatalog[]) => void;
4
+ hasWritten: (path: string) => boolean;
5
+ };
6
+ declare const createCatalogWrites: () => CatalogWrites;
7
+ export { type CatalogWrites, createCatalogWrites };
8
+ //# sourceMappingURL=catalog-writes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-writes.d.ts","sourceRoot":"","sources":["../../src/dev/catalog-writes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,KAAK,aAAa,GAAG;IACjB,MAAM,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC7C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC,CAAC;AAUF,QAAA,MAAM,mBAAmB,QAAO,aAe/B,CAAC;AAEF,OAAO,EAAE,KAAK,aAAa,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ const hasContent = (path, content) => {
4
+ try {
5
+ return readFileSync(path).equals(content);
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ };
11
+ const createCatalogWrites = () => {
12
+ const contents = new Map();
13
+ return {
14
+ record: (catalogs) => {
15
+ for (const catalog of catalogs) {
16
+ contents.set(resolve(catalog.path), catalog.content);
17
+ }
18
+ },
19
+ hasWritten: (path) => {
20
+ const content = contents.get(resolve(path));
21
+ return content !== undefined && hasContent(path, content);
22
+ },
23
+ };
24
+ };
25
+ export { createCatalogWrites };
26
+ //# sourceMappingURL=catalog-writes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-writes.js","sourceRoot":"","sources":["../../src/dev/catalog-writes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,OAAe,EAAW,EAAE;IAC1D,IAAI,CAAC;QACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,GAAkB,EAAE;IAC5C,MAAM,QAAQ,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEhD,OAAO;QACH,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;YACjB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC7B,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACzD,CAAC;QACL,CAAC;QACD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;YACjB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAE5C,OAAO,OAAO,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9D,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAsB,mBAAmB,EAAE,CAAC","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { WrittenCatalog } from \"../i18n/catalogs.js\";\n\ntype CatalogWrites = {\n record: (catalogs: WrittenCatalog[]) => void;\n hasWritten: (path: string) => boolean;\n};\n\nconst hasContent = (path: string, content: Buffer): boolean => {\n try {\n return readFileSync(path).equals(content);\n } catch {\n return false;\n }\n};\n\nconst createCatalogWrites = (): CatalogWrites => {\n const contents: Map<string, Buffer> = new Map();\n\n return {\n record: (catalogs) => {\n for (const catalog of catalogs) {\n contents.set(resolve(catalog.path), catalog.content);\n }\n },\n hasWritten: (path) => {\n const content = contents.get(resolve(path));\n\n return content !== undefined && hasContent(path, content);\n },\n };\n};\n\nexport { type CatalogWrites, createCatalogWrites };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"runner-deps.d.ts","sourceRoot":"","sources":["../../src/dev/runner-deps.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsCjD,QAAA,MAAM,oBAAoB,GAAI,YAAY,MAAM,KAAG,aAkDjD,CAAC;AAEH,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"runner-deps.d.ts","sourceRoot":"","sources":["../../src/dev/runner-deps.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+FjD,QAAA,MAAM,oBAAoB,GAAI,YAAY,MAAM,KAAG,aACO,CAAC;AAE3D,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -11,6 +11,7 @@ import { isRefreshBoundary, performRefresh, staleExportName } from "../refresh-r
11
11
  import { gtkxFastRefresh } from "../vite-plugins/fast-refresh/swc-refresh.js";
12
12
  import { gtkxVitePlugins } from "../vite-plugins/index.js";
13
13
  import { gtkxReactDomPrebundle } from "../vite-plugins/react-dom-prebundle.js";
14
+ import { createCatalogWrites } from "./catalog-writes.js";
14
15
  const DEV_MODE = "development";
15
16
  const APPLICATION_POLL_INTERVAL_MS = 50;
16
17
  const currentApplicationId = () => Gio.Application.getDefault()?.applicationId ?? null;
@@ -28,7 +29,12 @@ const waitForApplicationId = async (timeoutMs, shouldKeepWaiting) => {
28
29
  return applicationId;
29
30
  };
30
31
  const readFileRevision = (path) => readFile(path, "utf8");
31
- const defaultDevRunnerDeps = (configFile) => ({
32
+ const devPlugins = (configFile, catalogWrites) => (entryPath) => [
33
+ ...gtkxVitePlugins({ mode: DEV_MODE, entryPath, configFile, onCatalogsWritten: catalogWrites.record }),
34
+ ...gtkxFastRefresh(),
35
+ gtkxReactDomPrebundle(),
36
+ ];
37
+ const createDevRunnerDeps = (configFile, catalogWrites) => ({
32
38
  createServer,
33
39
  waitForApplicationId,
34
40
  getConfiguredApplicationId: async (root) => {
@@ -67,13 +73,11 @@ const defaultDevRunnerDeps = (configFile) => ({
67
73
  isRefreshBoundary,
68
74
  staleExportName,
69
75
  readFileRevision,
70
- plugins: (entryPath) => [
71
- ...gtkxVitePlugins({ mode: DEV_MODE, entryPath, configFile }),
72
- ...gtkxFastRefresh(),
73
- gtkxReactDomPrebundle(),
74
- ],
76
+ hasWrittenCatalog: catalogWrites.hasWritten,
77
+ plugins: devPlugins(configFile, catalogWrites),
75
78
  log: info,
76
79
  exit: (code) => process.exit(code),
77
80
  });
81
+ const defaultDevRunnerDeps = (configFile) => createDevRunnerDeps(configFile, createCatalogWrites());
78
82
  export { defaultDevRunnerDeps };
79
83
  //# sourceMappingURL=runner-deps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner-deps.js","sourceRoot":"","sources":["../../src/dev/runner-deps.ts"],"names":[],"mappings":"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","sourcesContent":["import { loadConfig } from \"@gtkx/config\";\nimport * as Gio from \"@gtkx/gi/gio\";\nimport { quitApplication } from \"@gtkx/runtime\";\nimport { type ApplicationInstance, getApplicationInstance } from \"@gtkx/runtime/internal\";\nimport { info, installGracefulShutdown } from \"@gtkx/utils\";\nimport { readFile } from \"node:fs/promises\";\nimport { createServer } from \"vite\";\nimport type { DevRunnerDeps } from \"./runner.js\";\nimport { startMcpClient, stopMcpClient } from \"../mcp/index.js\";\nimport {\n mergeTestingModule,\n setTestingModuleLoader,\n type TestingInternalModule,\n type TestingPublicModule,\n} from \"../mcp/testing-loader.js\";\nimport { isRefreshBoundary, performRefresh, staleExportName } from \"../refresh-runtime.js\";\nimport { gtkxFastRefresh } from \"../vite-plugins/fast-refresh/swc-refresh.js\";\nimport { gtkxVitePlugins } from \"../vite-plugins/index.js\";\nimport { gtkxReactDomPrebundle } from \"../vite-plugins/react-dom-prebundle.js\";\n\nconst DEV_MODE = \"development\";\nconst APPLICATION_POLL_INTERVAL_MS = 50;\n\nconst currentApplicationId = (): string | null => Gio.Application.getDefault()?.applicationId ?? null;\n\nconst currentApplicationInstance = (): ApplicationInstance => {\n const application = Gio.Application.getDefault();\n\n return application === null ? \"unregistered\" : getApplicationInstance(application);\n};\n\nconst waitForApplicationId = async (timeoutMs: number, shouldKeepWaiting: () => boolean): Promise<string | null> => {\n const deadline = Date.now() + timeoutMs;\n let applicationId = currentApplicationId();\n\n while (applicationId === null && Date.now() < deadline && shouldKeepWaiting()) {\n await new Promise((resolve) => setTimeout(resolve, APPLICATION_POLL_INTERVAL_MS));\n applicationId = currentApplicationId();\n }\n\n return applicationId;\n};\n\nconst readFileRevision = (path: string): Promise<string> => readFile(path, \"utf8\");\n\nconst defaultDevRunnerDeps = (configFile: string): DevRunnerDeps => ({\n createServer,\n waitForApplicationId,\n getConfiguredApplicationId: async (root: string) => {\n const loaded = await loadConfig(root, { mode: DEV_MODE, configFile });\n\n return loaded.config.applicationId;\n },\n startMcpClient: (applicationId, loadAppModule) => {\n setTestingModuleLoader(async () => {\n const [publicApi, internals] = await Promise.all([\n loadAppModule(\"@gtkx/testing\") as Promise<TestingPublicModule>,\n loadAppModule(\"@gtkx/testing/internal\") as Promise<TestingInternalModule>,\n ]);\n\n return mergeTestingModule(publicApi, internals);\n });\n\n return startMcpClient(applicationId);\n },\n stopMcpClient,\n watchApplicationShutdown: (onShutdown) => {\n Gio.Application.getDefault()?.on(\"shutdown\", onShutdown);\n },\n watchUncaughtErrors: (onUncaughtError) => {\n process.on(\"uncaughtException\", onUncaughtError);\n process.on(\"unhandledRejection\", onUncaughtError);\n },\n getApplicationInstance: currentApplicationInstance,\n installShutdownHandlers: (onSignal) => {\n installGracefulShutdown({ onSignal });\n },\n quitDefaultApplication: () => {\n const application = Gio.Application.getDefault();\n\n if (application) {\n quitApplication(application);\n }\n },\n performRefresh,\n isRefreshBoundary,\n staleExportName,\n readFileRevision,\n plugins: (entryPath) => [\n ...gtkxVitePlugins({ mode: DEV_MODE, entryPath, configFile }),\n ...gtkxFastRefresh(),\n gtkxReactDomPrebundle(),\n ],\n log: info,\n exit: (code: number): never => process.exit(code),\n});\n\nexport { defaultDevRunnerDeps };\n"]}
1
+ {"version":3,"file":"runner-deps.js","sourceRoot":"","sources":["../../src/dev/runner-deps.ts"],"names":[],"mappings":"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","sourcesContent":["import { loadConfig } from \"@gtkx/config\";\nimport * as Gio from \"@gtkx/gi/gio\";\nimport { quitApplication } from \"@gtkx/runtime\";\nimport { type ApplicationInstance, getApplicationInstance } from \"@gtkx/runtime/internal\";\nimport { info, installGracefulShutdown } from \"@gtkx/utils\";\nimport { readFile } from \"node:fs/promises\";\nimport { createServer } from \"vite\";\nimport type { DevRunnerDeps } from \"./runner.js\";\nimport { startMcpClient, stopMcpClient } from \"../mcp/index.js\";\nimport {\n mergeTestingModule,\n setTestingModuleLoader,\n type TestingInternalModule,\n type TestingPublicModule,\n} from \"../mcp/testing-loader.js\";\nimport { isRefreshBoundary, performRefresh, staleExportName } from \"../refresh-runtime.js\";\nimport { gtkxFastRefresh } from \"../vite-plugins/fast-refresh/swc-refresh.js\";\nimport { gtkxVitePlugins } from \"../vite-plugins/index.js\";\nimport { gtkxReactDomPrebundle } from \"../vite-plugins/react-dom-prebundle.js\";\nimport { type CatalogWrites, createCatalogWrites } from \"./catalog-writes.js\";\n\nconst DEV_MODE = \"development\";\nconst APPLICATION_POLL_INTERVAL_MS = 50;\n\nconst currentApplicationId = (): string | null => Gio.Application.getDefault()?.applicationId ?? null;\n\nconst currentApplicationInstance = (): ApplicationInstance => {\n const application = Gio.Application.getDefault();\n\n return application === null ? \"unregistered\" : getApplicationInstance(application);\n};\n\nconst waitForApplicationId = async (timeoutMs: number, shouldKeepWaiting: () => boolean): Promise<string | null> => {\n const deadline = Date.now() + timeoutMs;\n let applicationId = currentApplicationId();\n\n while (applicationId === null && Date.now() < deadline && shouldKeepWaiting()) {\n await new Promise((resolve) => setTimeout(resolve, APPLICATION_POLL_INTERVAL_MS));\n applicationId = currentApplicationId();\n }\n\n return applicationId;\n};\n\nconst readFileRevision = (path: string): Promise<string> => readFile(path, \"utf8\");\n\nconst devPlugins = (configFile: string, catalogWrites: CatalogWrites): DevRunnerDeps[\"plugins\"] =>\n (entryPath) => [\n ...gtkxVitePlugins({ mode: DEV_MODE, entryPath, configFile, onCatalogsWritten: catalogWrites.record }),\n ...gtkxFastRefresh(),\n gtkxReactDomPrebundle(),\n ];\n\nconst createDevRunnerDeps = (configFile: string, catalogWrites: CatalogWrites): DevRunnerDeps => ({\n createServer,\n waitForApplicationId,\n getConfiguredApplicationId: async (root: string) => {\n const loaded = await loadConfig(root, { mode: DEV_MODE, configFile });\n\n return loaded.config.applicationId;\n },\n startMcpClient: (applicationId, loadAppModule) => {\n setTestingModuleLoader(async () => {\n const [publicApi, internals] = await Promise.all([\n loadAppModule(\"@gtkx/testing\") as Promise<TestingPublicModule>,\n loadAppModule(\"@gtkx/testing/internal\") as Promise<TestingInternalModule>,\n ]);\n\n return mergeTestingModule(publicApi, internals);\n });\n\n return startMcpClient(applicationId);\n },\n stopMcpClient,\n watchApplicationShutdown: (onShutdown) => {\n Gio.Application.getDefault()?.on(\"shutdown\", onShutdown);\n },\n watchUncaughtErrors: (onUncaughtError) => {\n process.on(\"uncaughtException\", onUncaughtError);\n process.on(\"unhandledRejection\", onUncaughtError);\n },\n getApplicationInstance: currentApplicationInstance,\n installShutdownHandlers: (onSignal) => {\n installGracefulShutdown({ onSignal });\n },\n quitDefaultApplication: () => {\n const application = Gio.Application.getDefault();\n\n if (application) {\n quitApplication(application);\n }\n },\n performRefresh,\n isRefreshBoundary,\n staleExportName,\n readFileRevision,\n hasWrittenCatalog: catalogWrites.hasWritten,\n plugins: devPlugins(configFile, catalogWrites),\n log: info,\n exit: (code: number): never => process.exit(code),\n});\n\nconst defaultDevRunnerDeps = (configFile: string): DevRunnerDeps =>\n createDevRunnerDeps(configFile, createCatalogWrites());\n\nexport { defaultDevRunnerDeps };\n"]}
@@ -17,6 +17,7 @@ type DevRunnerDeps = {
17
17
  isRefreshBoundary(module: Record<string, unknown>): boolean;
18
18
  staleExportName(previous: Record<string, unknown>, current: Record<string, unknown>): string | null;
19
19
  readFileRevision(path: string): Promise<string>;
20
+ hasWrittenCatalog(path: string): boolean;
20
21
  plugins(entryPath: string): Plugin[];
21
22
  log(message: string): void;
22
23
  exit(code: number): never;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/dev/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AASjD,OAAO,EAEH,KAAK,SAAS,EAIjB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,aAAa,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtE,KAAK,aAAa,GAAG;IACjB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClG,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtE,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,aAAa,IAAI,IAAI,CAAC;IACtB,wBAAwB,CAAC,UAAU,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACvD,mBAAmB,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACrE,sBAAsB,IAAI,mBAAmB,CAAC;IAC9C,uBAAuB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,sBAAsB,IAAI,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IAC5D,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IACpG,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACrC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,CAAC;AAEF,KAAK,SAAS,GAAG;IACb,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC,CAAC;AAwjBF,QAAA,MAAM,eAAe,GAAI,MAAM,aAAa,KAAG,SAe7C,CAAC;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/dev/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AASjD,OAAO,EAEH,KAAK,SAAS,EAIjB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,aAAa,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtE,KAAK,aAAa,GAAG;IACjB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClG,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtE,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,aAAa,IAAI,IAAI,CAAC;IACtB,wBAAwB,CAAC,UAAU,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACvD,mBAAmB,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACrE,sBAAsB,IAAI,mBAAmB,CAAC;IAC9C,uBAAuB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,sBAAsB,IAAI,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IAC5D,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IACpG,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACrC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,CAAC;AAEF,KAAK,SAAS,GAAG;IACb,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC,CAAC;AAgkBF,QAAA,MAAM,eAAe,GAAI,MAAM,aAAa,KAAG,SAe7C,CAAC;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,CAAC"}
@@ -214,13 +214,19 @@ const restartForServerConfig = async (session, changedPath) => {
214
214
  session.deps.log(`Server config changed: ${changedPath}`);
215
215
  await requestRestart(session);
216
216
  };
217
+ const restartForCatalog = async (session, changedPath) => {
218
+ if (session.deps.hasWrittenCatalog(changedPath)) {
219
+ return;
220
+ }
221
+ session.deps.log(`Translation catalog changed: ${changedPath}`);
222
+ await requestRestart(session);
223
+ };
217
224
  const applyChange = async (session, change) => {
218
225
  if (session.controller.isShuttingDown()) {
219
226
  return;
220
227
  }
221
228
  if (isCatalogSource(session.server.config.root, change.path)) {
222
- session.deps.log(`Translation catalog changed: ${change.path}`);
223
- await requestRestart(session);
229
+ await restartForCatalog(session, change.path);
224
230
  return;
225
231
  }
226
232
  if (isServerConfigFile(session.server.config, change.path)) {