@jterrats/smart-deployment 1.2.6 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +31 -1
  2. package/lib/analysis/project-analysis-service.d.ts +5 -0
  3. package/lib/analysis/project-analysis-service.js +18 -0
  4. package/lib/analysis/project-analysis-service.js.map +1 -1
  5. package/lib/commands/ci/preset.d.ts +25 -0
  6. package/lib/commands/ci/preset.js +125 -0
  7. package/lib/commands/ci/preset.js.map +1 -0
  8. package/lib/commands/graph/export.d.ts +20 -0
  9. package/lib/commands/graph/export.js +107 -0
  10. package/lib/commands/graph/export.js.map +1 -0
  11. package/lib/commands/impact.d.ts +18 -0
  12. package/lib/commands/impact.js +105 -0
  13. package/lib/commands/impact.js.map +1 -0
  14. package/lib/commands/init.d.ts +19 -0
  15. package/lib/commands/init.js +83 -0
  16. package/lib/commands/init.js.map +1 -0
  17. package/lib/commands/plan/explain.d.ts +14 -0
  18. package/lib/commands/plan/explain.js +134 -0
  19. package/lib/commands/plan/explain.js.map +1 -0
  20. package/lib/commands/resume.d.ts +1 -0
  21. package/lib/commands/resume.js +17 -3
  22. package/lib/commands/resume.js.map +1 -1
  23. package/lib/commands/retrieve.d.ts +20 -0
  24. package/lib/commands/retrieve.js +111 -0
  25. package/lib/commands/retrieve.js.map +1 -0
  26. package/lib/commands/start.d.ts +21 -0
  27. package/lib/commands/start.js +124 -14
  28. package/lib/commands/start.js.map +1 -1
  29. package/lib/commands/status.d.ts +1 -0
  30. package/lib/commands/status.js +15 -3
  31. package/lib/commands/status.js.map +1 -1
  32. package/lib/commands/validate.d.ts +8 -0
  33. package/lib/commands/validate.js +14 -0
  34. package/lib/commands/validate.js.map +1 -1
  35. package/lib/config/init-config-generation-service.d.ts +27 -0
  36. package/lib/config/init-config-generation-service.js +88 -0
  37. package/lib/config/init-config-generation-service.js.map +1 -0
  38. package/lib/config/repo-config.d.ts +25 -0
  39. package/lib/config/repo-config.js.map +1 -1
  40. package/lib/dependencies/impact-analysis-service.d.ts +77 -0
  41. package/lib/dependencies/impact-analysis-service.js +234 -0
  42. package/lib/dependencies/impact-analysis-service.js.map +1 -0
  43. package/lib/deployment/ci-preset-service.d.ts +44 -0
  44. package/lib/deployment/ci-preset-service.js +65 -0
  45. package/lib/deployment/ci-preset-service.js.map +1 -0
  46. package/lib/deployment/commit-scope-service.d.ts +43 -0
  47. package/lib/deployment/commit-scope-service.js +209 -0
  48. package/lib/deployment/commit-scope-service.js.map +1 -0
  49. package/lib/deployment/deployment-context-service.d.ts +3 -0
  50. package/lib/deployment/deployment-context-service.js +1 -0
  51. package/lib/deployment/deployment-context-service.js.map +1 -1
  52. package/lib/deployment/deployment-error-diagnostics.d.ts +11 -0
  53. package/lib/deployment/deployment-error-diagnostics.js +187 -0
  54. package/lib/deployment/deployment-error-diagnostics.js.map +1 -0
  55. package/lib/deployment/deployment-runner.d.ts +1 -0
  56. package/lib/deployment/deployment-runner.js +35 -15
  57. package/lib/deployment/deployment-runner.js.map +1 -1
  58. package/lib/deployment/deployment-status-service.d.ts +9 -2
  59. package/lib/deployment/deployment-status-service.js +56 -3
  60. package/lib/deployment/deployment-status-service.js.map +1 -1
  61. package/lib/deployment/deployment-validation-service.d.ts +3 -0
  62. package/lib/deployment/deployment-validation-service.js +32 -4
  63. package/lib/deployment/deployment-validation-service.js.map +1 -1
  64. package/lib/deployment/plan-explain-service.d.ts +88 -0
  65. package/lib/deployment/plan-explain-service.js +171 -0
  66. package/lib/deployment/plan-explain-service.js.map +1 -0
  67. package/lib/deployment/resume-deployment-service.d.ts +6 -2
  68. package/lib/deployment/resume-deployment-service.js +27 -3
  69. package/lib/deployment/resume-deployment-service.js.map +1 -1
  70. package/lib/deployment/retrieve-forceignore-service.d.ts +51 -0
  71. package/lib/deployment/retrieve-forceignore-service.js +139 -0
  72. package/lib/deployment/retrieve-forceignore-service.js.map +1 -0
  73. package/lib/deployment/rollback-planning-service.d.ts +49 -0
  74. package/lib/deployment/rollback-planning-service.js +178 -0
  75. package/lib/deployment/rollback-planning-service.js.map +1 -0
  76. package/lib/deployment/sf-cli-integration.d.ts +4 -0
  77. package/lib/deployment/sf-cli-integration.js +22 -2
  78. package/lib/deployment/sf-cli-integration.js.map +1 -1
  79. package/lib/deployment/start-execution-service.d.ts +1 -0
  80. package/lib/deployment/start-execution-service.js +14 -8
  81. package/lib/deployment/start-execution-service.js.map +1 -1
  82. package/lib/deployment/wave-manifest-service.d.ts +8 -0
  83. package/lib/deployment/wave-manifest-service.js +39 -20
  84. package/lib/deployment/wave-manifest-service.js.map +1 -1
  85. package/lib/presentation/plan-explain-presenter.d.ts +9 -0
  86. package/lib/presentation/plan-explain-presenter.js +40 -0
  87. package/lib/presentation/plan-explain-presenter.js.map +1 -0
  88. package/lib/presentation/start-command-presenter.d.ts +4 -0
  89. package/lib/presentation/start-command-presenter.js +4 -0
  90. package/lib/presentation/start-command-presenter.js.map +1 -1
  91. package/lib/reports/deployment-plan-report-service.d.ts +76 -0
  92. package/lib/reports/deployment-plan-report-service.js +234 -0
  93. package/lib/reports/deployment-plan-report-service.js.map +1 -0
  94. package/lib/reports/graph-export-service.d.ts +85 -0
  95. package/lib/reports/graph-export-service.js +296 -0
  96. package/lib/reports/graph-export-service.js.map +1 -0
  97. package/lib/services/metadata-scanner-service.js +4 -2
  98. package/lib/services/metadata-scanner-service.js.map +1 -1
  99. package/lib/services/scanners/automation-ai-metadata-scanner.d.ts +1 -0
  100. package/lib/services/scanners/automation-ai-metadata-scanner.js +39 -0
  101. package/lib/services/scanners/automation-ai-metadata-scanner.js.map +1 -1
  102. package/messages/ci.preset.json +22 -0
  103. package/messages/graph.export.json +20 -0
  104. package/messages/impact.json +18 -0
  105. package/messages/init.json +16 -0
  106. package/messages/plan.explain.json +20 -0
  107. package/messages/resume.json +1 -0
  108. package/messages/retrieve.json +26 -0
  109. package/messages/start.json +16 -2
  110. package/messages/status.json +1 -0
  111. package/messages/validate.json +3 -1
  112. package/npm-shrinkwrap.json +45 -70
  113. package/oclif.lock +44 -41
  114. package/oclif.manifest.json +801 -25
  115. package/package.json +9 -8
@@ -0,0 +1,88 @@
1
+ import type { DependencyEdge, NodeId } from '../types/dependency.js';
2
+ import type { MetadataComponent } from '../types/metadata.js';
3
+ import { DeploymentContextService, type DeploymentContextBuildOptions } from './deployment-context-service.js';
4
+ import { SpecialDeploymentPlanService } from './special-deployment-plan.js';
5
+ export type PlanExplainOptions = DeploymentContextBuildOptions & {
6
+ targetOrg?: string;
7
+ since?: string;
8
+ autoActivate?: boolean;
9
+ };
10
+ export type PlanExplainDependency = {
11
+ from: NodeId;
12
+ to: NodeId;
13
+ type: DependencyEdge['type'];
14
+ source: NonNullable<DependencyEdge['source']> | 'unknown';
15
+ reason: string;
16
+ confidence: number;
17
+ resolved: boolean;
18
+ fromWave?: number;
19
+ toWave?: number;
20
+ };
21
+ export type PlanExplainComponent = {
22
+ nodeId: NodeId;
23
+ type: MetadataComponent['type'];
24
+ name: string;
25
+ filePath: string;
26
+ wave: number;
27
+ placement: {
28
+ rationale: string;
29
+ confidence: number;
30
+ directDependencies: NodeId[];
31
+ transitiveBlockers: NodeId[];
32
+ unresolvedReferences: NodeId[];
33
+ };
34
+ };
35
+ export type PlanExplainProviderDecision = {
36
+ kind: string;
37
+ label: string;
38
+ decision: 'included' | 'skipped' | 'blocked';
39
+ components: string[];
40
+ excludedTypes: string[];
41
+ commands: Array<{
42
+ tool: string;
43
+ args: string[];
44
+ reason: string;
45
+ }>;
46
+ reason: string;
47
+ warnings: string[];
48
+ errors: string[];
49
+ };
50
+ export type PlanExplainResult = {
51
+ success: boolean;
52
+ projectRoot: string;
53
+ apiVersion: string;
54
+ components: PlanExplainComponent[];
55
+ dependencies: PlanExplainDependency[];
56
+ unresolvedReferences: PlanExplainDependency[];
57
+ providerDecisions: PlanExplainProviderDecision[];
58
+ summary: {
59
+ componentCount: number;
60
+ dependencyCount: number;
61
+ unresolvedReferenceCount: number;
62
+ providerDecisionCount: number;
63
+ waves: number;
64
+ };
65
+ ai?: {
66
+ enabled: boolean;
67
+ provider?: string;
68
+ model?: string;
69
+ fallback?: boolean;
70
+ inferredDependencies?: number;
71
+ inferenceFallback?: boolean;
72
+ };
73
+ architecturalConcerns: {
74
+ inherited: string[];
75
+ selfImposed: string[];
76
+ };
77
+ };
78
+ type PlanExplainServiceDependencies = {
79
+ deploymentContextService?: Pick<DeploymentContextService, 'buildContext'>;
80
+ specialDeploymentPlanService?: Pick<SpecialDeploymentPlanService, 'buildPlan'>;
81
+ };
82
+ export declare class PlanExplainService {
83
+ private readonly deploymentContextService;
84
+ private readonly specialDeploymentPlanService;
85
+ constructor(dependencies?: PlanExplainServiceDependencies);
86
+ explain(options?: PlanExplainOptions): Promise<PlanExplainResult>;
87
+ }
88
+ export {};
@@ -0,0 +1,171 @@
1
+ import { DeploymentContextService } from './deployment-context-service.js';
2
+ import { SpecialDeploymentPlanService } from './special-deployment-plan.js';
3
+ export class PlanExplainService {
4
+ deploymentContextService;
5
+ specialDeploymentPlanService;
6
+ constructor(dependencies = {}) {
7
+ this.deploymentContextService = dependencies.deploymentContextService ?? new DeploymentContextService();
8
+ this.specialDeploymentPlanService = dependencies.specialDeploymentPlanService ?? new SpecialDeploymentPlanService();
9
+ }
10
+ async explain(options = {}) {
11
+ const context = await this.deploymentContextService.buildContext(options);
12
+ const providerPlan = await this.specialDeploymentPlanService.buildPlan({
13
+ sourcePath: options.sourcePath,
14
+ targetOrg: options.targetOrg,
15
+ since: options.since,
16
+ dryRun: true,
17
+ autoActivate: options.autoActivate ?? false,
18
+ });
19
+ const waveByNodeId = buildWaveIndex(context.orderedWaves);
20
+ const dependencyResult = context.scanResult.dependencyResult;
21
+ const dependencies = dependencyResult.edges.map((edge) => explainDependency(edge, dependencyResult, waveByNodeId));
22
+ const unresolvedReferences = dependencies.filter((dependency) => !dependency.resolved);
23
+ return {
24
+ success: context.scanResult.errors.length === 0 && providerPlan.success,
25
+ projectRoot: context.scanResult.projectRoot,
26
+ apiVersion: context.scanResult.apiVersion,
27
+ components: context.scanResult.components
28
+ .map((component) => explainComponent(component, dependencyResult, waveByNodeId))
29
+ .sort((left, right) => left.nodeId.localeCompare(right.nodeId)),
30
+ dependencies: dependencies.sort(compareDependency),
31
+ unresolvedReferences: unresolvedReferences.sort(compareDependency),
32
+ providerDecisions: explainProviderDecisions(providerPlan),
33
+ summary: {
34
+ componentCount: context.scanResult.components.length,
35
+ dependencyCount: dependencies.length,
36
+ unresolvedReferenceCount: unresolvedReferences.length,
37
+ providerDecisionCount: providerPlan.phases.length,
38
+ waves: context.orderedWaves.length,
39
+ },
40
+ ai: context.aiContext
41
+ ? {
42
+ enabled: context.aiContext.enabled,
43
+ provider: context.aiContext.provider,
44
+ model: context.aiContext.model,
45
+ fallback: context.aiContext.fallback,
46
+ inferredDependencies: context.aiContext.inferredDependencies,
47
+ inferenceFallback: context.aiContext.inferenceFallback,
48
+ }
49
+ : undefined,
50
+ architecturalConcerns: {
51
+ inherited: [],
52
+ selfImposed: [
53
+ 'Introduces a stable JSON explanation contract over existing deployment analysis outputs without changing wave generation.',
54
+ ],
55
+ },
56
+ };
57
+ }
58
+ }
59
+ function explainComponent(component, dependencyResult, waveByNodeId) {
60
+ const nodeId = toNodeId(component);
61
+ const directDependencies = [...(dependencyResult.graph.get(nodeId) ?? [])].sort();
62
+ const unresolvedReferences = directDependencies
63
+ .filter((dependency) => !dependencyResult.components.has(dependency))
64
+ .sort();
65
+ const transitiveBlockers = collectTransitiveBlockers(nodeId, dependencyResult.graph, dependencyResult.components);
66
+ const wave = waveByNodeId.get(nodeId) ?? 0;
67
+ return {
68
+ nodeId,
69
+ type: component.type,
70
+ name: component.name,
71
+ filePath: component.filePath,
72
+ wave,
73
+ placement: {
74
+ rationale: formatPlacementRationale(wave, directDependencies, transitiveBlockers, unresolvedReferences),
75
+ confidence: calculatePlacementConfidence(directDependencies, unresolvedReferences, transitiveBlockers),
76
+ directDependencies,
77
+ transitiveBlockers,
78
+ unresolvedReferences,
79
+ },
80
+ };
81
+ }
82
+ function explainDependency(edge, dependencyResult, waveByNodeId) {
83
+ return {
84
+ from: edge.from,
85
+ to: edge.to,
86
+ type: edge.type,
87
+ source: edge.source ?? 'unknown',
88
+ reason: edge.reason ?? `${edge.from} depends on ${edge.to}`,
89
+ confidence: edge.confidence ?? (edge.type === 'inferred' ? 0.7 : 1),
90
+ resolved: dependencyResult.components.has(edge.to),
91
+ fromWave: waveByNodeId.get(edge.from),
92
+ toWave: waveByNodeId.get(edge.to),
93
+ };
94
+ }
95
+ function explainProviderDecisions(plan) {
96
+ return plan.phases.map((phase) => ({
97
+ kind: phase.kind,
98
+ label: phase.label,
99
+ decision: (phase.errors?.length ?? 0) > 0 ? 'blocked' : phase.skipped ? 'skipped' : 'included',
100
+ components: [...phase.components].sort(),
101
+ excludedTypes: [...(phase.excludedTypes ?? [])].sort(),
102
+ commands: phase.commands.map((command) => ({
103
+ tool: command.tool,
104
+ args: [...command.args],
105
+ reason: command.reason,
106
+ })),
107
+ reason: phase.skipReason ?? phase.commands.map((command) => command.reason).join(' '),
108
+ warnings: [...(phase.warnings ?? [])],
109
+ errors: [...(phase.errors ?? [])],
110
+ }));
111
+ }
112
+ function buildWaveIndex(waves) {
113
+ const waveByNodeId = new Map();
114
+ for (const wave of waves) {
115
+ for (const nodeId of wave.components) {
116
+ waveByNodeId.set(nodeId, wave.number);
117
+ }
118
+ }
119
+ return waveByNodeId;
120
+ }
121
+ function collectTransitiveBlockers(nodeId, graph, components) {
122
+ const direct = graph.get(nodeId) ?? new Set();
123
+ const blockers = new Set();
124
+ const visited = new Set([nodeId]);
125
+ const stack = [...direct];
126
+ while (stack.length > 0) {
127
+ const dependency = stack.pop();
128
+ if (visited.has(dependency)) {
129
+ continue;
130
+ }
131
+ visited.add(dependency);
132
+ if (!direct.has(dependency) && components.has(dependency)) {
133
+ blockers.add(dependency);
134
+ }
135
+ for (const next of graph.get(dependency) ?? []) {
136
+ stack.push(next);
137
+ }
138
+ }
139
+ return [...blockers].sort();
140
+ }
141
+ function formatPlacementRationale(wave, directDependencies, transitiveBlockers, unresolvedReferences) {
142
+ if (wave === 0) {
143
+ return 'Component was not assigned to a deployment wave.';
144
+ }
145
+ if (unresolvedReferences.length > 0) {
146
+ return `Placed in wave ${wave} with unresolved references requiring target-org or pre-existing metadata checks.`;
147
+ }
148
+ if (directDependencies.length === 0) {
149
+ return `Placed in wave ${wave} because it has no deployment dependencies.`;
150
+ }
151
+ if (transitiveBlockers.length > 0) {
152
+ return `Placed in wave ${wave} after direct dependencies and ${transitiveBlockers.length} transitive blocker(s).`;
153
+ }
154
+ return `Placed in wave ${wave} after its direct dependencies are available.`;
155
+ }
156
+ function calculatePlacementConfidence(directDependencies, unresolvedReferences, transitiveBlockers) {
157
+ if (unresolvedReferences.length > 0) {
158
+ return 0.55;
159
+ }
160
+ if (directDependencies.length === 0) {
161
+ return 1;
162
+ }
163
+ return transitiveBlockers.length > 0 ? 0.9 : 0.95;
164
+ }
165
+ function toNodeId(component) {
166
+ return `${component.type}:${component.name}`;
167
+ }
168
+ function compareDependency(left, right) {
169
+ return left.from.localeCompare(right.from) || left.to.localeCompare(right.to);
170
+ }
171
+ //# sourceMappingURL=plan-explain-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-explain-service.js","sourceRoot":"","sources":["../../src/deployment/plan-explain-service.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { StateManager } from './state-manager.js';
2
+ import { SfCliIntegration } from './sf-cli-integration.js';
2
3
  export type ResumeRetryStrategy = 'standard' | 'quick' | 'validate-only';
3
4
  export type ResumePreparation = {
4
5
  deploymentId: string;
@@ -9,6 +10,9 @@ export type ResumePreparation = {
9
10
  };
10
11
  export declare class ResumeDeploymentService {
11
12
  private readonly stateManager;
12
- constructor(stateManager?: StateManager);
13
- prepareResume(retryStrategy: ResumeRetryStrategy): Promise<ResumePreparation>;
13
+ private readonly sfCli;
14
+ constructor(stateManager?: StateManager, sfCli?: Pick<SfCliIntegration, 'resumeDeployment'>);
15
+ prepareResume(retryStrategy: ResumeRetryStrategy, options?: {
16
+ targetOrg?: string;
17
+ }): Promise<ResumePreparation>;
14
18
  }
@@ -1,17 +1,41 @@
1
1
  import { createResumedState, summarizeDeploymentState } from './deployment-state-summary.js';
2
2
  import { StateManager } from './state-manager.js';
3
+ import { SfCliIntegration } from './sf-cli-integration.js';
3
4
  export class ResumeDeploymentService {
4
5
  stateManager;
5
- constructor(stateManager = new StateManager()) {
6
+ sfCli;
7
+ constructor(stateManager = new StateManager(), sfCli = new SfCliIntegration()) {
6
8
  this.stateManager = stateManager;
9
+ this.sfCli = sfCli;
7
10
  }
8
- async prepareResume(retryStrategy) {
11
+ async prepareResume(retryStrategy, options = {}) {
9
12
  const state = await this.stateManager.loadState();
10
13
  if (!state?.failedWave) {
11
14
  throw new Error('No failed deployment state found to resume');
12
15
  }
13
16
  const summary = summarizeDeploymentState(state);
14
- const resumedState = createResumedState(state, retryStrategy);
17
+ const remoteResult = options.targetOrg
18
+ ? await this.sfCli.resumeDeployment(state.deploymentId, options.targetOrg)
19
+ : undefined;
20
+ if (remoteResult?.success === false) {
21
+ throw new Error(`Remote resume failed: ${remoteResult.output}`);
22
+ }
23
+ const resumedState = createResumedState(remoteResult
24
+ ? {
25
+ ...state,
26
+ targetOrg: options.targetOrg ?? state.targetOrg,
27
+ metadata: {
28
+ ...(state.metadata ?? {}),
29
+ lastKnownStatus: remoteResult.status,
30
+ remoteResumeStatus: remoteResult.status,
31
+ remoteResumeCheckedAt: new Date().toISOString(),
32
+ remoteComponentSuccesses: remoteResult.componentSuccesses,
33
+ remoteComponentFailures: remoteResult.componentFailures,
34
+ remoteTestsRun: remoteResult.testsRun,
35
+ remoteTestFailures: remoteResult.testFailures,
36
+ },
37
+ }
38
+ : state, retryStrategy);
15
39
  await this.stateManager.saveState(resumedState);
16
40
  return {
17
41
  deploymentId: summary.deploymentId,
@@ -1 +1 @@
1
- {"version":3,"file":"resume-deployment-service.js","sourceRoot":"","sources":["../../src/deployment/resume-deployment-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAYlD,MAAM,OAAO,uBAAuB;IACE;IAApC,YAAoC,eAA6B,IAAI,YAAY,EAAE;QAA/C,iBAAY,GAAZ,YAAY,CAAmC;IAAG,CAAC;IAEhF,KAAK,CAAC,aAAa,CAAC,aAAkC;QAC3D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;QAElD,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,OAAO,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAE9D,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAEhD,OAAO;YACL,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"resume-deployment-service.js","sourceRoot":"","sources":["../../src/deployment/resume-deployment-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAY3D,MAAM,OAAO,uBAAuB;IAEf;IACA;IAFnB,YACmB,eAA6B,IAAI,YAAY,EAAE,EAC/C,QAAoD,IAAI,gBAAgB,EAAE;QAD1E,iBAAY,GAAZ,YAAY,CAAmC;QAC/C,UAAK,GAAL,KAAK,CAAqE;IAC1F,CAAC;IAEG,KAAK,CAAC,aAAa,CACxB,aAAkC,EAClC,UAAkC,EAAE;QAEpC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;QAElD,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,OAAO,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS;YACpC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC;YAC1E,CAAC,CAAC,SAAS,CAAC;QAEd,IAAI,YAAY,EAAE,OAAO,KAAK,KAAK,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,yBAAyB,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,YAAY,GAAG,kBAAkB,CACrC,YAAY;YACV,CAAC,CAAC;gBACE,GAAG,KAAK;gBACR,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS;gBAC/C,QAAQ,EAAE;oBACR,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;oBACzB,eAAe,EAAE,YAAY,CAAC,MAAM;oBACpC,kBAAkB,EAAE,YAAY,CAAC,MAAM;oBACvC,qBAAqB,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBAC/C,wBAAwB,EAAE,YAAY,CAAC,kBAAkB;oBACzD,uBAAuB,EAAE,YAAY,CAAC,iBAAiB;oBACvD,cAAc,EAAE,YAAY,CAAC,QAAQ;oBACrC,kBAAkB,EAAE,YAAY,CAAC,YAAY;iBAC9C;aACF;YACH,CAAC,CAAC,KAAK,EACT,aAAa,CACd,CAAC;QAEF,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAEhD,OAAO;YACL,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,51 @@
1
+ export type RetrieveForceIgnoreOptions = {
2
+ projectRoot?: string;
3
+ targetOrg?: string;
4
+ metadata?: string[];
5
+ manifest?: string;
6
+ wait?: number;
7
+ strictIgnore?: boolean;
8
+ normalizeMeta?: boolean;
9
+ };
10
+ export type RetrieveForceIgnoreResult = {
11
+ success: boolean;
12
+ projectRoot: string;
13
+ retrieveOutput: string;
14
+ changedPaths: string[];
15
+ protectedPaths: string[];
16
+ restoredPaths: string[];
17
+ normalizedPaths: string[];
18
+ strictViolation: boolean;
19
+ architecturalConcerns: {
20
+ inherited: string[];
21
+ selfImposed: string[];
22
+ };
23
+ };
24
+ export type GitStatusEntry = {
25
+ path: string;
26
+ indexStatus: string;
27
+ workingTreeStatus: string;
28
+ untracked: boolean;
29
+ };
30
+ type RetrieveForceIgnoreServiceDependencies = {
31
+ sfRetrieveRunner?: Pick<SfRetrieveRunner, 'retrieve'>;
32
+ gitProvider?: Pick<GitWorkspaceProvider, 'listChangedPaths' | 'restorePaths'>;
33
+ };
34
+ export declare class RetrieveForceIgnoreService {
35
+ private readonly sfRetrieveRunner;
36
+ private readonly gitProvider;
37
+ constructor(dependencies?: RetrieveForceIgnoreServiceDependencies);
38
+ retrieve(options?: RetrieveForceIgnoreOptions): Promise<RetrieveForceIgnoreResult>;
39
+ }
40
+ export declare class SfRetrieveRunner {
41
+ retrieve(projectRoot: string, options: RetrieveForceIgnoreOptions): Promise<string>;
42
+ }
43
+ export declare class GitWorkspaceProvider {
44
+ listChangedPaths(projectRoot: string): Promise<GitStatusEntry[]>;
45
+ restorePaths(projectRoot: string, entries: GitStatusEntry[]): Promise<string[]>;
46
+ }
47
+ declare function parseGitStatus(output: string): GitStatusEntry[];
48
+ export declare const retrieveForceIgnoreInternals: {
49
+ parseGitStatus: typeof parseGitStatus;
50
+ };
51
+ export {};
@@ -0,0 +1,139 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { readFile, rm, writeFile } from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ import { glob } from 'glob';
6
+ import { ForceIgnoreParser } from '../scanner/forceignore-parser.js';
7
+ const execFileAsync = promisify(execFile);
8
+ export class RetrieveForceIgnoreService {
9
+ sfRetrieveRunner;
10
+ gitProvider;
11
+ constructor(dependencies = {}) {
12
+ this.sfRetrieveRunner = dependencies.sfRetrieveRunner ?? new SfRetrieveRunner();
13
+ this.gitProvider = dependencies.gitProvider ?? new GitWorkspaceProvider();
14
+ }
15
+ async retrieve(options = {}) {
16
+ const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
17
+ const retrieveOutput = await this.sfRetrieveRunner.retrieve(projectRoot, options);
18
+ const normalizedPaths = options.normalizeMeta === true ? await normalizeDigitalExperienceMeta(projectRoot) : [];
19
+ const parser = new ForceIgnoreParser();
20
+ const loadResult = await parser.load(projectRoot);
21
+ const changedEntries = await this.gitProvider.listChangedPaths(projectRoot);
22
+ const changedPaths = changedEntries.map((entry) => entry.path).sort();
23
+ const protectedEntries = loadResult.found
24
+ ? changedEntries.filter((entry) => parser.isIgnored(path.join(projectRoot, entry.path)))
25
+ : [];
26
+ const protectedPaths = protectedEntries.map((entry) => entry.path).sort();
27
+ const restoredPaths = protectedPaths.length > 0 ? await this.gitProvider.restorePaths(projectRoot, protectedEntries) : [];
28
+ const strictViolation = options.strictIgnore === true && protectedPaths.length > 0;
29
+ return {
30
+ success: !strictViolation,
31
+ projectRoot,
32
+ retrieveOutput,
33
+ changedPaths,
34
+ protectedPaths,
35
+ restoredPaths,
36
+ normalizedPaths,
37
+ strictViolation,
38
+ architecturalConcerns: {
39
+ inherited: [
40
+ 'Salesforce CLI may retrieve composite bundle sub-paths even when .forceignore excludes leaf paths.',
41
+ ],
42
+ selfImposed: [
43
+ 'Adds a retrieve wrapper that enforces .forceignore after the Salesforce CLI writes files because the underlying CLI does not expose reliable leaf-level bundle filtering.',
44
+ ],
45
+ },
46
+ };
47
+ }
48
+ }
49
+ export class SfRetrieveRunner {
50
+ async retrieve(projectRoot, options) {
51
+ const args = ['project', 'retrieve', 'start', '--json'];
52
+ for (const metadata of options.metadata ?? []) {
53
+ args.push('--metadata', metadata);
54
+ }
55
+ if (options.manifest) {
56
+ args.push('--manifest', options.manifest);
57
+ }
58
+ if (options.targetOrg) {
59
+ args.push('--target-org', options.targetOrg);
60
+ }
61
+ if (options.wait !== undefined) {
62
+ args.push('--wait', String(options.wait));
63
+ }
64
+ const { stdout, stderr } = await execFileAsync('sf', args, { cwd: projectRoot });
65
+ return stdout + stderr;
66
+ }
67
+ }
68
+ export class GitWorkspaceProvider {
69
+ async listChangedPaths(projectRoot) {
70
+ const { stdout } = await execFileAsync('git', ['status', '--porcelain', '--untracked-files=all'], {
71
+ cwd: projectRoot,
72
+ });
73
+ return parseGitStatus(stdout);
74
+ }
75
+ async restorePaths(projectRoot, entries) {
76
+ const restored = await entries.reduce(async (previous, entry) => {
77
+ const restoredPaths = await previous;
78
+ await restoreGitStatusEntry(projectRoot, entry);
79
+ return [...restoredPaths, entry.path];
80
+ }, Promise.resolve([]));
81
+ return restored.sort();
82
+ }
83
+ }
84
+ async function restoreGitStatusEntry(projectRoot, entry) {
85
+ const absolutePath = path.join(projectRoot, entry.path);
86
+ if (entry.untracked) {
87
+ await rm(absolutePath, { recursive: true, force: true });
88
+ return;
89
+ }
90
+ await execFileAsync('git', ['checkout', 'HEAD', '--', entry.path], { cwd: projectRoot });
91
+ }
92
+ function parseGitStatus(output) {
93
+ return output
94
+ .split('\n')
95
+ .filter(Boolean)
96
+ .map((line) => {
97
+ const indexStatus = line[0] ?? ' ';
98
+ const workingTreeStatus = line[1] ?? ' ';
99
+ const rawPath = line.slice(3);
100
+ const filePath = rawPath.includes(' -> ') ? rawPath.split(' -> ').at(-1) : rawPath;
101
+ return {
102
+ path: normalizeGitPath(filePath),
103
+ indexStatus,
104
+ workingTreeStatus,
105
+ untracked: indexStatus === '?' && workingTreeStatus === '?',
106
+ };
107
+ });
108
+ }
109
+ async function normalizeDigitalExperienceMeta(projectRoot) {
110
+ const files = await glob('**/digitalExperiences/**/*_meta.json', {
111
+ cwd: projectRoot,
112
+ absolute: true,
113
+ nodir: true,
114
+ dot: true,
115
+ ignore: ['**/node_modules/**', '**/.git/**'],
116
+ });
117
+ const normalizedPaths = await Promise.all(files.map(async (file) => {
118
+ const raw = await readFile(file, 'utf8');
119
+ const normalized = JSON.stringify(JSON.parse(raw), null, 2) + '\n';
120
+ if (raw === normalized) {
121
+ return undefined;
122
+ }
123
+ await writeFile(file, normalized, 'utf8');
124
+ return normalizeRelativePath(projectRoot, file);
125
+ }));
126
+ return normalizedPaths.filter((filePath) => filePath !== undefined).sort();
127
+ }
128
+ function normalizeGitPath(filePath) {
129
+ const unquoted = filePath.startsWith('"') && filePath.endsWith('"') ? JSON.parse(filePath) : filePath;
130
+ return unquoted.split(path.sep).join('/');
131
+ }
132
+ function normalizeRelativePath(projectRoot, filePath) {
133
+ const relativePath = path.relative(projectRoot, filePath);
134
+ return relativePath.split(path.sep).join('/');
135
+ }
136
+ export const retrieveForceIgnoreInternals = {
137
+ parseGitStatus,
138
+ };
139
+ //# sourceMappingURL=retrieve-forceignore-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve-forceignore-service.js","sourceRoot":"","sources":["../../src/deployment/retrieve-forceignore-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import type { NodeId } from '../types/dependency.js';
2
+ import type { DeploymentContext } from './deployment-context-service.js';
3
+ export type RollbackChangeStatus = 'added' | 'modified' | 'deleted';
4
+ export type RollbackGitChange = {
5
+ status: RollbackChangeStatus;
6
+ path: string;
7
+ };
8
+ export type RollbackSummary = {
9
+ from: string;
10
+ to: string;
11
+ changes: RollbackGitChange[];
12
+ destructiveComponents: NodeId[];
13
+ restoreComponents: NodeId[];
14
+ };
15
+ export type RollbackExecutionPlan = {
16
+ summary: RollbackSummary;
17
+ destructiveContext?: DeploymentContext;
18
+ restoreContext?: DeploymentContext;
19
+ cleanup: () => Promise<void>;
20
+ };
21
+ type RollbackPlanningServiceDependencies = {
22
+ gitProvider?: RollbackGitProvider;
23
+ };
24
+ type BuildContext = (sourcePath: string) => Promise<DeploymentContext>;
25
+ export type RollbackGitProvider = {
26
+ listChanges(projectRoot: string, fromRef: string, toRef: string): Promise<RollbackGitChange[]>;
27
+ checkoutArchive(projectRoot: string, ref: string): Promise<RollbackWorkspace>;
28
+ };
29
+ export type RollbackWorkspace = {
30
+ projectRoot: string;
31
+ cleanup: () => Promise<void>;
32
+ };
33
+ export declare class RollbackPlanningService {
34
+ private readonly gitProvider;
35
+ constructor(dependencies?: RollbackPlanningServiceDependencies);
36
+ buildExecutionPlan(options: {
37
+ projectRoot: string;
38
+ fromRef: string;
39
+ toRef: string;
40
+ currentContext: DeploymentContext;
41
+ buildContext: BuildContext;
42
+ }): Promise<RollbackExecutionPlan>;
43
+ filterContextByChanges(context: DeploymentContext, changes: RollbackGitChange[]): DeploymentContext;
44
+ }
45
+ declare function parseNameStatus(output: string): RollbackGitChange[];
46
+ export declare const rollbackPlanningInternals: {
47
+ parseNameStatus: typeof parseNameStatus;
48
+ };
49
+ export {};