@fuzdev/fuz_gitops 0.57.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/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/ModulesDetail.svelte +180 -0
- package/dist/ModulesDetail.svelte.d.ts +10 -0
- package/dist/ModulesDetail.svelte.d.ts.map +1 -0
- package/dist/ModulesNav.svelte +43 -0
- package/dist/ModulesNav.svelte.d.ts +11 -0
- package/dist/ModulesNav.svelte.d.ts.map +1 -0
- package/dist/ModulesPage.svelte +50 -0
- package/dist/ModulesPage.svelte.d.ts +9 -0
- package/dist/ModulesPage.svelte.d.ts.map +1 -0
- package/dist/PageFooter.svelte +15 -0
- package/dist/PageFooter.svelte.d.ts +19 -0
- package/dist/PageFooter.svelte.d.ts.map +1 -0
- package/dist/PageHeader.svelte +35 -0
- package/dist/PageHeader.svelte.d.ts +19 -0
- package/dist/PageHeader.svelte.d.ts.map +1 -0
- package/dist/PullRequestsDetail.svelte +53 -0
- package/dist/PullRequestsDetail.svelte.d.ts +10 -0
- package/dist/PullRequestsDetail.svelte.d.ts.map +1 -0
- package/dist/PullRequestsPage.svelte +47 -0
- package/dist/PullRequestsPage.svelte.d.ts +11 -0
- package/dist/PullRequestsPage.svelte.d.ts.map +1 -0
- package/dist/ReposTable.svelte +189 -0
- package/dist/ReposTable.svelte.d.ts +9 -0
- package/dist/ReposTable.svelte.d.ts.map +1 -0
- package/dist/ReposTree.svelte +88 -0
- package/dist/ReposTree.svelte.d.ts +11 -0
- package/dist/ReposTree.svelte.d.ts.map +1 -0
- package/dist/ReposTreeNav.svelte +55 -0
- package/dist/ReposTreeNav.svelte.d.ts +11 -0
- package/dist/ReposTreeNav.svelte.d.ts.map +1 -0
- package/dist/TablePage.svelte +46 -0
- package/dist/TablePage.svelte.d.ts +9 -0
- package/dist/TablePage.svelte.d.ts.map +1 -0
- package/dist/TreeItemPage.svelte +75 -0
- package/dist/TreeItemPage.svelte.d.ts +10 -0
- package/dist/TreeItemPage.svelte.d.ts.map +1 -0
- package/dist/TreePage.svelte +64 -0
- package/dist/TreePage.svelte.d.ts +9 -0
- package/dist/TreePage.svelte.d.ts.map +1 -0
- package/dist/changeset_generator.d.ts +38 -0
- package/dist/changeset_generator.d.ts.map +1 -0
- package/dist/changeset_generator.js +110 -0
- package/dist/changeset_reader.d.ts +75 -0
- package/dist/changeset_reader.d.ts.map +1 -0
- package/dist/changeset_reader.js +167 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/dependency_graph.d.ts +120 -0
- package/dist/dependency_graph.d.ts.map +1 -0
- package/dist/dependency_graph.js +341 -0
- package/dist/dependency_updater.d.ts +46 -0
- package/dist/dependency_updater.d.ts.map +1 -0
- package/dist/dependency_updater.js +213 -0
- package/dist/fetch_repo_data.d.ts +19 -0
- package/dist/fetch_repo_data.d.ts.map +1 -0
- package/dist/fetch_repo_data.js +49 -0
- package/dist/fs_fetch_value_cache.d.ts +24 -0
- package/dist/fs_fetch_value_cache.d.ts.map +1 -0
- package/dist/fs_fetch_value_cache.js +61 -0
- package/dist/git_operations.d.ts +54 -0
- package/dist/git_operations.d.ts.map +1 -0
- package/dist/git_operations.js +144 -0
- package/dist/github.d.ts +91 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +94 -0
- package/dist/github_helpers.d.ts +10 -0
- package/dist/github_helpers.d.ts.map +1 -0
- package/dist/github_helpers.js +13 -0
- package/dist/gitops_analyze.task.d.ts +17 -0
- package/dist/gitops_analyze.task.d.ts.map +1 -0
- package/dist/gitops_analyze.task.js +188 -0
- package/dist/gitops_config.d.ts +56 -0
- package/dist/gitops_config.d.ts.map +1 -0
- package/dist/gitops_config.js +63 -0
- package/dist/gitops_plan.task.d.ts +28 -0
- package/dist/gitops_plan.task.d.ts.map +1 -0
- package/dist/gitops_plan.task.js +217 -0
- package/dist/gitops_publish.task.d.ts +29 -0
- package/dist/gitops_publish.task.d.ts.map +1 -0
- package/dist/gitops_publish.task.js +178 -0
- package/dist/gitops_sync.task.d.ts +18 -0
- package/dist/gitops_sync.task.d.ts.map +1 -0
- package/dist/gitops_sync.task.js +95 -0
- package/dist/gitops_task_helpers.d.ts +63 -0
- package/dist/gitops_task_helpers.d.ts.map +1 -0
- package/dist/gitops_task_helpers.js +84 -0
- package/dist/gitops_validate.task.d.ts +12 -0
- package/dist/gitops_validate.task.d.ts.map +1 -0
- package/dist/gitops_validate.task.js +210 -0
- package/dist/graph_validation.d.ts +39 -0
- package/dist/graph_validation.d.ts.map +1 -0
- package/dist/graph_validation.js +79 -0
- package/dist/local_repo.d.ts +84 -0
- package/dist/local_repo.d.ts.map +1 -0
- package/dist/local_repo.js +213 -0
- package/dist/log_helpers.d.ts +43 -0
- package/dist/log_helpers.d.ts.map +1 -0
- package/dist/log_helpers.js +98 -0
- package/dist/multi_repo_publisher.d.ts +34 -0
- package/dist/multi_repo_publisher.d.ts.map +1 -0
- package/dist/multi_repo_publisher.js +364 -0
- package/dist/npm_install_helpers.d.ts +23 -0
- package/dist/npm_install_helpers.d.ts.map +1 -0
- package/dist/npm_install_helpers.js +60 -0
- package/dist/npm_registry.d.ts +46 -0
- package/dist/npm_registry.d.ts.map +1 -0
- package/dist/npm_registry.js +96 -0
- package/dist/operations.d.ts +409 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +34 -0
- package/dist/operations_defaults.d.ts +19 -0
- package/dist/operations_defaults.d.ts.map +1 -0
- package/dist/operations_defaults.js +279 -0
- package/dist/output_helpers.d.ts +27 -0
- package/dist/output_helpers.d.ts.map +1 -0
- package/dist/output_helpers.js +39 -0
- package/dist/paths.d.ts +11 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +10 -0
- package/dist/preflight_checks.d.ts +47 -0
- package/dist/preflight_checks.d.ts.map +1 -0
- package/dist/preflight_checks.js +181 -0
- package/dist/publishing_plan.d.ts +100 -0
- package/dist/publishing_plan.d.ts.map +1 -0
- package/dist/publishing_plan.js +353 -0
- package/dist/publishing_plan_helpers.d.ts +30 -0
- package/dist/publishing_plan_helpers.d.ts.map +1 -0
- package/dist/publishing_plan_helpers.js +112 -0
- package/dist/publishing_plan_logging.d.ts +18 -0
- package/dist/publishing_plan_logging.d.ts.map +1 -0
- package/dist/publishing_plan_logging.js +342 -0
- package/dist/repo.svelte.d.ts +52 -0
- package/dist/repo.svelte.d.ts.map +1 -0
- package/dist/repo.svelte.js +70 -0
- package/dist/repo_ops.d.ts +57 -0
- package/dist/repo_ops.d.ts.map +1 -0
- package/dist/repo_ops.js +167 -0
- package/dist/resolved_gitops_config.d.ts +9 -0
- package/dist/resolved_gitops_config.d.ts.map +1 -0
- package/dist/resolved_gitops_config.js +12 -0
- package/dist/semver.d.ts +24 -0
- package/dist/semver.d.ts.map +1 -0
- package/dist/semver.js +140 -0
- package/dist/serialization_types.d.ts +57 -0
- package/dist/serialization_types.d.ts.map +1 -0
- package/dist/serialization_types.js +40 -0
- package/dist/version_utils.d.ts +48 -0
- package/dist/version_utils.d.ts.map +1 -0
- package/dist/version_utils.js +125 -0
- package/package.json +107 -0
- package/src/lib/changeset_generator.ts +162 -0
- package/src/lib/changeset_reader.ts +218 -0
- package/src/lib/constants.ts +8 -0
- package/src/lib/dependency_graph.ts +423 -0
- package/src/lib/dependency_updater.ts +297 -0
- package/src/lib/fetch_repo_data.ts +64 -0
- package/src/lib/fs_fetch_value_cache.ts +75 -0
- package/src/lib/git_operations.ts +208 -0
- package/src/lib/github.ts +128 -0
- package/src/lib/github_helpers.ts +31 -0
- package/src/lib/gitops_analyze.task.ts +261 -0
- package/src/lib/gitops_config.ts +123 -0
- package/src/lib/gitops_plan.task.ts +272 -0
- package/src/lib/gitops_publish.task.ts +227 -0
- package/src/lib/gitops_sync.task.ts +109 -0
- package/src/lib/gitops_task_helpers.ts +126 -0
- package/src/lib/gitops_validate.task.ts +248 -0
- package/src/lib/graph_validation.ts +109 -0
- package/src/lib/local_repo.ts +359 -0
- package/src/lib/log_helpers.ts +147 -0
- package/src/lib/multi_repo_publisher.ts +464 -0
- package/src/lib/npm_install_helpers.ts +85 -0
- package/src/lib/npm_registry.ts +143 -0
- package/src/lib/operations.ts +334 -0
- package/src/lib/operations_defaults.ts +335 -0
- package/src/lib/output_helpers.ts +64 -0
- package/src/lib/paths.ts +11 -0
- package/src/lib/preflight_checks.ts +269 -0
- package/src/lib/publishing_plan.ts +531 -0
- package/src/lib/publishing_plan_helpers.ts +145 -0
- package/src/lib/publishing_plan_logging.ts +470 -0
- package/src/lib/repo.svelte.ts +95 -0
- package/src/lib/repo_ops.ts +213 -0
- package/src/lib/resolved_gitops_config.ts +27 -0
- package/src/lib/semver.ts +166 -0
- package/src/lib/serialization_types.ts +90 -0
- package/src/lib/version_utils.ts +150 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared dependency graph validation logic used across multiple workflows.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates graph building, cycle detection, and publishing order computation
|
|
5
|
+
* that was duplicated in three places: `multi_repo_publisher.ts`, `publishing_plan.ts`,
|
|
6
|
+
* and `gitops_analyze.task.ts`.
|
|
7
|
+
*
|
|
8
|
+
* Options pattern supports different behaviors: analyze can tolerate cycles for
|
|
9
|
+
* reporting, while publish must throw on production cycles.
|
|
10
|
+
*
|
|
11
|
+
* See also: `dependency_graph.ts` for core graph data structure and algorithms.
|
|
12
|
+
*/
|
|
13
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
14
|
+
import { DependencyGraph } from './dependency_graph.js';
|
|
15
|
+
import type { LocalRepo } from './local_repo.js';
|
|
16
|
+
export interface GraphValidationResult {
|
|
17
|
+
graph: DependencyGraph;
|
|
18
|
+
publishing_order: Array<string>;
|
|
19
|
+
production_cycles: Array<Array<string>>;
|
|
20
|
+
dev_cycles: Array<Array<string>>;
|
|
21
|
+
sort_error?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Shared utility for building dependency graph, detecting cycles, and computing publishing order.
|
|
25
|
+
* This centralizes logic that was duplicated across multi_repo_publisher, publishing_plan, and gitops_analyze.
|
|
26
|
+
*
|
|
27
|
+
* @param options.throw_on_prod_cycles whether to throw an error if production cycles are detected (default: true)
|
|
28
|
+
* @param options.log_cycles whether to log cycle information (default: true)
|
|
29
|
+
* @param options.log_order whether to log publishing order (default: true)
|
|
30
|
+
* @returns graph validation result with graph, publishing order, and detected cycles
|
|
31
|
+
* @throws {TaskError} if production cycles detected and throw_on_prod_cycles is true
|
|
32
|
+
*/
|
|
33
|
+
export declare const validate_dependency_graph: (repos: Array<LocalRepo>, options?: {
|
|
34
|
+
log?: Logger;
|
|
35
|
+
throw_on_prod_cycles?: boolean;
|
|
36
|
+
log_cycles?: boolean;
|
|
37
|
+
log_order?: boolean;
|
|
38
|
+
}) => GraphValidationResult;
|
|
39
|
+
//# sourceMappingURL=graph_validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph_validation.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/graph_validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAIpD,OAAO,EAAC,eAAe,EAAyB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,eAAe,CAAC;IACvB,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAChC,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GACrC,OAAO,KAAK,CAAC,SAAS,CAAC,EACvB,UAAS;IACR,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACf,KACJ,qBA8DF,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared dependency graph validation logic used across multiple workflows.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates graph building, cycle detection, and publishing order computation
|
|
5
|
+
* that was duplicated in three places: `multi_repo_publisher.ts`, `publishing_plan.ts`,
|
|
6
|
+
* and `gitops_analyze.task.ts`.
|
|
7
|
+
*
|
|
8
|
+
* Options pattern supports different behaviors: analyze can tolerate cycles for
|
|
9
|
+
* reporting, while publish must throw on production cycles.
|
|
10
|
+
*
|
|
11
|
+
* See also: `dependency_graph.ts` for core graph data structure and algorithms.
|
|
12
|
+
*/
|
|
13
|
+
import { TaskError } from '@ryanatkn/gro';
|
|
14
|
+
import { styleText as st } from 'node:util';
|
|
15
|
+
import { DependencyGraph, DependencyGraphBuilder } from './dependency_graph.js';
|
|
16
|
+
/**
|
|
17
|
+
* Shared utility for building dependency graph, detecting cycles, and computing publishing order.
|
|
18
|
+
* This centralizes logic that was duplicated across multi_repo_publisher, publishing_plan, and gitops_analyze.
|
|
19
|
+
*
|
|
20
|
+
* @param options.throw_on_prod_cycles whether to throw an error if production cycles are detected (default: true)
|
|
21
|
+
* @param options.log_cycles whether to log cycle information (default: true)
|
|
22
|
+
* @param options.log_order whether to log publishing order (default: true)
|
|
23
|
+
* @returns graph validation result with graph, publishing order, and detected cycles
|
|
24
|
+
* @throws {TaskError} if production cycles detected and throw_on_prod_cycles is true
|
|
25
|
+
*/
|
|
26
|
+
export const validate_dependency_graph = (repos, options = {}) => {
|
|
27
|
+
const { log, throw_on_prod_cycles = true, log_cycles = true, log_order = true } = options;
|
|
28
|
+
// Build dependency graph
|
|
29
|
+
log?.info('📊 Analyzing dependencies...');
|
|
30
|
+
const builder = new DependencyGraphBuilder();
|
|
31
|
+
const graph = builder.build_from_repos(repos);
|
|
32
|
+
// Check for cycles
|
|
33
|
+
const { production_cycles, dev_cycles } = graph.detect_cycles_by_type();
|
|
34
|
+
// Log production cycles
|
|
35
|
+
if (production_cycles.length > 0 && log_cycles) {
|
|
36
|
+
log?.error(st('red', '❌ Production/peer dependency cycles detected:'));
|
|
37
|
+
for (const cycle of production_cycles) {
|
|
38
|
+
log?.error(` ${cycle.join(' → ')}`);
|
|
39
|
+
}
|
|
40
|
+
if (throw_on_prod_cycles) {
|
|
41
|
+
throw new TaskError(`Cannot publish with production/peer dependency cycles. ` +
|
|
42
|
+
`These must be resolved before publishing.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Log dev cycles (informational, not an error)
|
|
46
|
+
if (dev_cycles.length > 0 && log_cycles) {
|
|
47
|
+
log?.info(st('dim', 'ℹ️ Dev dependency cycles detected (this is normal):'));
|
|
48
|
+
for (const cycle of dev_cycles) {
|
|
49
|
+
log?.info(st('dim', ` ${cycle.join(' → ')}`));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Compute publishing order
|
|
53
|
+
let publishing_order;
|
|
54
|
+
let sort_error;
|
|
55
|
+
try {
|
|
56
|
+
publishing_order = graph.topological_sort(true); // exclude dev deps to break cycles
|
|
57
|
+
if (log_order && publishing_order.length > 0) {
|
|
58
|
+
log?.info(` Publishing order: ${publishing_order.join(' → ')}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Capture the sort error message for callers to report
|
|
63
|
+
sort_error = 'Failed to compute publishing order: ' + error;
|
|
64
|
+
// If topological sort fails (due to cycles), return empty array
|
|
65
|
+
// Only throw if production cycles exist AND throw_on_prod_cycles is true
|
|
66
|
+
if (production_cycles.length > 0 && throw_on_prod_cycles) {
|
|
67
|
+
throw new TaskError(sort_error);
|
|
68
|
+
}
|
|
69
|
+
// Otherwise, return empty publishing order (let caller handle it)
|
|
70
|
+
publishing_order = [];
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
graph,
|
|
74
|
+
publishing_order,
|
|
75
|
+
production_cycles,
|
|
76
|
+
dev_cycles,
|
|
77
|
+
sort_error,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { LibraryJson } from '@fuzdev/fuz_util/library_json.js';
|
|
2
|
+
import { Library } from '@fuzdev/fuz_ui/library.svelte.js';
|
|
3
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
4
|
+
import type { GitOperations, NpmOperations } from './operations.js';
|
|
5
|
+
import type { GitopsConfig, GitopsRepoConfig } from './gitops_config.js';
|
|
6
|
+
import type { ResolvedGitopsConfig } from './resolved_gitops_config.js';
|
|
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.
|
|
10
|
+
*/
|
|
11
|
+
export interface LocalRepo {
|
|
12
|
+
library: Library;
|
|
13
|
+
library_json: LibraryJson;
|
|
14
|
+
repo_dir: string;
|
|
15
|
+
repo_git_ssh_url: string;
|
|
16
|
+
repo_config: GitopsRepoConfig;
|
|
17
|
+
dependencies?: Map<string, string>;
|
|
18
|
+
dev_dependencies?: Map<string, string>;
|
|
19
|
+
peer_dependencies?: Map<string, string>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A repo that has been located on the filesystem (path exists).
|
|
23
|
+
* Used before loading - just filesystem/git concerns.
|
|
24
|
+
*/
|
|
25
|
+
export interface LocalRepoPath {
|
|
26
|
+
type: 'local_repo_path';
|
|
27
|
+
repo_name: string;
|
|
28
|
+
repo_dir: string;
|
|
29
|
+
repo_url: string;
|
|
30
|
+
repo_git_ssh_url: string;
|
|
31
|
+
repo_config: GitopsRepoConfig;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A repo that is missing from the filesystem (needs cloning).
|
|
35
|
+
*/
|
|
36
|
+
export interface LocalRepoMissing {
|
|
37
|
+
type: 'local_repo_missing';
|
|
38
|
+
repo_name: string;
|
|
39
|
+
repo_url: string;
|
|
40
|
+
repo_git_ssh_url: string;
|
|
41
|
+
repo_config: GitopsRepoConfig;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Loads repo data with automatic syncing and dependency management.
|
|
45
|
+
*
|
|
46
|
+
* Workflow:
|
|
47
|
+
* 1. Records current commit hash (for detecting changes)
|
|
48
|
+
* 2. Switches to target branch if needed (requires clean workspace)
|
|
49
|
+
* 3. Pulls latest changes from remote (skipped for local-only repos)
|
|
50
|
+
* 4. Validates workspace is clean after pull
|
|
51
|
+
* 5. Auto-installs dependencies if package.json changed
|
|
52
|
+
* 6. Imports library_json from src/routes/library.ts
|
|
53
|
+
* 7. Creates Library and extracts dependency maps
|
|
54
|
+
*
|
|
55
|
+
* This ensures repos are always in sync with their configured branch
|
|
56
|
+
* before being used by gitops commands.
|
|
57
|
+
*
|
|
58
|
+
* @throws {TaskError} if workspace dirty, branch switch fails, install fails, or library.ts missing
|
|
59
|
+
*/
|
|
60
|
+
export declare const local_repo_load: ({ local_repo_path, log: _log, git_ops, npm_ops, }: {
|
|
61
|
+
local_repo_path: LocalRepoPath;
|
|
62
|
+
log?: Logger;
|
|
63
|
+
git_ops?: GitOperations;
|
|
64
|
+
npm_ops?: NpmOperations;
|
|
65
|
+
}) => Promise<LocalRepo>;
|
|
66
|
+
export declare const local_repos_ensure: ({ resolved_config, repos_dir, gitops_config, download, log, npm_ops, }: {
|
|
67
|
+
resolved_config: ResolvedGitopsConfig;
|
|
68
|
+
repos_dir: string;
|
|
69
|
+
gitops_config: GitopsConfig;
|
|
70
|
+
download: boolean;
|
|
71
|
+
log?: Logger;
|
|
72
|
+
npm_ops?: NpmOperations;
|
|
73
|
+
}) => Promise<Array<LocalRepoPath>>;
|
|
74
|
+
export declare const local_repos_load: ({ local_repo_paths, log, git_ops, npm_ops, }: {
|
|
75
|
+
local_repo_paths: Array<LocalRepoPath>;
|
|
76
|
+
log?: Logger;
|
|
77
|
+
git_ops?: GitOperations;
|
|
78
|
+
npm_ops?: NpmOperations;
|
|
79
|
+
}) => Promise<Array<LocalRepo>>;
|
|
80
|
+
export declare const local_repo_locate: ({ repo_config, repos_dir, }: {
|
|
81
|
+
repo_config: GitopsRepoConfig;
|
|
82
|
+
repos_dir: string;
|
|
83
|
+
}) => LocalRepoPath | LocalRepoMissing;
|
|
84
|
+
//# sourceMappingURL=local_repo.d.ts.map
|
|
@@ -0,0 +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;AAIzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,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;AAEtE;;;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,CAiJpB,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,8CAKpC;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;CACxB,KAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAM3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,6BAG/B;IACF,WAAW,EAAE,gBAAgB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CAClB,KAAG,aAAa,GAAG,gBAoBnB,CAAC"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { strip_end } from '@fuzdev/fuz_util/string.js';
|
|
2
|
+
import { Library } from '@fuzdev/fuz_ui/library.svelte.js';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { TaskError } from '@ryanatkn/gro';
|
|
6
|
+
import { spawn } from '@fuzdev/fuz_util/process.js';
|
|
7
|
+
import { default_git_operations, default_npm_operations } from './operations_defaults.js';
|
|
8
|
+
/**
|
|
9
|
+
* Loads repo data with automatic syncing and dependency management.
|
|
10
|
+
*
|
|
11
|
+
* Workflow:
|
|
12
|
+
* 1. Records current commit hash (for detecting changes)
|
|
13
|
+
* 2. Switches to target branch if needed (requires clean workspace)
|
|
14
|
+
* 3. Pulls latest changes from remote (skipped for local-only repos)
|
|
15
|
+
* 4. Validates workspace is clean after pull
|
|
16
|
+
* 5. Auto-installs dependencies if package.json changed
|
|
17
|
+
* 6. Imports library_json from src/routes/library.ts
|
|
18
|
+
* 7. Creates Library and extracts dependency maps
|
|
19
|
+
*
|
|
20
|
+
* This ensures repos are always in sync with their configured branch
|
|
21
|
+
* before being used by gitops commands.
|
|
22
|
+
*
|
|
23
|
+
* @throws {TaskError} if workspace dirty, branch switch fails, install fails, or library.ts missing
|
|
24
|
+
*/
|
|
25
|
+
export const local_repo_load = async ({ local_repo_path, log: _log, git_ops = default_git_operations, npm_ops = default_npm_operations, }) => {
|
|
26
|
+
const { repo_config, repo_dir, repo_name, repo_git_ssh_url } = local_repo_path;
|
|
27
|
+
// Record commit hash before any changes
|
|
28
|
+
const commit_before_result = await git_ops.current_commit_hash({ cwd: repo_dir });
|
|
29
|
+
if (!commit_before_result.ok) {
|
|
30
|
+
throw new TaskError(`Failed to get commit hash in ${repo_dir}: ${commit_before_result.message}`);
|
|
31
|
+
}
|
|
32
|
+
const commit_before = commit_before_result.value;
|
|
33
|
+
// Switch to target branch if needed
|
|
34
|
+
const branch_result = await git_ops.current_branch_name({ cwd: repo_dir });
|
|
35
|
+
if (!branch_result.ok) {
|
|
36
|
+
throw new TaskError(`Failed to get current branch in ${repo_dir}: ${branch_result.message}`);
|
|
37
|
+
}
|
|
38
|
+
const switched_branches = branch_result.value !== repo_config.branch;
|
|
39
|
+
if (switched_branches) {
|
|
40
|
+
const clean_result = await git_ops.check_clean_workspace({ cwd: repo_dir });
|
|
41
|
+
if (!clean_result.ok) {
|
|
42
|
+
throw new TaskError(`Failed to check workspace in ${repo_dir}: ${clean_result.message}`);
|
|
43
|
+
}
|
|
44
|
+
if (!clean_result.value) {
|
|
45
|
+
throw new TaskError(`Repo ${repo_dir} is not on branch "${repo_config.branch}" and the workspace is unclean, blocking switch`);
|
|
46
|
+
}
|
|
47
|
+
const checkout_result = await git_ops.checkout({ branch: repo_config.branch, cwd: repo_dir });
|
|
48
|
+
if (!checkout_result.ok) {
|
|
49
|
+
throw new TaskError(`Failed to checkout branch "${repo_config.branch}" in ${repo_dir}: ${checkout_result.message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Only pull if remote exists (skip for local-only repos, test fixtures)
|
|
53
|
+
const origin_result = await git_ops.has_remote({ remote: 'origin', cwd: repo_dir });
|
|
54
|
+
if (!origin_result.ok) {
|
|
55
|
+
throw new TaskError(`Failed to check for remote in ${repo_dir}: ${origin_result.message}`);
|
|
56
|
+
}
|
|
57
|
+
if (origin_result.value) {
|
|
58
|
+
const pull_result = await git_ops.pull({ cwd: repo_dir });
|
|
59
|
+
if (!pull_result.ok) {
|
|
60
|
+
throw new TaskError(`Failed to pull in ${repo_dir}: ${pull_result.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Check clean workspace after pull to ensure we're in a good state
|
|
64
|
+
const clean_after_result = await git_ops.check_clean_workspace({ cwd: repo_dir });
|
|
65
|
+
if (!clean_after_result.ok) {
|
|
66
|
+
throw new TaskError(`Failed to check workspace in ${repo_dir}: ${clean_after_result.message}`);
|
|
67
|
+
}
|
|
68
|
+
if (!clean_after_result.value) {
|
|
69
|
+
throw new TaskError(`Workspace ${repo_dir} is unclean after pulling branch "${repo_config.branch}"`);
|
|
70
|
+
}
|
|
71
|
+
// Record commit hash after pull
|
|
72
|
+
const commit_after_result = await git_ops.current_commit_hash({ cwd: repo_dir });
|
|
73
|
+
if (!commit_after_result.ok) {
|
|
74
|
+
throw new TaskError(`Failed to get commit hash in ${repo_dir}: ${commit_after_result.message}`);
|
|
75
|
+
}
|
|
76
|
+
const commit_after = commit_after_result.value;
|
|
77
|
+
// Track if we got new commits
|
|
78
|
+
const got_new_commits = commit_before !== commit_after;
|
|
79
|
+
// Only install if package.json changed
|
|
80
|
+
if (got_new_commits) {
|
|
81
|
+
const changed_result = await git_ops.has_file_changed({
|
|
82
|
+
from_commit: commit_before,
|
|
83
|
+
to_commit: commit_after,
|
|
84
|
+
file_path: 'package.json',
|
|
85
|
+
cwd: repo_dir,
|
|
86
|
+
});
|
|
87
|
+
if (!changed_result.ok) {
|
|
88
|
+
throw new TaskError(`Failed to check if package.json changed in ${repo_dir}: ${changed_result.message}`);
|
|
89
|
+
}
|
|
90
|
+
if (changed_result.value) {
|
|
91
|
+
const install_result = await npm_ops.install({ cwd: repo_dir });
|
|
92
|
+
if (!install_result.ok) {
|
|
93
|
+
throw new TaskError(`Failed to install dependencies in ${repo_dir}: ${install_result.message}${install_result.stderr ? `\n${install_result.stderr}` : ''}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Validate and load library.ts
|
|
98
|
+
const library_path = join(repo_dir, 'src/routes/library.ts');
|
|
99
|
+
if (!existsSync(library_path)) {
|
|
100
|
+
throw new TaskError(`Repo "${repo_name}" is missing src/routes/library.ts\n` +
|
|
101
|
+
`This file is required for fuz_gitops. To fix:\n` +
|
|
102
|
+
` 1. Create src/routes/library.gen.ts with:\n` +
|
|
103
|
+
` import {library_gen} from '@fuzdev/fuz_ui/library_gen.js';\n` +
|
|
104
|
+
` export const gen = library_gen();\n` +
|
|
105
|
+
` 2. Run: cd ${repo_dir} && gro gen`);
|
|
106
|
+
}
|
|
107
|
+
const library_module = await import(library_path);
|
|
108
|
+
const { library_json } = library_module;
|
|
109
|
+
if (!library_json) {
|
|
110
|
+
throw new TaskError(`Repo "${repo_name}" has invalid src/routes/library.ts - missing library_json export\n` +
|
|
111
|
+
`The file must export a library_json object. To fix:\n` +
|
|
112
|
+
` 1. Ensure src/routes/library.gen.ts uses library_gen from @fuzdev/fuz_ui\n` +
|
|
113
|
+
` 2. Run: cd ${repo_dir} && gro gen`);
|
|
114
|
+
}
|
|
115
|
+
const library = new Library(library_json);
|
|
116
|
+
const local_repo = {
|
|
117
|
+
library,
|
|
118
|
+
library_json,
|
|
119
|
+
repo_dir,
|
|
120
|
+
repo_git_ssh_url,
|
|
121
|
+
repo_config,
|
|
122
|
+
};
|
|
123
|
+
// Extract dependencies from package_json
|
|
124
|
+
const { package_json } = library;
|
|
125
|
+
if (package_json.dependencies) {
|
|
126
|
+
local_repo.dependencies = new Map(Object.entries(package_json.dependencies));
|
|
127
|
+
}
|
|
128
|
+
if (package_json.devDependencies) {
|
|
129
|
+
local_repo.dev_dependencies = new Map(Object.entries(package_json.devDependencies));
|
|
130
|
+
}
|
|
131
|
+
if (package_json.peerDependencies) {
|
|
132
|
+
local_repo.peer_dependencies = new Map(Object.entries(package_json.peerDependencies));
|
|
133
|
+
}
|
|
134
|
+
return local_repo;
|
|
135
|
+
};
|
|
136
|
+
export const local_repos_ensure = async ({ resolved_config, repos_dir, gitops_config, download, log, npm_ops = default_npm_operations, }) => {
|
|
137
|
+
let local_repo_paths = null;
|
|
138
|
+
if (!resolved_config.local_repos_missing) {
|
|
139
|
+
local_repo_paths = resolved_config.local_repo_paths;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
if (download) {
|
|
143
|
+
const downloaded = await download_repos({
|
|
144
|
+
repos_dir,
|
|
145
|
+
local_repos_missing: resolved_config.local_repos_missing,
|
|
146
|
+
log,
|
|
147
|
+
npm_ops,
|
|
148
|
+
});
|
|
149
|
+
local_repo_paths = (resolved_config.local_repo_paths ?? [])
|
|
150
|
+
.concat(downloaded)
|
|
151
|
+
.sort((a, b) => gitops_config.repos.findIndex((r) => r.repo_url === a.repo_url) -
|
|
152
|
+
gitops_config.repos.findIndex((r) => r.repo_url === b.repo_url));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
log?.error(`Failed to resolve local repos in ${repos_dir} - do you need to pass \`--download\` or configure the directory?`, // TODO leaking task impl details
|
|
156
|
+
resolved_config.local_repos_missing.map((r) => r.repo_url));
|
|
157
|
+
throw new TaskError('Failed to resolve local configs');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (!local_repo_paths) {
|
|
161
|
+
throw new TaskError('No repos are configured in `gitops_config.ts`');
|
|
162
|
+
}
|
|
163
|
+
return local_repo_paths;
|
|
164
|
+
};
|
|
165
|
+
export const local_repos_load = async ({ local_repo_paths, log, git_ops = default_git_operations, npm_ops = default_npm_operations, }) => {
|
|
166
|
+
const loaded = [];
|
|
167
|
+
for (const local_repo_path of local_repo_paths) {
|
|
168
|
+
loaded.push(await local_repo_load({ local_repo_path, log, git_ops, npm_ops })); // eslint-disable-line no-await-in-loop
|
|
169
|
+
}
|
|
170
|
+
return loaded;
|
|
171
|
+
};
|
|
172
|
+
export const local_repo_locate = ({ repo_config, repos_dir, }) => {
|
|
173
|
+
const { repo_url } = repo_config;
|
|
174
|
+
const repo_name = strip_end(repo_url, '/').split('/').at(-1);
|
|
175
|
+
if (!repo_name)
|
|
176
|
+
throw Error('Invalid `repo_config.repo_url` ' + repo_url);
|
|
177
|
+
const repo_git_ssh_url = to_repo_git_ssh_url(repo_url);
|
|
178
|
+
const repo_dir = repo_config.repo_dir ?? join(repos_dir, repo_name);
|
|
179
|
+
if (!existsSync(repo_dir)) {
|
|
180
|
+
return { type: 'local_repo_missing', repo_name, repo_url, repo_git_ssh_url, repo_config };
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
type: 'local_repo_path',
|
|
184
|
+
repo_name,
|
|
185
|
+
repo_dir,
|
|
186
|
+
repo_url,
|
|
187
|
+
repo_git_ssh_url,
|
|
188
|
+
repo_config,
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
const to_repo_git_ssh_url = (repo_url) => {
|
|
192
|
+
const url = new URL(repo_url);
|
|
193
|
+
return `git@${url.hostname}:${url.pathname.substring(1)}`;
|
|
194
|
+
};
|
|
195
|
+
const download_repos = async ({ repos_dir, local_repos_missing, log, npm_ops = default_npm_operations, }) => {
|
|
196
|
+
const resolved = [];
|
|
197
|
+
for (const { repo_config, repo_git_ssh_url } of local_repos_missing) {
|
|
198
|
+
log?.info(`cloning repo ${repo_git_ssh_url} to ${repos_dir}`);
|
|
199
|
+
await spawn('git', ['clone', repo_git_ssh_url], { cwd: repos_dir }); // eslint-disable-line no-await-in-loop
|
|
200
|
+
const local_repo = local_repo_locate({ repo_config, repos_dir });
|
|
201
|
+
if (local_repo.type === 'local_repo_missing') {
|
|
202
|
+
throw new TaskError(`Failed to clone repo ${repo_git_ssh_url} to ${repos_dir}`);
|
|
203
|
+
}
|
|
204
|
+
// Always install dependencies after cloning
|
|
205
|
+
log?.info(`installing dependencies for newly cloned repo ${local_repo.repo_dir}`);
|
|
206
|
+
const install_result = await npm_ops.install({ cwd: local_repo.repo_dir }); // eslint-disable-line no-await-in-loop
|
|
207
|
+
if (!install_result.ok) {
|
|
208
|
+
throw new TaskError(`Failed to install dependencies in ${local_repo.repo_dir}: ${install_result.message}${install_result.stderr ? `\n${install_result.stderr}` : ''}`);
|
|
209
|
+
}
|
|
210
|
+
resolved.push(local_repo);
|
|
211
|
+
}
|
|
212
|
+
return resolved;
|
|
213
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
2
|
+
import type { DependencyGraphBuilder } from './dependency_graph.js';
|
|
3
|
+
/**
|
|
4
|
+
* Formats wildcard dependencies as styled strings.
|
|
5
|
+
* Returns array of lines for inclusion in output.
|
|
6
|
+
*/
|
|
7
|
+
export declare const format_wildcard_dependencies: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>) => Array<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Formats dev circular dependencies as styled strings.
|
|
10
|
+
* Returns array of lines for inclusion in output.
|
|
11
|
+
*/
|
|
12
|
+
export declare const format_dev_cycles: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>) => Array<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Formats production/peer circular dependencies as styled strings.
|
|
15
|
+
* Returns array of lines for inclusion in output.
|
|
16
|
+
*/
|
|
17
|
+
export declare const format_production_cycles: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>) => Array<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Logs wildcard dependencies as warnings.
|
|
20
|
+
* Wildcard dependencies require attention and should be reviewed.
|
|
21
|
+
*/
|
|
22
|
+
export declare const log_wildcard_dependencies: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>, log: Logger, indent?: string) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Logs dev circular dependencies as info.
|
|
25
|
+
* Dev cycles are normal and non-blocking, so they're informational, not warnings.
|
|
26
|
+
*/
|
|
27
|
+
export declare const log_dev_cycles: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>, log: Logger, indent?: string) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Logs production/peer circular dependencies as errors.
|
|
30
|
+
* Production cycles block publishing and must be resolved.
|
|
31
|
+
*/
|
|
32
|
+
export declare const log_production_cycles: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>, log: Logger, indent?: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Logs all dependency analysis results (wildcards, production cycles, dev cycles).
|
|
35
|
+
* Convenience function that calls all three logging functions in order.
|
|
36
|
+
*/
|
|
37
|
+
export declare const log_dependency_analysis: (analysis: ReturnType<DependencyGraphBuilder["analyze"]>, log: Logger, indent?: string) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Logs a simple bulleted list with a header.
|
|
40
|
+
* Common pattern for warnings, info messages, and other lists.
|
|
41
|
+
*/
|
|
42
|
+
export declare const log_list: (items: Array<string>, header: string, color: "cyan" | "yellow" | "red" | "dim", log: Logger, log_method?: "info" | "warn" | "error") => void;
|
|
43
|
+
//# sourceMappingURL=log_helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/log_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,uBAAuB,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACxC,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,KACrD,KAAK,CAAC,MAAM,CASd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC7B,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,KACrD,KAAK,CAAC,MAAM,CAcd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACpC,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,KACrD,KAAK,CAAC,MAAM,CAcd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,GACrC,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,EACvD,KAAK,MAAM,EACX,eAAW,KACT,IAKF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAC1B,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,EACvD,KAAK,MAAM,EACX,eAAW,KACT,IAKF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GACjC,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,EACvD,KAAK,MAAM,EACX,eAAW,KACT,IAKF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GACnC,UAAU,UAAU,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,EACvD,KAAK,MAAM,EACX,eAAW,KACT,IAIF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GACpB,OAAO,KAAK,CAAC,MAAM,CAAC,EACpB,QAAQ,MAAM,EACd,OAAO,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,EACxC,KAAK,MAAM,EACX,aAAY,MAAM,GAAG,MAAM,GAAG,OAAgB,KAC5C,IAWF,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { styleText as st } from 'node:util';
|
|
2
|
+
/**
|
|
3
|
+
* Formats wildcard dependencies as styled strings.
|
|
4
|
+
* Returns array of lines for inclusion in output.
|
|
5
|
+
*/
|
|
6
|
+
export const format_wildcard_dependencies = (analysis) => {
|
|
7
|
+
if (analysis.wildcard_deps.length === 0)
|
|
8
|
+
return [];
|
|
9
|
+
const lines = [];
|
|
10
|
+
lines.push(st('yellow', `\n⚠️ Found ${analysis.wildcard_deps.length} wildcard dependencies:`));
|
|
11
|
+
for (const { pkg, dep, version } of analysis.wildcard_deps) {
|
|
12
|
+
lines.push(` ${pkg} → ${dep} ${st('red', version)}`);
|
|
13
|
+
}
|
|
14
|
+
return lines;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Formats dev circular dependencies as styled strings.
|
|
18
|
+
* Returns array of lines for inclusion in output.
|
|
19
|
+
*/
|
|
20
|
+
export const format_dev_cycles = (analysis) => {
|
|
21
|
+
if (analysis.dev_cycles.length === 0)
|
|
22
|
+
return [];
|
|
23
|
+
const lines = [];
|
|
24
|
+
lines.push(st('dim', `\nℹ️ Found ${analysis.dev_cycles.length} dev circular dependencies (normal, non-blocking):`));
|
|
25
|
+
for (const cycle of analysis.dev_cycles) {
|
|
26
|
+
lines.push(st('dim', ` ${cycle.join(' → ')}`));
|
|
27
|
+
}
|
|
28
|
+
return lines;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Formats production/peer circular dependencies as styled strings.
|
|
32
|
+
* Returns array of lines for inclusion in output.
|
|
33
|
+
*/
|
|
34
|
+
export const format_production_cycles = (analysis) => {
|
|
35
|
+
if (analysis.production_cycles.length === 0)
|
|
36
|
+
return [];
|
|
37
|
+
const lines = [];
|
|
38
|
+
lines.push(st('red', `\n❌ Found ${analysis.production_cycles.length} production/peer circular dependencies (blocks publishing):`));
|
|
39
|
+
for (const cycle of analysis.production_cycles) {
|
|
40
|
+
lines.push(` ${st('red', cycle.join(' → '))}`);
|
|
41
|
+
}
|
|
42
|
+
return lines;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Logs wildcard dependencies as warnings.
|
|
46
|
+
* Wildcard dependencies require attention and should be reviewed.
|
|
47
|
+
*/
|
|
48
|
+
export const log_wildcard_dependencies = (analysis, log, indent = '') => {
|
|
49
|
+
const lines = format_wildcard_dependencies(analysis);
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
log.warn(indent + line);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Logs dev circular dependencies as info.
|
|
56
|
+
* Dev cycles are normal and non-blocking, so they're informational, not warnings.
|
|
57
|
+
*/
|
|
58
|
+
export const log_dev_cycles = (analysis, log, indent = '') => {
|
|
59
|
+
const lines = format_dev_cycles(analysis);
|
|
60
|
+
for (const line of lines) {
|
|
61
|
+
log.info(indent + line);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Logs production/peer circular dependencies as errors.
|
|
66
|
+
* Production cycles block publishing and must be resolved.
|
|
67
|
+
*/
|
|
68
|
+
export const log_production_cycles = (analysis, log, indent = '') => {
|
|
69
|
+
const lines = format_production_cycles(analysis);
|
|
70
|
+
for (const line of lines) {
|
|
71
|
+
log.error(indent + line);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Logs all dependency analysis results (wildcards, production cycles, dev cycles).
|
|
76
|
+
* Convenience function that calls all three logging functions in order.
|
|
77
|
+
*/
|
|
78
|
+
export const log_dependency_analysis = (analysis, log, indent = '') => {
|
|
79
|
+
log_wildcard_dependencies(analysis, log, indent);
|
|
80
|
+
log_production_cycles(analysis, log, indent);
|
|
81
|
+
log_dev_cycles(analysis, log, indent);
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Logs a simple bulleted list with a header.
|
|
85
|
+
* Common pattern for warnings, info messages, and other lists.
|
|
86
|
+
*/
|
|
87
|
+
export const log_list = (items, header, color, log, log_method = 'info') => {
|
|
88
|
+
if (items.length === 0)
|
|
89
|
+
return;
|
|
90
|
+
// Only add newline prefix if header is non-empty
|
|
91
|
+
const formatted_header = header ? `\n${header}` : '';
|
|
92
|
+
if (formatted_header) {
|
|
93
|
+
log[log_method](st(color, formatted_header));
|
|
94
|
+
}
|
|
95
|
+
for (const item of items) {
|
|
96
|
+
log[log_method](st(color, ` • ${item}`));
|
|
97
|
+
}
|
|
98
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
2
|
+
import type { LocalRepo } from './local_repo.js';
|
|
3
|
+
import { type VersionStrategy } from './dependency_updater.js';
|
|
4
|
+
import type { GitopsOperations } from './operations.js';
|
|
5
|
+
export interface PublishingOptions {
|
|
6
|
+
dry_run: boolean;
|
|
7
|
+
update_deps: boolean;
|
|
8
|
+
version_strategy?: VersionStrategy;
|
|
9
|
+
deploy?: boolean;
|
|
10
|
+
max_wait?: number;
|
|
11
|
+
skip_install?: boolean;
|
|
12
|
+
log?: Logger;
|
|
13
|
+
ops?: GitopsOperations;
|
|
14
|
+
}
|
|
15
|
+
export interface PublishedVersion {
|
|
16
|
+
name: string;
|
|
17
|
+
old_version: string;
|
|
18
|
+
new_version: string;
|
|
19
|
+
bump_type: 'major' | 'minor' | 'patch';
|
|
20
|
+
breaking: boolean;
|
|
21
|
+
commit: string;
|
|
22
|
+
tag: string;
|
|
23
|
+
}
|
|
24
|
+
export interface PublishingResult {
|
|
25
|
+
ok: boolean;
|
|
26
|
+
published: Array<PublishedVersion>;
|
|
27
|
+
failed: Array<{
|
|
28
|
+
name: string;
|
|
29
|
+
error: Error;
|
|
30
|
+
}>;
|
|
31
|
+
duration: number;
|
|
32
|
+
}
|
|
33
|
+
export declare const publish_repos: (repos: Array<LocalRepo>, options: PublishingOptions) => Promise<PublishingResult>;
|
|
34
|
+
//# sourceMappingURL=multi_repo_publisher.d.ts.map
|
|
@@ -0,0 +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;AAOtD,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,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,CAmU1B,CAAC"}
|