@fuzdev/fuz_gitops 0.77.0 → 0.78.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 (162) hide show
  1. package/README.md +25 -5
  2. package/dist/ModulesDetail.svelte +14 -12
  3. package/dist/ModulesDetail.svelte.d.ts.map +1 -1
  4. package/dist/ModulesNav.svelte +6 -6
  5. package/dist/ModulesNav.svelte.d.ts.map +1 -1
  6. package/dist/ModulesPage.svelte +2 -2
  7. package/dist/ModulesPage.svelte.d.ts.map +1 -1
  8. package/dist/PageFooter.svelte +2 -2
  9. package/dist/PageHeader.svelte +5 -5
  10. package/dist/PageHeader.svelte.d.ts +1 -1
  11. package/dist/PageHeader.svelte.d.ts.map +1 -1
  12. package/dist/PullRequestsDetail.svelte +25 -17
  13. package/dist/PullRequestsDetail.svelte.d.ts.map +1 -1
  14. package/dist/PullRequestsPage.svelte +3 -3
  15. package/dist/PullRequestsPage.svelte.d.ts.map +1 -1
  16. package/dist/ReposTable.svelte +24 -15
  17. package/dist/ReposTable.svelte.d.ts.map +1 -1
  18. package/dist/ReposTree.svelte +8 -6
  19. package/dist/ReposTree.svelte.d.ts.map +1 -1
  20. package/dist/ReposTreeNav.svelte +10 -11
  21. package/dist/ReposTreeNav.svelte.d.ts.map +1 -1
  22. package/dist/TablePage.svelte +2 -2
  23. package/dist/TablePage.svelte.d.ts.map +1 -1
  24. package/dist/TreeItemPage.svelte +2 -2
  25. package/dist/TreeItemPage.svelte.d.ts.map +1 -1
  26. package/dist/TreePage.svelte +2 -2
  27. package/dist/TreePage.svelte.d.ts.map +1 -1
  28. package/dist/cargo_toml.d.ts +33 -0
  29. package/dist/cargo_toml.d.ts.map +1 -0
  30. package/dist/cargo_toml.js +74 -0
  31. package/dist/changeset_generator.d.ts +1 -1
  32. package/dist/changeset_generator.d.ts.map +1 -1
  33. package/dist/changeset_generator.js +2 -2
  34. package/dist/changeset_reader.d.ts +1 -1
  35. package/dist/changeset_reader.d.ts.map +1 -1
  36. package/dist/changeset_reader.js +3 -3
  37. package/dist/config_reconcile.d.ts.map +1 -1
  38. package/dist/config_reconcile.js +6 -2
  39. package/dist/dependency_graph.d.ts +2 -2
  40. package/dist/dependency_graph.d.ts.map +1 -1
  41. package/dist/dependency_graph.js +9 -9
  42. package/dist/dependency_updater.d.ts +1 -1
  43. package/dist/dependency_updater.d.ts.map +1 -1
  44. package/dist/dependency_updater.js +8 -8
  45. package/dist/fetch_repo_data.d.ts +2 -2
  46. package/dist/fetch_repo_data.d.ts.map +1 -1
  47. package/dist/fetch_repo_data.js +4 -4
  48. package/dist/fs_fetch_value_cache.d.ts +1 -1
  49. package/dist/fs_fetch_value_cache.d.ts.map +1 -1
  50. package/dist/fs_fetch_value_cache.js +5 -5
  51. package/dist/git_operations.d.ts +1 -1
  52. package/dist/git_operations.d.ts.map +1 -1
  53. package/dist/git_operations.js +2 -2
  54. package/dist/github.d.ts +2 -2
  55. package/dist/github.d.ts.map +1 -1
  56. package/dist/github.js +7 -7
  57. package/dist/github_helpers.d.ts.map +1 -1
  58. package/dist/github_helpers.js +1 -1
  59. package/dist/gitops_analyze.task.d.ts.map +1 -1
  60. package/dist/gitops_analyze.task.js +21 -14
  61. package/dist/gitops_config.d.ts +2 -2
  62. package/dist/gitops_config.d.ts.map +1 -1
  63. package/dist/gitops_config.js +5 -5
  64. package/dist/gitops_plan.task.d.ts.map +1 -1
  65. package/dist/gitops_plan.task.js +8 -8
  66. package/dist/gitops_publish.task.d.ts.map +1 -1
  67. package/dist/gitops_publish.task.js +15 -12
  68. package/dist/gitops_run.task.d.ts.map +1 -1
  69. package/dist/gitops_run.task.js +10 -10
  70. package/dist/gitops_sync.task.d.ts.map +1 -1
  71. package/dist/gitops_sync.task.js +15 -13
  72. package/dist/gitops_task_helpers.d.ts +1 -1
  73. package/dist/gitops_task_helpers.d.ts.map +1 -1
  74. package/dist/gitops_task_helpers.js +4 -4
  75. package/dist/gitops_validate.task.d.ts.map +1 -1
  76. package/dist/gitops_validate.task.js +14 -14
  77. package/dist/graph_validation.d.ts +2 -2
  78. package/dist/graph_validation.d.ts.map +1 -1
  79. package/dist/graph_validation.js +5 -3
  80. package/dist/local_repo.d.ts +21 -7
  81. package/dist/local_repo.d.ts.map +1 -1
  82. package/dist/local_repo.js +64 -16
  83. package/dist/log_helpers.d.ts +1 -1
  84. package/dist/log_helpers.d.ts.map +1 -1
  85. package/dist/multi_repo_publisher.d.ts +3 -3
  86. package/dist/multi_repo_publisher.d.ts.map +1 -1
  87. package/dist/multi_repo_publisher.js +24 -20
  88. package/dist/npm_registry.d.ts +1 -1
  89. package/dist/npm_registry.d.ts.map +1 -1
  90. package/dist/npm_registry.js +4 -4
  91. package/dist/operations.d.ts +4 -4
  92. package/dist/operations.d.ts.map +1 -1
  93. package/dist/operations_defaults.d.ts.map +1 -1
  94. package/dist/operations_defaults.js +16 -16
  95. package/dist/output_helpers.d.ts +1 -1
  96. package/dist/output_helpers.d.ts.map +1 -1
  97. package/dist/preflight_checks.d.ts +2 -2
  98. package/dist/preflight_checks.d.ts.map +1 -1
  99. package/dist/preflight_checks.js +5 -5
  100. package/dist/publish_gate.d.ts.map +1 -1
  101. package/dist/publish_steps.d.ts.map +1 -1
  102. package/dist/publish_steps.js +4 -4
  103. package/dist/publishing_event.d.ts.map +1 -1
  104. package/dist/publishing_event.js +16 -14
  105. package/dist/publishing_event_handler.d.ts.map +1 -1
  106. package/dist/publishing_event_handler.js +6 -6
  107. package/dist/publishing_plan.d.ts +3 -3
  108. package/dist/publishing_plan.d.ts.map +1 -1
  109. package/dist/publishing_plan.js +25 -15
  110. package/dist/publishing_plan_helpers.d.ts.map +1 -1
  111. package/dist/publishing_plan_helpers.js +3 -3
  112. package/dist/publishing_plan_logging.d.ts +1 -1
  113. package/dist/publishing_plan_logging.d.ts.map +1 -1
  114. package/dist/publishing_plan_logging.js +2 -2
  115. package/dist/repo.svelte.d.ts +5 -5
  116. package/dist/repo.svelte.d.ts.map +1 -1
  117. package/dist/repo.svelte.js +2 -2
  118. package/dist/repo_ops.js +2 -2
  119. package/dist/resolved_gitops_config.d.ts.map +1 -1
  120. package/dist/resolved_gitops_config.js +1 -1
  121. package/dist/version_utils.js +1 -1
  122. package/package.json +16 -15
  123. package/src/lib/cargo_toml.ts +82 -0
  124. package/src/lib/changeset_generator.ts +20 -20
  125. package/src/lib/changeset_reader.ts +18 -18
  126. package/src/lib/ci_reconcile.ts +5 -5
  127. package/src/lib/config_reconcile.ts +8 -4
  128. package/src/lib/dependency_graph.ts +28 -28
  129. package/src/lib/dependency_updater.ts +30 -30
  130. package/src/lib/fetch_repo_data.ts +11 -11
  131. package/src/lib/fs_fetch_value_cache.ts +14 -10
  132. package/src/lib/git_operations.ts +31 -31
  133. package/src/lib/github.ts +19 -19
  134. package/src/lib/github_helpers.ts +6 -6
  135. package/src/lib/gitops_analyze.task.ts +56 -48
  136. package/src/lib/gitops_config.ts +14 -14
  137. package/src/lib/gitops_plan.task.ts +32 -32
  138. package/src/lib/gitops_publish.task.ts +52 -49
  139. package/src/lib/gitops_run.task.ts +29 -29
  140. package/src/lib/gitops_sync.task.ts +39 -30
  141. package/src/lib/gitops_task_helpers.ts +21 -21
  142. package/src/lib/gitops_validate.task.ts +38 -38
  143. package/src/lib/graph_validation.ts +14 -13
  144. package/src/lib/local_repo.ts +130 -64
  145. package/src/lib/log_helpers.ts +15 -15
  146. package/src/lib/multi_repo_publisher.ts +75 -74
  147. package/src/lib/npm_registry.ts +13 -13
  148. package/src/lib/operations.ts +50 -39
  149. package/src/lib/operations_defaults.ts +108 -106
  150. package/src/lib/output_helpers.ts +4 -4
  151. package/src/lib/preflight_checks.ts +28 -28
  152. package/src/lib/publish_gate.ts +7 -9
  153. package/src/lib/publish_steps.ts +15 -15
  154. package/src/lib/publishing_event.ts +22 -20
  155. package/src/lib/publishing_event_handler.ts +8 -8
  156. package/src/lib/publishing_plan.ts +69 -57
  157. package/src/lib/publishing_plan_helpers.ts +16 -12
  158. package/src/lib/publishing_plan_logging.ts +23 -23
  159. package/src/lib/repo.svelte.ts +8 -8
  160. package/src/lib/repo_ops.ts +12 -12
  161. package/src/lib/resolved_gitops_config.ts +5 -5
  162. package/src/lib/version_utils.ts +3 -3
@@ -1,30 +1,30 @@
1
- import type {Logger} from '@fuzdev/fuz_util/log.js';
2
- import {TaskError} from '@fuzdev/gro';
3
- import {join} from 'node:path';
4
- import {styleText as st} from 'node:util';
1
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
2
+ import { TaskError } from '@fuzdev/gro';
3
+ import { join } from 'node:path';
4
+ import { styleText as st } from 'node:util';
5
5
 
6
- import type {LocalRepo} from './local_repo.js';
7
- import {update_package_json, type VersionStrategy} from './dependency_updater.js';
6
+ import { repo_is_npm, type LocalRepo } from './local_repo.ts';
7
+ import { update_package_json, type VersionStrategy } from './dependency_updater.ts';
8
8
  import {
9
9
  generate_publishing_plan,
10
10
  type VersionChange,
11
11
  type DependencyUpdate,
12
- type PublishingPlan,
13
- } from './publishing_plan.js';
14
- import type {PreflightOptions} from './preflight_checks.js';
15
- import type {GitopsOperations} from './operations.js';
16
- import {default_gitops_operations} from './operations_defaults.js';
17
- import {GITOPS_NPM_WAIT_TIMEOUT_DEFAULT} from './gitops_constants.js';
12
+ type PublishingPlan
13
+ } from './publishing_plan.ts';
14
+ import type { PreflightOptions } from './preflight_checks.ts';
15
+ import type { GitopsOperations } from './operations.ts';
16
+ import { default_gitops_operations } from './operations_defaults.ts';
17
+ import { GITOPS_NPM_WAIT_TIMEOUT_DEFAULT } from './gitops_constants.ts';
18
18
  import {
19
19
  type PublishingEvent,
20
20
  type PublishingRunSummary,
21
- summarize_events,
22
- } from './publishing_event.js';
21
+ summarize_events
22
+ } from './publishing_event.ts';
23
23
  import {
24
24
  type PublishingEventHandler,
25
25
  capture_handler,
26
- multi_handler,
27
- } from './publishing_event_handler.js';
26
+ multi_handler
27
+ } from './publishing_event_handler.ts';
28
28
 
29
29
  export interface PublishingOptions {
30
30
  wetrun: boolean;
@@ -50,7 +50,7 @@ export interface PublishedVersion {
50
50
  export interface PublishingResult {
51
51
  ok: boolean;
52
52
  published: Array<PublishedVersion>;
53
- failed: Array<{name: string; error: Error}>;
53
+ failed: Array<{ name: string; error: Error }>;
54
54
  duration: number;
55
55
  /** The structured event stream for this run, in emission order. */
56
56
  events: Array<PublishingEvent>;
@@ -64,13 +64,13 @@ export interface PublishingResult {
64
64
 
65
65
  export const publish_repos = async (
66
66
  repos: Array<LocalRepo>,
67
- options: PublishingOptions,
67
+ options: PublishingOptions
68
68
  ): Promise<PublishingResult> => {
69
- const {log, ops = default_gitops_operations} = options;
69
+ const { log, ops = default_gitops_operations } = options;
70
70
  // Convenience entry: generate the plan, then execute it. Callers that already hold a
71
71
  // plan (e.g. to display and confirm it first) call `execute_publishing_plan` directly,
72
72
  // so the plan is generated exactly once per command.
73
- const plan = await generate_publishing_plan(repos, {log, ops: ops.changeset});
73
+ const plan = await generate_publishing_plan(repos, { log, ops: ops.changeset });
74
74
  return execute_publishing_plan(repos, plan, options);
75
75
  };
76
76
 
@@ -83,19 +83,23 @@ export const publish_repos = async (
83
83
  * `ok: false`. This is the single error gate — `--no-plan` can't bypass it.
84
84
  */
85
85
  export const execute_publishing_plan = async (
86
- repos: Array<LocalRepo>,
86
+ all_repos: Array<LocalRepo>,
87
87
  plan: PublishingPlan,
88
- options: PublishingOptions,
88
+ options: PublishingOptions
89
89
  ): Promise<PublishingResult> => {
90
90
  const start_time = Date.now();
91
- const {wetrun, log, ops = default_gitops_operations} = options;
91
+ const { wetrun, log, ops = default_gitops_operations } = options;
92
+
93
+ // Only npm repos publish; drop any non-npm repos (e.g. cargo) so preflight and the
94
+ // executor's name lookup never touch them. The plan already excludes them too.
95
+ const repos = all_repos.filter(repo_is_npm);
92
96
 
93
97
  // Fail loud on an incomplete plan. Executing one with errors would silently skip the
94
98
  // affected packages. A wetrun aborts before touching npm or git; a dry run proceeds
95
99
  // (no side effects) but the result is not ok (see the summary below).
96
100
  if (wetrun && plan.errors.length > 0) {
97
101
  throw new TaskError(
98
- `Cannot publish — the plan has ${plan.errors.length} error(s):\n ${plan.errors.join('\n ')}`,
102
+ `Cannot publish — the plan has ${plan.errors.length} error(s):\n ${plan.errors.join('\n ')}`
99
103
  );
100
104
  }
101
105
 
@@ -111,7 +115,7 @@ export const execute_publishing_plan = async (
111
115
  const preflight_options: PreflightOptions = {
112
116
  skip_changesets: false, // Always check for changesets
113
117
  required_branch: 'main',
114
- log,
118
+ log
115
119
  };
116
120
  const preflight = await ops.preflight.run_preflight_checks({
117
121
  repos,
@@ -119,7 +123,7 @@ export const execute_publishing_plan = async (
119
123
  git_ops: ops.git,
120
124
  npm_ops: ops.npm,
121
125
  build_ops: ops.build,
122
- changeset_ops: ops.changeset,
126
+ changeset_ops: ops.changeset
123
127
  });
124
128
 
125
129
  if (!preflight.ok) {
@@ -134,13 +138,13 @@ export const execute_publishing_plan = async (
134
138
  // frozen topological order directly, re-deriving nothing.
135
139
  const order = plan.publishing_order;
136
140
  const plan_changes: Map<string, VersionChange> = new Map(
137
- plan.version_changes.map((vc) => [vc.package_name, vc]),
141
+ plan.version_changes.map((vc) => [vc.package_name, vc])
138
142
  );
139
143
  if (order.length > 0) {
140
144
  log?.info(` Publishing order: ${order.join(' → ')}`);
141
145
  }
142
146
 
143
- emit({event: 'run_started', wetrun, total: order.length});
147
+ emit({ event: 'run_started', wetrun, total: order.length });
144
148
 
145
149
  const published: Map<string, PublishedVersion> = new Map();
146
150
  const failed: Map<string, Error> = new Map();
@@ -161,7 +165,7 @@ export const execute_publishing_plan = async (
161
165
 
162
166
  // Not in the plan = no changesets and no dependency updates = nothing to publish.
163
167
  if (!planned) {
164
- emit({event: 'package_skipped', name: pkg_name, reason: 'no changesets'});
168
+ emit({ event: 'package_skipped', name: pkg_name, reason: 'no changesets' });
165
169
  log?.info(st('yellow', ` ⚠️ Skipping ${pkg_name} - no changesets`));
166
170
  continue;
167
171
  }
@@ -178,8 +182,8 @@ export const execute_publishing_plan = async (
178
182
  log?.info(
179
183
  st(
180
184
  'dim',
181
- ` [${i + 1}/${order.length}] ${wetrun ? 'Publishing' : 'Would publish'} ${pkg_name}...`,
182
- ),
185
+ ` [${i + 1}/${order.length}] ${wetrun ? 'Publishing' : 'Would publish'} ${pkg_name}...`
186
+ )
183
187
  );
184
188
  const version = await publish_single_repo(repo, options, ops, planned);
185
189
 
@@ -190,10 +194,10 @@ export const execute_publishing_plan = async (
190
194
  if (wetrun && version.new_version !== planned.to) {
191
195
  const err = new Error(
192
196
  `Plan drift for ${pkg_name}: published ${version.new_version} but the plan predicted ${planned.to}. ` +
193
- `Aborting — re-run 'gro gitops_publish --wetrun' to re-plan from the current state.`,
197
+ `Aborting — re-run 'gro gitops_publish --wetrun' to re-plan from the current state.`
194
198
  );
195
199
  failed.set(pkg_name, err);
196
- emit({event: 'package_failed', name: pkg_name, error: err.message, code: 'drift'});
200
+ emit({ event: 'package_failed', name: pkg_name, error: err.message, code: 'drift' });
197
201
  log?.error(st('red', ` ❌ ${err.message}`));
198
202
  break;
199
203
  }
@@ -208,12 +212,12 @@ export const execute_publishing_plan = async (
208
212
  bump_type: version.bump_type,
209
213
  breaking: version.breaking,
210
214
  commit: version.commit,
211
- tag: version.tag,
215
+ tag: version.tag
212
216
  });
213
217
  log?.info(
214
218
  wetrun
215
219
  ? st('green', ` ✅ Published ${pkg_name}@${version.new_version}`)
216
- : st('cyan', ` ◇ Would publish ${pkg_name}@${version.new_version}`),
220
+ : st('cyan', ` ◇ Would publish ${pkg_name}@${version.new_version}`)
217
221
  );
218
222
 
219
223
  if (wetrun) {
@@ -226,9 +230,9 @@ export const execute_publishing_plan = async (
226
230
  max_attempts: 30,
227
231
  initial_delay: 1000,
228
232
  max_delay: 60000,
229
- timeout: options.max_wait ?? GITOPS_NPM_WAIT_TIMEOUT_DEFAULT,
233
+ timeout: options.max_wait ?? GITOPS_NPM_WAIT_TIMEOUT_DEFAULT
230
234
  },
231
- log,
235
+ log
232
236
  });
233
237
 
234
238
  if (!wait_result.ok) {
@@ -236,14 +240,14 @@ export const execute_publishing_plan = async (
236
240
  // carries a typed `timeout` signal, so we know this is a network failure
237
241
  // without sniffing the message.
238
242
  const err = new Error(
239
- `Failed to wait for package: ${wait_result.message}${wait_result.timeout ? ' (timeout)' : ''}`,
243
+ `Failed to wait for package: ${wait_result.message}${wait_result.timeout ? ' (timeout)' : ''}`
240
244
  );
241
245
  failed.set(pkg_name, err);
242
- emit({event: 'package_failed', name: pkg_name, error: err.message, code: 'network'});
246
+ emit({ event: 'package_failed', name: pkg_name, error: err.message, code: 'network' });
243
247
  log?.error(st('red', ` ❌ Failed to publish ${pkg_name}: ${err.message}`));
244
248
  break; // fail fast
245
249
  }
246
- emit({event: 'npm_waited', name: pkg_name, version: version.new_version});
250
+ emit({ event: 'npm_waited', name: pkg_name, version: version.new_version });
247
251
 
248
252
  // 3. Update every dependent the plan says has a prod/peer dep on this package.
249
253
  // This rewrites their package.json ranges and creates their auto-changeset,
@@ -254,7 +258,7 @@ export const execute_publishing_plan = async (
254
258
  published,
255
259
  (update) =>
256
260
  update.updated_dependency === pkg_name &&
257
- (update.type === 'dependencies' || update.type === 'peerDependencies'),
261
+ (update.type === 'dependencies' || update.type === 'peerDependencies')
258
262
  );
259
263
  for (const [dependent_name, updates] of dependent_updates) {
260
264
  const dependent_repo = repo_by_name.get(dependent_name);
@@ -273,7 +277,7 @@ export const execute_publishing_plan = async (
273
277
  dependency: dep_name,
274
278
  version: dep_version,
275
279
  dep_type: dependency_update_type(plan, dependent_name, dep_name),
276
- creates_changeset: republishes,
280
+ creates_changeset: republishes
277
281
  });
278
282
  }
279
283
  changed_repos.add(dependent_name); // Mark as changed for deployment
@@ -283,7 +287,7 @@ export const execute_publishing_plan = async (
283
287
  published_versions: published, // creates the auto-changeset
284
288
  log,
285
289
  git_ops: ops.git,
286
- fs_ops: ops.fs,
290
+ fs_ops: ops.fs
287
291
  });
288
292
  } else {
289
293
  // update-only leaf: rewrite ranges + commit, no changeset (it won't republish)
@@ -291,7 +295,7 @@ export const execute_publishing_plan = async (
291
295
  strategy: options.version_strategy || 'caret',
292
296
  log,
293
297
  git_ops: ops.git,
294
- fs_ops: ops.fs,
298
+ fs_ops: ops.fs
295
299
  });
296
300
  }
297
301
  }
@@ -306,7 +310,7 @@ export const execute_publishing_plan = async (
306
310
  // TODO: emit a precise code once the npm/process ops return typed errors —
307
311
  // today a publish-step cause lives in unstructured stderr, so use the honest
308
312
  // coarse bucket rather than guessing 'auth'/'network'/'build' from the message.
309
- code: 'publish',
313
+ code: 'publish'
310
314
  });
311
315
  log?.error(st('red', ` ❌ Failed to publish ${pkg_name}: ${err.message}`));
312
316
  break; // Always fail fast on error
@@ -323,7 +327,7 @@ export const execute_publishing_plan = async (
323
327
  const dev_updates_by_repo = group_dependency_updates(
324
328
  plan.dependency_updates,
325
329
  published,
326
- (update) => update.type === 'devDependencies',
330
+ (update) => update.type === 'devDependencies'
327
331
  );
328
332
 
329
333
  if (dev_updates_by_repo.size > 0) {
@@ -342,7 +346,7 @@ export const execute_publishing_plan = async (
342
346
  dependency: dep_name,
343
347
  version: dep_version,
344
348
  dep_type: 'dev',
345
- creates_changeset: false, // dev-dep updates redeploy without republishing
349
+ creates_changeset: false // dev-dep updates redeploy without republishing
346
350
  });
347
351
  }
348
352
  changed_repos.add(repo_name); // Mark as changed for deployment
@@ -353,7 +357,7 @@ export const execute_publishing_plan = async (
353
357
  strategy: options.version_strategy || 'caret',
354
358
  log,
355
359
  git_ops: ops.git,
356
- fs_ops: ops.fs,
360
+ fs_ops: ops.fs
357
361
  });
358
362
  }
359
363
  }
@@ -367,15 +371,12 @@ export const execute_publishing_plan = async (
367
371
  .map((name) => repo_by_name.get(name))
368
372
  .filter((r): r is LocalRepo => r !== undefined);
369
373
  log?.info(
370
- st(
371
- 'cyan',
372
- `\n🚢 Deploying ${repos_to_deploy.length}/${repos.length} repos with changes...\n`,
373
- ),
374
+ st('cyan', `\n🚢 Deploying ${repos_to_deploy.length}/${repos.length} repos with changes...\n`)
374
375
  );
375
376
 
376
377
  for (const repo of repos_to_deploy) {
377
378
  try {
378
- emit({event: 'deploy_started', name: repo.library.name});
379
+ emit({ event: 'deploy_started', name: repo.library.name });
379
380
  log?.info(` Deploying ${repo.library.name}...`);
380
381
  // Build fresh (no --no-build): a deployed site bundles its dependencies, so it
381
382
  // must be rebuilt against the versions this run just published — the preflight
@@ -383,19 +384,19 @@ export const execute_publishing_plan = async (
383
384
  const deploy_result = await ops.process.spawn({
384
385
  cmd: 'gro',
385
386
  args: ['deploy'],
386
- cwd: repo.repo_dir,
387
+ cwd: repo.repo_dir
387
388
  });
388
389
 
389
390
  if (deploy_result.ok) {
390
- emit({event: 'deploy_completed', name: repo.library.name});
391
+ emit({ event: 'deploy_completed', name: repo.library.name });
391
392
  log?.info(st('green', ` ✅ Deployed ${repo.library.name}`));
392
393
  } else {
393
- emit({event: 'deploy_failed', name: repo.library.name, error: deploy_result.message});
394
+ emit({ event: 'deploy_failed', name: repo.library.name, error: deploy_result.message });
394
395
  log?.warn(st('yellow', ` ⚠️ Failed to deploy ${repo.library.name}`));
395
396
  }
396
397
  } catch (error) {
397
398
  const err = error instanceof Error ? error : new Error(String(error));
398
- emit({event: 'deploy_failed', name: repo.library.name, error: err.message});
399
+ emit({ event: 'deploy_failed', name: repo.library.name, error: err.message });
399
400
  log?.error(st('red', ` ❌ Error deploying ${repo.library.name}: ${err.message}`));
400
401
  }
401
402
  }
@@ -431,8 +432,8 @@ export const execute_publishing_plan = async (
431
432
  log?.info(
432
433
  st(
433
434
  'green',
434
- `\n✨ Dry run complete — ${published.size} package(s) would be published. Re-run with --wetrun to publish.`,
435
- ),
435
+ `\n✨ Dry run complete — ${published.size} package(s) would be published. Re-run with --wetrun to publish.`
436
+ )
436
437
  );
437
438
  // The dry run is driven by the same plan as `gro gitops_plan`, so this
438
439
  // count includes bump escalations and auto-generated changesets — it
@@ -445,22 +446,22 @@ export const execute_publishing_plan = async (
445
446
  'red',
446
447
  wetrun
447
448
  ? '\n❌ Some packages failed to publish\n'
448
- : '\n❌ Some packages failed during dry run\n',
449
- ),
449
+ : '\n❌ Some packages failed during dry run\n'
450
+ )
450
451
  );
451
452
  }
452
453
 
453
- emit({event: 'run_finished', summary});
454
+ emit({ event: 'run_finished', summary });
454
455
 
455
456
  return {
456
457
  ok,
457
458
  published: Array.from(published.values()),
458
- failed: Array.from(failed.entries()).map(([name, error]) => ({name, error})),
459
+ failed: Array.from(failed.entries()).map(([name, error]) => ({ name, error })),
459
460
  duration,
460
461
  events: capture.events,
461
462
  summary,
462
463
  plan_errors: plan.errors,
463
- plan_warnings: plan.warnings,
464
+ plan_warnings: plan.warnings
464
465
  };
465
466
  };
466
467
 
@@ -479,9 +480,9 @@ const publish_single_repo = async (
479
480
  repo: LocalRepo,
480
481
  options: PublishingOptions,
481
482
  ops: GitopsOperations,
482
- planned: VersionChange,
483
+ planned: VersionChange
483
484
  ): Promise<PublishedVersion> => {
484
- const {wetrun} = options;
485
+ const { wetrun } = options;
485
486
 
486
487
  if (!wetrun) {
487
488
  // Dry run reports the precomputed plan — the single source of truth for the
@@ -493,7 +494,7 @@ const publish_single_repo = async (
493
494
  bump_type: planned.bump_type,
494
495
  breaking: planned.breaking,
495
496
  commit: 'simulated',
496
- tag: `v${planned.to}`,
497
+ tag: `v${planned.to}`
497
498
  };
498
499
  }
499
500
 
@@ -501,7 +502,7 @@ const publish_single_repo = async (
501
502
  const publish_result = await ops.process.spawn({
502
503
  cmd: 'gro',
503
504
  args: ['publish', '--no-build'],
504
- cwd: repo.repo_dir,
505
+ cwd: repo.repo_dir
505
506
  });
506
507
 
507
508
  if (!publish_result.ok) {
@@ -510,7 +511,7 @@ const publish_single_repo = async (
510
511
 
511
512
  // Read the new version from package.json after gro publish
512
513
  const package_json_path = join(repo.repo_dir, 'package.json');
513
- const content_result = await ops.fs.readFile({path: package_json_path, encoding: 'utf8'});
514
+ const content_result = await ops.fs.readFile({ path: package_json_path, encoding: 'utf8' });
514
515
 
515
516
  if (!content_result.ok) {
516
517
  throw new Error(`Failed to read package.json: ${content_result.message}`);
@@ -520,7 +521,7 @@ const publish_single_repo = async (
520
521
  const new_version = package_json.version;
521
522
 
522
523
  // Get actual commit hash
523
- const commit_result = await ops.git.current_commit_hash({cwd: repo.repo_dir});
524
+ const commit_result = await ops.git.current_commit_hash({ cwd: repo.repo_dir });
524
525
 
525
526
  if (!commit_result.ok) {
526
527
  throw new Error(`Failed to get commit hash: ${commit_result.message}`);
@@ -537,7 +538,7 @@ const publish_single_repo = async (
537
538
  bump_type: planned.bump_type,
538
539
  breaking: planned.breaking,
539
540
  commit,
540
- tag: `v${new_version}`,
541
+ tag: `v${new_version}`
541
542
  };
542
543
  };
543
544
 
@@ -550,7 +551,7 @@ const publish_single_repo = async (
550
551
  export const group_dependency_updates = (
551
552
  updates: Array<DependencyUpdate>,
552
553
  published: Map<string, PublishedVersion>,
553
- predicate: (update: DependencyUpdate) => boolean,
554
+ predicate: (update: DependencyUpdate) => boolean
554
555
  ): Map<string, Map<string, string>> => {
555
556
  const by_repo: Map<string, Map<string, string>> = new Map();
556
557
  for (const update of updates) {
@@ -573,13 +574,13 @@ export const group_dependency_updates = (
573
574
  const dependency_update_type = (
574
575
  plan: PublishingPlan,
575
576
  dependent: string,
576
- dependency: string,
577
+ dependency: string
577
578
  ): 'prod' | 'peer' =>
578
579
  plan.dependency_updates.some(
579
580
  (u) =>
580
581
  u.dependent_package === dependent &&
581
582
  u.updated_dependency === dependency &&
582
- u.type === 'peerDependencies',
583
+ u.type === 'peerDependencies'
583
584
  )
584
585
  ? 'peer'
585
586
  : 'prod';
@@ -1,7 +1,7 @@
1
- import type {Logger} from '@fuzdev/fuz_util/log.js';
2
- import {spawn_out} from '@fuzdev/fuz_util/process.js';
3
- import {wait} from '@fuzdev/fuz_util/async.js';
4
- import {styleText as st} from 'node:util';
1
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
2
+ import { spawn_out } from '@fuzdev/fuz_util/process.ts';
3
+ import { wait } from '@fuzdev/fuz_util/async.ts';
4
+ import { styleText as st } from 'node:util';
5
5
 
6
6
  export interface WaitOptions {
7
7
  log?: Logger;
@@ -19,9 +19,9 @@ export interface PackageInfo {
19
19
  export const check_package_available = async (
20
20
  pkg: string,
21
21
  version: string,
22
- options: {log?: Logger} = {},
22
+ options: { log?: Logger } = {}
23
23
  ): Promise<boolean> => {
24
- const {log} = options;
24
+ const { log } = options;
25
25
  try {
26
26
  // Use npm view to check if the specific version exists
27
27
  const result = await spawn_out('npm', ['view', `${pkg}@${version}`, 'version']);
@@ -57,14 +57,14 @@ export const check_package_available = async (
57
57
  export const wait_for_package = async (
58
58
  pkg: string,
59
59
  version: string,
60
- options: WaitOptions = {},
60
+ options: WaitOptions = {}
61
61
  ): Promise<void> => {
62
62
  const {
63
63
  log,
64
64
  max_attempts = 30,
65
65
  initial_delay = 1000,
66
66
  max_delay = 60000,
67
- timeout = 300000, // 5 minutes default
67
+ timeout = 300000 // 5 minutes default
68
68
  } = options;
69
69
 
70
70
  const start_time = Date.now();
@@ -81,7 +81,7 @@ export const wait_for_package = async (
81
81
 
82
82
  // Check if package is available
83
83
 
84
- if (await check_package_available(pkg, version, {log})) {
84
+ if (await check_package_available(pkg, version, { log })) {
85
85
  log?.info(st('green', ` ✓ ${pkg}@${version} is now available on NPM`));
86
86
  return;
87
87
  }
@@ -113,9 +113,9 @@ export const wait_for_package = async (
113
113
  */
114
114
  export const get_package_info = async (
115
115
  pkg: string,
116
- options: {log?: Logger} = {},
116
+ options: { log?: Logger } = {}
117
117
  ): Promise<PackageInfo | null> => {
118
- const {log} = options;
118
+ const { log } = options;
119
119
  try {
120
120
  const result = await spawn_out('npm', ['view', pkg, '--json']);
121
121
 
@@ -123,7 +123,7 @@ export const get_package_info = async (
123
123
  const data = JSON.parse(result.stdout);
124
124
  return {
125
125
  name: data.name,
126
- version: data.version,
126
+ version: data.version
127
127
  };
128
128
  }
129
129
 
@@ -136,7 +136,7 @@ export const get_package_info = async (
136
136
 
137
137
  export const package_exists = async (
138
138
  pkg: string,
139
- options: {log?: Logger} = {},
139
+ options: { log?: Logger } = {}
140
140
  ): Promise<boolean> => {
141
141
  const info = await get_package_info(pkg, options);
142
142
  return info !== null;