@fuzdev/fuz_gitops 0.78.0 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.md +91 -17
  2. package/dist/ModulesDetail.svelte +22 -27
  3. package/dist/ModulesDetail.svelte.d.ts.map +1 -1
  4. package/dist/ModulesNav.svelte +8 -5
  5. package/dist/ModulesNav.svelte.d.ts.map +1 -1
  6. package/dist/ModulesPage.svelte +3 -5
  7. package/dist/ModulesPage.svelte.d.ts.map +1 -1
  8. package/dist/PageFooter.svelte +2 -2
  9. package/dist/PageHeader.svelte +6 -6
  10. package/dist/PageHeader.svelte.d.ts +0 -3
  11. package/dist/PageHeader.svelte.d.ts.map +1 -1
  12. package/dist/PullRequestsDetail.svelte +29 -20
  13. package/dist/PullRequestsDetail.svelte.d.ts.map +1 -1
  14. package/dist/PullRequestsPage.svelte +4 -6
  15. package/dist/PullRequestsPage.svelte.d.ts.map +1 -1
  16. package/dist/ReposTable.svelte +43 -55
  17. package/dist/ReposTable.svelte.d.ts.map +1 -1
  18. package/dist/ReposTree.svelte +9 -21
  19. package/dist/ReposTree.svelte.d.ts.map +1 -1
  20. package/dist/ReposTreeNav.svelte +9 -12
  21. package/dist/ReposTreeNav.svelte.d.ts.map +1 -1
  22. package/dist/TablePage.svelte +3 -5
  23. package/dist/TablePage.svelte.d.ts.map +1 -1
  24. package/dist/TreeItemPage.svelte +3 -5
  25. package/dist/TreeItemPage.svelte.d.ts.map +1 -1
  26. package/dist/TreePage.svelte +3 -5
  27. package/dist/TreePage.svelte.d.ts.map +1 -1
  28. package/dist/changeset_generator.d.ts.map +1 -1
  29. package/dist/changeset_generator.js +2 -2
  30. package/dist/changeset_reader.d.ts.map +1 -1
  31. package/dist/changeset_reader.js +3 -3
  32. package/dist/ci_reconcile.d.ts +6 -10
  33. package/dist/ci_reconcile.d.ts.map +1 -1
  34. package/dist/ci_reconcile.js +6 -8
  35. package/dist/dependency_graph.d.ts +26 -49
  36. package/dist/dependency_graph.d.ts.map +1 -1
  37. package/dist/dependency_graph.js +40 -83
  38. package/dist/dependency_updater.d.ts +1 -1
  39. package/dist/dependency_updater.d.ts.map +1 -1
  40. package/dist/dependency_updater.js +14 -9
  41. package/dist/fetch_repo_data.d.ts +34 -8
  42. package/dist/fetch_repo_data.d.ts.map +1 -1
  43. package/dist/fetch_repo_data.js +44 -22
  44. package/dist/fs_fetch_value_cache.d.ts +1 -1
  45. package/dist/fs_fetch_value_cache.d.ts.map +1 -1
  46. package/dist/fs_fetch_value_cache.js +3 -3
  47. package/dist/git_operations.d.ts +6 -49
  48. package/dist/git_operations.d.ts.map +1 -1
  49. package/dist/git_operations.js +13 -126
  50. package/dist/github.d.ts +17 -2
  51. package/dist/github.d.ts.map +1 -1
  52. package/dist/github.js +17 -8
  53. package/dist/github_helpers.d.ts.map +1 -1
  54. package/dist/github_helpers.js +3 -11
  55. package/dist/gitops_analyze.task.d.ts +24 -2
  56. package/dist/gitops_analyze.task.d.ts.map +1 -1
  57. package/dist/gitops_analyze.task.js +47 -34
  58. package/dist/gitops_config.d.ts +34 -79
  59. package/dist/gitops_config.d.ts.map +1 -1
  60. package/dist/gitops_config.js +76 -53
  61. package/dist/gitops_constants.d.ts +6 -4
  62. package/dist/gitops_constants.d.ts.map +1 -1
  63. package/dist/gitops_constants.js +6 -4
  64. package/dist/gitops_plan.task.d.ts +29 -3
  65. package/dist/gitops_plan.task.d.ts.map +1 -1
  66. package/dist/gitops_plan.task.js +83 -61
  67. package/dist/gitops_publish.task.d.ts +62 -2
  68. package/dist/gitops_publish.task.d.ts.map +1 -1
  69. package/dist/gitops_publish.task.js +193 -105
  70. package/dist/gitops_run.task.d.ts +74 -0
  71. package/dist/gitops_run.task.d.ts.map +1 -1
  72. package/dist/gitops_run.task.js +176 -162
  73. package/dist/gitops_sync.task.d.ts +65 -3
  74. package/dist/gitops_sync.task.d.ts.map +1 -1
  75. package/dist/gitops_sync.task.js +163 -37
  76. package/dist/gitops_task_helpers.d.ts +86 -59
  77. package/dist/gitops_task_helpers.d.ts.map +1 -1
  78. package/dist/gitops_task_helpers.js +120 -79
  79. package/dist/gitops_validate.task.d.ts +1 -2
  80. package/dist/gitops_validate.task.d.ts.map +1 -1
  81. package/dist/gitops_validate.task.js +25 -32
  82. package/dist/graph_validation.d.ts +16 -27
  83. package/dist/graph_validation.d.ts.map +1 -1
  84. package/dist/graph_validation.js +24 -65
  85. package/dist/local_repo.d.ts +50 -62
  86. package/dist/local_repo.d.ts.map +1 -1
  87. package/dist/local_repo.js +83 -196
  88. package/dist/log_helpers.d.ts +8 -8
  89. package/dist/log_helpers.d.ts.map +1 -1
  90. package/dist/multi_repo_publisher.d.ts +10 -0
  91. package/dist/multi_repo_publisher.d.ts.map +1 -1
  92. package/dist/multi_repo_publisher.js +125 -61
  93. package/dist/npm_registry.d.ts +23 -19
  94. package/dist/npm_registry.d.ts.map +1 -1
  95. package/dist/npm_registry.js +21 -48
  96. package/dist/operations.d.ts +75 -180
  97. package/dist/operations.d.ts.map +1 -1
  98. package/dist/operations.js +15 -7
  99. package/dist/operations_defaults.d.ts +17 -2
  100. package/dist/operations_defaults.d.ts.map +1 -1
  101. package/dist/operations_defaults.js +111 -128
  102. package/dist/output_helpers.d.ts +36 -0
  103. package/dist/output_helpers.d.ts.map +1 -1
  104. package/dist/output_helpers.js +37 -3
  105. package/dist/preflight_checks.d.ts +20 -27
  106. package/dist/preflight_checks.d.ts.map +1 -1
  107. package/dist/preflight_checks.js +37 -126
  108. package/dist/publish_gate.d.ts.map +1 -1
  109. package/dist/publish_steps.d.ts +2 -4
  110. package/dist/publish_steps.d.ts.map +1 -1
  111. package/dist/publish_steps.js +4 -8
  112. package/dist/publishing_event.d.ts +2 -8
  113. package/dist/publishing_event.d.ts.map +1 -1
  114. package/dist/publishing_event.js +20 -17
  115. package/dist/publishing_event_handler.d.ts +10 -8
  116. package/dist/publishing_event_handler.d.ts.map +1 -1
  117. package/dist/publishing_event_handler.js +19 -17
  118. package/dist/publishing_plan.d.ts +16 -1
  119. package/dist/publishing_plan.d.ts.map +1 -1
  120. package/dist/publishing_plan.js +332 -254
  121. package/dist/publishing_plan_helpers.d.ts.map +1 -1
  122. package/dist/publishing_plan_helpers.js +3 -3
  123. package/dist/publishing_plan_logging.d.ts +1 -1
  124. package/dist/publishing_plan_logging.d.ts.map +1 -1
  125. package/dist/publishing_plan_logging.js +22 -15
  126. package/dist/repo.svelte.d.ts +7 -0
  127. package/dist/repo.svelte.d.ts.map +1 -1
  128. package/dist/repo.svelte.js +3 -0
  129. package/dist/repo_readiness.d.ts +210 -0
  130. package/dist/repo_readiness.d.ts.map +1 -0
  131. package/dist/repo_readiness.js +516 -0
  132. package/dist/repos_status.d.ts +3340 -0
  133. package/dist/repos_status.d.ts.map +1 -0
  134. package/dist/repos_status.js +555 -0
  135. package/dist/repos_status_load.d.ts +65 -0
  136. package/dist/repos_status_load.d.ts.map +1 -0
  137. package/dist/repos_status_load.js +131 -0
  138. package/dist/version_utils.js +1 -1
  139. package/package.json +15 -34
  140. package/src/lib/cargo_toml.ts +3 -3
  141. package/src/lib/changeset_generator.ts +19 -19
  142. package/src/lib/changeset_reader.ts +18 -18
  143. package/src/lib/ci_reconcile.ts +12 -16
  144. package/src/lib/dependency_graph.ts +61 -113
  145. package/src/lib/dependency_updater.ts +36 -30
  146. package/src/lib/fetch_repo_data.ts +71 -34
  147. package/src/lib/fs_fetch_value_cache.ts +15 -11
  148. package/src/lib/git_operations.ts +22 -194
  149. package/src/lib/github.ts +33 -21
  150. package/src/lib/github_helpers.ts +9 -16
  151. package/src/lib/gitops_analyze.task.ts +104 -66
  152. package/src/lib/gitops_config.ts +90 -139
  153. package/src/lib/gitops_constants.ts +6 -4
  154. package/src/lib/gitops_plan.task.ts +128 -76
  155. package/src/lib/gitops_publish.task.ts +280 -144
  156. package/src/lib/gitops_run.task.ts +265 -193
  157. package/src/lib/gitops_sync.task.ts +236 -52
  158. package/src/lib/gitops_task_helpers.ts +170 -114
  159. package/src/lib/gitops_validate.task.ts +44 -54
  160. package/src/lib/graph_validation.ts +28 -89
  161. package/src/lib/local_repo.ts +128 -335
  162. package/src/lib/log_helpers.ts +18 -28
  163. package/src/lib/multi_repo_publisher.ts +192 -110
  164. package/src/lib/npm_registry.ts +42 -67
  165. package/src/lib/operations.ts +99 -160
  166. package/src/lib/operations_defaults.ts +157 -201
  167. package/src/lib/output_helpers.ts +58 -6
  168. package/src/lib/preflight_checks.ts +52 -188
  169. package/src/lib/publish_gate.ts +7 -9
  170. package/src/lib/publish_steps.ts +27 -25
  171. package/src/lib/publishing_event.ts +26 -23
  172. package/src/lib/publishing_event_handler.ts +24 -22
  173. package/src/lib/publishing_plan.ts +474 -310
  174. package/src/lib/publishing_plan_helpers.ts +16 -12
  175. package/src/lib/publishing_plan_logging.ts +53 -44
  176. package/src/lib/repo.svelte.ts +16 -8
  177. package/src/lib/repo_readiness.ts +647 -0
  178. package/src/lib/repos_status.ts +671 -0
  179. package/src/lib/repos_status_load.ts +173 -0
  180. package/src/lib/version_utils.ts +3 -3
  181. package/dist/config_reconcile.d.ts +0 -46
  182. package/dist/config_reconcile.d.ts.map +0 -1
  183. package/dist/config_reconcile.js +0 -60
  184. package/dist/paths.d.ts +0 -7
  185. package/dist/paths.d.ts.map +0 -1
  186. package/dist/paths.js +0 -6
  187. package/dist/repo_ops.d.ts +0 -59
  188. package/dist/repo_ops.d.ts.map +0 -1
  189. package/dist/repo_ops.js +0 -170
  190. package/dist/resolved_gitops_config.d.ts +0 -9
  191. package/dist/resolved_gitops_config.d.ts.map +0 -1
  192. package/dist/resolved_gitops_config.js +0 -12
  193. package/src/lib/config_reconcile.ts +0 -94
  194. package/src/lib/paths.ts +0 -6
  195. package/src/lib/repo_ops.ts +0 -216
  196. package/src/lib/resolved_gitops_config.ts +0 -27
@@ -1,18 +1,30 @@
1
- import {TaskError, type Task} from '@fuzdev/gro';
2
- import {z} from 'zod';
3
- import {readFile, writeFile} from 'node:fs/promises';
4
- import {format_file} from '@fuzdev/gro/format_file.ts';
5
- import {basename, resolve} from 'node:path';
6
- import {print_path} from '@fuzdev/gro/paths.ts';
7
- import {load_from_env} from '@fuzdev/gro/env.ts';
8
- import {package_json_load} from '@fuzdev/gro/package_json.ts';
9
- import {existsSync} from 'node:fs';
10
- import {compactReplacer} from 'svelte-docinfo';
11
-
12
- import {fetch_repo_data} from './fetch_repo_data.ts';
13
- import {create_fs_fetch_value_cache} from './fs_fetch_value_cache.ts';
14
- import {get_gitops_ready} from './gitops_task_helpers.ts';
15
- import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.ts';
1
+ import { TaskError, type Task } from '@fuzdev/gro';
2
+ import { z } from 'zod';
3
+ import { readFile, writeFile } from 'node:fs/promises';
4
+ import { format_file } from '@fuzdev/gro/format_file.ts';
5
+ import { basename, join, resolve } from 'node:path';
6
+ import { print_path } from '@fuzdev/gro/paths.ts';
7
+ import { load_from_env } from '@fuzdev/gro/env.ts';
8
+ import { package_json_load } from '@fuzdev/gro/package_json.ts';
9
+ import { existsSync, readFileSync } from 'node:fs';
10
+ import { styleText as st } from 'node:util';
11
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
12
+ import { compactReplacer } from 'svelte-docinfo';
13
+
14
+ import { fetch_repo_data } from './fetch_repo_data.ts';
15
+ import { create_fs_fetch_value_cache } from './fs_fetch_value_cache.ts';
16
+ import { resolve_gitops_repos } from './gitops_task_helpers.ts';
17
+ import { GITOPS_CONFIG_PATH_DEFAULT } from './gitops_constants.ts';
18
+ import {
19
+ local_repos_load,
20
+ local_repos_resolve,
21
+ type LocalRepo,
22
+ type LocalRepoPath
23
+ } from './local_repo.ts';
24
+ import { load_repos_status, to_repos_command } from './repos_status_load.ts';
25
+ import { check_gen_readiness } from './repo_readiness.ts';
26
+ import type { ReposOperations } from './operations.ts';
27
+ import { default_repos_operations } from './operations_defaults.ts';
16
28
 
17
29
  // TODO add flag to ignore or invalidate cache -- no-cache? clean?
18
30
 
@@ -20,84 +32,93 @@ import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.ts';
20
32
  export const Args = z.strictObject({
21
33
  config: z
22
34
  .string()
23
- .meta({description: 'path to the gitops config file, absolute or relative to the cwd'})
35
+ .meta({ description: 'path to the gitops config file, absolute or relative to the cwd' })
24
36
  .default(GITOPS_CONFIG_PATH_DEFAULT),
25
- dir: z
37
+ registry: z
26
38
  .string()
27
- .meta({description: 'path containing the repos, defaults to the parent of the config dir'})
39
+ .meta({
40
+ description:
41
+ 'path to the repos.toml registry, when `repos` would not find it walking up from the cwd'
42
+ })
28
43
  .optional(),
29
44
  outdir: z
30
45
  .string()
31
- .meta({description: 'path to the directory for the generated files, defaults to $routes/'})
46
+ .meta({ description: 'path to the directory for the generated files, defaults to $routes/' })
32
47
  .optional(),
33
- download: z.boolean().meta({description: 'download all missing local repos'}).default(false),
34
48
  check: z
35
49
  .boolean()
36
- .meta({description: 'check repos are ready without fetching remote data'})
50
+ .meta({
51
+ description:
52
+ 'report whether the repos are ready to generate from, as of the local refs, and exit non-zero if a real run would refuse; fetches nothing, needs no token, and writes nothing'
53
+ })
37
54
  .default(false),
38
55
  allow_dirty: z
39
56
  .boolean()
40
57
  .meta({
41
58
  description:
42
- 'sync (switch branch, pull) tolerating uncommitted changes instead of failing on a dirty workspace',
59
+ 'read repos off their registry branch, dirty, or mid-operation as they sit, warning instead of refusing'
43
60
  })
44
- .default(false),
61
+ .default(false)
45
62
  });
46
63
  export type Args = z.infer<typeof Args>;
47
64
 
48
65
  /**
49
- * This is a task not a `.gen.` file because it makes network calls.
66
+ * Generates the dashboard's site data (`repos.json` and `repos.ts`) from each
67
+ * configured repo's working tree and its GitHub CI status and pull requests.
68
+ * It never moves a repo: see `prepare_gitops_sync` for what it reads and
69
+ * refuses. This is a task not a `.gen.` file because it makes network calls.
50
70
  *
51
71
  * @nodocs
52
72
  */
53
73
  export const task: Task<Args> = {
54
74
  Args,
55
- summary: 'syncs local repos and generates UI data from repo metadata',
56
- run: async ({args, log, svelte_config, invoke_task}) => {
57
- const {config, dir, outdir = svelte_config.routes_path, download, check, allow_dirty} = args;
75
+ summary: 'generates UI data from repo metadata, reading each repo as it sits',
76
+ run: async (ctx) => {
77
+ const { args, log, invoke_task } = ctx;
78
+ // `ctx.svelte_config` is a lazy getter, so it's only read when `outdir` isn't provided
79
+ const {
80
+ config,
81
+ registry,
82
+ outdir = (await ctx.svelte_config).routes_path,
83
+ check,
84
+ allow_dirty
85
+ } = args;
86
+
87
+ // The generated `repos.json` is the host project's site data, so a public host
88
+ // must never carry a private repo's metadata: `host` refuses the private repos
89
+ // the registry declares, before any fetch.
90
+ const package_json = await package_json_load();
58
91
 
59
- // `gitops_sync` is the task whose job is to mutate working trees, so it always syncs.
60
- const {local_repos} = await get_gitops_ready({
92
+ const prepared = await prepare_gitops_sync({
61
93
  config,
62
- dir,
63
- download,
64
- sync: true,
94
+ registry,
95
+ host: { name: package_json.name, private: package_json.private === true },
96
+ check,
65
97
  allow_dirty,
66
- log,
98
+ log
67
99
  });
100
+ if (!prepared) return;
101
+ const { local_repos, token } = prepared;
68
102
 
69
103
  const outfile_json = resolve(outdir, 'repos.json');
70
104
  const outfile_ts = resolve(outdir, 'repos.ts');
71
105
 
72
- // This searches the parent directory for the env var, so we don't use SvelteKit's $env imports
73
- const token = load_from_env('SECRET_GITHUB_API_TOKEN');
74
- if (!token) {
75
- throw new TaskError('the env var SECRET_GITHUB_API_TOKEN was not found');
76
- }
77
-
78
- // Exit early if only checking repo readiness
79
- if (check) {
80
- log.info('repos are ready');
81
- return;
82
- }
83
-
84
106
  const cache = await create_fs_fetch_value_cache('repos');
85
107
 
86
108
  log.info('fetching remote repo data');
87
- const repos_json = await fetch_repo_data(local_repos, token, cache.data, log);
109
+ const repos_json = await fetch_repo_data({ local_repos, token, cache: cache.data, log });
88
110
 
89
111
  // TODO should package_json be provided in the Gro task/gen contexts? check if it's always loaded
90
- const package_json = await package_json_load();
91
112
  const repo_specifier =
92
113
  package_json.name === '@fuzdev/fuz_gitops'
93
- ? '$lib/repo.svelte.js'
94
- : '@fuzdev/fuz_gitops/repo.svelte.js';
114
+ ? '$lib/repo.svelte.ts'
115
+ : '@fuzdev/fuz_gitops/repo.svelte.ts';
95
116
 
96
117
  log.info(`generating ${outfile_json} and ${outfile_ts}`);
97
118
 
98
119
  // Generate repos.json with the raw data
99
- const json_contents = await format_file(JSON.stringify(repos_json, compactReplacer), {
100
- filepath: outfile_json,
120
+ const json_contents = format_file(JSON.stringify(repos_json, compactReplacer), {
121
+ lang: 'json'
101
122
  });
102
123
  const existing_json = existsSync(outfile_json) ? await readFile(outfile_json, 'utf8') : '';
103
124
  const json_changed = existing_json !== json_contents;
@@ -123,7 +144,7 @@ export const task: Task<Args> = {
123
144
  export const repos_json: Array<RepoJson> = json as unknown as Array<RepoJson>;
124
145
  `;
125
146
  // TODO think about possibly using the `gen` functionality in this task, not sure what the API design could look like
126
- const formatted_ts = await format_file(ts_contents, {filepath: outfile_ts});
147
+ const formatted_ts = format_file(ts_contents, { filepath: outfile_ts });
127
148
  const existing_ts = existsSync(outfile_ts) ? await readFile(outfile_ts, 'utf8') : '';
128
149
  if (existing_ts === formatted_ts) {
129
150
  log.info(`no changes to ${print_path(outfile_ts)}`);
@@ -142,5 +163,168 @@ export const task: Task<Args> = {
142
163
  } else {
143
164
  log.info('repos cache did not change');
144
165
  }
166
+ }
167
+ };
168
+
169
+ /**
170
+ * The side effects `prepare_gitops_sync` reaches through, injectable for tests.
171
+ *
172
+ * @nodocs
173
+ */
174
+ export interface GitopsSyncDeps {
175
+ /** Runs `repos status`. */
176
+ repos_ops: ReposOperations;
177
+ /** Loads each resolved repo's library as it sits (`local_repos_load`). */
178
+ load_repos: (options: {
179
+ local_repo_paths: Array<LocalRepoPath>;
180
+ log?: Logger;
181
+ }) => Promise<Array<LocalRepo>>;
182
+ /** Reads `SECRET_GITHUB_API_TOKEN`; `undefined` when it isn't set. */
183
+ load_token: () => string | undefined;
184
+ /** Whether a path exists, for the analysis-setup warning. */
185
+ exists: (path: string) => boolean;
186
+ /** Reads a file as UTF-8, for the analysis-setup warning. */
187
+ read_file: (path: string) => string;
188
+ }
189
+
190
+ const default_gitops_sync_deps: GitopsSyncDeps = {
191
+ repos_ops: default_repos_operations,
192
+ load_repos: local_repos_load,
193
+ // this searches the parent directory for the env var, so we don't use SvelteKit's $env imports
194
+ load_token: () => load_from_env('SECRET_GITHUB_API_TOKEN') || undefined,
195
+ exists: existsSync,
196
+ read_file: (path) => readFileSync(path, 'utf8')
197
+ };
198
+
199
+ /**
200
+ * Everything `gitops_sync` does before it fetches from GitHub, in order:
201
+ *
202
+ * 1. resolves the config's repos from `repos status <keys…> --json` (local
203
+ * refs), refusing a private repo when the host package is public
204
+ * 2. checks each repo is ready to generate from (`check_gen_readiness`): on
205
+ * its registry branch, clean, and idle, unless `allow_dirty` — refusing
206
+ * before any network. With `check`, that report is the whole run: its
207
+ * warnings are logged, and it throws when a real run would refuse
208
+ * 3. reads `SECRET_GITHUB_API_TOKEN`
209
+ * 4. fetches the repos from origin (`repos status <keys…> --fetch --json`,
210
+ * which writes remote-tracking refs and nothing else) and checks them
211
+ * again, warning on a followed branch not in sync with origin and a
212
+ * failed fetch
213
+ * 5. warns on each npm repo the library analysis can't fully read: no
214
+ * `node_modules`, or no `.svelte-kit/tsconfig.json` when its tsconfig
215
+ * extends it (external types then read as `any`) — it installs nothing
216
+ * 6. loads each repo's library as it sits
217
+ *
218
+ * @returns the loaded repos and the token, or `null` when `check` passed
219
+ * @throws {TaskError} if resolving fails, a repo isn't ready, or the token is missing
220
+ * @nodocs
221
+ */
222
+ export const prepare_gitops_sync = async (
223
+ options: {
224
+ config: string;
225
+ registry?: string;
226
+ host?: { name: string; private: boolean };
227
+ check?: boolean;
228
+ allow_dirty?: boolean;
229
+ log: Logger;
145
230
  },
231
+ deps: Partial<GitopsSyncDeps> = {}
232
+ ): Promise<{ local_repos: Array<LocalRepo>; token: string } | null> => {
233
+ const { config, registry, host, check = false, allow_dirty = false, log } = options;
234
+ const { repos_ops, load_repos, load_token, exists, read_file } = {
235
+ ...default_gitops_sync_deps,
236
+ ...deps
237
+ };
238
+ const repos_command = to_repos_command(registry);
239
+
240
+ const { config_path, gitops_config, report } = await resolve_gitops_repos({
241
+ config,
242
+ registry,
243
+ host,
244
+ log,
245
+ repos_ops
246
+ });
247
+ const keys = gitops_config.repos;
248
+
249
+ const local = check_gen_readiness({ report, keys, allow_dirty, repos_command });
250
+ if (check) {
251
+ log_gen_warnings(local.warnings, log);
252
+ if (!local.ok) throw new TaskError(local.message);
253
+ log.info(st('green', `all ${keys.length} repos are ready to generate the site data from`));
254
+ return null;
255
+ }
256
+ if (!local.ok) throw new TaskError(local.message);
257
+
258
+ const token = load_token();
259
+ if (!token) {
260
+ throw new TaskError('the env var SECRET_GITHUB_API_TOKEN was not found');
261
+ }
262
+
263
+ log.info(`fetching ${keys.length} repos from origin`);
264
+ const fetched = await load_repos_status({ keys, registry, fetch: true, repos_ops });
265
+ if (!fetched.ok) {
266
+ throw new TaskError(`fetching the repos failed: ${fetched.message}`);
267
+ }
268
+ const resolved = local_repos_resolve({ keys, report: fetched.report, host, registry });
269
+ if (!resolved.ok) {
270
+ throw new TaskError(`${config_path}: ${resolved.message}`);
271
+ }
272
+ const checked = check_gen_readiness({
273
+ report: fetched.report,
274
+ keys,
275
+ allow_dirty,
276
+ repos_command
277
+ });
278
+ log_gen_warnings(checked.warnings, log);
279
+ if (!checked.ok) throw new TaskError(checked.message);
280
+
281
+ const local_repo_paths = resolved.value;
282
+ const gaps = local_repo_paths
283
+ .map((p) => ({ key: p.repo_name, missing: analysis_setup_gaps(p.repo_dir, exists, read_file) }))
284
+ .filter((g) => g.missing.length > 0);
285
+ if (gaps.length > 0) {
286
+ log.warn(
287
+ st(
288
+ 'yellow',
289
+ "the library analysis reads these repos without their dependencies' types, so external types read as `any` — `npm install` and `gro sync` in each fixes it:"
290
+ )
291
+ );
292
+ for (const { key, missing } of gaps) {
293
+ log.warn(st('yellow', ` ${key}: no ${missing.join(' or ')}`));
294
+ }
295
+ }
296
+
297
+ const local_repos = await load_repos({ local_repo_paths, log });
298
+ return { local_repos, token };
299
+ };
300
+
301
+ const log_gen_warnings = (warnings: Array<string>, log: Logger): void => {
302
+ if (warnings.length === 0) return;
303
+ log.warn(st('yellow', "read as they sit, beside origin's CI:"));
304
+ for (const line of warnings) log.warn(st('yellow', ` ${line}`));
305
+ };
306
+
307
+ /**
308
+ * What an npm repo lacks for the library analysis to resolve its dependencies'
309
+ * types: `node_modules`, and `.svelte-kit/tsconfig.json` when its
310
+ * `tsconfig.json` extends it. Empty for a repo without a `package.json`.
311
+ */
312
+ const analysis_setup_gaps = (
313
+ repo_dir: string,
314
+ exists: (path: string) => boolean,
315
+ read_file: (path: string) => string
316
+ ): Array<string> => {
317
+ if (!exists(join(repo_dir, 'package.json'))) return [];
318
+ const missing: Array<string> = [];
319
+ if (!exists(join(repo_dir, 'node_modules'))) missing.push('`node_modules`');
320
+ const tsconfig_path = join(repo_dir, 'tsconfig.json');
321
+ const svelte_kit_tsconfig = '.svelte-kit/tsconfig.json';
322
+ if (
323
+ exists(tsconfig_path) &&
324
+ read_file(tsconfig_path).includes(svelte_kit_tsconfig) &&
325
+ !exists(join(repo_dir, svelte_kit_tsconfig))
326
+ ) {
327
+ missing.push(`\`${svelte_kit_tsconfig}\``);
328
+ }
329
+ return missing;
146
330
  };