@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.
- package/README.md +25 -5
- package/dist/ModulesDetail.svelte +14 -12
- package/dist/ModulesDetail.svelte.d.ts.map +1 -1
- package/dist/ModulesNav.svelte +6 -6
- package/dist/ModulesNav.svelte.d.ts.map +1 -1
- package/dist/ModulesPage.svelte +2 -2
- package/dist/ModulesPage.svelte.d.ts.map +1 -1
- package/dist/PageFooter.svelte +2 -2
- package/dist/PageHeader.svelte +5 -5
- package/dist/PageHeader.svelte.d.ts +1 -1
- package/dist/PageHeader.svelte.d.ts.map +1 -1
- package/dist/PullRequestsDetail.svelte +25 -17
- package/dist/PullRequestsDetail.svelte.d.ts.map +1 -1
- package/dist/PullRequestsPage.svelte +3 -3
- package/dist/PullRequestsPage.svelte.d.ts.map +1 -1
- package/dist/ReposTable.svelte +24 -15
- package/dist/ReposTable.svelte.d.ts.map +1 -1
- package/dist/ReposTree.svelte +8 -6
- package/dist/ReposTree.svelte.d.ts.map +1 -1
- package/dist/ReposTreeNav.svelte +10 -11
- package/dist/ReposTreeNav.svelte.d.ts.map +1 -1
- package/dist/TablePage.svelte +2 -2
- package/dist/TablePage.svelte.d.ts.map +1 -1
- package/dist/TreeItemPage.svelte +2 -2
- package/dist/TreeItemPage.svelte.d.ts.map +1 -1
- package/dist/TreePage.svelte +2 -2
- package/dist/TreePage.svelte.d.ts.map +1 -1
- package/dist/cargo_toml.d.ts +33 -0
- package/dist/cargo_toml.d.ts.map +1 -0
- package/dist/cargo_toml.js +74 -0
- package/dist/changeset_generator.d.ts +1 -1
- package/dist/changeset_generator.d.ts.map +1 -1
- package/dist/changeset_generator.js +2 -2
- package/dist/changeset_reader.d.ts +1 -1
- package/dist/changeset_reader.d.ts.map +1 -1
- package/dist/changeset_reader.js +3 -3
- package/dist/config_reconcile.d.ts.map +1 -1
- package/dist/config_reconcile.js +6 -2
- package/dist/dependency_graph.d.ts +2 -2
- package/dist/dependency_graph.d.ts.map +1 -1
- package/dist/dependency_graph.js +9 -9
- package/dist/dependency_updater.d.ts +1 -1
- package/dist/dependency_updater.d.ts.map +1 -1
- package/dist/dependency_updater.js +8 -8
- package/dist/fetch_repo_data.d.ts +2 -2
- package/dist/fetch_repo_data.d.ts.map +1 -1
- package/dist/fetch_repo_data.js +4 -4
- package/dist/fs_fetch_value_cache.d.ts +1 -1
- package/dist/fs_fetch_value_cache.d.ts.map +1 -1
- package/dist/fs_fetch_value_cache.js +5 -5
- package/dist/git_operations.d.ts +1 -1
- package/dist/git_operations.d.ts.map +1 -1
- package/dist/git_operations.js +2 -2
- package/dist/github.d.ts +2 -2
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +7 -7
- package/dist/github_helpers.d.ts.map +1 -1
- package/dist/github_helpers.js +1 -1
- package/dist/gitops_analyze.task.d.ts.map +1 -1
- package/dist/gitops_analyze.task.js +21 -14
- package/dist/gitops_config.d.ts +2 -2
- package/dist/gitops_config.d.ts.map +1 -1
- package/dist/gitops_config.js +5 -5
- package/dist/gitops_plan.task.d.ts.map +1 -1
- package/dist/gitops_plan.task.js +8 -8
- package/dist/gitops_publish.task.d.ts.map +1 -1
- package/dist/gitops_publish.task.js +15 -12
- package/dist/gitops_run.task.d.ts.map +1 -1
- package/dist/gitops_run.task.js +10 -10
- package/dist/gitops_sync.task.d.ts.map +1 -1
- package/dist/gitops_sync.task.js +15 -13
- package/dist/gitops_task_helpers.d.ts +1 -1
- package/dist/gitops_task_helpers.d.ts.map +1 -1
- package/dist/gitops_task_helpers.js +4 -4
- package/dist/gitops_validate.task.d.ts.map +1 -1
- package/dist/gitops_validate.task.js +14 -14
- package/dist/graph_validation.d.ts +2 -2
- package/dist/graph_validation.d.ts.map +1 -1
- package/dist/graph_validation.js +5 -3
- package/dist/local_repo.d.ts +21 -7
- package/dist/local_repo.d.ts.map +1 -1
- package/dist/local_repo.js +64 -16
- package/dist/log_helpers.d.ts +1 -1
- package/dist/log_helpers.d.ts.map +1 -1
- package/dist/multi_repo_publisher.d.ts +3 -3
- package/dist/multi_repo_publisher.d.ts.map +1 -1
- package/dist/multi_repo_publisher.js +24 -20
- package/dist/npm_registry.d.ts +1 -1
- package/dist/npm_registry.d.ts.map +1 -1
- package/dist/npm_registry.js +4 -4
- package/dist/operations.d.ts +4 -4
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations_defaults.d.ts.map +1 -1
- package/dist/operations_defaults.js +16 -16
- package/dist/output_helpers.d.ts +1 -1
- package/dist/output_helpers.d.ts.map +1 -1
- package/dist/preflight_checks.d.ts +2 -2
- package/dist/preflight_checks.d.ts.map +1 -1
- package/dist/preflight_checks.js +5 -5
- package/dist/publish_gate.d.ts.map +1 -1
- package/dist/publish_steps.d.ts.map +1 -1
- package/dist/publish_steps.js +4 -4
- package/dist/publishing_event.d.ts.map +1 -1
- package/dist/publishing_event.js +16 -14
- package/dist/publishing_event_handler.d.ts.map +1 -1
- package/dist/publishing_event_handler.js +6 -6
- package/dist/publishing_plan.d.ts +3 -3
- package/dist/publishing_plan.d.ts.map +1 -1
- package/dist/publishing_plan.js +25 -15
- package/dist/publishing_plan_helpers.d.ts.map +1 -1
- package/dist/publishing_plan_helpers.js +3 -3
- package/dist/publishing_plan_logging.d.ts +1 -1
- package/dist/publishing_plan_logging.d.ts.map +1 -1
- package/dist/publishing_plan_logging.js +2 -2
- package/dist/repo.svelte.d.ts +5 -5
- package/dist/repo.svelte.d.ts.map +1 -1
- package/dist/repo.svelte.js +2 -2
- package/dist/repo_ops.js +2 -2
- package/dist/resolved_gitops_config.d.ts.map +1 -1
- package/dist/resolved_gitops_config.js +1 -1
- package/dist/version_utils.js +1 -1
- package/package.json +16 -15
- package/src/lib/cargo_toml.ts +82 -0
- package/src/lib/changeset_generator.ts +20 -20
- package/src/lib/changeset_reader.ts +18 -18
- package/src/lib/ci_reconcile.ts +5 -5
- package/src/lib/config_reconcile.ts +8 -4
- package/src/lib/dependency_graph.ts +28 -28
- package/src/lib/dependency_updater.ts +30 -30
- package/src/lib/fetch_repo_data.ts +11 -11
- package/src/lib/fs_fetch_value_cache.ts +14 -10
- package/src/lib/git_operations.ts +31 -31
- package/src/lib/github.ts +19 -19
- package/src/lib/github_helpers.ts +6 -6
- package/src/lib/gitops_analyze.task.ts +56 -48
- package/src/lib/gitops_config.ts +14 -14
- package/src/lib/gitops_plan.task.ts +32 -32
- package/src/lib/gitops_publish.task.ts +52 -49
- package/src/lib/gitops_run.task.ts +29 -29
- package/src/lib/gitops_sync.task.ts +39 -30
- package/src/lib/gitops_task_helpers.ts +21 -21
- package/src/lib/gitops_validate.task.ts +38 -38
- package/src/lib/graph_validation.ts +14 -13
- package/src/lib/local_repo.ts +130 -64
- package/src/lib/log_helpers.ts +15 -15
- package/src/lib/multi_repo_publisher.ts +75 -74
- package/src/lib/npm_registry.ts +13 -13
- package/src/lib/operations.ts +50 -39
- package/src/lib/operations_defaults.ts +108 -106
- package/src/lib/output_helpers.ts +4 -4
- package/src/lib/preflight_checks.ts +28 -28
- package/src/lib/publish_gate.ts +7 -9
- package/src/lib/publish_steps.ts +15 -15
- package/src/lib/publishing_event.ts +22 -20
- package/src/lib/publishing_event_handler.ts +8 -8
- package/src/lib/publishing_plan.ts +69 -57
- package/src/lib/publishing_plan_helpers.ts +16 -12
- package/src/lib/publishing_plan_logging.ts +23 -23
- package/src/lib/repo.svelte.ts +8 -8
- package/src/lib/repo_ops.ts +12 -12
- package/src/lib/resolved_gitops_config.ts +5 -5
- 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.
|
|
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.
|
|
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.
|
|
2
|
-
import {z} from 'zod';
|
|
3
|
-
import {fetch_value, type FetchValueCache} from '@fuzdev/fuz_util/fetch.
|
|
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.
|
|
1
|
+
import { ensure_end } from '@fuzdev/fuz_util/string.ts';
|
|
2
2
|
|
|
3
|
-
import type {GithubPullRequest} from './github.
|
|
4
|
-
import type {Repo} from './repo.svelte.
|
|
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.
|
|
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.
|
|
7
|
-
import type {DependencyGraph} from './dependency_graph.
|
|
8
|
-
import
|
|
9
|
-
import {analyze_repos, type DependencyAnalysis} from './graph_validation.
|
|
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.
|
|
15
|
-
import {format_and_output, type OutputFormatters} from './output_helpers.
|
|
16
|
-
import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.
|
|
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.
|
|
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**: ${
|
|
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 ${
|
|
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: ${
|
|
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}`);
|
package/src/lib/gitops_config.ts
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type {Url} from '@fuzdev/fuz_util/url.
|
|
15
|
-
import {existsSync} from 'node:fs';
|
|
16
|
-
import {strip_end} from '@fuzdev/fuz_util/string.
|
|
17
|
-
import type {GitBranch} from '@fuzdev/fuz_util/git.
|
|
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.
|
|
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
|
};
|