@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,5 +1,5 @@
1
- import {spawn_out, spawn_result_to_message} from '@fuzdev/fuz_util/process.js';
2
- import type {SpawnOptions} from 'node:child_process';
1
+ import { spawn_out, spawn_result_to_message } from '@fuzdev/fuz_util/process.ts';
2
+ import type { SpawnOptions } from 'node:child_process';
3
3
  import {
4
4
  git_check_clean_workspace as gro_git_check_clean_workspace,
5
5
  git_checkout as gro_git_checkout,
@@ -7,21 +7,21 @@ import {
7
7
  git_current_branch_name as gro_git_current_branch_name,
8
8
  git_current_commit_hash as gro_git_current_commit_hash,
9
9
  type GitBranch,
10
- type GitOrigin,
11
- } from '@fuzdev/fuz_util/git.js';
10
+ type GitOrigin
11
+ } from '@fuzdev/fuz_util/git.ts';
12
12
 
13
13
  /**
14
14
  * Adds files to git staging area and throws if anything goes wrong.
15
15
  */
16
16
  export const git_add = async (
17
17
  files: string | Array<string>,
18
- options?: SpawnOptions,
18
+ options?: SpawnOptions
19
19
  ): Promise<void> => {
20
20
  const file_list = Array.isArray(files) ? files : [files];
21
- const {result, stderr} = await spawn_out('git', ['add', ...file_list], options);
21
+ const { result, stderr } = await spawn_out('git', ['add', ...file_list], options);
22
22
  if (!result.ok) {
23
23
  throw Error(
24
- `git_add failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`,
24
+ `git_add failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`
25
25
  );
26
26
  }
27
27
  };
@@ -30,10 +30,10 @@ export const git_add = async (
30
30
  * Commits staged changes with a message and throws if anything goes wrong.
31
31
  */
32
32
  export const git_commit = async (message: string, options?: SpawnOptions): Promise<void> => {
33
- const {result, stderr} = await spawn_out('git', ['commit', '-m', message], options);
33
+ const { result, stderr } = await spawn_out('git', ['commit', '-m', message], options);
34
34
  if (!result.ok) {
35
35
  throw Error(
36
- `git_commit failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`,
36
+ `git_commit failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`
37
37
  );
38
38
  }
39
39
  };
@@ -44,7 +44,7 @@ export const git_commit = async (message: string, options?: SpawnOptions): Promi
44
44
  export const git_add_and_commit = async (
45
45
  files: string | Array<string>,
46
46
  message: string,
47
- options?: SpawnOptions,
47
+ options?: SpawnOptions
48
48
  ): Promise<void> => {
49
49
  await git_add(files, options);
50
50
  await git_commit(message, options);
@@ -56,14 +56,14 @@ export const git_add_and_commit = async (
56
56
  export const git_tag = async (
57
57
  tag_name: string,
58
58
  message?: string,
59
- options?: SpawnOptions,
59
+ options?: SpawnOptions
60
60
  ): Promise<void> => {
61
61
  const args = message ? ['tag', '-a', tag_name, '-m', message] : ['tag', tag_name];
62
62
 
63
- const {result, stderr} = await spawn_out('git', args, options);
63
+ const { result, stderr } = await spawn_out('git', args, options);
64
64
  if (!result.ok) {
65
65
  throw Error(
66
- `git_tag failed for tag '${tag_name}' with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`,
66
+ `git_tag failed for tag '${tag_name}' with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`
67
67
  );
68
68
  }
69
69
  };
@@ -74,12 +74,12 @@ export const git_tag = async (
74
74
  export const git_push_tag = async (
75
75
  tag_name: string,
76
76
  origin: GitOrigin = 'origin' as GitOrigin,
77
- options?: SpawnOptions,
77
+ options?: SpawnOptions
78
78
  ): Promise<void> => {
79
- const {result, stderr} = await spawn_out('git', ['push', origin, tag_name], options);
79
+ const { result, stderr } = await spawn_out('git', ['push', origin, tag_name], options);
80
80
  if (!result.ok) {
81
81
  throw Error(
82
- `git_push_tag failed for tag '${tag_name}' with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`,
82
+ `git_push_tag failed for tag '${tag_name}' with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`
83
83
  );
84
84
  }
85
85
  };
@@ -90,7 +90,7 @@ export const git_push_tag = async (
90
90
  * which reports only tracked working-tree changes relative to HEAD.
91
91
  */
92
92
  export const git_has_changes = async (options?: SpawnOptions): Promise<boolean> => {
93
- const {stdout} = await spawn_out('git', ['status', '--porcelain'], options);
93
+ const { stdout } = await spawn_out('git', ['status', '--porcelain'], options);
94
94
  return stdout ? stdout.trim().length > 0 : false;
95
95
  };
96
96
 
@@ -98,9 +98,9 @@ export const git_has_changes = async (options?: SpawnOptions): Promise<boolean>
98
98
  * Lists uncommitted files in the working tree (`git diff --name-only HEAD`).
99
99
  */
100
100
  export const git_list_uncommitted_files = async (
101
- options?: SpawnOptions,
101
+ options?: SpawnOptions
102
102
  ): Promise<Array<string>> => {
103
- const {stdout} = await spawn_out('git', ['diff', '--name-only', 'HEAD'], options);
103
+ const { stdout } = await spawn_out('git', ['diff', '--name-only', 'HEAD'], options);
104
104
  if (!stdout) return [];
105
105
 
106
106
  return stdout
@@ -113,12 +113,12 @@ export const git_has_file_changed = async (
113
113
  from_commit: string,
114
114
  to_commit: string,
115
115
  file_path: string,
116
- options?: SpawnOptions,
116
+ options?: SpawnOptions
117
117
  ): Promise<boolean> => {
118
- const {stdout} = await spawn_out(
118
+ const { stdout } = await spawn_out(
119
119
  'git',
120
120
  ['diff', '--name-only', from_commit, to_commit, '--', file_path],
121
- options,
121
+ options
122
122
  );
123
123
  return stdout ? stdout.trim().length > 0 : false;
124
124
  };
@@ -129,10 +129,10 @@ export const git_has_file_changed = async (
129
129
  export const git_stash = async (message?: string, options?: SpawnOptions): Promise<void> => {
130
130
  const args = message ? ['stash', 'push', '-m', message] : ['stash', 'push'];
131
131
 
132
- const {result, stderr} = await spawn_out('git', args, options);
132
+ const { result, stderr } = await spawn_out('git', args, options);
133
133
  if (!result.ok) {
134
134
  throw Error(
135
- `git_stash failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`,
135
+ `git_stash failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`
136
136
  );
137
137
  }
138
138
  };
@@ -141,10 +141,10 @@ export const git_stash = async (message?: string, options?: SpawnOptions): Promi
141
141
  * Applies stashed changes and throws if anything goes wrong.
142
142
  */
143
143
  export const git_stash_pop = async (options?: SpawnOptions): Promise<void> => {
144
- const {result, stderr} = await spawn_out('git', ['stash', 'pop'], options);
144
+ const { result, stderr } = await spawn_out('git', ['stash', 'pop'], options);
145
145
  if (!result.ok) {
146
146
  throw Error(
147
- `git_stash_pop failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`,
147
+ `git_stash_pop failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`
148
148
  );
149
149
  }
150
150
  };
@@ -155,7 +155,7 @@ export const git_stash_pop = async (options?: SpawnOptions): Promise<void> => {
155
155
  export const git_switch_branch = async (
156
156
  branch: GitBranch,
157
157
  pull: boolean = true,
158
- options?: SpawnOptions,
158
+ options?: SpawnOptions
159
159
  ): Promise<void> => {
160
160
  // Check if workspace is clean first
161
161
  const error = await gro_git_check_clean_workspace(options);
@@ -194,7 +194,7 @@ export const git_current_branch_name_required = async (options?: SpawnOptions):
194
194
  */
195
195
  export const git_current_commit_hash_required = async (
196
196
  branch?: string,
197
- options?: SpawnOptions,
197
+ options?: SpawnOptions
198
198
  ): Promise<string> => {
199
199
  const hash = await gro_git_current_commit_hash(branch, options);
200
200
  if (!hash) {
@@ -207,7 +207,7 @@ export const git_current_commit_hash_required = async (
207
207
  * Wrapper for gro's `git_check_clean_workspace` that returns a boolean.
208
208
  */
209
209
  export const git_check_clean_workspace_as_boolean = async (
210
- options?: SpawnOptions,
210
+ options?: SpawnOptions
211
211
  ): Promise<boolean> => {
212
212
  const error = await gro_git_check_clean_workspace(options);
213
213
  return error === null;
@@ -215,9 +215,9 @@ export const git_check_clean_workspace_as_boolean = async (
215
215
 
216
216
  export const git_has_remote = async (
217
217
  remote: string = 'origin',
218
- options?: SpawnOptions,
218
+ options?: SpawnOptions
219
219
  ): Promise<boolean> => {
220
- const {stdout} = await spawn_out('git', ['remote'], options);
220
+ const { stdout } = await spawn_out('git', ['remote'], options);
221
221
  if (!stdout) return false;
222
222
  const remotes = stdout
223
223
  .split('\n')
package/src/lib/github.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type {Logger} from '@fuzdev/fuz_util/log.js';
2
- import {z} from 'zod';
3
- import {fetch_value, type FetchValueCache} from '@fuzdev/fuz_util/fetch.js';
1
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
2
+ import { z } from 'zod';
3
+ import { fetch_value, type FetchValueCache } from '@fuzdev/fuz_util/fetch.ts';
4
4
 
5
5
  /**
6
6
  * Minimal interface for GitHub API calls - works with both `Pkg` and `Repo`.
@@ -17,9 +17,9 @@ export const GithubPullRequest = z.object({
17
17
  number: z.number(),
18
18
  title: z.string(),
19
19
  user: z.object({
20
- login: z.string(),
20
+ login: z.string()
21
21
  }),
22
- draft: z.boolean(),
22
+ draft: z.boolean()
23
23
  });
24
24
  export type GithubPullRequest = z.infer<typeof GithubPullRequest>;
25
25
  export const GithubPullRequests = z.array(GithubPullRequest);
@@ -35,24 +35,24 @@ export const fetch_github_pull_requests = async (
35
35
  log?: Logger;
36
36
  token?: string;
37
37
  api_version?: string;
38
- } = {},
38
+ } = {}
39
39
  ): Promise<GithubPullRequests | null> => {
40
- const {cache, log, token, api_version} = options;
40
+ const { cache, log, token, api_version } = options;
41
41
  if (!repo_info.owner_name) throw Error('owner_name is required');
42
- const headers = api_version ? new Headers({'x-github-api-version': api_version}) : undefined;
42
+ const headers = api_version ? new Headers({ 'x-github-api-version': api_version }) : undefined;
43
43
  const url = `https://api.github.com/repos/${repo_info.owner_name}/${repo_info.repo_name}/pulls`;
44
44
  const fetched = await fetch_value(url, {
45
- request: {headers},
45
+ request: { headers },
46
46
  parse: GithubPullRequests.parse,
47
47
  token,
48
48
  cache,
49
- log,
49
+ log
50
50
  });
51
51
  if (!fetched.ok) {
52
52
  // TODO @many this is messy but I think it's the main case we need to worry about?
53
53
  if (fetched.status === 401) {
54
54
  throw Error(
55
- '401 response fetching github pull requests - check your SECRET_GITHUB_API_TOKEN',
55
+ '401 response fetching github pull requests - check your SECRET_GITHUB_API_TOKEN'
56
56
  );
57
57
  }
58
58
  return null;
@@ -67,12 +67,12 @@ export const GithubCheckRunsItem = z.object({
67
67
  status: z.enum(['queued', 'in_progress', 'completed']),
68
68
  conclusion: z
69
69
  .enum(['success', 'failure', 'neutral', 'cancelled', 'skipped', 'timed_out', 'action_required'])
70
- .nullable(),
70
+ .nullable()
71
71
  });
72
72
  export type GithubCheckRunsItem = z.infer<typeof GithubCheckRunsItem>;
73
73
  export const GithubCheckRuns = z.object({
74
74
  total_count: z.number(),
75
- check_runs: z.array(GithubCheckRunsItem),
75
+ check_runs: z.array(GithubCheckRunsItem)
76
76
  });
77
77
  export type GithubCheckRuns = z.infer<typeof GithubCheckRuns>;
78
78
 
@@ -87,18 +87,18 @@ export const fetch_github_check_runs = async (
87
87
  token?: string;
88
88
  api_version?: string;
89
89
  ref?: string;
90
- } = {},
90
+ } = {}
91
91
  ): Promise<GithubCheckRunsItem | null> => {
92
- const {cache, log, token, api_version, ref = 'main'} = options;
92
+ const { cache, log, token, api_version, ref = 'main' } = options;
93
93
  if (!repo_info.owner_name) throw Error('owner_name is required');
94
- const headers = api_version ? new Headers({'x-github-api-version': api_version}) : undefined;
94
+ const headers = api_version ? new Headers({ 'x-github-api-version': api_version }) : undefined;
95
95
  const url = `https://api.github.com/repos/${repo_info.owner_name}/${repo_info.repo_name}/commits/${ref}/check-runs`;
96
96
  const fetched = await fetch_value(url, {
97
- request: {headers},
97
+ request: { headers },
98
98
  parse: (v) => reduce_check_runs(GithubCheckRuns.parse(v).check_runs),
99
99
  token,
100
100
  cache,
101
- log,
101
+ log
102
102
  });
103
103
  if (!fetched.ok) {
104
104
  // TODO @many this is messy but I think it's the main case we need to worry about?
@@ -123,5 +123,5 @@ const reduce_check_runs = (check_runs: Array<GithubCheckRunsItem>): GithubCheckR
123
123
  conclusion = check_run.conclusion;
124
124
  }
125
125
  }
126
- return {status, conclusion};
126
+ return { status, conclusion };
127
127
  };
@@ -1,7 +1,7 @@
1
- import {ensure_end} from '@fuzdev/fuz_util/string.js';
1
+ import { ensure_end } from '@fuzdev/fuz_util/string.ts';
2
2
 
3
- import type {GithubPullRequest} from './github.js';
4
- import type {Repo} from './repo.svelte.js';
3
+ import type { GithubPullRequest } from './github.ts';
4
+ import type { Repo } from './repo.svelte.ts';
5
5
 
6
6
  export type FilterPullRequest = (pull_request: GithubPullRequest, repo: Repo) => boolean;
7
7
 
@@ -12,7 +12,7 @@ export interface PullRequestMeta {
12
12
 
13
13
  export const to_pull_requests = (
14
14
  repos: Array<Repo>,
15
- filter_pull_request?: FilterPullRequest,
15
+ filter_pull_request?: FilterPullRequest
16
16
  ): Array<PullRequestMeta> =>
17
17
  repos
18
18
  .flatMap((repo) => {
@@ -21,8 +21,8 @@ export const to_pull_requests = (
21
21
  return repo.pull_requests.map((pull_request) =>
22
22
  repo.package_json.homepage &&
23
23
  (!filter_pull_request || filter_pull_request(pull_request, repo))
24
- ? {repo, pull_request}
25
- : null,
24
+ ? { repo, pull_request }
25
+ : null
26
26
  );
27
27
  })
28
28
  .filter((v) => v !== null);
@@ -1,42 +1,42 @@
1
- import type {Task} from '@fuzdev/gro';
2
- import {z} from 'zod';
3
- import {styleText as st} from 'node:util';
4
- import type {Logger} from '@fuzdev/fuz_util/log.js';
1
+ import type { Task } from '@fuzdev/gro';
2
+ import { z } from 'zod';
3
+ import { styleText as st } from 'node:util';
4
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
5
5
 
6
- import {get_gitops_ready} from './gitops_task_helpers.js';
7
- import type {DependencyGraph} from './dependency_graph.js';
8
- import type {LocalRepo} from './local_repo.js';
9
- import {analyze_repos, type DependencyAnalysis} from './graph_validation.js';
6
+ import { get_gitops_ready } from './gitops_task_helpers.ts';
7
+ import type { DependencyGraph } from './dependency_graph.ts';
8
+ import { repo_is_npm } from './local_repo.ts';
9
+ import { analyze_repos, type DependencyAnalysis } from './graph_validation.ts';
10
10
  import {
11
11
  format_wildcard_dependencies,
12
12
  format_dev_cycles,
13
- format_production_cycles,
14
- } from './log_helpers.js';
15
- import {format_and_output, type OutputFormatters} from './output_helpers.js';
16
- import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.js';
13
+ format_production_cycles
14
+ } from './log_helpers.ts';
15
+ import { format_and_output, type OutputFormatters } from './output_helpers.ts';
16
+ import { GITOPS_CONFIG_PATH_DEFAULT } from './gitops_constants.ts';
17
17
 
18
18
  /** @nodocs */
19
19
  export const Args = z.strictObject({
20
20
  config: z
21
21
  .string()
22
- .meta({description: 'path to the gitops config file, absolute or relative to the cwd'})
22
+ .meta({ description: 'path to the gitops config file, absolute or relative to the cwd' })
23
23
  .default(GITOPS_CONFIG_PATH_DEFAULT),
24
24
  dir: z
25
25
  .string()
26
- .meta({description: 'path containing the repos, defaults to the parent of the config dir'})
26
+ .meta({ description: 'path containing the repos, defaults to the parent of the config dir' })
27
27
  .optional(),
28
28
  format: z
29
29
  .enum(['stdout', 'json', 'markdown'])
30
- .meta({description: 'output format'})
30
+ .meta({ description: 'output format' })
31
31
  .default('stdout'),
32
- outfile: z.string().meta({description: 'write output to file instead of logging'}).optional(),
32
+ outfile: z.string().meta({ description: 'write output to file instead of logging' }).optional(),
33
33
  sync: z
34
34
  .boolean()
35
35
  .meta({
36
36
  description:
37
- 'sync repos (switch branch, pull, install) before analyzing instead of reading the working tree as-is',
37
+ 'sync repos (switch branch, pull, install) before analyzing instead of reading the working tree as-is'
38
38
  })
39
- .default(false),
39
+ .default(false)
40
40
  });
41
41
  export type Args = z.infer<typeof Args>;
42
42
 
@@ -44,30 +44,41 @@ export type Args = z.infer<typeof Args>;
44
44
  export const task: Task<Args> = {
45
45
  Args,
46
46
  summary: 'analyze dependency structure and relationships across repos',
47
- run: async ({args, log}) => {
48
- const {config, dir, format, outfile, sync} = args;
47
+ run: async ({ args, log }) => {
48
+ const { config, dir, format, outfile, sync } = args;
49
49
 
50
50
  // Get repos ready (without downloading); read the working tree as-is unless `--sync`
51
- const {local_repos} = await get_gitops_ready({config, dir, download: false, sync, log});
51
+ const { local_repos } = await get_gitops_ready({ config, dir, download: false, sync, log });
52
+
53
+ // Only npm packages form the dependency graph; note any non-npm repos (e.g. cargo)
54
+ // that are excluded so the omission isn't silent.
55
+ const non_npm_repos = local_repos.filter((r) => !repo_is_npm(r));
56
+ if (non_npm_repos.length > 0) {
57
+ log.info(
58
+ st(
59
+ 'dim',
60
+ `excluding ${non_npm_repos.length} non-npm repo(s) from analysis (dashboard-only): ` +
61
+ non_npm_repos.map((r) => r.library.name).join(', ')
62
+ )
63
+ );
64
+ }
52
65
 
53
66
  // Build the dependency graph and analyze cycles/wildcards (tolerating cycles)
54
- const {graph, analysis, publishing_order} = analyze_repos(local_repos);
67
+ const { graph, analysis, publishing_order } = analyze_repos(local_repos);
55
68
 
56
69
  // Format and output using output_helpers
57
70
  const data = {
58
- repos: local_repos,
59
71
  graph,
60
72
  analysis,
61
- publishing_order,
73
+ publishing_order
62
74
  };
63
75
 
64
- await format_and_output(data, create_formatters(), {format, outfile, log});
65
- },
76
+ await format_and_output(data, create_formatters(), { format, outfile, log });
77
+ }
66
78
  };
67
79
 
68
80
  // Data type for analysis output
69
81
  interface AnalysisData {
70
- repos: Array<LocalRepo>;
71
82
  graph: DependencyGraph;
72
83
  analysis: DependencyAnalysis;
73
84
  publishing_order: Array<string> | null;
@@ -76,51 +87,49 @@ interface AnalysisData {
76
87
  // Create formatters for output_helpers
77
88
  const create_formatters = (): OutputFormatters<AnalysisData> => ({
78
89
  json: (data) => format_json(data.graph, data.analysis, data.publishing_order),
79
- markdown: (data) => format_markdown(data.repos, data.graph, data.analysis, data.publishing_order),
80
- stdout: (data, log) =>
81
- format_stdout(data.repos, data.graph, data.analysis, data.publishing_order, log),
90
+ markdown: (data) => format_markdown(data.graph, data.analysis, data.publishing_order),
91
+ stdout: (data, log) => format_stdout(data.graph, data.analysis, data.publishing_order, log)
82
92
  });
83
93
 
84
94
  // Helper to calculate common statistics
85
95
  const calculate_stats = (graph: DependencyGraph) => {
86
96
  const total_deps = Array.from(graph.nodes.values()).reduce(
87
97
  (sum, node) => sum + node.dependencies.size,
88
- 0,
98
+ 0
89
99
  );
90
100
  const internal_deps = Array.from(graph.nodes.values()).reduce(
91
101
  (sum, node) =>
92
102
  sum + Array.from(node.dependencies.keys()).filter((name) => graph.nodes.has(name)).length,
93
- 0,
103
+ 0
94
104
  );
95
- return {total_deps, internal_deps};
105
+ return { total_deps, internal_deps };
96
106
  };
97
107
 
98
108
  const format_json = (
99
109
  graph: DependencyGraph,
100
110
  analysis: DependencyAnalysis,
101
- publishing_order: Array<string> | null,
111
+ publishing_order: Array<string> | null
102
112
  ): string => {
103
113
  const output = {
104
114
  graph: graph.toJSON(),
105
115
  analysis,
106
- publishing_order,
116
+ publishing_order
107
117
  };
108
118
  return JSON.stringify(output, null, 2);
109
119
  };
110
120
 
111
121
  const format_markdown = (
112
- repos: Array<LocalRepo>,
113
122
  graph: DependencyGraph,
114
123
  analysis: DependencyAnalysis,
115
- publishing_order: Array<string> | null,
124
+ publishing_order: Array<string> | null
116
125
  ): Array<string> => {
117
126
  const lines: Array<string> = ['# Dependency Analysis'];
118
127
 
119
128
  // Summary stats
120
- const {total_deps, internal_deps} = calculate_stats(graph);
129
+ const { total_deps, internal_deps } = calculate_stats(graph);
121
130
 
122
131
  lines.push('', '## Summary', '');
123
- lines.push(`- **Total packages**: ${repos.length}`);
132
+ lines.push(`- **Total packages**: ${graph.nodes.size}`);
124
133
  lines.push(`- **Total dependencies**: ${total_deps}`);
125
134
  lines.push(`- **Internal dependencies**: ${internal_deps}`);
126
135
  lines.push(`- **Wildcard dependencies**: ${analysis.wildcard_deps.length}`);
@@ -161,7 +170,7 @@ const format_markdown = (
161
170
  lines.push('', '## ⚠️ Wildcard Dependencies', '');
162
171
  lines.push('| Package | Dependency | Version |');
163
172
  lines.push('|---------|------------|---------|');
164
- for (const {pkg, dep, version} of analysis.wildcard_deps) {
173
+ for (const { pkg, dep, version } of analysis.wildcard_deps) {
165
174
  lines.push(`| \`${pkg}\` | \`${dep}\` | \`${version}\` |`);
166
175
  }
167
176
  }
@@ -170,7 +179,7 @@ const format_markdown = (
170
179
  lines.push('', '## Internal Dependencies', '');
171
180
  for (const node of graph.nodes.values()) {
172
181
  const internal_deps = Array.from(node.dependencies.entries()).filter(([name]) =>
173
- graph.nodes.has(name),
182
+ graph.nodes.has(name)
174
183
  );
175
184
  if (internal_deps.length > 0) {
176
185
  lines.push(`- **${node.name}**`);
@@ -185,13 +194,12 @@ const format_markdown = (
185
194
  };
186
195
 
187
196
  const format_stdout = (
188
- repos: Array<LocalRepo>,
189
197
  graph: DependencyGraph,
190
198
  analysis: DependencyAnalysis,
191
199
  publishing_order: Array<string> | null,
192
- log: Logger,
200
+ log: Logger
193
201
  ): void => {
194
- log.info(st('cyan', `📊 Analyzing ${repos.length} repositories...`));
202
+ log.info(st('cyan', `📊 Analyzing ${graph.nodes.size} repositories...`));
195
203
 
196
204
  // Publishing order
197
205
  if (publishing_order) {
@@ -208,14 +216,14 @@ const format_stdout = (
208
216
  log.info(st('yellow', 'Dependency relationships:'));
209
217
  for (const node of graph.nodes.values()) {
210
218
  const internal_deps = Array.from(node.dependencies.entries()).filter(([name]) =>
211
- graph.nodes.has(name),
219
+ graph.nodes.has(name)
212
220
  );
213
221
  if (internal_deps.length > 0) {
214
222
  log.info(` ${st('cyan', node.name)}`);
215
223
  for (const [dep_name, spec] of internal_deps) {
216
224
  const type_color = spec.type === 'peer' ? 'magenta' : spec.type === 'dev' ? 'dim' : 'white';
217
225
  log.info(
218
- ` ${st(type_color, '→')} ${dep_name} ${st('dim', `(${spec.type}: ${spec.version})`)}`,
226
+ ` ${st(type_color, '→')} ${dep_name} ${st('dim', `(${spec.type}: ${spec.version})`)}`
219
227
  );
220
228
  }
221
229
  }
@@ -244,11 +252,11 @@ const format_stdout = (
244
252
  }
245
253
 
246
254
  // Summary
247
- const {total_deps, internal_deps} = calculate_stats(graph);
255
+ const { total_deps, internal_deps } = calculate_stats(graph);
248
256
 
249
257
  log.info('');
250
258
  log.info(st('cyan', 'Summary:'));
251
- log.info(` Total packages: ${repos.length}`);
259
+ log.info(` Total packages: ${graph.nodes.size}`);
252
260
  log.info(` Total dependencies: ${total_deps}`);
253
261
  log.info(` Internal dependencies: ${internal_deps}`);
254
262
  log.info(` Wildcard dependencies: ${analysis.wildcard_deps.length}`);
@@ -11,12 +11,12 @@
11
11
  * @module
12
12
  */
13
13
 
14
- import type {Url} from '@fuzdev/fuz_util/url.js';
15
- import {existsSync} from 'node:fs';
16
- import {strip_end} from '@fuzdev/fuz_util/string.js';
17
- import type {GitBranch} from '@fuzdev/fuz_util/git.js';
14
+ import type { Url } from '@fuzdev/fuz_util/url.ts';
15
+ import { existsSync } from 'node:fs';
16
+ import { strip_end } from '@fuzdev/fuz_util/string.ts';
17
+ import type { GitBranch } from '@fuzdev/fuz_util/git.ts';
18
18
 
19
- import {DEFAULT_REPOS_DIR} from './paths.js';
19
+ import { DEFAULT_REPOS_DIR } from './paths.ts';
20
20
 
21
21
  export interface GitopsConfig {
22
22
  repos: Array<GitopsRepoConfig>;
@@ -24,7 +24,7 @@ export interface GitopsConfig {
24
24
  }
25
25
 
26
26
  export type CreateGitopsConfig = (
27
- base_config: GitopsConfig,
27
+ base_config: GitopsConfig
28
28
  ) => RawGitopsConfig | Promise<RawGitopsConfig>;
29
29
 
30
30
  export interface RawGitopsConfig {
@@ -99,7 +99,7 @@ export interface RawGitopsRepoConfig {
99
99
 
100
100
  export const create_empty_gitops_config = (): GitopsConfig => ({
101
101
  repos: [],
102
- repos_dir: DEFAULT_REPOS_DIR,
102
+ repos_dir: DEFAULT_REPOS_DIR
103
103
  });
104
104
 
105
105
  /**
@@ -110,11 +110,11 @@ export const normalize_gitops_config = (raw_config: RawGitopsConfig): GitopsConf
110
110
  const empty_config = create_empty_gitops_config();
111
111
  // All of the raw config properties are optional,
112
112
  // so fall back to the empty values when `undefined`.
113
- const {repos, repos_dir} = raw_config;
113
+ const { repos, repos_dir } = raw_config;
114
114
  return {
115
115
  repos: repos ? repos.map((r) => parse_fuz_repo_config(r)) : empty_config.repos,
116
116
  // Default to two dirs up from config if not specified
117
- repos_dir: repos_dir ?? DEFAULT_REPOS_DIR,
117
+ repos_dir: repos_dir ?? DEFAULT_REPOS_DIR
118
118
  };
119
119
  };
120
120
 
@@ -126,7 +126,7 @@ const parse_fuz_repo_config = (r: Url | RawGitopsRepoConfig): GitopsRepoConfig =
126
126
  branch: 'main' as GitBranch, // TODO @zts use flavored for GitBranch
127
127
  visibility: 'public',
128
128
  ci: true,
129
- archived: false,
129
+ archived: false
130
130
  };
131
131
  }
132
132
  const visibility = r.visibility ?? 'public';
@@ -136,7 +136,7 @@ const parse_fuz_repo_config = (r: Url | RawGitopsRepoConfig): GitopsRepoConfig =
136
136
  branch: r.branch ?? ('main' as GitBranch), // TODO @zts use flavored for GitBranch
137
137
  visibility,
138
138
  ci: r.ci ?? visibility === 'public',
139
- archived: r.archived ?? false,
139
+ archived: r.archived ?? false
140
140
  };
141
141
  };
142
142
 
@@ -155,20 +155,20 @@ export const load_gitops_config = async (config_path: string): Promise<GitopsCon
155
155
  return normalize_gitops_config(
156
156
  typeof config_module.default === 'function'
157
157
  ? await config_module.default(create_empty_gitops_config())
158
- : config_module.default,
158
+ : config_module.default
159
159
  );
160
160
  };
161
161
 
162
162
  export const validate_gitops_config_module: (
163
163
  config_module: any,
164
- config_path: string,
164
+ config_path: string
165
165
  ) => asserts config_module is GitopsConfigModule = (config_module, config_path) => {
166
166
  const config = config_module.default;
167
167
  if (!config) {
168
168
  throw Error(`Invalid Fuz config module at ${config_path}: expected a default export`);
169
169
  } else if (!(typeof config === 'function' || typeof config === 'object')) {
170
170
  throw Error(
171
- `Invalid Fuz config module at ${config_path}: the default export must be a function or object`,
171
+ `Invalid Fuz config module at ${config_path}: the default export must be a function or object`
172
172
  );
173
173
  }
174
174
  };