@fern-api/replay 0.6.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +354 -48
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +329 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -7
- package/dist/index.d.ts +50 -7
- package/dist/index.js +332 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -23,6 +23,10 @@ interface StoredPatch {
|
|
|
23
23
|
base_generation: string;
|
|
24
24
|
files: string[];
|
|
25
25
|
patch_content: string;
|
|
26
|
+
/** When "unresolved", the patch conflicted during CI and needs local resolution.
|
|
27
|
+
* When "resolving", the resolve command has applied patches to the working tree
|
|
28
|
+
* and is waiting for the customer to resolve conflicts and run resolve again. */
|
|
29
|
+
status?: "unresolved" | "resolving";
|
|
26
30
|
}
|
|
27
31
|
interface CustomizationsConfig {
|
|
28
32
|
exclude?: string[];
|
|
@@ -96,6 +100,7 @@ declare class GitClient {
|
|
|
96
100
|
}>>;
|
|
97
101
|
isAncestor(commit: string, descendant: string): Promise<boolean>;
|
|
98
102
|
commitExists(sha: string): Promise<boolean>;
|
|
103
|
+
getCommitBody(commitSha: string): Promise<string>;
|
|
99
104
|
getRepoPath(): string;
|
|
100
105
|
}
|
|
101
106
|
|
|
@@ -104,6 +109,12 @@ declare const FERN_BOT_EMAIL = "115122769+fern-api[bot]@users.noreply.github.com
|
|
|
104
109
|
declare const FERN_BOT_LOGIN = "fern-api[bot]";
|
|
105
110
|
declare function isGenerationCommit(commit: CommitInfo): boolean;
|
|
106
111
|
declare function isReplayCommit(commit: CommitInfo): boolean;
|
|
112
|
+
/** Check if a commit message indicates a git revert */
|
|
113
|
+
declare function isRevertCommit(message: string): boolean;
|
|
114
|
+
/** Extract the reverted commit SHA from a full commit body containing "This reverts commit SHA." */
|
|
115
|
+
declare function parseRevertedSha(fullBody: string): string | undefined;
|
|
116
|
+
/** Extract the original commit message from a revert subject like 'Revert "original message"' */
|
|
117
|
+
declare function parseRevertedMessage(subject: string): string | undefined;
|
|
107
118
|
|
|
108
119
|
declare class LockfileManager {
|
|
109
120
|
private outputDir;
|
|
@@ -123,9 +134,13 @@ declare class LockfileManager {
|
|
|
123
134
|
save(): void;
|
|
124
135
|
addGeneration(record: GenerationRecord): void;
|
|
125
136
|
addPatch(patch: StoredPatch): void;
|
|
126
|
-
updatePatch(patchId: string, updates: Partial<Pick<StoredPatch, "base_generation" | "patch_content" | "content_hash" | "files">>): void;
|
|
137
|
+
updatePatch(patchId: string, updates: Partial<Pick<StoredPatch, "base_generation" | "patch_content" | "content_hash" | "files" | "status">>): void;
|
|
127
138
|
removePatch(patchId: string): void;
|
|
128
139
|
clearPatches(): void;
|
|
140
|
+
getUnresolvedPatches(): StoredPatch[];
|
|
141
|
+
getResolvingPatches(): StoredPatch[];
|
|
142
|
+
markPatchUnresolved(patchId: string): void;
|
|
143
|
+
markPatchResolved(patchId: string, updates: Pick<StoredPatch, "patch_content" | "content_hash" | "base_generation" | "files">): void;
|
|
129
144
|
getPatches(): StoredPatch[];
|
|
130
145
|
setReplaySkippedAt(timestamp: string): void;
|
|
131
146
|
clearReplaySkippedAt(): void;
|
|
@@ -135,20 +150,28 @@ declare class LockfileManager {
|
|
|
135
150
|
private ensureLoaded;
|
|
136
151
|
}
|
|
137
152
|
|
|
153
|
+
interface DetectionResult {
|
|
154
|
+
patches: StoredPatch[];
|
|
155
|
+
revertedPatchIds: string[];
|
|
156
|
+
}
|
|
138
157
|
declare class ReplayDetector {
|
|
139
158
|
private git;
|
|
140
159
|
private lockManager;
|
|
141
160
|
private sdkOutputDir;
|
|
142
161
|
readonly warnings: string[];
|
|
143
162
|
constructor(git: GitClient, lockManager: LockfileManager, sdkOutputDir: string);
|
|
144
|
-
detectNewPatches(): Promise<
|
|
163
|
+
detectNewPatches(): Promise<DetectionResult>;
|
|
145
164
|
/**
|
|
146
165
|
* Compute content hash for deduplication.
|
|
147
166
|
* Removes commit SHA line and index lines before hashing,
|
|
148
167
|
* so rebased commits with same content produce the same hash.
|
|
149
168
|
*/
|
|
150
169
|
computeContentHash(patchContent: string): string;
|
|
151
|
-
/**
|
|
170
|
+
/**
|
|
171
|
+
* Detect patches via tree diff for non-linear history. Returns a composite patch.
|
|
172
|
+
* Revert reconciliation is skipped here because tree-diff produces a single composite
|
|
173
|
+
* patch from the aggregate diff — individual revert commits are not distinguishable.
|
|
174
|
+
*/
|
|
152
175
|
private detectPatchesViaTreeDiff;
|
|
153
176
|
private parseGitLog;
|
|
154
177
|
private getLastGeneration;
|
|
@@ -201,7 +224,7 @@ declare class ReplayCommitter {
|
|
|
201
224
|
private outputDir;
|
|
202
225
|
constructor(git: GitClient, outputDir: string);
|
|
203
226
|
commitGeneration(message: string, options?: CommitOptions): Promise<string>;
|
|
204
|
-
commitReplay(_patchCount: number, patches?: StoredPatch[]): Promise<string>;
|
|
227
|
+
commitReplay(_patchCount: number, patches?: StoredPatch[], message?: string): Promise<string>;
|
|
205
228
|
createGenerationRecord(options?: CommitOptions): Promise<GenerationRecord>;
|
|
206
229
|
stageAll(): Promise<void>;
|
|
207
230
|
hasStagedChanges(): Promise<boolean>;
|
|
@@ -216,6 +239,12 @@ interface ConflictDetail {
|
|
|
216
239
|
/** Files that applied cleanly in a patch that also had conflicts. */
|
|
217
240
|
cleanFiles?: string[];
|
|
218
241
|
}
|
|
242
|
+
interface UnresolvedPatchInfo {
|
|
243
|
+
patchId: string;
|
|
244
|
+
patchMessage: string;
|
|
245
|
+
files: string[];
|
|
246
|
+
conflictDetails: FileResult[];
|
|
247
|
+
}
|
|
219
248
|
interface ReplayReport {
|
|
220
249
|
flow: "first-generation" | "no-patches" | "normal-regeneration" | "skip-application";
|
|
221
250
|
patchesDetected: number;
|
|
@@ -228,9 +257,12 @@ interface ReplayReport {
|
|
|
228
257
|
patchesKeptAsUserOwned?: number;
|
|
229
258
|
patchesPartiallyApplied?: number;
|
|
230
259
|
patchesConflictResolved?: number;
|
|
260
|
+
patchesReverted?: number;
|
|
231
261
|
patchesRefreshed?: number;
|
|
232
262
|
conflicts: FileResult[];
|
|
233
263
|
conflictDetails?: ConflictDetail[];
|
|
264
|
+
/** Patches that conflicted and need local resolution via `fern-replay resolve` */
|
|
265
|
+
unresolvedPatches?: UnresolvedPatchInfo[];
|
|
234
266
|
wouldApply?: StoredPatch[];
|
|
235
267
|
warnings?: string[];
|
|
236
268
|
}
|
|
@@ -303,6 +335,11 @@ declare class ReplayService {
|
|
|
303
335
|
* Called BEFORE commitGeneration() while HEAD has customer code.
|
|
304
336
|
*/
|
|
305
337
|
private preGenerationRebase;
|
|
338
|
+
/**
|
|
339
|
+
* After applyPatches(), strip conflict markers from conflicting files
|
|
340
|
+
* so only clean content is committed. Keeps the Generated (OURS) side.
|
|
341
|
+
*/
|
|
342
|
+
private revertConflictingFiles;
|
|
306
343
|
private readFernignorePatterns;
|
|
307
344
|
private buildReport;
|
|
308
345
|
}
|
|
@@ -427,10 +464,16 @@ interface ResolveResult {
|
|
|
427
464
|
success: boolean;
|
|
428
465
|
/** Commit SHA of the [fern-replay] commit, if created */
|
|
429
466
|
commitSha?: string;
|
|
430
|
-
/** Reason for failure */
|
|
467
|
+
/** Reason for failure or current state */
|
|
431
468
|
reason?: string;
|
|
432
|
-
/** Files that
|
|
469
|
+
/** Files that have conflict markers */
|
|
433
470
|
unresolvedFiles?: string[];
|
|
471
|
+
/** Phase the command executed */
|
|
472
|
+
phase?: "applied" | "committed" | "nothing-to-resolve";
|
|
473
|
+
/** Number of patches applied to working tree (phase 1) */
|
|
474
|
+
patchesApplied?: number;
|
|
475
|
+
/** Number of patches resolved and committed (phase 2) */
|
|
476
|
+
patchesResolved?: number;
|
|
434
477
|
}
|
|
435
478
|
declare function resolve(outputDir: string, options?: ResolveOptions): Promise<ResolveResult>;
|
|
436
479
|
|
|
@@ -460,4 +503,4 @@ interface StatusGeneration {
|
|
|
460
503
|
}
|
|
461
504
|
declare function status(outputDir: string): StatusResult;
|
|
462
505
|
|
|
463
|
-
export { type BootstrapOptions, type BootstrapResult, type CommitInfo, type CommitOptions, type ConflictDetail, type ConflictMetadata, type ConflictReason, type ConflictRegion, type CustomizationsConfig, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_BOT_NAME, FernignoreMigrator, type FileResult, type ForgetOptions, type ForgetResult, type GenerationLock, type GenerationRecord, GitClient, LockfileManager, type MergeResult, type MigrationAnalysis, type MigrationResult, type MoveDeclaration, ReplayApplicator, ReplayCommitter, type ReplayConfig, ReplayDetector, type ReplayOptions, type ReplayReport, type ReplayResult, ReplayService, type ResetOptions, type ResetResult, type ResolveOptions, type ResolveResult, type StatusGeneration, type StatusPatch, type StatusResult, type StoredPatch, bootstrap, forget, isGenerationCommit, isReplayCommit, reset, resolve, status, threeWayMerge };
|
|
506
|
+
export { type BootstrapOptions, type BootstrapResult, type CommitInfo, type CommitOptions, type ConflictDetail, type ConflictMetadata, type ConflictReason, type ConflictRegion, type CustomizationsConfig, type DetectionResult, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_BOT_NAME, FernignoreMigrator, type FileResult, type ForgetOptions, type ForgetResult, type GenerationLock, type GenerationRecord, GitClient, LockfileManager, type MergeResult, type MigrationAnalysis, type MigrationResult, type MoveDeclaration, ReplayApplicator, ReplayCommitter, type ReplayConfig, ReplayDetector, type ReplayOptions, type ReplayReport, type ReplayResult, ReplayService, type ResetOptions, type ResetResult, type ResolveOptions, type ResolveResult, type StatusGeneration, type StatusPatch, type StatusResult, type StoredPatch, type UnresolvedPatchInfo, bootstrap, forget, isGenerationCommit, isReplayCommit, isRevertCommit, parseRevertedMessage, parseRevertedSha, reset, resolve, status, threeWayMerge };
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ interface StoredPatch {
|
|
|
23
23
|
base_generation: string;
|
|
24
24
|
files: string[];
|
|
25
25
|
patch_content: string;
|
|
26
|
+
/** When "unresolved", the patch conflicted during CI and needs local resolution.
|
|
27
|
+
* When "resolving", the resolve command has applied patches to the working tree
|
|
28
|
+
* and is waiting for the customer to resolve conflicts and run resolve again. */
|
|
29
|
+
status?: "unresolved" | "resolving";
|
|
26
30
|
}
|
|
27
31
|
interface CustomizationsConfig {
|
|
28
32
|
exclude?: string[];
|
|
@@ -96,6 +100,7 @@ declare class GitClient {
|
|
|
96
100
|
}>>;
|
|
97
101
|
isAncestor(commit: string, descendant: string): Promise<boolean>;
|
|
98
102
|
commitExists(sha: string): Promise<boolean>;
|
|
103
|
+
getCommitBody(commitSha: string): Promise<string>;
|
|
99
104
|
getRepoPath(): string;
|
|
100
105
|
}
|
|
101
106
|
|
|
@@ -104,6 +109,12 @@ declare const FERN_BOT_EMAIL = "115122769+fern-api[bot]@users.noreply.github.com
|
|
|
104
109
|
declare const FERN_BOT_LOGIN = "fern-api[bot]";
|
|
105
110
|
declare function isGenerationCommit(commit: CommitInfo): boolean;
|
|
106
111
|
declare function isReplayCommit(commit: CommitInfo): boolean;
|
|
112
|
+
/** Check if a commit message indicates a git revert */
|
|
113
|
+
declare function isRevertCommit(message: string): boolean;
|
|
114
|
+
/** Extract the reverted commit SHA from a full commit body containing "This reverts commit SHA." */
|
|
115
|
+
declare function parseRevertedSha(fullBody: string): string | undefined;
|
|
116
|
+
/** Extract the original commit message from a revert subject like 'Revert "original message"' */
|
|
117
|
+
declare function parseRevertedMessage(subject: string): string | undefined;
|
|
107
118
|
|
|
108
119
|
declare class LockfileManager {
|
|
109
120
|
private outputDir;
|
|
@@ -123,9 +134,13 @@ declare class LockfileManager {
|
|
|
123
134
|
save(): void;
|
|
124
135
|
addGeneration(record: GenerationRecord): void;
|
|
125
136
|
addPatch(patch: StoredPatch): void;
|
|
126
|
-
updatePatch(patchId: string, updates: Partial<Pick<StoredPatch, "base_generation" | "patch_content" | "content_hash" | "files">>): void;
|
|
137
|
+
updatePatch(patchId: string, updates: Partial<Pick<StoredPatch, "base_generation" | "patch_content" | "content_hash" | "files" | "status">>): void;
|
|
127
138
|
removePatch(patchId: string): void;
|
|
128
139
|
clearPatches(): void;
|
|
140
|
+
getUnresolvedPatches(): StoredPatch[];
|
|
141
|
+
getResolvingPatches(): StoredPatch[];
|
|
142
|
+
markPatchUnresolved(patchId: string): void;
|
|
143
|
+
markPatchResolved(patchId: string, updates: Pick<StoredPatch, "patch_content" | "content_hash" | "base_generation" | "files">): void;
|
|
129
144
|
getPatches(): StoredPatch[];
|
|
130
145
|
setReplaySkippedAt(timestamp: string): void;
|
|
131
146
|
clearReplaySkippedAt(): void;
|
|
@@ -135,20 +150,28 @@ declare class LockfileManager {
|
|
|
135
150
|
private ensureLoaded;
|
|
136
151
|
}
|
|
137
152
|
|
|
153
|
+
interface DetectionResult {
|
|
154
|
+
patches: StoredPatch[];
|
|
155
|
+
revertedPatchIds: string[];
|
|
156
|
+
}
|
|
138
157
|
declare class ReplayDetector {
|
|
139
158
|
private git;
|
|
140
159
|
private lockManager;
|
|
141
160
|
private sdkOutputDir;
|
|
142
161
|
readonly warnings: string[];
|
|
143
162
|
constructor(git: GitClient, lockManager: LockfileManager, sdkOutputDir: string);
|
|
144
|
-
detectNewPatches(): Promise<
|
|
163
|
+
detectNewPatches(): Promise<DetectionResult>;
|
|
145
164
|
/**
|
|
146
165
|
* Compute content hash for deduplication.
|
|
147
166
|
* Removes commit SHA line and index lines before hashing,
|
|
148
167
|
* so rebased commits with same content produce the same hash.
|
|
149
168
|
*/
|
|
150
169
|
computeContentHash(patchContent: string): string;
|
|
151
|
-
/**
|
|
170
|
+
/**
|
|
171
|
+
* Detect patches via tree diff for non-linear history. Returns a composite patch.
|
|
172
|
+
* Revert reconciliation is skipped here because tree-diff produces a single composite
|
|
173
|
+
* patch from the aggregate diff — individual revert commits are not distinguishable.
|
|
174
|
+
*/
|
|
152
175
|
private detectPatchesViaTreeDiff;
|
|
153
176
|
private parseGitLog;
|
|
154
177
|
private getLastGeneration;
|
|
@@ -201,7 +224,7 @@ declare class ReplayCommitter {
|
|
|
201
224
|
private outputDir;
|
|
202
225
|
constructor(git: GitClient, outputDir: string);
|
|
203
226
|
commitGeneration(message: string, options?: CommitOptions): Promise<string>;
|
|
204
|
-
commitReplay(_patchCount: number, patches?: StoredPatch[]): Promise<string>;
|
|
227
|
+
commitReplay(_patchCount: number, patches?: StoredPatch[], message?: string): Promise<string>;
|
|
205
228
|
createGenerationRecord(options?: CommitOptions): Promise<GenerationRecord>;
|
|
206
229
|
stageAll(): Promise<void>;
|
|
207
230
|
hasStagedChanges(): Promise<boolean>;
|
|
@@ -216,6 +239,12 @@ interface ConflictDetail {
|
|
|
216
239
|
/** Files that applied cleanly in a patch that also had conflicts. */
|
|
217
240
|
cleanFiles?: string[];
|
|
218
241
|
}
|
|
242
|
+
interface UnresolvedPatchInfo {
|
|
243
|
+
patchId: string;
|
|
244
|
+
patchMessage: string;
|
|
245
|
+
files: string[];
|
|
246
|
+
conflictDetails: FileResult[];
|
|
247
|
+
}
|
|
219
248
|
interface ReplayReport {
|
|
220
249
|
flow: "first-generation" | "no-patches" | "normal-regeneration" | "skip-application";
|
|
221
250
|
patchesDetected: number;
|
|
@@ -228,9 +257,12 @@ interface ReplayReport {
|
|
|
228
257
|
patchesKeptAsUserOwned?: number;
|
|
229
258
|
patchesPartiallyApplied?: number;
|
|
230
259
|
patchesConflictResolved?: number;
|
|
260
|
+
patchesReverted?: number;
|
|
231
261
|
patchesRefreshed?: number;
|
|
232
262
|
conflicts: FileResult[];
|
|
233
263
|
conflictDetails?: ConflictDetail[];
|
|
264
|
+
/** Patches that conflicted and need local resolution via `fern-replay resolve` */
|
|
265
|
+
unresolvedPatches?: UnresolvedPatchInfo[];
|
|
234
266
|
wouldApply?: StoredPatch[];
|
|
235
267
|
warnings?: string[];
|
|
236
268
|
}
|
|
@@ -303,6 +335,11 @@ declare class ReplayService {
|
|
|
303
335
|
* Called BEFORE commitGeneration() while HEAD has customer code.
|
|
304
336
|
*/
|
|
305
337
|
private preGenerationRebase;
|
|
338
|
+
/**
|
|
339
|
+
* After applyPatches(), strip conflict markers from conflicting files
|
|
340
|
+
* so only clean content is committed. Keeps the Generated (OURS) side.
|
|
341
|
+
*/
|
|
342
|
+
private revertConflictingFiles;
|
|
306
343
|
private readFernignorePatterns;
|
|
307
344
|
private buildReport;
|
|
308
345
|
}
|
|
@@ -427,10 +464,16 @@ interface ResolveResult {
|
|
|
427
464
|
success: boolean;
|
|
428
465
|
/** Commit SHA of the [fern-replay] commit, if created */
|
|
429
466
|
commitSha?: string;
|
|
430
|
-
/** Reason for failure */
|
|
467
|
+
/** Reason for failure or current state */
|
|
431
468
|
reason?: string;
|
|
432
|
-
/** Files that
|
|
469
|
+
/** Files that have conflict markers */
|
|
433
470
|
unresolvedFiles?: string[];
|
|
471
|
+
/** Phase the command executed */
|
|
472
|
+
phase?: "applied" | "committed" | "nothing-to-resolve";
|
|
473
|
+
/** Number of patches applied to working tree (phase 1) */
|
|
474
|
+
patchesApplied?: number;
|
|
475
|
+
/** Number of patches resolved and committed (phase 2) */
|
|
476
|
+
patchesResolved?: number;
|
|
434
477
|
}
|
|
435
478
|
declare function resolve(outputDir: string, options?: ResolveOptions): Promise<ResolveResult>;
|
|
436
479
|
|
|
@@ -460,4 +503,4 @@ interface StatusGeneration {
|
|
|
460
503
|
}
|
|
461
504
|
declare function status(outputDir: string): StatusResult;
|
|
462
505
|
|
|
463
|
-
export { type BootstrapOptions, type BootstrapResult, type CommitInfo, type CommitOptions, type ConflictDetail, type ConflictMetadata, type ConflictReason, type ConflictRegion, type CustomizationsConfig, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_BOT_NAME, FernignoreMigrator, type FileResult, type ForgetOptions, type ForgetResult, type GenerationLock, type GenerationRecord, GitClient, LockfileManager, type MergeResult, type MigrationAnalysis, type MigrationResult, type MoveDeclaration, ReplayApplicator, ReplayCommitter, type ReplayConfig, ReplayDetector, type ReplayOptions, type ReplayReport, type ReplayResult, ReplayService, type ResetOptions, type ResetResult, type ResolveOptions, type ResolveResult, type StatusGeneration, type StatusPatch, type StatusResult, type StoredPatch, bootstrap, forget, isGenerationCommit, isReplayCommit, reset, resolve, status, threeWayMerge };
|
|
506
|
+
export { type BootstrapOptions, type BootstrapResult, type CommitInfo, type CommitOptions, type ConflictDetail, type ConflictMetadata, type ConflictReason, type ConflictRegion, type CustomizationsConfig, type DetectionResult, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_BOT_NAME, FernignoreMigrator, type FileResult, type ForgetOptions, type ForgetResult, type GenerationLock, type GenerationRecord, GitClient, LockfileManager, type MergeResult, type MigrationAnalysis, type MigrationResult, type MoveDeclaration, ReplayApplicator, ReplayCommitter, type ReplayConfig, ReplayDetector, type ReplayOptions, type ReplayReport, type ReplayResult, ReplayService, type ResetOptions, type ResetResult, type ResolveOptions, type ResolveResult, type StatusGeneration, type StatusPatch, type StatusResult, type StoredPatch, type UnresolvedPatchInfo, bootstrap, forget, isGenerationCommit, isReplayCommit, isRevertCommit, parseRevertedMessage, parseRevertedSha, reset, resolve, status, threeWayMerge };
|