@gtkx/cli 1.6.0 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +5 -5
  2. package/dist/codegen/freshness.d.ts.map +1 -1
  3. package/dist/codegen/freshness.js +45 -16
  4. package/dist/codegen/freshness.js.map +1 -1
  5. package/dist/codegen/reference.d.ts.map +1 -1
  6. package/dist/codegen/reference.js +1 -7
  7. package/dist/codegen/reference.js.map +1 -1
  8. package/dist/codegen/report.d.ts.map +1 -1
  9. package/dist/codegen/report.js +5 -16
  10. package/dist/codegen/report.js.map +1 -1
  11. package/dist/codegen/run-codegen.d.ts +3 -5
  12. package/dist/codegen/run-codegen.d.ts.map +1 -1
  13. package/dist/codegen/run-codegen.js +23 -100
  14. package/dist/codegen/run-codegen.js.map +1 -1
  15. package/dist/codegen/store-resolver.d.ts +0 -1
  16. package/dist/codegen/store-resolver.d.ts.map +1 -1
  17. package/dist/codegen/store-resolver.js +8 -17
  18. package/dist/codegen/store-resolver.js.map +1 -1
  19. package/dist/commands/docs.d.ts.map +1 -1
  20. package/dist/commands/docs.js +5 -15
  21. package/dist/commands/docs.js.map +1 -1
  22. package/dist/deploy/freedesktop/copyright.d.ts.map +1 -1
  23. package/dist/deploy/freedesktop/copyright.js +2 -13
  24. package/dist/deploy/freedesktop/copyright.js.map +1 -1
  25. package/dist/deploy/freedesktop/xml.d.ts.map +1 -1
  26. package/dist/deploy/freedesktop/xml.js +21 -25
  27. package/dist/deploy/freedesktop/xml.js.map +1 -1
  28. package/dist/deploy/node-runtime/license.d.ts.map +1 -1
  29. package/dist/deploy/node-runtime/license.js +2 -9
  30. package/dist/deploy/node-runtime/license.js.map +1 -1
  31. package/dist/deploy/notices/packages.d.ts.map +1 -1
  32. package/dist/deploy/notices/packages.js +3 -10
  33. package/dist/deploy/notices/packages.js.map +1 -1
  34. package/dist/deploy/payload/copy-tree.d.ts.map +1 -1
  35. package/dist/deploy/payload/copy-tree.js +3 -3
  36. package/dist/deploy/payload/copy-tree.js.map +1 -1
  37. package/dist/deploy/payload/stage.d.ts.map +1 -1
  38. package/dist/deploy/payload/stage.js +1 -3
  39. package/dist/deploy/payload/stage.js.map +1 -1
  40. package/dist/deploy/settings/build-manifest.d.ts.map +1 -1
  41. package/dist/deploy/settings/build-manifest.js +4 -15
  42. package/dist/deploy/settings/build-manifest.js.map +1 -1
  43. package/dist/deploy/settings/libraries.d.ts.map +1 -1
  44. package/dist/deploy/settings/libraries.js +2 -19
  45. package/dist/deploy/settings/libraries.js.map +1 -1
  46. package/dist/deploy/settings/paths.d.ts +1 -2
  47. package/dist/deploy/settings/paths.d.ts.map +1 -1
  48. package/dist/deploy/settings/paths.js +5 -15
  49. package/dist/deploy/settings/paths.js.map +1 -1
  50. package/dist/deploy/settings/screenshots.d.ts.map +1 -1
  51. package/dist/deploy/settings/screenshots.js +6 -31
  52. package/dist/deploy/settings/screenshots.js.map +1 -1
  53. package/dist/deploy/targets/flatpak-pnpm.js +4 -4
  54. package/dist/deploy/targets/flatpak-pnpm.js.map +1 -1
  55. package/dist/deploy/targets/flatpak-source.d.ts.map +1 -1
  56. package/dist/deploy/targets/flatpak-source.js +4 -4
  57. package/dist/deploy/targets/flatpak-source.js.map +1 -1
  58. package/dist/deploy/targets/flatpak-sources.js +1 -1
  59. package/dist/deploy/targets/flatpak-sources.js.map +1 -1
  60. package/dist/dev/runner-main.d.ts.map +1 -1
  61. package/dist/dev/runner-main.js +1 -2
  62. package/dist/dev/runner-main.js.map +1 -1
  63. package/dist/dev/schema-dir.d.ts +1 -1
  64. package/dist/dev/schema-dir.d.ts.map +1 -1
  65. package/dist/dev/schema-dir.js +2 -4
  66. package/dist/dev/schema-dir.js.map +1 -1
  67. package/dist/i18n/catalogs.d.ts.map +1 -1
  68. package/dist/i18n/catalogs.js +2 -1
  69. package/dist/i18n/catalogs.js.map +1 -1
  70. package/dist/i18n/metadata-templates.d.ts.map +1 -1
  71. package/dist/i18n/metadata-templates.js +2 -1
  72. package/dist/i18n/metadata-templates.js.map +1 -1
  73. package/dist/i18n/source-messages.d.ts +3 -21
  74. package/dist/i18n/source-messages.d.ts.map +1 -1
  75. package/dist/i18n/source-messages.js +66 -85
  76. package/dist/i18n/source-messages.js.map +1 -1
  77. package/dist/i18n/types.d.ts +6 -7
  78. package/dist/i18n/types.d.ts.map +1 -1
  79. package/dist/i18n/types.js +83 -96
  80. package/dist/i18n/types.js.map +1 -1
  81. package/dist/internal/docs-elements.js +2 -2
  82. package/dist/internal/docs-elements.js.map +1 -1
  83. package/dist/internal/icon-path.d.ts.map +1 -1
  84. package/dist/internal/icon-path.js +5 -16
  85. package/dist/internal/icon-path.js.map +1 -1
  86. package/dist/internal/source-imports.d.ts.map +1 -1
  87. package/dist/internal/source-imports.js +10 -41
  88. package/dist/internal/source-imports.js.map +1 -1
  89. package/dist/settings/render.d.ts +0 -1
  90. package/dist/settings/render.d.ts.map +1 -1
  91. package/dist/settings/render.js +1 -11
  92. package/dist/settings/render.js.map +1 -1
  93. package/dist/settings/schema.d.ts +2 -2
  94. package/dist/settings/schema.d.ts.map +1 -1
  95. package/dist/settings/schema.js +21 -62
  96. package/dist/settings/schema.js.map +1 -1
  97. package/dist/vite-plugins/asset-imports.d.ts +1 -2
  98. package/dist/vite-plugins/asset-imports.d.ts.map +1 -1
  99. package/dist/vite-plugins/asset-imports.js +19 -32
  100. package/dist/vite-plugins/asset-imports.js.map +1 -1
  101. package/dist/vite-plugins/asset-specifier.d.ts +1 -3
  102. package/dist/vite-plugins/asset-specifier.d.ts.map +1 -1
  103. package/dist/vite-plugins/asset-specifier.js +1 -4
  104. package/dist/vite-plugins/asset-specifier.js.map +1 -1
  105. package/dist/vite-plugins/i18n.d.ts.map +1 -1
  106. package/dist/vite-plugins/i18n.js +2 -1
  107. package/dist/vite-plugins/i18n.js.map +1 -1
  108. package/dist/vite-plugins/index.d.ts.map +1 -1
  109. package/dist/vite-plugins/index.js +2 -4
  110. package/dist/vite-plugins/index.js.map +1 -1
  111. package/dist/vite-plugins/resources.d.ts.map +1 -1
  112. package/dist/vite-plugins/resources.js +32 -97
  113. package/dist/vite-plugins/resources.js.map +1 -1
  114. package/dist/vite-plugins/settings-worker-env.d.ts.map +1 -1
  115. package/dist/vite-plugins/settings-worker-env.js +2 -4
  116. package/dist/vite-plugins/settings-worker-env.js.map +1 -1
  117. package/dist/vite-plugins/settings.d.ts +1 -2
  118. package/dist/vite-plugins/settings.d.ts.map +1 -1
  119. package/dist/vite-plugins/settings.js +8 -14
  120. package/dist/vite-plugins/settings.js.map +1 -1
  121. package/dist/vite-plugins/undeclared-library.d.ts.map +1 -1
  122. package/dist/vite-plugins/undeclared-library.js +10 -13
  123. package/dist/vite-plugins/undeclared-library.js.map +1 -1
  124. package/dist/vite-plugins/worker.d.ts.map +1 -1
  125. package/dist/vite-plugins/worker.js +0 -1
  126. package/dist/vite-plugins/worker.js.map +1 -1
  127. package/package.json +21 -15
  128. package/src/codegen/freshness.ts +66 -17
  129. package/src/codegen/reference.ts +1 -8
  130. package/src/codegen/report.ts +5 -21
  131. package/src/codegen/run-codegen.ts +28 -145
  132. package/src/codegen/store-resolver.ts +8 -24
  133. package/src/commands/docs.ts +5 -17
  134. package/src/deploy/freedesktop/copyright.ts +2 -14
  135. package/src/deploy/freedesktop/xml.ts +24 -32
  136. package/src/deploy/node-runtime/license.ts +2 -8
  137. package/src/deploy/notices/packages.ts +3 -11
  138. package/src/deploy/payload/copy-tree.ts +3 -4
  139. package/src/deploy/payload/stage.ts +2 -6
  140. package/src/deploy/settings/build-manifest.ts +4 -16
  141. package/src/deploy/settings/libraries.ts +1 -22
  142. package/src/deploy/settings/paths.ts +6 -16
  143. package/src/deploy/settings/screenshots.ts +8 -46
  144. package/src/deploy/targets/flatpak-pnpm.ts +4 -4
  145. package/src/deploy/targets/flatpak-source.ts +4 -4
  146. package/src/deploy/targets/flatpak-sources.ts +1 -1
  147. package/src/dev/runner-main.ts +1 -2
  148. package/src/dev/schema-dir.ts +2 -4
  149. package/src/i18n/catalogs.ts +2 -1
  150. package/src/i18n/metadata-templates.ts +2 -1
  151. package/src/i18n/source-messages.ts +77 -115
  152. package/src/i18n/types.ts +97 -131
  153. package/src/internal/docs-elements.ts +2 -2
  154. package/src/internal/icon-path.ts +6 -19
  155. package/src/internal/source-imports.ts +14 -50
  156. package/src/settings/render.ts +1 -13
  157. package/src/settings/schema.ts +19 -81
  158. package/src/vite-plugins/asset-imports.ts +20 -44
  159. package/src/vite-plugins/asset-specifier.ts +0 -5
  160. package/src/vite-plugins/i18n.ts +2 -1
  161. package/src/vite-plugins/index.ts +2 -4
  162. package/src/vite-plugins/resources.ts +37 -140
  163. package/src/vite-plugins/settings-worker-env.ts +2 -4
  164. package/src/vite-plugins/settings.ts +11 -20
  165. package/src/vite-plugins/undeclared-library.ts +14 -20
  166. package/src/vite-plugins/worker.ts +0 -1
  167. package/dist/i18n/binding-extractor.d.ts +0 -30
  168. package/dist/i18n/binding-extractor.d.ts.map +0 -1
  169. package/dist/i18n/binding-extractor.js +0 -1324
  170. package/dist/i18n/binding-extractor.js.map +0 -1
  171. package/dist/i18n/extractor-plugin.d.ts +0 -8
  172. package/dist/i18n/extractor-plugin.d.ts.map +0 -1
  173. package/dist/i18n/extractor-plugin.js +0 -247
  174. package/dist/i18n/extractor-plugin.js.map +0 -1
  175. package/dist/internal/data-dir.d.ts +0 -4
  176. package/dist/internal/data-dir.d.ts.map +0 -1
  177. package/dist/internal/data-dir.js +0 -52
  178. package/dist/internal/data-dir.js.map +0 -1
  179. package/dist/vite-plugins/animated.d.ts +0 -5
  180. package/dist/vite-plugins/animated.d.ts.map +0 -1
  181. package/dist/vite-plugins/animated.js +0 -325
  182. package/dist/vite-plugins/animated.js.map +0 -1
  183. package/src/i18n/binding-extractor.ts +0 -1969
  184. package/src/i18n/extractor-plugin.ts +0 -413
  185. package/src/internal/data-dir.ts +0 -70
  186. package/src/vite-plugins/animated.ts +0 -486
@@ -1,29 +1,20 @@
1
1
  import { runCodegen as runCodegenCore } from "@gtkx/codegen";
2
- import {
3
- getShadowingStorePaths,
4
- LIBRARIES_WILDCARD,
5
- redundantLibraries,
6
- sweepProjectStaging,
7
- } from "@gtkx/codegen/internal";
2
+ import { getShadowingStorePaths, sweepProjectStaging } from "@gtkx/codegen/internal";
8
3
  import { type Config, loadConfig } from "@gtkx/config";
9
4
  import {
10
5
  isAgentRulesEnabled,
11
- type ResolvedFuture,
12
6
  resolveElementComponents,
13
7
  resolveElementProps,
14
- resolveFuture,
15
8
  resolveLazyElements,
16
9
  resolveOmittedProps,
17
- unknownFutureKeys,
18
10
  } from "@gtkx/config/internal";
19
- import { info, warn } from "@gtkx/utils";
11
+ import { info } from "@gtkx/utils";
20
12
  import { existsSync, rmSync } from "node:fs";
21
13
  import { join, resolve } from "node:path";
22
14
  import { resolveCatalogProject, synchronizeCatalogs } from "../i18n/catalogs.js";
23
15
  import { extractSourceCatalog } from "../i18n/source-messages.js";
24
- import { emitI18nTypes } from "../i18n/types.js";
16
+ import { clearI18nTypes, emitI18nTypes } from "../i18n/types.js";
25
17
  import { upsertAgentRules } from "../internal/agent-rules.js";
26
- import { resolveDataDir } from "../internal/data-dir.js";
27
18
  import { discoverSourceFiles } from "../internal/source-imports.js";
28
19
  import { emitSchemaEnv } from "../settings/schema.js";
29
20
  import { type CodegenInputs, isCodegenStale, resolveCodegenInputs } from "./freshness.js";
@@ -48,12 +39,10 @@ type RunCodegenResult = {
48
39
  isRegenerated: boolean;
49
40
  namespaces: number;
50
41
  intrinsicElements: number;
51
- notices: string[];
52
42
  duration: number;
53
- girPath?: string[] | undefined;
54
- configFile?: string | undefined;
55
- libraries?: string[] | undefined;
56
- future?: string[] | undefined;
43
+ girPath: string[];
44
+ configFile: string;
45
+ libraries: string[];
57
46
  reference?: ReferenceResult | undefined;
58
47
  };
59
48
 
@@ -62,7 +51,6 @@ type CodegenOptionsInput = {
62
51
  libraries: string[];
63
52
  girPath: string[];
64
53
  elements: Config["elements"];
65
- future: ResolvedFuture;
66
54
  };
67
55
 
68
56
  type PreparedCodegen = CodegenInputs & { isForced: boolean };
@@ -73,14 +61,6 @@ type EnsureGeneratedOptions = {
73
61
  shouldPreserveI18nMetadata?: boolean | undefined;
74
62
  };
75
63
 
76
- type RunOptionsInput = {
77
- root: string;
78
- mode: string | undefined;
79
- inputs: CodegenInputs | null;
80
- resolved: LoadedConfig;
81
- shouldPreserveI18nMetadata: boolean | undefined;
82
- };
83
-
84
64
  const GIR_PATH_MISSING_MESSAGE =
85
65
  "No GIR search paths available. Install gobject-introspection " +
86
66
  "(Linux: `sudo dnf install gobject-introspection-devel` or `sudo apt install libgirepository1.0-dev`), " +
@@ -97,14 +77,9 @@ const removeShadowingStores = (cwd: string): void => {
97
77
  removeStores(getShadowingStorePaths(cwd));
98
78
  };
99
79
 
100
- const codegenOptions = ({ store, libraries, girPath, elements, future }: CodegenOptionsInput) => ({
80
+ const codegenOptions = ({ store, libraries, girPath, elements }: CodegenOptionsInput) => ({
101
81
  libraries,
102
82
  girPath,
103
- isByteArrayTyped: future.isByteArrayTyped,
104
- isValueUnwrapped: future.isValueUnwrapped,
105
- isFinishTrimmed: future.isFinishTrimmed,
106
- isInoutInPlace: future.isInoutInPlace,
107
- isTreeShaken: future.isTreeShaken,
108
83
  gi: {
109
84
  storeDir: store.giStoreDir,
110
85
  linkDir: store.giLinkDir,
@@ -118,93 +93,30 @@ const codegenOptions = ({ store, libraries, girPath, elements, future }: Codegen
118
93
  linkDir: store.jsxLinkDir,
119
94
  version: store.react.version,
120
95
  },
121
- reactSubexports: store.react?.subexports ?? [],
122
96
  userComponents: resolveElementComponents(elements),
123
97
  userProps: resolveElementProps(elements),
124
98
  userLazyElements: resolveLazyElements(elements),
125
99
  userOmittedProps: resolveOmittedProps(elements),
126
100
  });
127
101
 
128
- const enabledFutureFlags = (config: Config): string[] => {
129
- const unknown: Set<string> = new Set(unknownFutureKeys(config.future));
130
-
131
- return Object.entries(config.future ?? {})
132
- .filter(([name, value]) => value === true && !unknown.has(name))
133
- .map(([name]) => name);
134
- };
135
-
136
- const disabledCodegenResult = (configFile: string, notices: string[]): RunCodegenResult => ({
102
+ const disabledCodegenResult = (configFile: string): RunCodegenResult => ({
137
103
  isRegenerated: false,
138
104
  namespaces: 0,
139
105
  intrinsicElements: 0,
140
- notices,
141
106
  duration: 0,
142
107
  girPath: [],
143
108
  configFile,
144
109
  libraries: [],
145
110
  });
146
111
 
147
- const warnNotices = (notices: string[]): void => {
148
- for (const notice of notices) {
149
- warn(notice);
150
- }
151
- };
152
-
153
- const unknownFutureNotice = (keys: string[]): string[] => {
154
- if (keys.length === 0) {
155
- return [];
156
- }
157
-
158
- return [
159
- `gtkx.config.ts: \`future\` has no ${keys.join(", ")} flag, so the key is ignored. Check it against ` +
160
- "the flags the configuration guide lists.",
161
- ];
162
- };
163
-
164
- const redundantLibraryNotice = (entries: string[]): string[] => {
165
- if (entries.length === 0) {
166
- return [];
167
- }
168
-
169
- return [
170
- `gtkx.config.ts: \`future.v2DefaultLibraries\` binds ${entries.join(", ")} on its own, so naming them ` +
171
- "in `libraries` changes nothing. Drop them; naming them becomes a configuration error in GTKX 2.0.",
172
- ];
173
- };
174
-
175
- const wildcardLibrariesNotice = (libraries: Config["libraries"]): string[] => {
176
- if (libraries !== LIBRARIES_WILDCARD) {
177
- return [];
178
- }
179
-
180
- return [
181
- 'gtkx.config.ts: `libraries: "*"` binds whatever the build host happens to have installed, so the ' +
182
- "store changes with the machine. Instead, list the libraries the project needs; the wildcard is " +
183
- "removed in GTKX 2.0.",
184
- ];
185
- };
186
-
187
- const configNotices = (config: Config, future: ResolvedFuture): string[] => [
188
- ...unknownFutureNotice(unknownFutureKeys(config.future)),
189
- ...wildcardLibrariesNotice(config.libraries),
190
- ...redundantLibraryNotice(redundantLibraries(config.libraries, future.isAdwaitaDefault)),
191
- ];
192
-
193
- const regeneratedStorePaths = (store: CodegenStore): string[] => {
194
- if (store.react === null) {
195
- return [store.giStoreDir, store.giLinkDir];
196
- }
197
-
198
- return [store.giStoreDir, store.giLinkDir, store.jsxStoreDir, store.jsxLinkDir];
199
- };
200
-
201
112
  const clearGeneratedStores = (store: CodegenStore): void => {
202
- removeStores(regeneratedStorePaths(store));
113
+ removeStores(
114
+ store.react === null
115
+ ? [store.giStoreDir, store.giLinkDir]
116
+ : [store.giStoreDir, store.giLinkDir, store.jsxStoreDir, store.jsxLinkDir],
117
+ );
203
118
  };
204
119
 
205
- const resolveLoadedConfig = async (options: RunCodegenOptions, cwd: string): Promise<LoadedConfig> =>
206
- options.resolved ?? (await loadConfig(cwd, { mode: options.mode }));
207
-
208
120
  const prepareCodegen = (options: RunCodegenOptions, cwd: string, config: Config): PreparedCodegen => {
209
121
  const { girPath, libraries, store } = options.inputs ?? resolveCodegenInputs(cwd, config);
210
122
 
@@ -219,17 +131,14 @@ const prepareCodegen = (options: RunCodegenOptions, cwd: string, config: Config)
219
131
 
220
132
  const runCodegen = async (options: RunCodegenOptions = {}): Promise<RunCodegenResult> => {
221
133
  const cwd = options.cwd ?? process.cwd();
222
- const { config, configFile } = await resolveLoadedConfig(options, cwd);
223
- const future = resolveFuture(config.future);
224
- const configured = configNotices(config, future);
225
- warnNotices(configured);
134
+ const { config, configFile } = options.resolved ?? (await loadConfig(cwd, { mode: options.mode }));
226
135
  await syncI18n(cwd, config.applicationId, options.shouldPreserveI18nMetadata);
227
- syncSchemaEnv(cwd, future.isResourceImported);
136
+ emitSchemaEnv(cwd);
228
137
 
229
138
  if (config.codegen === false) {
230
139
  removeShadowingStores(cwd);
231
140
 
232
- return disabledCodegenResult(configFile, configured);
141
+ return disabledCodegenResult(configFile);
233
142
  }
234
143
 
235
144
  const { girPath, libraries, store, isForced } = prepareCodegen(options, cwd, config);
@@ -239,35 +148,28 @@ const runCodegen = async (options: RunCodegenOptions = {}): Promise<RunCodegenRe
239
148
  }
240
149
 
241
150
  const result = await runCodegenCore({
242
- ...codegenOptions({ store, libraries, girPath, elements: config.elements, future }),
151
+ ...codegenOptions({ store, libraries, girPath, elements: config.elements }),
243
152
  isForced,
244
153
  });
245
154
 
246
- warnNotices(result.notices);
247
- const notices = [...configured, ...result.notices];
248
155
  const reference = await writeReference({ root: cwd, config, girPath, libraries, isForced });
249
- syncAgentRules(cwd, config);
156
+
157
+ if (isAgentRulesEnabled(config)) {
158
+ upsertAgentRules(cwd);
159
+ }
250
160
 
251
161
  return {
252
162
  isRegenerated: result.isRegenerated,
253
163
  namespaces: result.namespaces,
254
164
  intrinsicElements: result.intrinsicElements,
255
- notices,
256
165
  duration: result.duration,
257
166
  girPath,
258
167
  configFile,
259
168
  libraries,
260
- future: enabledFutureFlags(config),
261
169
  reference,
262
170
  };
263
171
  };
264
172
 
265
- const syncAgentRules = (root: string, config: Config): void => {
266
- if (isAgentRulesEnabled(config)) {
267
- upsertAgentRules(root);
268
- }
269
- };
270
-
271
173
  const syncI18n = async (
272
174
  root: string,
273
175
  applicationId: string,
@@ -276,16 +178,16 @@ const syncI18n = async (
276
178
  const project = resolveCatalogProject(root, applicationId);
277
179
 
278
180
  if (project === null) {
279
- emitI18nTypes(root, [], false);
181
+ clearI18nTypes(root);
280
182
 
281
183
  return;
282
184
  }
283
185
 
284
186
  const srcDir = join(root, "src");
285
187
  const sourceFiles = discoverSourceFiles(existsSync(srcDir) ? srcDir : root);
286
- const catalog = await extractSourceCatalog(project, sourceFiles, shouldPreserveMetadataMessages);
188
+ await extractSourceCatalog(project, sourceFiles, shouldPreserveMetadataMessages);
287
189
  synchronizeCatalogs(project);
288
- emitI18nTypes(root, catalog.messages);
190
+ await emitI18nTypes(root);
289
191
  };
290
192
 
291
193
  const isCodegenDisabled = async (cwd: string, mode?: string): Promise<boolean> => {
@@ -298,11 +200,6 @@ const isCodegenDisabled = async (cwd: string, mode?: string): Promise<boolean> =
298
200
  }
299
201
  };
300
202
 
301
- const syncSchemaEnv = (cwd: string, isV2ResourceImports = false): void => {
302
- const dataDir = isV2ResourceImports ? null : resolveDataDir(cwd);
303
- emitSchemaEnv(cwd, dataDir, isV2ResourceImports);
304
- };
305
-
306
203
  const resolveInputsOrNull = (cwd: string, config: Config): CodegenInputs | null => {
307
204
  try {
308
205
  return resolveCodegenInputs(cwd, config);
@@ -321,20 +218,6 @@ const maybeAnnounceStale = (shouldAnnounce: boolean | undefined, inputs: Codegen
321
218
  }
322
219
  };
323
220
 
324
- const getRunOptions = ({
325
- root,
326
- mode,
327
- inputs,
328
- resolved,
329
- shouldPreserveI18nMetadata,
330
- }: RunOptionsInput): RunCodegenOptions => {
331
- if (inputs === null) {
332
- return { cwd: root, mode, resolved, shouldPreserveI18nMetadata };
333
- }
334
-
335
- return { cwd: root, mode, inputs, resolved, shouldPreserveI18nMetadata };
336
- };
337
-
338
221
  const isPreflightSkipped = (options: EnsureGeneratedOptions): boolean =>
339
222
  options.shouldAnnounce === true && process.env.GTKX_DISABLE_PREFLIGHT === "1";
340
223
 
@@ -355,13 +238,13 @@ const generate = async (context: CodegenContext, options: EnsureGeneratedOptions
355
238
  maybeAnnounceStale(options.shouldAnnounce, inputs);
356
239
  const resolved = { config: context.config, configFile: context.configFile };
357
240
 
358
- const result = await runCodegen(getRunOptions({
359
- root: context.root,
241
+ const result = await runCodegen({
242
+ cwd: context.root,
360
243
  mode: options.mode,
361
- inputs,
362
244
  resolved,
363
245
  shouldPreserveI18nMetadata: options.shouldPreserveI18nMetadata,
364
- }));
246
+ ...(inputs !== null && { inputs }),
247
+ });
365
248
 
366
249
  return result.isRegenerated;
367
250
  };
@@ -1,6 +1,6 @@
1
1
  import { resolveStore } from "@gtkx/codegen";
2
2
  import { type Config, loadConfig } from "@gtkx/config";
3
- import { existsSync, readFileSync, realpathSync } from "node:fs";
3
+ import { existsSync } from "node:fs";
4
4
  import { createRequire } from "node:module";
5
5
  import { dirname, join } from "node:path";
6
6
  import { pathToFileURL } from "node:url";
@@ -16,39 +16,23 @@ type CodegenStore = {
16
16
 
17
17
  type CodegenReactPackage = {
18
18
  version: string;
19
- subexports: string[];
20
19
  };
21
20
 
22
- type ResolvedPackage = { dir: string; version: string };
23
-
24
21
  type CodegenContext = {
25
22
  root: string;
26
23
  config: Config;
27
24
  configFile: string;
28
25
  };
29
26
 
30
- const readVersion = (packageJsonPath: string): string => {
31
- const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8")) as { version?: string };
32
-
33
- return parsed.version ?? "0.0.0";
34
- };
35
-
36
- const resolvePackage = (require: NodeJS.Require, dir: string, packageName: string): ResolvedPackage | null => {
27
+ const hasPackage = (require: NodeJS.Require, dir: string, packageName: string): boolean => {
37
28
  try {
38
- const real = realpathSync(require.resolve(`${packageName}/package.json`));
29
+ require.resolve(`${packageName}/package.json`);
39
30
 
40
- return { dir: dirname(real), version: readVersion(real) };
31
+ return true;
41
32
  } catch {
42
33
  const unscoped = packageName.replace(/^@[^/]+\//, "");
43
- const workspacePkg = join(dir, "packages", unscoped, "package.json");
44
-
45
- if (!existsSync(workspacePkg)) {
46
- return null;
47
- }
48
-
49
- const real = realpathSync(workspacePkg);
50
34
 
51
- return { dir: dirname(real), version: readVersion(real) };
35
+ return existsSync(join(dir, "packages", unscoped, "package.json"));
52
36
  }
53
37
  };
54
38
 
@@ -57,12 +41,12 @@ const siblingStore = (giDir: string): string => join(dirname(giDir), "jsx");
57
41
  const resolveCodegenStore = (dir: string): CodegenStore => {
58
42
  const require = createRequire(pathToFileURL(join(dir, "__gtkx_resolver__.js")).href);
59
43
 
60
- if (resolvePackage(require, dir, "@gtkx/native") === null) {
44
+ if (!hasPackage(require, dir, "@gtkx/native")) {
61
45
  throw new Error("Cannot resolve @gtkx/native from the project; is it installed?");
62
46
  }
63
47
 
64
48
  const store = resolveStore(dir);
65
- const hasReactRuntime = resolvePackage(require, dir, "react") !== null;
49
+ const hasReactRuntime = hasPackage(require, dir, "react");
66
50
 
67
51
  return {
68
52
  giStoreDir: store.gi.storeDir,
@@ -72,7 +56,7 @@ const resolveCodegenStore = (dir: string): CodegenStore => {
72
56
  runtimeVersion: store.gi.version,
73
57
  react:
74
58
  hasReactRuntime && store.jsx !== null
75
- ? { version: store.jsx.version, subexports: store.reactSubexports }
59
+ ? { version: store.jsx.version }
76
60
  : null,
77
61
  };
78
62
  };
@@ -1,10 +1,10 @@
1
1
  import { mergeOmittedProps, resolveGirPath, resolveLibraries } from "@gtkx/codegen";
2
2
  import { writeDocs } from "@gtkx/codegen/internal";
3
3
  import { loadConfig } from "@gtkx/config";
4
- import { resolveFuture, resolveOmittedProps } from "@gtkx/config/internal";
5
- import { info } from "@gtkx/utils";
4
+ import { resolveOmittedProps } from "@gtkx/config/internal";
5
+ import { info, isPathInside } from "@gtkx/utils";
6
6
  import { defineCommand } from "citty";
7
- import { isAbsolute, relative, resolve, sep } from "node:path";
7
+ import { resolve } from "node:path";
8
8
  import { resolveDocsElements } from "../internal/docs-elements.js";
9
9
  import { cwdArg, resolveCwd } from "../internal/entry-arg.js";
10
10
 
@@ -57,8 +57,7 @@ const docs = defineCommand({
57
57
  );
58
58
  }
59
59
 
60
- const future = resolveFuture(config.future);
61
- const libraries = resolveLibraries(config.libraries, girPath, future.isAdwaitaDefault);
60
+ const libraries = resolveLibraries(config.libraries);
62
61
  const startedAt = Date.now();
63
62
  const outDir = resolveOutDir(cwd, args.out);
64
63
  const builtin = await resolveDocsElements(cwd);
@@ -71,11 +70,6 @@ const docs = defineCommand({
71
70
  props: builtin.props,
72
71
  omittedProps: mergeOmittedProps(builtin.omittedProps, resolveOmittedProps(config.elements)),
73
72
  isForced: args.force,
74
- isByteArrayTyped: future.isByteArrayTyped,
75
- isValueUnwrapped: future.isValueUnwrapped,
76
- isFinishTrimmed: future.isFinishTrimmed,
77
- isInoutInPlace: future.isInoutInPlace,
78
- isTreeShaken: future.isTreeShaken,
79
73
  });
80
74
 
81
75
  if (!isRegenerated) {
@@ -93,12 +87,6 @@ const docs = defineCommand({
93
87
  },
94
88
  });
95
89
 
96
- const isBelow = (parent: string, child: string): boolean => {
97
- const path = relative(parent, child);
98
-
99
- return path !== "" && path !== ".." && !path.startsWith(`..${sep}`) && !isAbsolute(path);
100
- };
101
-
102
90
  const outDirReason = (cwd: string, out: string, outDir: string): string => {
103
91
  if (out.trim() === "") {
104
92
  return "it was empty, which names the project root itself";
@@ -114,7 +102,7 @@ const outDirReason = (cwd: string, out: string, outDir: string): string => {
114
102
  const resolveOutDir = (cwd: string, out: string): string => {
115
103
  const outDir = out.trim() === "" ? cwd : resolve(cwd, out);
116
104
 
117
- if (isBelow(cwd, outDir)) {
105
+ if (isPathInside(cwd, outDir)) {
118
106
  return outDir;
119
107
  }
120
108
 
@@ -1,6 +1,6 @@
1
- import { readFileSync } from "node:fs";
2
1
  import type { DeploySettings, Notice, NoticeSection } from "../types.js";
3
2
  import { BUNDLE_FILENAME } from "../../vite-plugins/esm-extension.js";
3
+ import { readLicenseText } from "../notices/text.js";
4
4
 
5
5
  type FileStanza = {
6
6
  settings: DeploySettings;
@@ -30,18 +30,6 @@ const foldedField = (name: string, lines: string[]): string[] => {
30
30
  return first === undefined ? [] : [`${name}: ${first}`, ...rest.map((line) => indentLine(line))];
31
31
  };
32
32
 
33
- const licenseText = (licenseFile: string | null): string | null => {
34
- if (licenseFile === null) {
35
- return null;
36
- }
37
-
38
- try {
39
- return readFileSync(licenseFile, "utf8").trimEnd();
40
- } catch {
41
- return null;
42
- }
43
- };
44
-
45
33
  const shortName = (license: string): string =>
46
34
  license
47
35
  .replaceAll(SPDX_GROUPING, " ")
@@ -159,7 +147,7 @@ const applicationStanza = (settings: DeploySettings, text: string | null): strin
159
147
  ];
160
148
 
161
149
  const renderCopyright = (settings: DeploySettings, sections: NoticeSection[]): string => {
162
- const own = licenseText(settings.paths.licenseFile);
150
+ const own = settings.paths.licenseFile === null ? null : readLicenseText(settings.paths.licenseFile);
163
151
  const reproduced: Set<string> = new Set(own === null ? [] : [own]);
164
152
 
165
153
  const stanzas = filePatterns(sections).flatMap((files) =>
@@ -1,3 +1,5 @@
1
+ import XMLBuilder from "fast-xml-builder";
2
+
1
3
  type XmlNode = {
2
4
  tag: string;
3
5
  attributes?: Record<string, string>;
@@ -5,23 +7,26 @@ type XmlNode = {
5
7
  text?: string;
6
8
  };
7
9
 
8
- const XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>';
9
- const INDENT = " ".repeat(4);
10
+ type OrderedNode = Record<string, unknown>;
10
11
 
11
- const ESCAPES: Record<string, string> = {
12
- '"': "&quot;",
13
- "&": "&amp;",
14
- "<": "&lt;",
15
- ">": "&gt;",
16
- };
12
+ const XML_ENCODING = ["UTF", "8"].join("-");
17
13
 
18
- const escapeXml = (value: string): string =>
19
- value.replaceAll(/["&<>]/g, (character) => ESCAPES[character] ?? character);
14
+ const builder = new XMLBuilder({
15
+ format: true,
16
+ ignoreAttributes: false,
17
+ indentBy: " ".repeat(4),
18
+ preserveOrder: true,
19
+ suppressEmptyNode: true,
20
+ });
20
21
 
21
- const renderAttributes = (attributes: Record<string, string> | undefined): string =>
22
- Object.entries(attributes ?? {})
23
- .map(([key, value]) => ` ${key}="${escapeXml(value)}"`)
24
- .join("");
22
+ const orderedNode = (node: XmlNode): OrderedNode => ({
23
+ [node.tag]: node.text === undefined
24
+ ? (node.children ?? []).map((child) => orderedNode(child))
25
+ : [{ "#text": node.text }],
26
+ ...(node.attributes && {
27
+ ":@": Object.fromEntries(Object.entries(node.attributes).map(([key, value]) => [`@_${key}`, value])),
28
+ }),
29
+ });
25
30
 
26
31
  const element = (tag: string, attributes: Record<string, string>, children: XmlNode[]): XmlNode => ({
27
32
  tag,
@@ -31,23 +36,10 @@ const element = (tag: string, attributes: Record<string, string>, children: XmlN
31
36
 
32
37
  const text = (tag: string, value: string): XmlNode => ({ tag, text: value });
33
38
 
34
- const renderNode = (node: XmlNode, depth: number): string[] => {
35
- const padding = INDENT.repeat(depth);
36
- const open = `${padding}<${node.tag}${renderAttributes(node.attributes)}`;
37
-
38
- if (node.text !== undefined) {
39
- return [`${open}>${escapeXml(node.text)}</${node.tag}>`];
40
- }
41
-
42
- const children = node.children ?? [];
43
-
44
- if (children.length === 0) {
45
- return [`${open}/>`];
46
- }
47
-
48
- return [`${open}>`, ...children.flatMap((child) => renderNode(child, depth + 1)), `${padding}</${node.tag}>`];
49
- };
50
-
51
- const renderDocument = (root: XmlNode): string => [XML_DECLARATION, ...renderNode(root, 0), ""].join("\n");
39
+ const renderDocument = (root: XmlNode): string =>
40
+ `${builder.build([
41
+ { "?xml": [{ "#text": "" }], ":@": { "@_version": "1.0", "@_encoding": XML_ENCODING } },
42
+ orderedNode(root),
43
+ ])}\n`;
52
44
 
53
45
  export { element, renderDocument, text, type XmlNode };
@@ -1,5 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
1
  import { dirname, join } from "node:path";
2
+ import { readLicenseText } from "../notices/text.js";
3
3
 
4
4
  const LICENSE_FILENAME = "LICENSE";
5
5
  const NODE_MARKER = "Node.js";
@@ -10,13 +10,7 @@ const licenseCandidates = (binary: string): string[] => {
10
10
  return [join(dir, LICENSE_FILENAME), join(dir, "..", LICENSE_FILENAME)];
11
11
  };
12
12
 
13
- const isNodeLicense = (path: string): boolean => {
14
- try {
15
- return readFileSync(path, "utf8").includes(NODE_MARKER);
16
- } catch {
17
- return false;
18
- }
19
- };
13
+ const isNodeLicense = (path: string): boolean => readLicenseText(path)?.includes(NODE_MARKER) === true;
20
14
 
21
15
  const licenseBesideNode = (binary: string): string | null =>
22
16
  licenseCandidates(binary).find((candidate) => isNodeLicense(candidate)) ?? null;
@@ -1,4 +1,5 @@
1
1
  import { sortStringsBy, warn } from "@gtkx/utils";
2
+ import hostedGitInfo from "hosted-git-info";
2
3
  import { existsSync, realpathSync } from "node:fs";
3
4
  import { join, resolve } from "node:path";
4
5
  import type { RecordedPackage } from "../../internal/build-manifest.js";
@@ -17,10 +18,6 @@ type BundledPackage = {
17
18
  };
18
19
 
19
20
  const MANIFEST_FILENAME = "package.json";
20
- const GIT_PREFIX = /^git\+/;
21
- const GIT_SUFFIX = /\.git$/;
22
- const GIT_SCHEME = /^git:\/\//;
23
- const GITHUB_SLUG = /^(?:github:)?(?<slug>[\w.-]+\/[\w.-]+)$/;
24
21
 
25
22
  const realPath = (path: string): string => {
26
23
  try {
@@ -47,14 +44,9 @@ const sourceUrl = (manifest: PackageManifest): string | null => {
47
44
  return null;
48
45
  }
49
46
 
50
- const url = configured.replace(GIT_PREFIX, "").replace(GIT_SUFFIX, "").replace(GIT_SCHEME, "https://");
51
- const slug = GITHUB_SLUG.exec(url)?.groups?.slug;
47
+ const url = configured.replace(/^git\+/, "").replace(/\.git$/, "").replace(/^git:\/\//, "https://");
52
48
 
53
- if (slug !== undefined) {
54
- return `https://github.com/${slug}`;
55
- }
56
-
57
- return url.startsWith("http") ? url : null;
49
+ return hostedGitInfo.fromUrl(url)?.browse() ?? (url.startsWith("http") ? url : null);
58
50
  };
59
51
 
60
52
  const missingPackage = (entry: RecordedPackage): BundledPackage => ({
@@ -1,5 +1,6 @@
1
+ import { isPathInside } from "@gtkx/utils";
1
2
  import { chmodSync, copyFileSync, mkdirSync, statSync, writeFileSync } from "node:fs";
2
- import { dirname, isAbsolute, join, relative } from "node:path";
3
+ import { dirname, join } from "node:path";
3
4
  import type { StagedFile } from "../types.js";
4
5
  import { listFilesRecursive } from "../../internal/list-files.js";
5
6
 
@@ -16,9 +17,7 @@ const modeFor = (rel: string): number => {
16
17
  };
17
18
 
18
19
  const assertInsideRoot = (root: string, rel: string, abs: string): void => {
19
- const escape = relative(root, abs);
20
-
21
- if (escape.length === 0 || escape.startsWith("..") || isAbsolute(escape)) {
20
+ if (!isPathInside(root, abs)) {
22
21
  throw new Error(`Cannot stage "${rel}": it resolves outside the staging directory`);
23
22
  }
24
23
  };
@@ -27,7 +27,6 @@ type StagedMetadata = {
27
27
  };
28
28
 
29
29
  const DIST_ICONS_DIR = "icons";
30
- const LEGACY_PACKAGES_MANIFEST_FILENAME = "gtkx-packages.json";
31
30
  const NOTICES_FILENAME = "THIRD-PARTY-NOTICES";
32
31
  const NODE_LICENSE_FILENAME = "LICENSE";
33
32
  const SHARE_APPLICATIONS = "share/applications";
@@ -50,10 +49,6 @@ const licenseDirFor = (settings: DeploySettings): string => `${SHARE_LICENSES}/$
50
49
  const licenseDestination = (settings: DeploySettings): string => `${licenseDirFor(settings)}/LICENSE`;
51
50
  const noticesDestination = (settings: DeploySettings): string => `${licenseDirFor(settings)}/${NOTICES_FILENAME}`;
52
51
  const isIconAsset = (rel: string): boolean => rel === DIST_ICONS_DIR || rel.startsWith(`${DIST_ICONS_DIR}/`);
53
-
54
- const isBuildMetadata = (rel: string): boolean =>
55
- rel === BUILD_MANIFEST_FILENAME || rel === LEGACY_PACKAGES_MANIFEST_FILENAME;
56
-
57
52
  const isLocaleAsset = (rel: string): boolean => rel === LOCALE_DIRNAME || rel.startsWith(`${LOCALE_DIRNAME}/`);
58
53
 
59
54
  const nodeLicenseDestination = (settings: DeploySettings): string =>
@@ -67,7 +62,8 @@ const stageRuntimeFiles = (settings: DeploySettings, root: string): StagedFile[]
67
62
  }
68
63
 
69
64
  return listFilesRecursive(dist)
70
- .filter((file) => !isIconAsset(file.rel) && !isBuildMetadata(file.rel) && !isLocaleAsset(file.rel))
65
+ .filter((file) =>
66
+ !isIconAsset(file.rel) && file.rel !== BUILD_MANIFEST_FILENAME && !isLocaleAsset(file.rel))
71
67
  .map((file) => copyInto(root, join(libDirFor(settings), file.rel), file.absPath));
72
68
  };
73
69