@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.
Files changed (190) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/ModulesDetail.svelte +180 -0
  4. package/dist/ModulesDetail.svelte.d.ts +10 -0
  5. package/dist/ModulesDetail.svelte.d.ts.map +1 -0
  6. package/dist/ModulesNav.svelte +43 -0
  7. package/dist/ModulesNav.svelte.d.ts +11 -0
  8. package/dist/ModulesNav.svelte.d.ts.map +1 -0
  9. package/dist/ModulesPage.svelte +50 -0
  10. package/dist/ModulesPage.svelte.d.ts +9 -0
  11. package/dist/ModulesPage.svelte.d.ts.map +1 -0
  12. package/dist/PageFooter.svelte +15 -0
  13. package/dist/PageFooter.svelte.d.ts +19 -0
  14. package/dist/PageFooter.svelte.d.ts.map +1 -0
  15. package/dist/PageHeader.svelte +35 -0
  16. package/dist/PageHeader.svelte.d.ts +19 -0
  17. package/dist/PageHeader.svelte.d.ts.map +1 -0
  18. package/dist/PullRequestsDetail.svelte +53 -0
  19. package/dist/PullRequestsDetail.svelte.d.ts +10 -0
  20. package/dist/PullRequestsDetail.svelte.d.ts.map +1 -0
  21. package/dist/PullRequestsPage.svelte +47 -0
  22. package/dist/PullRequestsPage.svelte.d.ts +11 -0
  23. package/dist/PullRequestsPage.svelte.d.ts.map +1 -0
  24. package/dist/ReposTable.svelte +189 -0
  25. package/dist/ReposTable.svelte.d.ts +9 -0
  26. package/dist/ReposTable.svelte.d.ts.map +1 -0
  27. package/dist/ReposTree.svelte +88 -0
  28. package/dist/ReposTree.svelte.d.ts +11 -0
  29. package/dist/ReposTree.svelte.d.ts.map +1 -0
  30. package/dist/ReposTreeNav.svelte +55 -0
  31. package/dist/ReposTreeNav.svelte.d.ts +11 -0
  32. package/dist/ReposTreeNav.svelte.d.ts.map +1 -0
  33. package/dist/TablePage.svelte +46 -0
  34. package/dist/TablePage.svelte.d.ts +9 -0
  35. package/dist/TablePage.svelte.d.ts.map +1 -0
  36. package/dist/TreeItemPage.svelte +75 -0
  37. package/dist/TreeItemPage.svelte.d.ts +10 -0
  38. package/dist/TreeItemPage.svelte.d.ts.map +1 -0
  39. package/dist/TreePage.svelte +64 -0
  40. package/dist/TreePage.svelte.d.ts +9 -0
  41. package/dist/TreePage.svelte.d.ts.map +1 -0
  42. package/dist/changeset_generator.d.ts +38 -0
  43. package/dist/changeset_generator.d.ts.map +1 -0
  44. package/dist/changeset_generator.js +110 -0
  45. package/dist/changeset_reader.d.ts +75 -0
  46. package/dist/changeset_reader.d.ts.map +1 -0
  47. package/dist/changeset_reader.js +167 -0
  48. package/dist/constants.d.ts +9 -0
  49. package/dist/constants.d.ts.map +1 -0
  50. package/dist/constants.js +8 -0
  51. package/dist/dependency_graph.d.ts +120 -0
  52. package/dist/dependency_graph.d.ts.map +1 -0
  53. package/dist/dependency_graph.js +341 -0
  54. package/dist/dependency_updater.d.ts +46 -0
  55. package/dist/dependency_updater.d.ts.map +1 -0
  56. package/dist/dependency_updater.js +213 -0
  57. package/dist/fetch_repo_data.d.ts +19 -0
  58. package/dist/fetch_repo_data.d.ts.map +1 -0
  59. package/dist/fetch_repo_data.js +49 -0
  60. package/dist/fs_fetch_value_cache.d.ts +24 -0
  61. package/dist/fs_fetch_value_cache.d.ts.map +1 -0
  62. package/dist/fs_fetch_value_cache.js +61 -0
  63. package/dist/git_operations.d.ts +54 -0
  64. package/dist/git_operations.d.ts.map +1 -0
  65. package/dist/git_operations.js +144 -0
  66. package/dist/github.d.ts +91 -0
  67. package/dist/github.d.ts.map +1 -0
  68. package/dist/github.js +94 -0
  69. package/dist/github_helpers.d.ts +10 -0
  70. package/dist/github_helpers.d.ts.map +1 -0
  71. package/dist/github_helpers.js +13 -0
  72. package/dist/gitops_analyze.task.d.ts +17 -0
  73. package/dist/gitops_analyze.task.d.ts.map +1 -0
  74. package/dist/gitops_analyze.task.js +188 -0
  75. package/dist/gitops_config.d.ts +56 -0
  76. package/dist/gitops_config.d.ts.map +1 -0
  77. package/dist/gitops_config.js +63 -0
  78. package/dist/gitops_plan.task.d.ts +28 -0
  79. package/dist/gitops_plan.task.d.ts.map +1 -0
  80. package/dist/gitops_plan.task.js +217 -0
  81. package/dist/gitops_publish.task.d.ts +29 -0
  82. package/dist/gitops_publish.task.d.ts.map +1 -0
  83. package/dist/gitops_publish.task.js +178 -0
  84. package/dist/gitops_sync.task.d.ts +18 -0
  85. package/dist/gitops_sync.task.d.ts.map +1 -0
  86. package/dist/gitops_sync.task.js +95 -0
  87. package/dist/gitops_task_helpers.d.ts +63 -0
  88. package/dist/gitops_task_helpers.d.ts.map +1 -0
  89. package/dist/gitops_task_helpers.js +84 -0
  90. package/dist/gitops_validate.task.d.ts +12 -0
  91. package/dist/gitops_validate.task.d.ts.map +1 -0
  92. package/dist/gitops_validate.task.js +210 -0
  93. package/dist/graph_validation.d.ts +39 -0
  94. package/dist/graph_validation.d.ts.map +1 -0
  95. package/dist/graph_validation.js +79 -0
  96. package/dist/local_repo.d.ts +84 -0
  97. package/dist/local_repo.d.ts.map +1 -0
  98. package/dist/local_repo.js +213 -0
  99. package/dist/log_helpers.d.ts +43 -0
  100. package/dist/log_helpers.d.ts.map +1 -0
  101. package/dist/log_helpers.js +98 -0
  102. package/dist/multi_repo_publisher.d.ts +34 -0
  103. package/dist/multi_repo_publisher.d.ts.map +1 -0
  104. package/dist/multi_repo_publisher.js +364 -0
  105. package/dist/npm_install_helpers.d.ts +23 -0
  106. package/dist/npm_install_helpers.d.ts.map +1 -0
  107. package/dist/npm_install_helpers.js +60 -0
  108. package/dist/npm_registry.d.ts +46 -0
  109. package/dist/npm_registry.d.ts.map +1 -0
  110. package/dist/npm_registry.js +96 -0
  111. package/dist/operations.d.ts +409 -0
  112. package/dist/operations.d.ts.map +1 -0
  113. package/dist/operations.js +34 -0
  114. package/dist/operations_defaults.d.ts +19 -0
  115. package/dist/operations_defaults.d.ts.map +1 -0
  116. package/dist/operations_defaults.js +279 -0
  117. package/dist/output_helpers.d.ts +27 -0
  118. package/dist/output_helpers.d.ts.map +1 -0
  119. package/dist/output_helpers.js +39 -0
  120. package/dist/paths.d.ts +11 -0
  121. package/dist/paths.d.ts.map +1 -0
  122. package/dist/paths.js +10 -0
  123. package/dist/preflight_checks.d.ts +47 -0
  124. package/dist/preflight_checks.d.ts.map +1 -0
  125. package/dist/preflight_checks.js +181 -0
  126. package/dist/publishing_plan.d.ts +100 -0
  127. package/dist/publishing_plan.d.ts.map +1 -0
  128. package/dist/publishing_plan.js +353 -0
  129. package/dist/publishing_plan_helpers.d.ts +30 -0
  130. package/dist/publishing_plan_helpers.d.ts.map +1 -0
  131. package/dist/publishing_plan_helpers.js +112 -0
  132. package/dist/publishing_plan_logging.d.ts +18 -0
  133. package/dist/publishing_plan_logging.d.ts.map +1 -0
  134. package/dist/publishing_plan_logging.js +342 -0
  135. package/dist/repo.svelte.d.ts +52 -0
  136. package/dist/repo.svelte.d.ts.map +1 -0
  137. package/dist/repo.svelte.js +70 -0
  138. package/dist/repo_ops.d.ts +57 -0
  139. package/dist/repo_ops.d.ts.map +1 -0
  140. package/dist/repo_ops.js +167 -0
  141. package/dist/resolved_gitops_config.d.ts +9 -0
  142. package/dist/resolved_gitops_config.d.ts.map +1 -0
  143. package/dist/resolved_gitops_config.js +12 -0
  144. package/dist/semver.d.ts +24 -0
  145. package/dist/semver.d.ts.map +1 -0
  146. package/dist/semver.js +140 -0
  147. package/dist/serialization_types.d.ts +57 -0
  148. package/dist/serialization_types.d.ts.map +1 -0
  149. package/dist/serialization_types.js +40 -0
  150. package/dist/version_utils.d.ts +48 -0
  151. package/dist/version_utils.d.ts.map +1 -0
  152. package/dist/version_utils.js +125 -0
  153. package/package.json +107 -0
  154. package/src/lib/changeset_generator.ts +162 -0
  155. package/src/lib/changeset_reader.ts +218 -0
  156. package/src/lib/constants.ts +8 -0
  157. package/src/lib/dependency_graph.ts +423 -0
  158. package/src/lib/dependency_updater.ts +297 -0
  159. package/src/lib/fetch_repo_data.ts +64 -0
  160. package/src/lib/fs_fetch_value_cache.ts +75 -0
  161. package/src/lib/git_operations.ts +208 -0
  162. package/src/lib/github.ts +128 -0
  163. package/src/lib/github_helpers.ts +31 -0
  164. package/src/lib/gitops_analyze.task.ts +261 -0
  165. package/src/lib/gitops_config.ts +123 -0
  166. package/src/lib/gitops_plan.task.ts +272 -0
  167. package/src/lib/gitops_publish.task.ts +227 -0
  168. package/src/lib/gitops_sync.task.ts +109 -0
  169. package/src/lib/gitops_task_helpers.ts +126 -0
  170. package/src/lib/gitops_validate.task.ts +248 -0
  171. package/src/lib/graph_validation.ts +109 -0
  172. package/src/lib/local_repo.ts +359 -0
  173. package/src/lib/log_helpers.ts +147 -0
  174. package/src/lib/multi_repo_publisher.ts +464 -0
  175. package/src/lib/npm_install_helpers.ts +85 -0
  176. package/src/lib/npm_registry.ts +143 -0
  177. package/src/lib/operations.ts +334 -0
  178. package/src/lib/operations_defaults.ts +335 -0
  179. package/src/lib/output_helpers.ts +64 -0
  180. package/src/lib/paths.ts +11 -0
  181. package/src/lib/preflight_checks.ts +269 -0
  182. package/src/lib/publishing_plan.ts +531 -0
  183. package/src/lib/publishing_plan_helpers.ts +145 -0
  184. package/src/lib/publishing_plan_logging.ts +470 -0
  185. package/src/lib/repo.svelte.ts +95 -0
  186. package/src/lib/repo_ops.ts +213 -0
  187. package/src/lib/resolved_gitops_config.ts +27 -0
  188. package/src/lib/semver.ts +166 -0
  189. package/src/lib/serialization_types.ts +90 -0
  190. package/src/lib/version_utils.ts +150 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Generic repository operations for scripts that work across repos.
3
+ *
4
+ * Provides lightweight utilities for:
5
+ * - Getting repo paths from gitops config (without full git sync)
6
+ * - Walking files in repos with sensible exclusions
7
+ * - Common exclusion patterns for node/svelte projects
8
+ *
9
+ * For full git sync/clone functionality, use `get_gitops_ready()` from gitops_task_helpers.
10
+ */
11
+ import { existsSync } from 'node:fs';
12
+ import { readdir, stat } from 'node:fs/promises';
13
+ import { join, resolve, dirname } from 'node:path';
14
+ import { load_gitops_config } from './gitops_config.js';
15
+ import { DEFAULT_REPOS_DIR } from './paths.js';
16
+ /** Default directories to exclude from file walking */
17
+ export const DEFAULT_EXCLUDE_DIRS = [
18
+ 'node_modules',
19
+ '.git',
20
+ '.gro',
21
+ '.svelte-kit',
22
+ '.deno',
23
+ '.vscode',
24
+ '.idea',
25
+ 'dist',
26
+ 'build',
27
+ 'coverage',
28
+ '.cache',
29
+ '.turbo',
30
+ ];
31
+ /** Default binary/non-text extensions to exclude from content processing */
32
+ export const DEFAULT_EXCLUDE_EXTENSIONS = [
33
+ '.png',
34
+ '.jpg',
35
+ '.jpeg',
36
+ '.gif',
37
+ '.svg',
38
+ '.ico',
39
+ '.webp',
40
+ '.woff',
41
+ '.woff2',
42
+ '.ttf',
43
+ '.eot',
44
+ '.mp4',
45
+ '.webm',
46
+ '.mp3',
47
+ '.wav',
48
+ '.ogg',
49
+ '.zip',
50
+ '.tar',
51
+ '.gz',
52
+ '.lock',
53
+ '.pdf',
54
+ ];
55
+ /**
56
+ * Get repo paths from gitops config without full git sync.
57
+ * Lighter weight than `get_gitops_ready()` - just resolves paths.
58
+ *
59
+ * @param config_path Path to gitops.config.ts (defaults to ./gitops.config.ts)
60
+ * @returns Array of repo info with name, path, and url
61
+ */
62
+ export const get_repo_paths = async (config_path) => {
63
+ const resolved_config_path = resolve(config_path ?? 'gitops.config.ts');
64
+ const config = await load_gitops_config(resolved_config_path);
65
+ if (!config) {
66
+ throw new Error(`No gitops config found at ${resolved_config_path}`);
67
+ }
68
+ const config_dir = dirname(resolved_config_path);
69
+ const repos_dir = resolve(config_dir, config.repos_dir || DEFAULT_REPOS_DIR);
70
+ const repos = [];
71
+ for (const repo_config of config.repos) {
72
+ const url = repo_config.repo_url;
73
+ const name = url.split('/').at(-1);
74
+ if (!name)
75
+ continue;
76
+ const path = repo_config.repo_dir
77
+ ? resolve(config_dir, repo_config.repo_dir)
78
+ : join(repos_dir, name);
79
+ if (existsSync(path)) {
80
+ repos.push({ name, path, url });
81
+ }
82
+ }
83
+ return repos;
84
+ };
85
+ /**
86
+ * Check if a path should be excluded based on options.
87
+ */
88
+ export const should_exclude_path = (file_path, options) => {
89
+ const exclude_dirs = options?.no_defaults
90
+ ? (options.exclude_dirs ?? [])
91
+ : [...DEFAULT_EXCLUDE_DIRS, ...(options?.exclude_dirs ?? [])];
92
+ const exclude_extensions = options?.no_defaults
93
+ ? (options.exclude_extensions ?? [])
94
+ : [...DEFAULT_EXCLUDE_EXTENSIONS, ...(options?.exclude_extensions ?? [])];
95
+ const normalized = file_path.toLowerCase();
96
+ // Check excluded directories
97
+ for (const dir of exclude_dirs) {
98
+ // Must match as a full directory component, not a prefix
99
+ if (normalized.includes(`/${dir}/`) || normalized.endsWith(`/${dir}`)) {
100
+ return true;
101
+ }
102
+ }
103
+ // Check excluded extensions
104
+ for (const ext of exclude_extensions) {
105
+ if (normalized.endsWith(ext)) {
106
+ return true;
107
+ }
108
+ }
109
+ return false;
110
+ };
111
+ /**
112
+ * Walk files in a directory, respecting common exclusions.
113
+ * Yields absolute paths to files (and optionally directories).
114
+ *
115
+ * @param dir Directory to walk
116
+ * @param options Walk options for exclusions and filtering
117
+ */
118
+ export async function* walk_repo_files(dir, options) {
119
+ const max_file_size = options?.max_file_size ?? 10 * 1024 * 1024;
120
+ const include_dirs = options?.include_dirs ?? false;
121
+ async function* walk(current_dir) {
122
+ let entries;
123
+ try {
124
+ entries = await readdir(current_dir, { withFileTypes: true });
125
+ }
126
+ catch {
127
+ // Skip directories we can't read
128
+ return;
129
+ }
130
+ for (const entry of entries) {
131
+ const full_path = join(current_dir, entry.name);
132
+ if (should_exclude_path(full_path, options)) {
133
+ continue;
134
+ }
135
+ if (entry.isDirectory()) {
136
+ if (include_dirs) {
137
+ yield full_path;
138
+ }
139
+ yield* walk(full_path);
140
+ }
141
+ else if (entry.isFile()) {
142
+ // Check file size
143
+ try {
144
+ const file_stat = await stat(full_path); // eslint-disable-line no-await-in-loop
145
+ if (file_stat.size <= max_file_size) {
146
+ yield full_path;
147
+ }
148
+ }
149
+ catch {
150
+ // Skip files we can't stat
151
+ }
152
+ }
153
+ }
154
+ }
155
+ yield* walk(dir);
156
+ }
157
+ /**
158
+ * Collect all files from walk_repo_files into an array.
159
+ * Convenience function for when you need all paths upfront.
160
+ */
161
+ export const collect_repo_files = async (dir, options) => {
162
+ const files = [];
163
+ for await (const file of walk_repo_files(dir, options)) {
164
+ files.push(file);
165
+ }
166
+ return files;
167
+ };
@@ -0,0 +1,9 @@
1
+ import type { GitopsConfig } from './gitops_config.js';
2
+ import { type LocalRepoPath, type LocalRepoMissing } from './local_repo.js';
3
+ export interface ResolvedGitopsConfig {
4
+ local_repos: Array<LocalRepoPath | LocalRepoMissing> | null;
5
+ local_repo_paths: Array<LocalRepoPath> | null;
6
+ local_repos_missing: Array<LocalRepoMissing> | null;
7
+ }
8
+ export declare const resolve_gitops_config: (gitops_config: GitopsConfig, repos_dir: string) => ResolvedGitopsConfig;
9
+ //# sourceMappingURL=resolved_gitops_config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved_gitops_config.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/resolved_gitops_config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAoB,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAE7F,MAAM,WAAW,oBAAoB;IACpC,WAAW,EAAE,KAAK,CAAC,aAAa,GAAG,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAC5D,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC9C,mBAAmB,EAAE,KAAK,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;CACpD;AAED,eAAO,MAAM,qBAAqB,GACjC,eAAe,YAAY,EAC3B,WAAW,MAAM,KACf,oBAcF,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { local_repo_locate } from './local_repo.js';
2
+ export const resolve_gitops_config = (gitops_config, repos_dir) => {
3
+ const local_repos = gitops_config.repos.map((r) => local_repo_locate({ repo_config: r, repos_dir }));
4
+ const local_repo_paths = local_repos.filter((r) => r.type === 'local_repo_path');
5
+ const local_repos_missing = local_repos.filter((r) => r.type === 'local_repo_missing');
6
+ const config = {
7
+ local_repos: local_repos.length ? local_repos : null,
8
+ local_repo_paths: local_repo_paths.length ? local_repo_paths : null,
9
+ local_repos_missing: local_repos_missing.length ? local_repos_missing : null,
10
+ };
11
+ return config;
12
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Semantic Versioning 2.0.0 utilities
3
+ * @see https://semver.org/
4
+ */
5
+ export type BumpType = 'major' | 'minor' | 'patch';
6
+ export interface Semver {
7
+ major: number;
8
+ minor: number;
9
+ patch: number;
10
+ prerelease?: string;
11
+ build?: string;
12
+ }
13
+ /**
14
+ * Compares two semver versions according to SemVer 2.0.0 spec.
15
+ * Returns -1 if a < b, 0 if a === b, 1 if a > b.
16
+ * Build metadata is ignored in precedence comparison.
17
+ */
18
+ export declare const semver_compare_versions: (a: string, b: string) => number;
19
+ /**
20
+ * Bumps a version according to the specified type.
21
+ * Resets lower version numbers per SemVer spec.
22
+ */
23
+ export declare const semver_bump_version: (version: string, type: BumpType) => string;
24
+ //# sourceMappingURL=semver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/semver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAiGD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAqB9D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,EAAE,MAAM,QAAQ,KAAG,MAuBrE,CAAC"}
package/dist/semver.js ADDED
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Semantic Versioning 2.0.0 utilities
3
+ * @see https://semver.org/
4
+ */
5
+ /**
6
+ * SemVer 2.0.0 validation regex.
7
+ * @see https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
8
+ */
9
+ const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
10
+ /**
11
+ * Parses a semver version string.
12
+ * Accepts optional 'v' prefix for convenience.
13
+ */
14
+ const semver_parse = (version) => {
15
+ // Remove leading 'v' if present (common in git tags)
16
+ const clean = version.replace(/^v/, '');
17
+ // Validate the cleaned version
18
+ if (!SEMVER_REGEX.test(clean)) {
19
+ throw new Error(`Invalid semver: ${version}`);
20
+ }
21
+ const match = SEMVER_REGEX.exec(clean);
22
+ return {
23
+ major: parseInt(match[1], 10),
24
+ minor: parseInt(match[2], 10),
25
+ patch: parseInt(match[3], 10),
26
+ prerelease: match[4],
27
+ build: match[5],
28
+ };
29
+ };
30
+ const semver_to_string = (semver) => {
31
+ let version = `${semver.major}.${semver.minor}.${semver.patch}`;
32
+ if (semver.prerelease) {
33
+ version += `-${semver.prerelease}`;
34
+ }
35
+ if (semver.build) {
36
+ version += `+${semver.build}`;
37
+ }
38
+ return version;
39
+ };
40
+ /**
41
+ * Compares two prerelease versions according to SemVer 2.0.0 spec.
42
+ * Returns -1 if a < b, 0 if a === b, 1 if a > b.
43
+ */
44
+ const semver_compare_prerelease = (a, b) => {
45
+ // Handle missing prereleases
46
+ if (!a && !b)
47
+ return 0;
48
+ if (!a)
49
+ return 1; // normal version > prerelease
50
+ if (!b)
51
+ return -1; // prerelease < normal version
52
+ // Split into identifiers
53
+ const a_parts = a.split('.');
54
+ const b_parts = b.split('.');
55
+ // Compare each identifier
56
+ const min_length = Math.min(a_parts.length, b_parts.length);
57
+ for (let i = 0; i < min_length; i++) {
58
+ const a_part = a_parts[i];
59
+ const b_part = b_parts[i];
60
+ // Check if numeric
61
+ const a_is_numeric = /^\d+$/.test(a_part);
62
+ const b_is_numeric = /^\d+$/.test(b_part);
63
+ if (a_is_numeric && b_is_numeric) {
64
+ // Both numeric - compare numerically
65
+ const a_num = parseInt(a_part, 10);
66
+ const b_num = parseInt(b_part, 10);
67
+ if (a_num !== b_num) {
68
+ return a_num < b_num ? -1 : 1;
69
+ }
70
+ }
71
+ else if (a_is_numeric && !b_is_numeric) {
72
+ // Numeric identifiers always have lower precedence
73
+ return -1;
74
+ }
75
+ else if (!a_is_numeric && b_is_numeric) {
76
+ // Numeric identifiers always have lower precedence
77
+ return 1;
78
+ }
79
+ else {
80
+ // Both alphanumeric - compare lexically
81
+ const cmp = a_part.localeCompare(b_part);
82
+ if (cmp !== 0) {
83
+ return cmp < 0 ? -1 : 1;
84
+ }
85
+ }
86
+ }
87
+ // All identifiers equal - larger set has higher precedence
88
+ if (a_parts.length !== b_parts.length) {
89
+ return a_parts.length < b_parts.length ? -1 : 1;
90
+ }
91
+ return 0;
92
+ };
93
+ /**
94
+ * Compares two semver versions according to SemVer 2.0.0 spec.
95
+ * Returns -1 if a < b, 0 if a === b, 1 if a > b.
96
+ * Build metadata is ignored in precedence comparison.
97
+ */
98
+ export const semver_compare_versions = (a, b) => {
99
+ const v1 = semver_parse(a);
100
+ const v2 = semver_parse(b);
101
+ // Compare major
102
+ if (v1.major !== v2.major) {
103
+ return v1.major < v2.major ? -1 : 1;
104
+ }
105
+ // Compare minor
106
+ if (v1.minor !== v2.minor) {
107
+ return v1.minor < v2.minor ? -1 : 1;
108
+ }
109
+ // Compare patch
110
+ if (v1.patch !== v2.patch) {
111
+ return v1.patch < v2.patch ? -1 : 1;
112
+ }
113
+ // Compare prerelease (build metadata is ignored)
114
+ return semver_compare_prerelease(v1.prerelease, v2.prerelease);
115
+ };
116
+ /**
117
+ * Bumps a version according to the specified type.
118
+ * Resets lower version numbers per SemVer spec.
119
+ */
120
+ export const semver_bump_version = (version, type) => {
121
+ const semver = semver_parse(version);
122
+ switch (type) {
123
+ case 'major':
124
+ semver.major++;
125
+ semver.minor = 0;
126
+ semver.patch = 0;
127
+ break;
128
+ case 'minor':
129
+ semver.minor++;
130
+ semver.patch = 0;
131
+ break;
132
+ case 'patch':
133
+ semver.patch++;
134
+ break;
135
+ }
136
+ // Remove prerelease and build when bumping
137
+ semver.prerelease = undefined;
138
+ semver.build = undefined;
139
+ return semver_to_string(semver);
140
+ };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * JSON-serializable types for command output formats.
3
+ *
4
+ * Gitops commands support `--format json` and `--format markdown` output modes
5
+ * in addition to styled terminal output. These types define the JSON schema for:
6
+ * - Dependency graph structures (`SerializedGraph`)
7
+ * - Publishing plan predictions (`SerializedPublishingPlan`)
8
+ *
9
+ * Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish --dry_run` when
10
+ * `--format json` or `--outfile` is specified.
11
+ */
12
+ import type { DependencyGraph } from './dependency_graph.js';
13
+ export interface SerializedNode {
14
+ name: string;
15
+ version: string;
16
+ dependencies: Array<{
17
+ name: string;
18
+ type: string;
19
+ version: string;
20
+ }>;
21
+ dependents: Array<string>;
22
+ publishable: boolean;
23
+ }
24
+ export interface SerializedGraph {
25
+ nodes: Array<SerializedNode>;
26
+ edges: Array<[string, string]>;
27
+ }
28
+ export interface SerializedPublishingPlan {
29
+ publishing_order: Array<string>;
30
+ version_changes: Array<{
31
+ package_name: string;
32
+ from: string;
33
+ to: string;
34
+ bump_type: string;
35
+ breaking: boolean;
36
+ has_changesets: boolean;
37
+ will_generate_changeset?: boolean;
38
+ needs_bump_escalation?: boolean;
39
+ existing_bump?: string;
40
+ required_bump?: string;
41
+ }>;
42
+ dependency_updates: Array<{
43
+ dependent_package: string;
44
+ updated_dependency: string;
45
+ new_version: string;
46
+ type: string;
47
+ causes_republish: boolean;
48
+ }>;
49
+ breaking_cascades: Record<string, Array<string>>;
50
+ warnings: Array<string>;
51
+ errors: Array<string>;
52
+ }
53
+ /**
54
+ * Serializes a dependency graph to a JSON-safe format.
55
+ */
56
+ export declare const serialize_graph: (graph: DependencyGraph) => SerializedGraph;
57
+ //# sourceMappingURL=serialization_types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialization_types.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/serialization_types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC7B,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACxC,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAChC,eAAe,EAAE,KAAK,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,cAAc,EAAE,OAAO,CAAC;QACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,kBAAkB,EAAE,KAAK,CAAC;QACzB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,EAAE,OAAO,CAAC;KAC1B,CAAC,CAAC;IACH,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,eAAe,KAAG,eA6BxD,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * JSON-serializable types for command output formats.
3
+ *
4
+ * Gitops commands support `--format json` and `--format markdown` output modes
5
+ * in addition to styled terminal output. These types define the JSON schema for:
6
+ * - Dependency graph structures (`SerializedGraph`)
7
+ * - Publishing plan predictions (`SerializedPublishingPlan`)
8
+ *
9
+ * Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish --dry_run` when
10
+ * `--format json` or `--outfile` is specified.
11
+ */
12
+ /**
13
+ * Serializes a dependency graph to a JSON-safe format.
14
+ */
15
+ export const serialize_graph = (graph) => {
16
+ const nodes = [];
17
+ const edges = [];
18
+ // Serialize nodes
19
+ for (const node of graph.nodes.values()) {
20
+ const dependencies = Array.from(node.dependencies, ([dep_name, spec]) => ({
21
+ name: dep_name,
22
+ type: spec.type,
23
+ version: spec.version,
24
+ }));
25
+ nodes.push({
26
+ name: node.name,
27
+ version: node.version,
28
+ dependencies,
29
+ dependents: Array.from(node.dependents),
30
+ publishable: node.publishable,
31
+ });
32
+ }
33
+ // Serialize edges
34
+ for (const [from, tos] of graph.edges) {
35
+ for (const to of tos) {
36
+ edges.push([from, to]);
37
+ }
38
+ }
39
+ return { nodes, edges };
40
+ };
@@ -0,0 +1,48 @@
1
+ import type { BumpType } from './semver.js';
2
+ export declare const is_wildcard: (version: string) => boolean;
3
+ /**
4
+ * Strips version prefix (^, ~, >=, <=, etc) from a version string.
5
+ */
6
+ export declare const strip_version_prefix: (version: string) => string;
7
+ /**
8
+ * Gets the version prefix (^, ~, >=, <=, or empty string).
9
+ */
10
+ export declare const get_version_prefix: (version: string) => string;
11
+ /**
12
+ * Normalizes version string for comparison.
13
+ *
14
+ * Strips prefixes (^, ~, >=) to get bare version number.
15
+ * Handles wildcards as-is. Used by needs_update to compare versions.
16
+ *
17
+ * @example normalize_version_for_comparison('^1.2.3') // '1.2.3'
18
+ * @example normalize_version_for_comparison('>=2.0.0') // '2.0.0'
19
+ * @example normalize_version_for_comparison('*') // '*'
20
+ */
21
+ export declare const normalize_version_for_comparison: (version: string) => string;
22
+ export declare const needs_update: (current: string, new_version: string) => boolean;
23
+ /**
24
+ * Determines version prefix to use when updating dependencies.
25
+ *
26
+ * Strategy:
27
+ * - Wildcard (*): Use caret (^) as default
28
+ * - Has existing prefix: Preserve it (^, ~, >=, <=, etc)
29
+ * - No prefix: Use default_strategy
30
+ *
31
+ * This preserves user intent while handling wildcard replacements sensibly.
32
+ *
33
+ * @param default_strategy prefix to use when no existing prefix found
34
+ */
35
+ export declare const get_update_prefix: (current_version: string, default_strategy?: "^" | "~" | "" | ">=") => string;
36
+ /**
37
+ * Determines if a bump is a breaking change based on semver rules.
38
+ * Pre-1.0: minor bumps are breaking
39
+ * 1.0+: major bumps are breaking
40
+ */
41
+ export declare const is_breaking_change: (old_version: string, bump_type: "major" | "minor" | "patch") => boolean;
42
+ export declare const detect_bump_type: (old_version: string, new_version: string) => "major" | "minor" | "patch";
43
+ /**
44
+ * Compares bump types. Returns positive if a > b, negative if a < b, 0 if equal.
45
+ */
46
+ export declare const compare_bump_types: (a: BumpType, b: BumpType) => number;
47
+ export declare const calculate_next_version: (current_version: string, bump_type: BumpType) => string;
48
+ //# sourceMappingURL=version_utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version_utils.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/version_utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,KAAG,OAE7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,MAEtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,MAGpD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,gCAAgC,GAAI,SAAS,MAAM,KAAG,MAWlE,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,EAAE,aAAa,MAAM,KAAG,OASnE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC7B,iBAAiB,MAAM,EACvB,mBAAkB,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAU,KAC3C,MAcF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC9B,aAAa,MAAM,EACnB,WAAW,OAAO,GAAG,OAAO,GAAG,OAAO,KACpC,OAWF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC5B,aAAa,MAAM,EACnB,aAAa,MAAM,KACjB,OAAO,GAAG,OAAO,GAAG,OAOtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,GAAG,QAAQ,EAAE,GAAG,QAAQ,KAAG,MAO7D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,iBAAiB,MAAM,EAAE,WAAW,QAAQ,KAAG,MAkBrF,CAAC"}
@@ -0,0 +1,125 @@
1
+ export const is_wildcard = (version) => {
2
+ return version === '*';
3
+ };
4
+ /**
5
+ * Strips version prefix (^, ~, >=, <=, etc) from a version string.
6
+ */
7
+ export const strip_version_prefix = (version) => {
8
+ return version.replace(/^(>=|<=|>|<|=|\^|~)/, '');
9
+ };
10
+ /**
11
+ * Gets the version prefix (^, ~, >=, <=, or empty string).
12
+ */
13
+ export const get_version_prefix = (version) => {
14
+ const match = /^(>=|<=|>|<|=|\^|~)/.exec(version);
15
+ return match ? match[1] : '';
16
+ };
17
+ /**
18
+ * Normalizes version string for comparison.
19
+ *
20
+ * Strips prefixes (^, ~, >=) to get bare version number.
21
+ * Handles wildcards as-is. Used by needs_update to compare versions.
22
+ *
23
+ * @example normalize_version_for_comparison('^1.2.3') // '1.2.3'
24
+ * @example normalize_version_for_comparison('>=2.0.0') // '2.0.0'
25
+ * @example normalize_version_for_comparison('*') // '*'
26
+ */
27
+ export const normalize_version_for_comparison = (version) => {
28
+ // Handle wildcards
29
+ if (is_wildcard(version))
30
+ return version;
31
+ // Handle >= ranges - extract just the version number
32
+ if (version.startsWith('>=')) {
33
+ return version.substring(2).trim();
34
+ }
35
+ // Strip other prefixes
36
+ return strip_version_prefix(version);
37
+ };
38
+ export const needs_update = (current, new_version) => {
39
+ // Always update wildcards
40
+ if (is_wildcard(current))
41
+ return true;
42
+ // Compare normalized versions
43
+ const current_normalized = normalize_version_for_comparison(current);
44
+ const new_normalized = normalize_version_for_comparison(new_version);
45
+ return current_normalized !== new_normalized;
46
+ };
47
+ /**
48
+ * Determines version prefix to use when updating dependencies.
49
+ *
50
+ * Strategy:
51
+ * - Wildcard (*): Use caret (^) as default
52
+ * - Has existing prefix: Preserve it (^, ~, >=, <=, etc)
53
+ * - No prefix: Use default_strategy
54
+ *
55
+ * This preserves user intent while handling wildcard replacements sensibly.
56
+ *
57
+ * @param default_strategy prefix to use when no existing prefix found
58
+ */
59
+ export const get_update_prefix = (current_version, default_strategy = '^') => {
60
+ // Use caret for wildcard replacements
61
+ if (is_wildcard(current_version)) {
62
+ return '^';
63
+ }
64
+ // Preserve existing prefix if present
65
+ const existing_prefix = get_version_prefix(current_version);
66
+ if (existing_prefix) {
67
+ return existing_prefix;
68
+ }
69
+ // Use default strategy
70
+ return default_strategy;
71
+ };
72
+ /**
73
+ * Determines if a bump is a breaking change based on semver rules.
74
+ * Pre-1.0: minor bumps are breaking
75
+ * 1.0+: major bumps are breaking
76
+ */
77
+ export const is_breaking_change = (old_version, bump_type) => {
78
+ const [major] = old_version.split('.').map(Number);
79
+ const is_pre_1_0 = major === 0;
80
+ if (is_pre_1_0) {
81
+ // In 0.x.x, minor bumps are breaking changes
82
+ return bump_type === 'minor' || bump_type === 'major';
83
+ }
84
+ else {
85
+ // In 1.x.x+, only major bumps are breaking
86
+ return bump_type === 'major';
87
+ }
88
+ };
89
+ export const detect_bump_type = (old_version, new_version) => {
90
+ const old_parts = old_version.split('.').map(Number);
91
+ const new_parts = new_version.split('.').map(Number);
92
+ if (new_parts[0] > old_parts[0])
93
+ return 'major';
94
+ if (new_parts[1] > old_parts[1])
95
+ return 'minor';
96
+ return 'patch';
97
+ };
98
+ /**
99
+ * Compares bump types. Returns positive if a > b, negative if a < b, 0 if equal.
100
+ */
101
+ export const compare_bump_types = (a, b) => {
102
+ const order = {
103
+ major: 3,
104
+ minor: 2,
105
+ patch: 1,
106
+ };
107
+ return order[a] - order[b];
108
+ };
109
+ export const calculate_next_version = (current_version, bump_type) => {
110
+ const parts = current_version.split('.').map(Number);
111
+ if (parts.length !== 3 || parts.some((p) => Number.isNaN(p))) {
112
+ throw new Error(`Invalid version format: ${current_version}`);
113
+ }
114
+ const [major, minor, patch] = parts;
115
+ switch (bump_type) {
116
+ case 'major':
117
+ return `${major + 1}.0.0`;
118
+ case 'minor':
119
+ return `${major}.${minor + 1}.0`;
120
+ case 'patch':
121
+ return `${major}.${minor}.${patch + 1}`;
122
+ default:
123
+ throw new Error(`Invalid bump type: ${bump_type}`);
124
+ }
125
+ };