@fuzdev/fuz_gitops 0.68.0 → 0.70.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.
- package/README.md +3 -3
- package/dist/ModulesDetail.svelte +14 -14
- package/dist/ModulesNav.svelte +2 -2
- package/dist/PageFooter.svelte +1 -1
- package/dist/ReposTable.svelte +1 -1
- package/dist/ReposTree.svelte +7 -7
- package/dist/TablePage.svelte +1 -7
- package/dist/TreeItemPage.svelte +3 -3
- package/dist/TreePage.svelte +3 -3
- package/dist/changeset_generator.d.ts +4 -4
- package/dist/changeset_generator.js +5 -5
- package/dist/changeset_reader.d.ts +6 -4
- package/dist/changeset_reader.d.ts.map +1 -1
- package/dist/changeset_reader.js +7 -5
- package/dist/dependency_graph.d.ts +3 -3
- package/dist/dependency_graph.js +3 -3
- package/dist/dependency_updater.d.ts +4 -4
- package/dist/dependency_updater.js +5 -5
- package/dist/fetch_repo_data.d.ts +4 -4
- package/dist/fetch_repo_data.d.ts.map +1 -1
- package/dist/fetch_repo_data.js +4 -5
- package/dist/fs_fetch_value_cache.d.ts +4 -4
- package/dist/fs_fetch_value_cache.js +4 -4
- package/dist/git_operations.d.ts +5 -5
- package/dist/git_operations.d.ts.map +1 -1
- package/dist/git_operations.js +18 -18
- package/dist/github.d.ts +1 -1
- package/dist/github.js +0 -1
- package/dist/gitops_analyze.task.d.ts +1 -1
- package/dist/gitops_plan.task.d.ts +4 -4
- package/dist/gitops_plan.task.js +3 -3
- package/dist/gitops_publish.task.d.ts +1 -1
- package/dist/gitops_run.task.d.ts +1 -1
- package/dist/gitops_run.task.js +2 -2
- package/dist/gitops_task_helpers.d.ts +5 -5
- package/dist/gitops_task_helpers.js +5 -5
- package/dist/graph_validation.d.ts +5 -5
- package/dist/graph_validation.js +5 -5
- package/dist/local_repo.d.ts +6 -6
- package/dist/local_repo.d.ts.map +1 -1
- package/dist/local_repo.js +22 -26
- package/dist/multi_repo_publisher.d.ts.map +1 -1
- package/dist/multi_repo_publisher.js +4 -4
- package/dist/npm_install_helpers.d.ts +3 -3
- package/dist/npm_install_helpers.js +3 -3
- package/dist/npm_registry.d.ts +4 -4
- package/dist/npm_registry.js +5 -6
- package/dist/operations.d.ts +19 -17
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +1 -1
- package/dist/operations_defaults.d.ts.map +1 -1
- package/dist/operations_defaults.js +49 -14
- package/dist/output_helpers.d.ts +2 -2
- package/dist/output_helpers.js +2 -2
- package/dist/paths.d.ts +1 -1
- package/dist/paths.js +1 -1
- package/dist/preflight_checks.d.ts +2 -2
- package/dist/preflight_checks.js +7 -7
- package/dist/publishing_plan.js +4 -4
- package/dist/publishing_plan_helpers.d.ts +1 -1
- package/dist/publishing_plan_helpers.js +1 -1
- package/dist/repo.svelte.d.ts +4 -5
- package/dist/repo.svelte.d.ts.map +1 -1
- package/dist/repo.svelte.js +2 -2
- package/dist/repo_ops.d.ts +6 -6
- package/dist/repo_ops.js +7 -7
- package/dist/version_utils.d.ts +2 -2
- package/dist/version_utils.js +2 -2
- package/package.json +18 -16
- package/src/lib/changeset_generator.ts +5 -5
- package/src/lib/changeset_reader.ts +7 -5
- package/src/lib/dependency_graph.ts +3 -3
- package/src/lib/dependency_updater.ts +5 -5
- package/src/lib/fetch_repo_data.ts +4 -6
- package/src/lib/fs_fetch_value_cache.ts +4 -4
- package/src/lib/git_operations.ts +32 -18
- package/src/lib/github.ts +1 -2
- package/src/lib/gitops_plan.task.ts +3 -3
- package/src/lib/gitops_run.task.ts +2 -2
- package/src/lib/gitops_task_helpers.ts +5 -5
- package/src/lib/graph_validation.ts +5 -5
- package/src/lib/local_repo.ts +28 -30
- package/src/lib/multi_repo_publisher.ts +4 -6
- package/src/lib/npm_install_helpers.ts +3 -3
- package/src/lib/npm_registry.ts +6 -6
- package/src/lib/operations.ts +19 -17
- package/src/lib/operations_defaults.ts +47 -16
- package/src/lib/output_helpers.ts +2 -2
- package/src/lib/paths.ts +1 -1
- package/src/lib/preflight_checks.ts +7 -7
- package/src/lib/publishing_plan.ts +4 -4
- package/src/lib/publishing_plan_helpers.ts +1 -1
- package/src/lib/repo.svelte.ts +4 -5
- package/src/lib/repo_ops.ts +7 -7
- package/src/lib/version_utils.ts +2 -2
package/dist/git_operations.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn_out, spawn_result_to_message } from '@fuzdev/fuz_util/process.js';
|
|
2
2
|
import { git_check_clean_workspace as gro_git_check_clean_workspace, git_checkout as gro_git_checkout, git_pull as gro_git_pull, git_current_branch_name as gro_git_current_branch_name, git_current_commit_hash as gro_git_current_commit_hash, } from '@fuzdev/fuz_util/git.js';
|
|
3
3
|
/**
|
|
4
4
|
* Adds files to git staging area and throws if anything goes wrong.
|
|
5
5
|
*/
|
|
6
6
|
export const git_add = async (files, options) => {
|
|
7
7
|
const file_list = Array.isArray(files) ? files : [files];
|
|
8
|
-
const result = await
|
|
8
|
+
const { result, stderr } = await spawn_out('git', ['add', ...file_list], options);
|
|
9
9
|
if (!result.ok) {
|
|
10
|
-
throw Error(`git_add failed with
|
|
10
|
+
throw Error(`git_add failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`);
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
14
|
* Commits staged changes with a message and throws if anything goes wrong.
|
|
15
15
|
*/
|
|
16
16
|
export const git_commit = async (message, options) => {
|
|
17
|
-
const result = await
|
|
17
|
+
const { result, stderr } = await spawn_out('git', ['commit', '-m', message], options);
|
|
18
18
|
if (!result.ok) {
|
|
19
|
-
throw Error(`git_commit failed with
|
|
19
|
+
throw Error(`git_commit failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`);
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
@@ -31,18 +31,18 @@ export const git_add_and_commit = async (files, message, options) => {
|
|
|
31
31
|
*/
|
|
32
32
|
export const git_tag = async (tag_name, message, options) => {
|
|
33
33
|
const args = message ? ['tag', '-a', tag_name, '-m', message] : ['tag', tag_name];
|
|
34
|
-
const result = await
|
|
34
|
+
const { result, stderr } = await spawn_out('git', args, options);
|
|
35
35
|
if (!result.ok) {
|
|
36
|
-
throw Error(`git_tag failed for tag '${tag_name}' with
|
|
36
|
+
throw Error(`git_tag failed for tag '${tag_name}' with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`);
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
40
40
|
* Pushes a tag to origin and throws if anything goes wrong.
|
|
41
41
|
*/
|
|
42
42
|
export const git_push_tag = async (tag_name, origin = 'origin', options) => {
|
|
43
|
-
const result = await
|
|
43
|
+
const { result, stderr } = await spawn_out('git', ['push', origin, tag_name], options);
|
|
44
44
|
if (!result.ok) {
|
|
45
|
-
throw Error(`git_push_tag failed for tag '${tag_name}' with
|
|
45
|
+
throw Error(`git_push_tag failed for tag '${tag_name}' with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`);
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
export const git_has_changes = async (options) => {
|
|
@@ -50,9 +50,9 @@ export const git_has_changes = async (options) => {
|
|
|
50
50
|
return stdout ? stdout.trim().length > 0 : false;
|
|
51
51
|
};
|
|
52
52
|
/**
|
|
53
|
-
*
|
|
53
|
+
* Lists uncommitted files in the working tree (`git diff --name-only HEAD`).
|
|
54
54
|
*/
|
|
55
|
-
export const
|
|
55
|
+
export const git_list_uncommitted_files = async (options) => {
|
|
56
56
|
const { stdout } = await spawn_out('git', ['diff', '--name-only', 'HEAD'], options);
|
|
57
57
|
if (!stdout)
|
|
58
58
|
return [];
|
|
@@ -70,18 +70,18 @@ export const git_has_file_changed = async (from_commit, to_commit, file_path, op
|
|
|
70
70
|
*/
|
|
71
71
|
export const git_stash = async (message, options) => {
|
|
72
72
|
const args = message ? ['stash', 'push', '-m', message] : ['stash', 'push'];
|
|
73
|
-
const result = await
|
|
73
|
+
const { result, stderr } = await spawn_out('git', args, options);
|
|
74
74
|
if (!result.ok) {
|
|
75
|
-
throw Error(`git_stash failed with
|
|
75
|
+
throw Error(`git_stash failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`);
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
/**
|
|
79
79
|
* Applies stashed changes and throws if anything goes wrong.
|
|
80
80
|
*/
|
|
81
81
|
export const git_stash_pop = async (options) => {
|
|
82
|
-
const result = await
|
|
82
|
+
const { result, stderr } = await spawn_out('git', ['stash', 'pop'], options);
|
|
83
83
|
if (!result.ok) {
|
|
84
|
-
throw Error(`git_stash_pop failed with
|
|
84
|
+
throw Error(`git_stash_pop failed with ${spawn_result_to_message(result)}${stderr ? ': ' + stderr.trim() : ''}`);
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
/**
|
|
@@ -106,7 +106,7 @@ export const git_switch_branch = async (branch, pull = true, options) => {
|
|
|
106
106
|
}
|
|
107
107
|
};
|
|
108
108
|
/**
|
|
109
|
-
* Wrapper for gro's git_current_branch_name that throws if null.
|
|
109
|
+
* Wrapper for gro's `git_current_branch_name` that throws if null.
|
|
110
110
|
*/
|
|
111
111
|
export const git_current_branch_name_required = async (options) => {
|
|
112
112
|
const branch = await gro_git_current_branch_name(options);
|
|
@@ -116,7 +116,7 @@ export const git_current_branch_name_required = async (options) => {
|
|
|
116
116
|
return branch;
|
|
117
117
|
};
|
|
118
118
|
/**
|
|
119
|
-
* Wrapper for gro's git_current_commit_hash that throws if null.
|
|
119
|
+
* Wrapper for gro's `git_current_commit_hash` that throws if null.
|
|
120
120
|
*/
|
|
121
121
|
export const git_current_commit_hash_required = async (branch, options) => {
|
|
122
122
|
const hash = await gro_git_current_commit_hash(branch, options);
|
|
@@ -126,7 +126,7 @@ export const git_current_commit_hash_required = async (branch, options) => {
|
|
|
126
126
|
return hash;
|
|
127
127
|
};
|
|
128
128
|
/**
|
|
129
|
-
* Wrapper for gro's git_check_clean_workspace that returns a boolean.
|
|
129
|
+
* Wrapper for gro's `git_check_clean_workspace` that returns a boolean.
|
|
130
130
|
*/
|
|
131
131
|
export const git_check_clean_workspace_as_boolean = async (options) => {
|
|
132
132
|
const error = await gro_git_check_clean_workspace(options);
|
package/dist/github.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { type FetchValueCache } from '@fuzdev/fuz_util/fetch.js';
|
|
4
4
|
/**
|
|
5
|
-
* Minimal interface for GitHub API calls - works with both Pkg and Repo
|
|
5
|
+
* Minimal interface for GitHub API calls - works with both `Pkg` and `Repo`.
|
|
6
6
|
*/
|
|
7
7
|
export interface GithubRepoInfo {
|
|
8
8
|
owner_name: string | null;
|
package/dist/github.js
CHANGED
|
@@ -82,7 +82,6 @@ const reduce_check_runs = (check_runs) => {
|
|
|
82
82
|
let status;
|
|
83
83
|
let conclusion;
|
|
84
84
|
for (const check_run of check_runs) {
|
|
85
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
86
85
|
if (!status || status === 'completed') {
|
|
87
86
|
status = check_run.status;
|
|
88
87
|
}
|
|
@@ -5,8 +5,8 @@ export declare const Args: z.ZodObject<{
|
|
|
5
5
|
config: z.ZodDefault<z.ZodString>;
|
|
6
6
|
dir: z.ZodOptional<z.ZodString>;
|
|
7
7
|
format: z.ZodDefault<z.ZodEnum<{
|
|
8
|
-
json: "json";
|
|
9
8
|
stdout: "stdout";
|
|
9
|
+
json: "json";
|
|
10
10
|
markdown: "markdown";
|
|
11
11
|
}>>;
|
|
12
12
|
outfile: z.ZodOptional<z.ZodString>;
|
|
@@ -5,8 +5,8 @@ export declare const Args: z.ZodObject<{
|
|
|
5
5
|
config: z.ZodDefault<z.ZodString>;
|
|
6
6
|
dir: z.ZodOptional<z.ZodString>;
|
|
7
7
|
format: z.ZodDefault<z.ZodEnum<{
|
|
8
|
-
json: "json";
|
|
9
8
|
stdout: "stdout";
|
|
9
|
+
json: "json";
|
|
10
10
|
markdown: "markdown";
|
|
11
11
|
}>>;
|
|
12
12
|
outfile: z.ZodOptional<z.ZodString>;
|
|
@@ -18,9 +18,9 @@ export type Args = z.infer<typeof Args>;
|
|
|
18
18
|
* Shows version changes, dependency updates, and breaking change cascades.
|
|
19
19
|
*
|
|
20
20
|
* Usage:
|
|
21
|
-
* gro gitops_plan
|
|
22
|
-
* gro gitops_plan --dir ../repos
|
|
23
|
-
* gro gitops_plan --config ./custom.config.ts
|
|
21
|
+
* `gro gitops_plan`
|
|
22
|
+
* `gro gitops_plan --dir ../repos`
|
|
23
|
+
* `gro gitops_plan --config ./custom.config.ts`
|
|
24
24
|
*
|
|
25
25
|
* @nodocs
|
|
26
26
|
*/
|
package/dist/gitops_plan.task.js
CHANGED
|
@@ -26,9 +26,9 @@ export const Args = z.strictObject({
|
|
|
26
26
|
* Shows version changes, dependency updates, and breaking change cascades.
|
|
27
27
|
*
|
|
28
28
|
* Usage:
|
|
29
|
-
* gro gitops_plan
|
|
30
|
-
* gro gitops_plan --dir ../repos
|
|
31
|
-
* gro gitops_plan --config ./custom.config.ts
|
|
29
|
+
* `gro gitops_plan`
|
|
30
|
+
* `gro gitops_plan --dir ../repos`
|
|
31
|
+
* `gro gitops_plan --config ./custom.config.ts`
|
|
32
32
|
*
|
|
33
33
|
* @nodocs
|
|
34
34
|
*/
|
|
@@ -5,8 +5,8 @@ export declare const Args: z.ZodObject<{
|
|
|
5
5
|
config: z.ZodDefault<z.ZodString>;
|
|
6
6
|
concurrency: z.ZodDefault<z.ZodNumber>;
|
|
7
7
|
format: z.ZodDefault<z.ZodEnum<{
|
|
8
|
-
json: "json";
|
|
9
8
|
text: "text";
|
|
9
|
+
json: "json";
|
|
10
10
|
}>>;
|
|
11
11
|
}, z.core.$strict>;
|
|
12
12
|
export type Args = z.infer<typeof Args>;
|
package/dist/gitops_run.task.js
CHANGED
|
@@ -25,7 +25,7 @@ export const task = {
|
|
|
25
25
|
summary: 'run a shell command across all repos in parallel',
|
|
26
26
|
run: async ({ args, log }) => {
|
|
27
27
|
const { command, config, concurrency, format } = args;
|
|
28
|
-
// Get repo paths (lightweight, no library
|
|
28
|
+
// Get repo paths (lightweight, no library-metadata loading needed)
|
|
29
29
|
const config_path = resolve(config);
|
|
30
30
|
const repos = await get_repo_paths(config_path);
|
|
31
31
|
if (repos.length === 0) {
|
|
@@ -50,7 +50,7 @@ export const task = {
|
|
|
50
50
|
repo_name,
|
|
51
51
|
repo_dir,
|
|
52
52
|
status: success ? 'success' : 'failure',
|
|
53
|
-
exit_code: spawned.result.code
|
|
53
|
+
exit_code: spawned.result.kind === 'exited' ? spawned.result.code : 0,
|
|
54
54
|
stdout: spawned.stdout || '',
|
|
55
55
|
stderr: spawned.stderr || '',
|
|
56
56
|
duration_ms,
|
|
@@ -36,17 +36,17 @@ export interface GetGitopsReadyOptions {
|
|
|
36
36
|
* 1. Loads and normalizes config from `gitops.config.ts`
|
|
37
37
|
* 2. Resolves local repo paths (creates missing with `--download`)
|
|
38
38
|
* 3. Switches branches and pulls latest changes (in parallel by default)
|
|
39
|
-
* 4. Auto-installs deps if package.json changed during pull
|
|
39
|
+
* 4. Auto-installs deps if `package.json` changed during pull
|
|
40
40
|
*
|
|
41
41
|
* Priority for path resolution:
|
|
42
42
|
* - `dir` argument (explicit override)
|
|
43
43
|
* - Config `repos_dir` setting
|
|
44
44
|
* - `DEFAULT_REPOS_DIR` constant
|
|
45
45
|
*
|
|
46
|
-
* @param options.git_ops for testing (defaults to real git operations)
|
|
47
|
-
* @param options.npm_ops for testing (defaults to real npm operations)
|
|
48
|
-
* @param options.parallel whether to load repos in parallel (default: true)
|
|
49
|
-
* @param options.concurrency max concurrent repo loads (default: 5)
|
|
46
|
+
* @param options.git_ops - for testing (defaults to real git operations)
|
|
47
|
+
* @param options.npm_ops - for testing (defaults to real npm operations)
|
|
48
|
+
* @param options.parallel - whether to load repos in parallel (default: true)
|
|
49
|
+
* @param options.concurrency - max concurrent repo loads (default: 5)
|
|
50
50
|
* @returns initialized config and fully loaded repos ready for operations
|
|
51
51
|
* @throws {TaskError} if config loading or repo resolution fails
|
|
52
52
|
*/
|
|
@@ -30,17 +30,17 @@ import { DEFAULT_REPOS_DIR } from './paths.js';
|
|
|
30
30
|
* 1. Loads and normalizes config from `gitops.config.ts`
|
|
31
31
|
* 2. Resolves local repo paths (creates missing with `--download`)
|
|
32
32
|
* 3. Switches branches and pulls latest changes (in parallel by default)
|
|
33
|
-
* 4. Auto-installs deps if package.json changed during pull
|
|
33
|
+
* 4. Auto-installs deps if `package.json` changed during pull
|
|
34
34
|
*
|
|
35
35
|
* Priority for path resolution:
|
|
36
36
|
* - `dir` argument (explicit override)
|
|
37
37
|
* - Config `repos_dir` setting
|
|
38
38
|
* - `DEFAULT_REPOS_DIR` constant
|
|
39
39
|
*
|
|
40
|
-
* @param options.git_ops for testing (defaults to real git operations)
|
|
41
|
-
* @param options.npm_ops for testing (defaults to real npm operations)
|
|
42
|
-
* @param options.parallel whether to load repos in parallel (default: true)
|
|
43
|
-
* @param options.concurrency max concurrent repo loads (default: 5)
|
|
40
|
+
* @param options.git_ops - for testing (defaults to real git operations)
|
|
41
|
+
* @param options.npm_ops - for testing (defaults to real npm operations)
|
|
42
|
+
* @param options.parallel - whether to load repos in parallel (default: true)
|
|
43
|
+
* @param options.concurrency - max concurrent repo loads (default: 5)
|
|
44
44
|
* @returns initialized config and fully loaded repos ready for operations
|
|
45
45
|
* @throws {TaskError} if config loading or repo resolution fails
|
|
46
46
|
*/
|
|
@@ -24,13 +24,13 @@ export interface GraphValidationResult {
|
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Shared utility for building dependency graph, detecting cycles, and computing publishing order.
|
|
27
|
-
* This centralizes logic that was duplicated across multi_repo_publisher
|
|
27
|
+
* This centralizes logic that was duplicated across `multi_repo_publisher`, `publishing_plan`, and `gitops_analyze`.
|
|
28
28
|
*
|
|
29
|
-
* @param options.throw_on_prod_cycles whether to throw an error if production cycles are detected (default: true)
|
|
30
|
-
* @param options.log_cycles whether to log cycle information (default: true)
|
|
31
|
-
* @param options.log_order whether to log publishing order (default: true)
|
|
29
|
+
* @param options.throw_on_prod_cycles - whether to throw an error if production cycles are detected (default: true)
|
|
30
|
+
* @param options.log_cycles - whether to log cycle information (default: true)
|
|
31
|
+
* @param options.log_order - whether to log publishing order (default: true)
|
|
32
32
|
* @returns graph validation result with graph, publishing order, and detected cycles
|
|
33
|
-
* @throws {TaskError} if production cycles detected and throw_on_prod_cycles is true
|
|
33
|
+
* @throws {TaskError} if production cycles detected and `throw_on_prod_cycles` is true
|
|
34
34
|
*/
|
|
35
35
|
export declare const validate_dependency_graph: (repos: Array<LocalRepo>, options?: {
|
|
36
36
|
log?: Logger;
|
package/dist/graph_validation.js
CHANGED
|
@@ -17,13 +17,13 @@ import { styleText as st } from 'node:util';
|
|
|
17
17
|
import { DependencyGraph, DependencyGraphBuilder } from './dependency_graph.js';
|
|
18
18
|
/**
|
|
19
19
|
* Shared utility for building dependency graph, detecting cycles, and computing publishing order.
|
|
20
|
-
* This centralizes logic that was duplicated across multi_repo_publisher
|
|
20
|
+
* This centralizes logic that was duplicated across `multi_repo_publisher`, `publishing_plan`, and `gitops_analyze`.
|
|
21
21
|
*
|
|
22
|
-
* @param options.throw_on_prod_cycles whether to throw an error if production cycles are detected (default: true)
|
|
23
|
-
* @param options.log_cycles whether to log cycle information (default: true)
|
|
24
|
-
* @param options.log_order whether to log publishing order (default: true)
|
|
22
|
+
* @param options.throw_on_prod_cycles - whether to throw an error if production cycles are detected (default: true)
|
|
23
|
+
* @param options.log_cycles - whether to log cycle information (default: true)
|
|
24
|
+
* @param options.log_order - whether to log publishing order (default: true)
|
|
25
25
|
* @returns graph validation result with graph, publishing order, and detected cycles
|
|
26
|
-
* @throws {TaskError} if production cycles detected and throw_on_prod_cycles is true
|
|
26
|
+
* @throws {TaskError} if production cycles detected and `throw_on_prod_cycles` is true
|
|
27
27
|
*/
|
|
28
28
|
export const validate_dependency_graph = (repos, options = {}) => {
|
|
29
29
|
const { log, throw_on_prod_cycles = true, log_cycles = true, log_order = true } = options;
|
package/dist/local_repo.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import type { GitOperations, NpmOperations } from './operations.js';
|
|
|
5
5
|
import type { GitopsConfig, GitopsRepoConfig } from './gitops_config.js';
|
|
6
6
|
import type { ResolvedGitopsConfig } from './resolved_gitops_config.js';
|
|
7
7
|
/**
|
|
8
|
-
* Fully loaded local repo with Library and extracted dependency data.
|
|
9
|
-
* Does not extend LocalRepoPath - Library is source of truth for name/repo_url/etc.
|
|
8
|
+
* Fully loaded local repo with `Library` and extracted dependency data.
|
|
9
|
+
* Does not extend `LocalRepoPath` - `Library` is source of truth for name/repo_url/etc.
|
|
10
10
|
*/
|
|
11
11
|
export interface LocalRepo {
|
|
12
12
|
library: Library;
|
|
@@ -48,14 +48,14 @@ export interface LocalRepoMissing {
|
|
|
48
48
|
* 2. Switches to target branch if needed (requires clean workspace)
|
|
49
49
|
* 3. Pulls latest changes from remote (skipped for local-only repos)
|
|
50
50
|
* 4. Validates workspace is clean after pull
|
|
51
|
-
* 5. Auto-installs dependencies if package.json changed
|
|
52
|
-
* 6.
|
|
53
|
-
* 7. Creates Library and extracts dependency maps
|
|
51
|
+
* 5. Auto-installs dependencies if `package.json` changed
|
|
52
|
+
* 6. Loads `library_json` via `library_load_from_repo` (svelte-docinfo analysis)
|
|
53
|
+
* 7. Creates `Library` and extracts dependency maps
|
|
54
54
|
*
|
|
55
55
|
* This ensures repos are always in sync with their configured branch
|
|
56
56
|
* before being used by gitops commands.
|
|
57
57
|
*
|
|
58
|
-
* @throws {TaskError} if workspace dirty, branch switch fails, install fails, or
|
|
58
|
+
* @throws {TaskError} if workspace dirty, branch switch fails, install fails, or analysis fails
|
|
59
59
|
*/
|
|
60
60
|
export declare const local_repo_load: ({ local_repo_path, log: _log, git_ops, npm_ops, }: {
|
|
61
61
|
local_repo_path: LocalRepoPath;
|
package/dist/local_repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local_repo.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/local_repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAC,OAAO,EAAC,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"local_repo.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/local_repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAC,OAAO,EAAC,MAAM,kCAAkC,CAAC;AAKzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAGlE,OAAO,KAAK,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AAGtE;;;GAGG;AACH,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,WAAW,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,gBAAgB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,GAAU,mDAKnC;IACF,eAAe,EAAE,aAAa,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,aAAa,CAAC;CACxB,KAAG,OAAO,CAAC,SAAS,CAuIpB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,wEAOtC;IACF,eAAe,EAAE,oBAAoB,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,YAAY,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;CACxB,KAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAkC/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,qEAOpC;IACF,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,KAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CA2C3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,6BAG/B;IACF,WAAW,EAAE,gBAAgB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CAClB,KAAG,aAAa,GAAG,gBAoBnB,CAAC"}
|
package/dist/local_repo.js
CHANGED
|
@@ -3,7 +3,8 @@ import { Library } from '@fuzdev/fuz_ui/library.svelte.js';
|
|
|
3
3
|
import { existsSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { TaskError } from '@fuzdev/gro';
|
|
6
|
-
import {
|
|
6
|
+
import { library_load_from_repo } from '@fuzdev/gro/library_load.js';
|
|
7
|
+
import { spawn_out } from '@fuzdev/fuz_util/process.js';
|
|
7
8
|
import { map_concurrent_settled } from '@fuzdev/fuz_util/async.js';
|
|
8
9
|
import { default_git_operations, default_npm_operations } from './operations_defaults.js';
|
|
9
10
|
import { GITOPS_CONCURRENCY_DEFAULT } from './gitops_constants.js';
|
|
@@ -15,14 +16,14 @@ import { GITOPS_CONCURRENCY_DEFAULT } from './gitops_constants.js';
|
|
|
15
16
|
* 2. Switches to target branch if needed (requires clean workspace)
|
|
16
17
|
* 3. Pulls latest changes from remote (skipped for local-only repos)
|
|
17
18
|
* 4. Validates workspace is clean after pull
|
|
18
|
-
* 5. Auto-installs dependencies if package.json changed
|
|
19
|
-
* 6.
|
|
20
|
-
* 7. Creates Library and extracts dependency maps
|
|
19
|
+
* 5. Auto-installs dependencies if `package.json` changed
|
|
20
|
+
* 6. Loads `library_json` via `library_load_from_repo` (svelte-docinfo analysis)
|
|
21
|
+
* 7. Creates `Library` and extracts dependency maps
|
|
21
22
|
*
|
|
22
23
|
* This ensures repos are always in sync with their configured branch
|
|
23
24
|
* before being used by gitops commands.
|
|
24
25
|
*
|
|
25
|
-
* @throws {TaskError} if workspace dirty, branch switch fails, install fails, or
|
|
26
|
+
* @throws {TaskError} if workspace dirty, branch switch fails, install fails, or analysis fails
|
|
26
27
|
*/
|
|
27
28
|
export const local_repo_load = async ({ local_repo_path, log: _log, git_ops = default_git_operations, npm_ops = default_npm_operations, }) => {
|
|
28
29
|
const { repo_config, repo_dir, repo_name, repo_git_ssh_url } = local_repo_path;
|
|
@@ -96,23 +97,15 @@ export const local_repo_load = async ({ local_repo_path, log: _log, git_ops = de
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
const library_module = await import(library_path);
|
|
110
|
-
const { library_json } = library_module;
|
|
111
|
-
if (!library_json) {
|
|
112
|
-
throw new TaskError(`Repo "${repo_name}" has invalid src/routes/library.ts - missing library_json export\n` +
|
|
113
|
-
`The file must export a library_json object. To fix:\n` +
|
|
114
|
-
` 1. Ensure src/routes/library.gen.ts uses library_gen from @fuzdev/fuz_ui\n` +
|
|
115
|
-
` 2. Run: cd ${repo_dir} && gro gen`);
|
|
100
|
+
// Load library metadata via svelte-docinfo analysis (cached under `.gro/library.json`).
|
|
101
|
+
let library_json;
|
|
102
|
+
try {
|
|
103
|
+
library_json = await library_load_from_repo(repo_dir, { log: _log });
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
107
|
+
_log?.warn(`Failed to load library metadata for repo "${repo_name}" in ${repo_dir}: ${message}`);
|
|
108
|
+
throw new TaskError(`Failed to load library metadata for repo "${repo_name}" in ${repo_dir}: ${message}`);
|
|
116
109
|
}
|
|
117
110
|
const library = new Library(library_json);
|
|
118
111
|
const local_repo = {
|
|
@@ -169,7 +162,7 @@ export const local_repos_load = async ({ local_repo_paths, log, git_ops = defaul
|
|
|
169
162
|
// Sequential loading (original behavior)
|
|
170
163
|
const loaded = [];
|
|
171
164
|
for (const local_repo_path of local_repo_paths) {
|
|
172
|
-
loaded.push(await local_repo_load({ local_repo_path, log, git_ops, npm_ops }));
|
|
165
|
+
loaded.push(await local_repo_load({ local_repo_path, log, git_ops, npm_ops }));
|
|
173
166
|
}
|
|
174
167
|
return loaded;
|
|
175
168
|
}
|
|
@@ -227,14 +220,17 @@ const download_repos = async ({ repos_dir, local_repos_missing, log, npm_ops = d
|
|
|
227
220
|
const resolved = [];
|
|
228
221
|
for (const { repo_config, repo_git_ssh_url } of local_repos_missing) {
|
|
229
222
|
log?.info(`cloning repo ${repo_git_ssh_url} to ${repos_dir}`);
|
|
230
|
-
await
|
|
223
|
+
const clone_result = await spawn_out('git', ['clone', repo_git_ssh_url], { cwd: repos_dir });
|
|
224
|
+
if (!clone_result.result.ok) {
|
|
225
|
+
throw new TaskError(`Failed to clone repo ${repo_git_ssh_url} to ${repos_dir}${clone_result.stderr ? ': ' + clone_result.stderr.trim() : ''}`);
|
|
226
|
+
}
|
|
231
227
|
const local_repo = local_repo_locate({ repo_config, repos_dir });
|
|
232
228
|
if (local_repo.type === 'local_repo_missing') {
|
|
233
|
-
throw new TaskError(`Failed to clone repo ${repo_git_ssh_url} to ${repos_dir}`);
|
|
229
|
+
throw new TaskError(`Failed to clone repo ${repo_git_ssh_url} to ${repos_dir}: directory not found after clone`);
|
|
234
230
|
}
|
|
235
231
|
// Always install dependencies after cloning
|
|
236
232
|
log?.info(`installing dependencies for newly cloned repo ${local_repo.repo_dir}`);
|
|
237
|
-
const install_result = await npm_ops.install({ cwd: local_repo.repo_dir });
|
|
233
|
+
const install_result = await npm_ops.install({ cwd: local_repo.repo_dir });
|
|
238
234
|
if (!install_result.ok) {
|
|
239
235
|
throw new TaskError(`Failed to install dependencies in ${local_repo.repo_dir}: ${install_result.message}${install_result.stderr ? `\n${install_result.stderr}` : ''}`);
|
|
240
236
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi_repo_publisher.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/multi_repo_publisher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAKpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAsB,KAAK,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAIlF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"multi_repo_publisher.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/multi_repo_publisher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAKpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAsB,KAAK,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAIlF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAQtD,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACnC,MAAM,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,aAAa,GACzB,OAAO,KAAK,CAAC,SAAS,CAAC,EACvB,SAAS,iBAAiB,KACxB,OAAO,CAAC,gBAAgB,CAqU1B,CAAC"}
|
|
@@ -254,7 +254,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
254
254
|
const deploy_result = await ops.process.spawn({
|
|
255
255
|
cmd: 'gro',
|
|
256
256
|
args: ['deploy', '--no-build'],
|
|
257
|
-
|
|
257
|
+
cwd: repo.repo_dir,
|
|
258
258
|
});
|
|
259
259
|
if (deploy_result.ok) {
|
|
260
260
|
log?.info(st('green', ` ✅ Deployed ${repo.library.name}`));
|
|
@@ -291,11 +291,11 @@ export const publish_repos = async (repos, options) => {
|
|
|
291
291
|
};
|
|
292
292
|
};
|
|
293
293
|
/**
|
|
294
|
-
* Publishes a single repo using gro publish
|
|
294
|
+
* Publishes a single repo using `gro publish`.
|
|
295
295
|
*
|
|
296
296
|
* Dry run mode: Predicts version from changesets without side effects.
|
|
297
297
|
* Real mode: Runs `gro publish --no-build` (builds already validated in preflight),
|
|
298
|
-
* reads new version from package.json
|
|
298
|
+
* reads new version from `package.json`, and returns metadata.
|
|
299
299
|
*
|
|
300
300
|
* @throws {Error} if changeset prediction fails (dry run) or publish fails (real)
|
|
301
301
|
*/
|
|
@@ -329,7 +329,7 @@ const publish_single_repo = async (repo, options, ops = default_gitops_operation
|
|
|
329
329
|
const publish_result = await ops.process.spawn({
|
|
330
330
|
cmd: 'gro',
|
|
331
331
|
args: ['publish', '--no-build'],
|
|
332
|
-
|
|
332
|
+
cwd: repo.repo_dir,
|
|
333
333
|
});
|
|
334
334
|
if (!publish_result.ok) {
|
|
335
335
|
throw new Error(`Failed to publish ${repo.library.name}: ${publish_result.message}`);
|
|
@@ -14,9 +14,9 @@ import type { GitopsOperations } from './operations.js';
|
|
|
14
14
|
* npm's local cache may still have stale "404" metadata. This healing
|
|
15
15
|
* strategy clears the cache to force fresh metadata fetch.
|
|
16
16
|
*
|
|
17
|
-
* @param repo -
|
|
18
|
-
* @param ops -
|
|
19
|
-
* @param log -
|
|
17
|
+
* @param repo - the repository to install dependencies for
|
|
18
|
+
* @param ops - gitops operations (for dependency injection)
|
|
19
|
+
* @param log - optional logger
|
|
20
20
|
* @throws Error if install fails (with details about cache healing attempts)
|
|
21
21
|
*/
|
|
22
22
|
export declare const install_with_cache_healing: (repo: LocalRepo, ops: GitopsOperations, log?: Logger) => Promise<void>;
|
|
@@ -26,9 +26,9 @@ const is_etarget_error = (message, stderr) => {
|
|
|
26
26
|
* npm's local cache may still have stale "404" metadata. This healing
|
|
27
27
|
* strategy clears the cache to force fresh metadata fetch.
|
|
28
28
|
*
|
|
29
|
-
* @param repo -
|
|
30
|
-
* @param ops -
|
|
31
|
-
* @param log -
|
|
29
|
+
* @param repo - the repository to install dependencies for
|
|
30
|
+
* @param ops - gitops operations (for dependency injection)
|
|
31
|
+
* @param log - optional logger
|
|
32
32
|
* @throws Error if install fails (with details about cache healing attempts)
|
|
33
33
|
*/
|
|
34
34
|
export const install_with_cache_healing = async (repo, ops, log) => {
|
package/dist/npm_registry.d.ts
CHANGED
|
@@ -22,10 +22,10 @@ export declare const check_package_available: (pkg: string, version: string, opt
|
|
|
22
22
|
* Critical for multi-repo publishing: ensures published packages are available
|
|
23
23
|
* before updating dependent packages.
|
|
24
24
|
*
|
|
25
|
-
* @param options.max_attempts max poll attempts (default 30)
|
|
26
|
-
* @param options.initial_delay starting delay in ms (default 1000)
|
|
27
|
-
* @param options.max_delay max delay between attempts (default 60000)
|
|
28
|
-
* @param options.timeout total timeout in ms (default 300000 = 5min)
|
|
25
|
+
* @param options.max_attempts - max poll attempts (default 30)
|
|
26
|
+
* @param options.initial_delay - starting delay in ms (default 1000)
|
|
27
|
+
* @param options.max_delay - max delay between attempts (default 60000)
|
|
28
|
+
* @param options.timeout - total timeout in ms (default 300000 = 5min)
|
|
29
29
|
* @throws {Error} if timeout reached or max attempts exceeded
|
|
30
30
|
*/
|
|
31
31
|
export declare const wait_for_package: (pkg: string, version: string, options?: WaitOptions) => Promise<void>;
|
package/dist/npm_registry.js
CHANGED
|
@@ -27,10 +27,10 @@ export const check_package_available = async (pkg, version, options = {}) => {
|
|
|
27
27
|
* Critical for multi-repo publishing: ensures published packages are available
|
|
28
28
|
* before updating dependent packages.
|
|
29
29
|
*
|
|
30
|
-
* @param options.max_attempts max poll attempts (default 30)
|
|
31
|
-
* @param options.initial_delay starting delay in ms (default 1000)
|
|
32
|
-
* @param options.max_delay max delay between attempts (default 60000)
|
|
33
|
-
* @param options.timeout total timeout in ms (default 300000 = 5min)
|
|
30
|
+
* @param options.max_attempts - max poll attempts (default 30)
|
|
31
|
+
* @param options.initial_delay - starting delay in ms (default 1000)
|
|
32
|
+
* @param options.max_delay - max delay between attempts (default 60000)
|
|
33
|
+
* @param options.timeout - total timeout in ms (default 300000 = 5min)
|
|
34
34
|
* @throws {Error} if timeout reached or max attempts exceeded
|
|
35
35
|
*/
|
|
36
36
|
export const wait_for_package = async (pkg, version, options = {}) => {
|
|
@@ -46,7 +46,6 @@ export const wait_for_package = async (pkg, version, options = {}) => {
|
|
|
46
46
|
throw new Error(`Timeout waiting for ${pkg}@${version} after ${timeout}ms`);
|
|
47
47
|
}
|
|
48
48
|
// Check if package is available
|
|
49
|
-
// eslint-disable-next-line no-await-in-loop
|
|
50
49
|
if (await check_package_available(pkg, version, { log })) {
|
|
51
50
|
log?.info(st('green', ` ✓ ${pkg}@${version} is now available on NPM`));
|
|
52
51
|
return;
|
|
@@ -58,7 +57,7 @@ export const wait_for_package = async (pkg, version, options = {}) => {
|
|
|
58
57
|
// Wait with exponential backoff + jitter
|
|
59
58
|
const jitter = Math.random() * delay * 0.1; // 10% jitter
|
|
60
59
|
const actual_delay = Math.min(delay + jitter, max_delay);
|
|
61
|
-
await wait(actual_delay);
|
|
60
|
+
await wait(actual_delay);
|
|
62
61
|
// Exponential backoff
|
|
63
62
|
delay = Math.min(delay * 1.5, max_delay);
|
|
64
63
|
}
|