@aspruyt/xfg 5.1.3 → 5.1.5

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 (81) hide show
  1. package/README.md +1 -0
  2. package/dist/cli/lifecycle-report-builder.d.ts +2 -0
  3. package/dist/cli/lifecycle-report-builder.js +15 -0
  4. package/dist/cli/program.js +16 -11
  5. package/dist/cli/settings-report-builder.d.ts +1 -1
  6. package/dist/cli/settings-report-builder.js +20 -32
  7. package/dist/cli/sync-command.js +59 -64
  8. package/dist/cli/types.d.ts +3 -6
  9. package/dist/config/formatter.js +1 -6
  10. package/dist/config/index.d.ts +2 -1
  11. package/dist/config/index.js +2 -0
  12. package/dist/config/merge.d.ts +0 -6
  13. package/dist/config/merge.js +0 -13
  14. package/dist/config/types.d.ts +0 -9
  15. package/dist/config/validator.d.ts +1 -1
  16. package/dist/config/validator.js +1 -1
  17. package/dist/lifecycle/github-lifecycle-provider.js +28 -45
  18. package/dist/lifecycle/lifecycle-helpers.d.ts +1 -1
  19. package/dist/lifecycle/repo-lifecycle-manager.d.ts +1 -1
  20. package/dist/lifecycle/types.d.ts +4 -4
  21. package/dist/output/github-summary.d.ts +0 -50
  22. package/dist/output/github-summary.js +0 -201
  23. package/dist/output/lifecycle-report.d.ts +0 -1
  24. package/dist/output/lifecycle-report.js +0 -15
  25. package/dist/output/settings-report.d.ts +1 -1
  26. package/dist/output/settings-report.js +20 -78
  27. package/dist/output/sync-report.d.ts +1 -0
  28. package/dist/output/sync-report.js +19 -1
  29. package/dist/output/unified-summary.d.ts +1 -2
  30. package/dist/output/unified-summary.js +1 -19
  31. package/dist/settings/base-processor.d.ts +8 -0
  32. package/dist/settings/base-processor.js +7 -0
  33. package/dist/settings/index.d.ts +2 -2
  34. package/dist/settings/index.js +3 -1
  35. package/dist/settings/labels/converter.d.ts +1 -1
  36. package/dist/settings/labels/diff.d.ts +1 -1
  37. package/dist/settings/labels/formatter.d.ts +1 -1
  38. package/dist/settings/repo-settings/processor.js +9 -5
  39. package/dist/settings/rulesets/formatter.js +97 -85
  40. package/dist/settings/rulesets/github-ruleset-strategy.d.ts +2 -2
  41. package/dist/settings/rulesets/github-ruleset-strategy.js +7 -4
  42. package/dist/settings/rulesets/index.d.ts +1 -1
  43. package/dist/settings/rulesets/index.js +0 -2
  44. package/dist/settings/rulesets/processor.js +5 -1
  45. package/dist/settings/rulesets/types.d.ts +6 -1
  46. package/dist/shared/gh-api-utils.d.ts +1 -1
  47. package/dist/shared/logger.d.ts +8 -8
  48. package/dist/shared/logger.js +9 -8
  49. package/dist/shared/repo-detector.js +0 -1
  50. package/dist/sync/branch-manager.js +2 -2
  51. package/dist/sync/commit-push-manager.js +2 -2
  52. package/dist/sync/diff-utils.d.ts +0 -9
  53. package/dist/sync/diff-utils.js +0 -9
  54. package/dist/sync/file-sync-orchestrator.js +1 -1
  55. package/dist/sync/file-sync-strategy.d.ts +1 -1
  56. package/dist/sync/file-writer.d.ts +1 -1
  57. package/dist/sync/file-writer.js +3 -1
  58. package/dist/sync/index.d.ts +1 -2
  59. package/dist/sync/index.js +1 -1
  60. package/dist/sync/manifest-manager.d.ts +1 -1
  61. package/dist/sync/manifest-manager.js +1 -1
  62. package/dist/sync/manifest.js +9 -1
  63. package/dist/sync/pr-merge-handler.js +2 -2
  64. package/dist/sync/sync-workflow.d.ts +1 -1
  65. package/dist/sync/types.d.ts +2 -2
  66. package/dist/vcs/authenticated-git-ops.d.ts +2 -1
  67. package/dist/vcs/commit-strategy-selector.d.ts +1 -1
  68. package/dist/vcs/commit-strategy-selector.js +1 -1
  69. package/dist/vcs/git-ops.d.ts +0 -1
  70. package/dist/vcs/git-ops.js +15 -8
  71. package/dist/vcs/github-pr-strategy.d.ts +0 -3
  72. package/dist/vcs/github-pr-strategy.js +4 -7
  73. package/dist/vcs/index.d.ts +3 -3
  74. package/dist/vcs/index.js +2 -2
  75. package/dist/vcs/pr-creator.js +9 -9
  76. package/dist/vcs/pr-strategy-factory.d.ts +1 -1
  77. package/dist/vcs/pr-strategy-factory.js +1 -1
  78. package/dist/vcs/pr-strategy.js +6 -11
  79. package/package.json +1 -1
  80. package/dist/output/summary-utils.d.ts +0 -20
  81. package/dist/output/summary-utils.js +0 -79
@@ -1,4 +1,4 @@
1
- import type { FileContent } from "../config/types.js";
1
+ import { type FileContent } from "../config/index.js";
2
2
  import type { IFileWriter, FileWriteContext, FileWriterDeps, FileWriteAllResult } from "./types.js";
3
3
  /**
4
4
  * Determines if a file should be marked as executable.
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { convertContentToString } from "../config/formatter.js";
3
+ import { convertContentToString, } from "../config/index.js";
4
4
  import { interpolateXfgContent } from "../shared/xfg-template.js";
5
5
  import { getFileStatus, generateDiff, createDiffStats, incrementDiffStats, computeUnifiedDiff, isBinaryFile, } from "./diff-utils.js";
6
6
  /**
@@ -87,6 +87,8 @@ export class FileWriter {
87
87
  gitOps.writeFile(file.fileName, fileContent);
88
88
  }
89
89
  }
90
+ // Separate pass for executable permissions: git add must happen after file
91
+ // content is written, and setExecutable needs the file to already be tracked.
90
92
  for (const file of files) {
91
93
  const tracked = fileChanges.get(file.fileName);
92
94
  if (tracked?.action === "skip") {
@@ -1,4 +1,3 @@
1
- export type { DiffStats } from "./diff-utils.js";
2
- export { computeUnifiedDiff, isBinaryFile, formatDiffLine, } from "./diff-utils.js";
1
+ export { formatDiffLine } from "./diff-utils.js";
3
2
  export type { FileChangeDetail, GitOpsFactory, IAuthOptionsBuilder, IBranchManager, ICommitPushManager, IFileSyncOrchestrator, IPRMergeHandler, IRepositoryProcessor, IRepositorySession, IWorkStrategy, ProcessorResult, SessionContext, WorkResult, } from "./types.js";
4
3
  export { RepositoryProcessor } from "./repository-processor.js";
@@ -1,2 +1,2 @@
1
- export { computeUnifiedDiff, isBinaryFile, formatDiffLine, } from "./diff-utils.js";
1
+ export { formatDiffLine } from "./diff-utils.js";
2
2
  export { RepositoryProcessor } from "./repository-processor.js";
@@ -9,7 +9,7 @@ export declare class ManifestManager implements IManifestManager {
9
9
  debug(msg: string): void;
10
10
  warn(msg: string): void;
11
11
  } | undefined);
12
- processOrphans(workDir: string, configId: string, filesWithDeleteOrphaned: Map<string, boolean | undefined>): OrphanProcessResult;
12
+ detectOrphans(workDir: string, configId: string, filesWithDeleteOrphaned: Map<string, boolean | undefined>): OrphanProcessResult;
13
13
  deleteOrphans(filesToDelete: string[], options: OrphanDeleteOptions, deps: OrphanDeleteDeps): void;
14
14
  saveUpdatedManifest(workDir: string, manifest: XfgManifest, existingManifest: XfgManifest | null, dryRun: boolean, fileChanges: Map<string, FileWriteResult>): void;
15
15
  }
@@ -10,7 +10,7 @@ export class ManifestManager {
10
10
  constructor(log) {
11
11
  this.log = log;
12
12
  }
13
- processOrphans(workDir, configId, filesWithDeleteOrphaned) {
13
+ detectOrphans(workDir, configId, filesWithDeleteOrphaned) {
14
14
  const existingManifest = loadManifest(workDir, this.log);
15
15
  const { manifest, filesToDelete } = updateManifest(existingManifest, configId, filesWithDeleteOrphaned);
16
16
  return { manifest, existingManifest, filesToDelete };
@@ -110,7 +110,15 @@ export function loadManifest(workDir, log) {
110
110
  export function parseManifestContent(content, log) {
111
111
  try {
112
112
  const parsed = JSON.parse(content);
113
- return migrateToV4(parsed);
113
+ const migrated = migrateToV4(parsed);
114
+ if (migrated)
115
+ return migrated;
116
+ if (isV1Manifest(parsed)) {
117
+ log?.debug("V1 manifest detected — treating as empty (no config-ID namespace)");
118
+ return null;
119
+ }
120
+ log?.warn("Unrecognized manifest format in content, ignoring");
121
+ return null;
114
122
  }
115
123
  catch (error) {
116
124
  log?.warn(`Failed to parse manifest content: ${toErrorMessage(error)}`);
@@ -1,4 +1,4 @@
1
- import { createPR, mergePR, getPRStrategy, } from "../vcs/index.js";
1
+ import { createPR, mergePR, createPRStrategy, } from "../vcs/index.js";
2
2
  export class PRMergeHandler {
3
3
  log;
4
4
  constructor(log) {
@@ -9,7 +9,7 @@ export class PRMergeHandler {
9
9
  this.log.info("Creating pull request...");
10
10
  const strategy = options.dryRun
11
11
  ? undefined
12
- : getPRStrategy(repoInfo, options.executor, this.log);
12
+ : createPRStrategy(repoInfo, options.executor, this.log);
13
13
  const prResult = await createPR({
14
14
  repoInfo,
15
15
  branchName: options.branchName,
@@ -1,4 +1,4 @@
1
- import type { RepoConfig } from "../config/types.js";
1
+ import type { RepoConfig } from "../config/index.js";
2
2
  import { RepoInfo } from "../shared/repo-detector.js";
3
3
  import type { DebugInfoLog } from "../shared/logger.js";
4
4
  import type { ISyncWorkflow, IWorkStrategy, IAuthOptionsBuilder, IRepositorySession, IBranchManager, ICommitPushManager, IPRMergeHandler, ProcessorOptions, ProcessorResult } from "./types.js";
@@ -1,4 +1,4 @@
1
- import type { FileContent, RepoConfig } from "../config/types.js";
1
+ import type { FileContent, RepoConfig } from "../config/index.js";
2
2
  import type { RepoInfo } from "../shared/repo-detector.js";
3
3
  import type { ILocalGitOps, IGitOps, GitAuthOptions, GitOpsOptions, FileAction } from "../vcs/index.js";
4
4
  import type { DiffStats } from "./diff-utils.js";
@@ -48,7 +48,7 @@ export interface OrphanDeleteDeps {
48
48
  fileChanges: Map<string, FileWriteResult>;
49
49
  }
50
50
  export interface IManifestManager {
51
- processOrphans(workDir: string, configId: string, filesWithDeleteOrphaned: Map<string, boolean | undefined>): OrphanProcessResult;
51
+ detectOrphans(workDir: string, configId: string, filesWithDeleteOrphaned: Map<string, boolean | undefined>): OrphanProcessResult;
52
52
  deleteOrphans(filesToDelete: string[], options: OrphanDeleteOptions, deps: OrphanDeleteDeps): void;
53
53
  saveUpdatedManifest(workDir: string, manifest: XfgManifest, existingManifest: XfgManifest | null, dryRun: boolean, fileChanges: Map<string, FileWriteResult>): void;
54
54
  }
@@ -8,7 +8,7 @@ import type { GitAuthOptions, ILocalGitOps, IGitOps } from "./types.js";
8
8
  * the remote origin. Subsequent operations (fetch, push, getDefaultBranch)
9
9
  * reuse that authenticated remote URL — no extra auth setup per operation.
10
10
  */
11
- export interface AuthenticatedGitOpsOptions {
11
+ interface AuthenticatedGitOpsOptions {
12
12
  localOps: ILocalGitOps;
13
13
  executor: ICommandExecutor;
14
14
  workDir: string;
@@ -81,3 +81,4 @@ export declare class AuthenticatedGitOps implements IGitOps {
81
81
  */
82
82
  fetchBranch(branchName: string): Promise<void>;
83
83
  }
84
+ export {};
@@ -14,5 +14,5 @@ export declare function createTokenManager(credentials?: GitHubAppCredentials):
14
14
  * Returns GraphQLCommitStrategy for GitHub repos with App credentials (verified commits),
15
15
  * or GitCommitStrategy for all other cases.
16
16
  */
17
- export declare function getCommitStrategy(repoInfo: RepoInfo, executor: ICommandExecutor, hasAppCredentials?: boolean): ICommitStrategy;
17
+ export declare function createCommitStrategy(repoInfo: RepoInfo, executor: ICommandExecutor, hasAppCredentials?: boolean): ICommitStrategy;
18
18
  export {};
@@ -15,7 +15,7 @@ export function createTokenManager(credentials) {
15
15
  * Returns GraphQLCommitStrategy for GitHub repos with App credentials (verified commits),
16
16
  * or GitCommitStrategy for all other cases.
17
17
  */
18
- export function getCommitStrategy(repoInfo, executor, hasAppCredentials) {
18
+ export function createCommitStrategy(repoInfo, executor, hasAppCredentials) {
19
19
  if (isGitHubRepo(repoInfo) && hasAppCredentials) {
20
20
  return new GraphQLCommitStrategy(executor);
21
21
  }
@@ -50,7 +50,6 @@ export declare class GitOps implements ILocalGitOps {
50
50
  /**
51
51
  * Get list of files that have changes according to git status.
52
52
  * Returns relative file paths for files that are modified, added, or untracked.
53
- * Uses the same this.exec() pattern as other methods in this class.
54
53
  */
55
54
  getChangedFiles(): Promise<string[]>;
56
55
  stageAll(): Promise<void>;
@@ -109,8 +109,7 @@ export class GitOps {
109
109
  if (code === "ENOENT" || code === "EACCES") {
110
110
  return null;
111
111
  }
112
- this.log?.debug(`Unexpected error reading ${fileName}: ${toErrorMessage(error)}`);
113
- return null;
112
+ throw error;
114
113
  }
115
114
  }
116
115
  /**
@@ -130,8 +129,12 @@ export class GitOps {
130
129
  return existingContent !== newContent;
131
130
  }
132
131
  catch (error) {
133
- this.log?.debug(`Failed to read ${fileName} for comparison: ${toErrorMessage(error)}`);
134
- return true;
132
+ const code = error.code;
133
+ if (code === "ENOENT" || code === "EACCES") {
134
+ this.log?.debug(`Failed to read ${fileName} for comparison: ${toErrorMessage(error)}`);
135
+ return true;
136
+ }
137
+ throw error;
135
138
  }
136
139
  }
137
140
  async hasChanges() {
@@ -141,7 +144,6 @@ export class GitOps {
141
144
  /**
142
145
  * Get list of files that have changes according to git status.
143
146
  * Returns relative file paths for files that are modified, added, or untracked.
144
- * Uses the same this.exec() pattern as other methods in this class.
145
147
  */
146
148
  async getChangedFiles() {
147
149
  const status = await this.exec("git status --porcelain", this._workDir);
@@ -169,9 +171,14 @@ export class GitOps {
169
171
  return true;
170
172
  }
171
173
  catch (error) {
172
- // Expected when file doesn't exist on branch
173
- this.log?.debug(`fileExistsOnBranch(${fileName}, ${branch}): ${toErrorMessage(error)}`);
174
- return false;
174
+ const message = toErrorMessage(error);
175
+ if (message.includes("does not exist") ||
176
+ message.includes("did not match") ||
177
+ message.includes("not found")) {
178
+ this.log?.debug(`fileExistsOnBranch(${fileName}, ${branch}): ${message}`);
179
+ return false;
180
+ }
181
+ throw error;
175
182
  }
176
183
  }
177
184
  fileExists(fileName) {
@@ -9,9 +9,6 @@ export declare class GitHubPRStrategy extends BasePRStrategy {
9
9
  * Check if auto-merge is enabled on the repository.
10
10
  */
11
11
  private checkAutoMergeEnabled;
12
- /**
13
- * Build merge strategy flag for gh pr merge command.
14
- */
15
12
  private getMergeStrategyFlag;
16
13
  merge(options: MergeOptions): Promise<MergeResult>;
17
14
  }
@@ -20,9 +20,6 @@ function getRepoFlag(repoInfo) {
20
20
  }
21
21
  return `${repoInfo.owner}/${repoInfo.repo}`;
22
22
  }
23
- /**
24
- * Build regex to match PR URLs for the given host.
25
- */
26
23
  function buildPRUrlRegex(host) {
27
24
  const escapedHost = escapeRegExp(host);
28
25
  return new RegExp(`https://${escapedHost}/[\\w-]+/[\\w.-]+/pull/\\d+`);
@@ -136,14 +133,14 @@ export class GitHubPRStrategy extends BasePRStrategy {
136
133
  return result.trim() === "true";
137
134
  }
138
135
  catch (error) {
139
- // If we can't check, assume auto-merge is not enabled
136
+ if (isPermanentError(error)) {
137
+ throw error;
138
+ }
139
+ // If we can't check due to transient errors, assume auto-merge is not enabled
140
140
  this.log?.warn(`Could not check auto-merge status: ${toErrorMessage(error)}`);
141
141
  return false;
142
142
  }
143
143
  }
144
- /**
145
- * Build merge strategy flag for gh pr merge command.
146
- */
147
144
  getMergeStrategyFlag(strategy) {
148
145
  switch (strategy) {
149
146
  case "squash":
@@ -1,5 +1,5 @@
1
- export type { PRMergeConfig, FileChange, FileAction, IGitOps, ILocalGitOps, INetworkGitOps, IPRStrategy, GitAuthOptions, PRResult, PRStrategyOptions, MergeOptions, MergeResult, CloseExistingPROptions, CommitOptions, CommitResult, ICommitStrategy, } from "./types.js";
1
+ export type { PRMergeConfig, FileChange, FileAction, IGitOps, ILocalGitOps, IPRStrategy, GitAuthOptions, PRResult, ICommitStrategy, } from "./types.js";
2
2
  export type { GitOpsOptions } from "./git-ops.js";
3
- export { getCommitStrategy, createTokenManager, } from "./commit-strategy-selector.js";
4
- export { getPRStrategy } from "./pr-strategy-factory.js";
3
+ export { createCommitStrategy, createTokenManager, } from "./commit-strategy-selector.js";
4
+ export { createPRStrategy } from "./pr-strategy-factory.js";
5
5
  export { createPR, mergePR } from "./pr-creator.js";
package/dist/vcs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Commit strategies
2
- export { getCommitStrategy, createTokenManager, } from "./commit-strategy-selector.js";
2
+ export { createCommitStrategy, createTokenManager, } from "./commit-strategy-selector.js";
3
3
  // PR strategy factory
4
- export { getPRStrategy } from "./pr-strategy-factory.js";
4
+ export { createPRStrategy } from "./pr-strategy-factory.js";
5
5
  // PR creation and merge
6
6
  export { createPR, mergePR } from "./pr-creator.js";
@@ -1,7 +1,7 @@
1
1
  import { readFileSync, existsSync } from "node:fs";
2
2
  import { join, dirname } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { getPRStrategy } from "./pr-strategy-factory.js";
4
+ import { createPRStrategy } from "./pr-strategy-factory.js";
5
5
  import { PRWorkflowExecutor } from "./pr-strategy.js";
6
6
  import { interpolateXfgContent } from "../shared/xfg-template.js";
7
7
  function loadDefaultTemplate() {
@@ -95,18 +95,18 @@ export function formatPRTitle(files) {
95
95
  }
96
96
  return `chore: sync ${changedFiles.length} config files`;
97
97
  }
98
- export async function createPR(options) {
98
+ export function createPR(options) {
99
99
  const { repoInfo, branchName, baseBranch, files, workDir, dryRun, retries, prTemplate, executor, token, labels, log, } = options;
100
100
  const title = formatPRTitle(files);
101
101
  const body = formatPRBody(files, repoInfo, prTemplate);
102
102
  if (dryRun) {
103
- return {
103
+ return Promise.resolve({
104
104
  success: true,
105
105
  message: `[DRY RUN] Would create PR: "${title}"`,
106
- };
106
+ });
107
107
  }
108
108
  // Get the appropriate strategy and execute via workflow executor
109
- const resolvedStrategy = options.strategy ?? getPRStrategy(repoInfo, executor, log);
109
+ const resolvedStrategy = options.strategy ?? createPRStrategy(repoInfo, executor, log);
110
110
  const workflow = new PRWorkflowExecutor(resolvedStrategy);
111
111
  return workflow.execute({
112
112
  repoInfo,
@@ -120,7 +120,7 @@ export async function createPR(options) {
120
120
  labels,
121
121
  });
122
122
  }
123
- export async function mergePR(options) {
123
+ export function mergePR(options) {
124
124
  const { repoInfo, prUrl, mergeConfig, workDir, dryRun, retries, executor, token, log, } = options;
125
125
  if (dryRun) {
126
126
  const modeText = mergeConfig.mode === "force"
@@ -128,14 +128,14 @@ export async function mergePR(options) {
128
128
  : mergeConfig.mode === "auto"
129
129
  ? "enable auto-merge"
130
130
  : "leave open for manual review";
131
- return {
131
+ return Promise.resolve({
132
132
  success: true,
133
133
  message: `[DRY RUN] Would ${modeText}`,
134
134
  merged: false,
135
- };
135
+ });
136
136
  }
137
137
  // Get the appropriate strategy and execute merge
138
- const resolvedStrategy = options.strategy ?? getPRStrategy(repoInfo, executor, log);
138
+ const resolvedStrategy = options.strategy ?? createPRStrategy(repoInfo, executor, log);
139
139
  return resolvedStrategy.merge({
140
140
  prUrl,
141
141
  repoInfo,
@@ -2,4 +2,4 @@ import { RepoInfo } from "../shared/repo-detector.js";
2
2
  import type { IPRStrategy } from "./types.js";
3
3
  import { ICommandExecutor } from "../shared/command-executor.js";
4
4
  import type { IPRStrategyLogger } from "./pr-strategy.js";
5
- export declare function getPRStrategy(repoInfo: RepoInfo, executor: ICommandExecutor, log?: IPRStrategyLogger): IPRStrategy;
5
+ export declare function createPRStrategy(repoInfo: RepoInfo, executor: ICommandExecutor, log?: IPRStrategyLogger): IPRStrategy;
@@ -3,7 +3,7 @@ import { SyncError } from "../shared/errors.js";
3
3
  import { GitHubPRStrategy } from "./github-pr-strategy.js";
4
4
  import { AzurePRStrategy } from "./azure-pr-strategy.js";
5
5
  import { GitLabPRStrategy } from "./gitlab-pr-strategy.js";
6
- export function getPRStrategy(repoInfo, executor, log) {
6
+ export function createPRStrategy(repoInfo, executor, log) {
7
7
  if (isGitHubRepo(repoInfo)) {
8
8
  return new GitHubPRStrategy(executor, log);
9
9
  }
@@ -13,17 +13,12 @@ export class BasePRStrategy {
13
13
  * Shared by all platform strategies to eliminate duplicated try/catch patterns.
14
14
  */
15
15
  async executeMergeCommand(execFn, retries, successResult, errorPrefix) {
16
- try {
17
- await withRetry(execFn, { retries, log: this.log });
18
- return successResult;
19
- }
20
- catch (error) {
21
- return {
22
- success: false,
23
- message: `${errorPrefix}: ${toErrorMessage(error)}`,
24
- merged: false,
25
- };
26
- }
16
+ const result = await withRetry(execFn, { retries, log: this.log }).then(() => successResult, (error) => {
17
+ const message = `${errorPrefix}: ${toErrorMessage(error)}`;
18
+ this.log?.warn(message);
19
+ return { success: false, message, merged: false };
20
+ });
21
+ return result;
27
22
  }
28
23
  }
29
24
  export class PRWorkflowExecutor {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspruyt/xfg",
3
- "version": "5.1.3",
3
+ "version": "5.1.5",
4
4
  "description": "Manage files, settings, and repositories across GitHub, Azure DevOps, and GitLab — declaratively, from a single YAML config",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,20 +0,0 @@
1
- import type { ProcessorResult } from "../sync/index.js";
2
- import { RepoConfig } from "../config/index.js";
3
- import { MergeOutcome, FileChanges, RepoResult } from "./github-summary.js";
4
- import type { DiffStats } from "../sync/index.js";
5
- /**
6
- * Determine merge outcome from repo config and processor result
7
- */
8
- export declare function getMergeOutcome(repoConfig: RepoConfig, result: ProcessorResult): MergeOutcome | undefined;
9
- /**
10
- * Convert DiffStats to FileChanges for summary output
11
- */
12
- export declare function toFileChanges(diffStats?: DiffStats): FileChanges | undefined;
13
- /**
14
- * Build a RepoResult from a ProcessorResult for the summary
15
- */
16
- export declare function buildRepoResult(repoName: string, repoConfig: RepoConfig, result: ProcessorResult): RepoResult;
17
- /**
18
- * Build a RepoResult for an error case
19
- */
20
- export declare function buildErrorResult(repoName: string, error: unknown): RepoResult;
@@ -1,79 +0,0 @@
1
- import { toErrorMessage } from "../shared/type-guards.js";
2
- /**
3
- * Determine merge outcome from repo config and processor result
4
- */
5
- export function getMergeOutcome(repoConfig, result) {
6
- if (!result.success || result.skipped)
7
- return undefined;
8
- const mergeMode = repoConfig.prOptions?.merge ?? "auto";
9
- if (mergeMode === "direct")
10
- return "direct";
11
- if (result.mergeResult?.merged)
12
- return "force";
13
- if (result.mergeResult?.autoMergeEnabled)
14
- return "auto";
15
- if (result.prUrl)
16
- return "manual";
17
- return undefined;
18
- }
19
- /**
20
- * Convert DiffStats to FileChanges for summary output
21
- */
22
- export function toFileChanges(diffStats) {
23
- if (!diffStats)
24
- return undefined;
25
- return {
26
- added: diffStats.newCount,
27
- modified: diffStats.modifiedCount,
28
- deleted: diffStats.deletedCount,
29
- unchanged: diffStats.unchangedCount,
30
- };
31
- }
32
- /**
33
- * Build a RepoResult from a ProcessorResult for the summary
34
- */
35
- export function buildRepoResult(repoName, repoConfig, result) {
36
- if (result.skipped) {
37
- return {
38
- repoName,
39
- status: "skipped",
40
- message: result.message,
41
- fileChanges: toFileChanges(result.diffStats),
42
- };
43
- }
44
- if (result.success) {
45
- let message = result.prUrl ? `PR: ${result.prUrl}` : result.message;
46
- if (result.mergeResult) {
47
- if (result.mergeResult.merged) {
48
- message += " (merged)";
49
- }
50
- else if (result.mergeResult.autoMergeEnabled) {
51
- message += " (auto-merge enabled)";
52
- }
53
- }
54
- return {
55
- repoName,
56
- status: "succeeded",
57
- message,
58
- prUrl: result.prUrl,
59
- mergeOutcome: getMergeOutcome(repoConfig, result),
60
- fileChanges: toFileChanges(result.diffStats),
61
- };
62
- }
63
- return {
64
- repoName,
65
- status: "failed",
66
- message: result.message,
67
- };
68
- }
69
- /**
70
- * Build a RepoResult for an error case
71
- */
72
- export function buildErrorResult(repoName, error) {
73
- const message = toErrorMessage(error);
74
- return {
75
- repoName,
76
- status: "failed",
77
- message,
78
- };
79
- }