@fern-api/replay 0.1.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/README.md +33 -0
- package/dist/ConflictPrompt.d.ts +13 -0
- package/dist/ConflictPrompt.d.ts.map +1 -0
- package/dist/ConflictPrompt.js +38 -0
- package/dist/ConflictPrompt.js.map +1 -0
- package/dist/ConflictResolver.d.ts +11 -0
- package/dist/ConflictResolver.d.ts.map +1 -0
- package/dist/ConflictResolver.js +53 -0
- package/dist/ConflictResolver.js.map +1 -0
- package/dist/FernignoreMigrator.d.ts +71 -0
- package/dist/FernignoreMigrator.d.ts.map +1 -0
- package/dist/FernignoreMigrator.js +243 -0
- package/dist/FernignoreMigrator.js.map +1 -0
- package/dist/LockfileManager.d.ts +27 -0
- package/dist/LockfileManager.d.ts.map +1 -0
- package/dist/LockfileManager.js +108 -0
- package/dist/LockfileManager.js.map +1 -0
- package/dist/ReplayApplicator.d.ts +68 -0
- package/dist/ReplayApplicator.d.ts.map +1 -0
- package/dist/ReplayApplicator.js +492 -0
- package/dist/ReplayApplicator.js.map +1 -0
- package/dist/ReplayCommitter.d.ts +39 -0
- package/dist/ReplayCommitter.d.ts.map +1 -0
- package/dist/ReplayCommitter.js +84 -0
- package/dist/ReplayCommitter.js.map +1 -0
- package/dist/ReplayDetector.d.ts +25 -0
- package/dist/ReplayDetector.d.ts.map +1 -0
- package/dist/ReplayDetector.js +110 -0
- package/dist/ReplayDetector.js.map +1 -0
- package/dist/ReplayService.d.ts +103 -0
- package/dist/ReplayService.d.ts.map +1 -0
- package/dist/ReplayService.js +457 -0
- package/dist/ReplayService.js.map +1 -0
- package/dist/ThreeWayMerge.d.ts +11 -0
- package/dist/ThreeWayMerge.d.ts.map +1 -0
- package/dist/ThreeWayMerge.js +48 -0
- package/dist/ThreeWayMerge.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +464 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/bootstrap.d.ts +44 -0
- package/dist/commands/bootstrap.d.ts.map +1 -0
- package/dist/commands/bootstrap.js +268 -0
- package/dist/commands/bootstrap.js.map +1 -0
- package/dist/commands/forget.d.ts +26 -0
- package/dist/commands/forget.d.ts.map +1 -0
- package/dist/commands/forget.js +37 -0
- package/dist/commands/forget.js.map +1 -0
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +6 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/reset.d.ts +28 -0
- package/dist/commands/reset.d.ts.map +1 -0
- package/dist/commands/reset.js +37 -0
- package/dist/commands/reset.js.map +1 -0
- package/dist/commands/resolve.d.ts +16 -0
- package/dist/commands/resolve.d.ts.map +1 -0
- package/dist/commands/resolve.js +28 -0
- package/dist/commands/resolve.js.map +1 -0
- package/dist/commands/status.d.ts +34 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +32 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/environment.d.ts +5 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +14 -0
- package/dist/environment.js.map +1 -0
- package/dist/git/CommitDetection.d.ts +17 -0
- package/dist/git/CommitDetection.d.ts.map +1 -0
- package/dist/git/CommitDetection.js +33 -0
- package/dist/git/CommitDetection.js.map +1 -0
- package/dist/git/GitClient.d.ts +28 -0
- package/dist/git/GitClient.d.ts.map +1 -0
- package/dist/git/GitClient.js +104 -0
- package/dist/git/GitClient.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Constants from Fern's PR #11502
|
|
2
|
+
export const FERN_BOT_NAME = "fern-api";
|
|
3
|
+
export const FERN_BOT_EMAIL = "115122769+fern-api[bot]@users.noreply.github.com";
|
|
4
|
+
export const FERN_BOT_LOGIN = "fern-api[bot]";
|
|
5
|
+
// Fern support team sometimes pushes manual onboarding commits through the
|
|
6
|
+
// bot GitHub App account. These share the bot email but use "fern-support"
|
|
7
|
+
// as author name. They should NOT be treated as generation commits.
|
|
8
|
+
const FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
|
|
9
|
+
/**
|
|
10
|
+
* Determines if a commit is a Fern generation commit using dual signals:
|
|
11
|
+
* 1. Author is fern-api bot (but NOT fern-support using the bot account)
|
|
12
|
+
* 2. Commit message contains generation markers
|
|
13
|
+
*
|
|
14
|
+
* Either signal indicates a generation commit.
|
|
15
|
+
*/
|
|
16
|
+
export function isGenerationCommit(commit) {
|
|
17
|
+
const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
|
|
18
|
+
const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN ||
|
|
19
|
+
commit.authorEmail === FERN_BOT_EMAIL ||
|
|
20
|
+
commit.authorName === FERN_BOT_NAME);
|
|
21
|
+
const hasGenerationMarker = commit.message.startsWith("[fern-generated]") ||
|
|
22
|
+
commit.message.startsWith("[fern-replay]") ||
|
|
23
|
+
commit.message.includes("Generated by Fern") ||
|
|
24
|
+
commit.message.includes("\u{1F916} Generated with Fern");
|
|
25
|
+
return isBotAuthor || hasGenerationMarker;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Determines if a commit is a replay commit (applied customizations).
|
|
29
|
+
*/
|
|
30
|
+
export function isReplayCommit(commit) {
|
|
31
|
+
return commit.message.startsWith("[fern-replay]");
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=CommitDetection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommitDetection.js","sourceRoot":"","sources":["../../src/git/CommitDetection.ts"],"names":[],"mappings":"AAEA,kCAAkC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,kDAAkD,CAAC;AACjF,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAC;AAE9C,2EAA2E;AAC3E,2EAA2E;AAC3E,oEAAoE;AACpE,MAAM,kBAAkB,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAkB;IACjD,MAAM,aAAa,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAErE,MAAM,WAAW,GACb,CAAC,aAAa,IAAI,CACd,MAAM,CAAC,WAAW,KAAK,cAAc;QACrC,MAAM,CAAC,WAAW,KAAK,cAAc;QACrC,MAAM,CAAC,UAAU,KAAK,aAAa,CACtC,CAAC;IAEN,MAAM,mBAAmB,GACrB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC;IAE7D,OAAO,WAAW,IAAI,mBAAmB,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC7C,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CommitInfo } from "../types.js";
|
|
2
|
+
export declare class GitClient {
|
|
3
|
+
private git;
|
|
4
|
+
private repoPath;
|
|
5
|
+
constructor(repoPath: string);
|
|
6
|
+
exec(args: string[]): Promise<string>;
|
|
7
|
+
execWithInput(args: string[], input: string): Promise<string>;
|
|
8
|
+
formatPatch(commitSha: string): Promise<string>;
|
|
9
|
+
applyPatch(patchContent: string): Promise<void>;
|
|
10
|
+
getTreeHash(commitSha: string): Promise<string>;
|
|
11
|
+
showFile(treeish: string, filePath: string): Promise<string | null>;
|
|
12
|
+
getCommitInfo(commitSha: string): Promise<CommitInfo>;
|
|
13
|
+
getCommitParents(commitSha: string): Promise<string[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Detect file renames between two tree hashes using git's rename detection.
|
|
16
|
+
* Returns an array of { from, to } pairs.
|
|
17
|
+
*/
|
|
18
|
+
detectRenames(fromTree: string, toTree: string): Promise<Array<{
|
|
19
|
+
from: string;
|
|
20
|
+
to: string;
|
|
21
|
+
}>>;
|
|
22
|
+
/**
|
|
23
|
+
* Check whether a commit SHA exists in the local repository.
|
|
24
|
+
*/
|
|
25
|
+
commitExists(sha: string): Promise<boolean>;
|
|
26
|
+
getRepoPath(): string;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=GitClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitClient.d.ts","sourceRoot":"","sources":["../../src/git/GitClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,qBAAa,SAAS;IAClB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAKtB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAIrC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B7D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/C,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/C,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQnE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAOrD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAK5D;;;OAGG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAsBnG;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASjD,WAAW,IAAI,MAAM;CAGxB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { simpleGit } from "simple-git";
|
|
2
|
+
export class GitClient {
|
|
3
|
+
git;
|
|
4
|
+
repoPath;
|
|
5
|
+
constructor(repoPath) {
|
|
6
|
+
this.repoPath = repoPath;
|
|
7
|
+
this.git = simpleGit(repoPath);
|
|
8
|
+
}
|
|
9
|
+
async exec(args) {
|
|
10
|
+
return this.git.raw(args);
|
|
11
|
+
}
|
|
12
|
+
async execWithInput(args, input) {
|
|
13
|
+
// simple-git's raw() doesn't support stdin directly,
|
|
14
|
+
// so we use spawn for commands that need stdin (e.g. git am)
|
|
15
|
+
const { spawn } = await import("node:child_process");
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const proc = spawn("git", args, { cwd: this.repoPath });
|
|
18
|
+
let stdout = "";
|
|
19
|
+
let stderr = "";
|
|
20
|
+
proc.stdout.on("data", (data) => { stdout += data.toString(); });
|
|
21
|
+
proc.stderr.on("data", (data) => { stderr += data.toString(); });
|
|
22
|
+
proc.on("close", (code) => {
|
|
23
|
+
if (code === 0) {
|
|
24
|
+
resolve(stdout);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
reject(new Error(`git ${args.join(" ")} failed (code ${code}): ${stderr}`));
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
proc.stdin.write(input);
|
|
31
|
+
proc.stdin.end();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async formatPatch(commitSha) {
|
|
35
|
+
return this.exec(["format-patch", "-1", commitSha, "--stdout"]);
|
|
36
|
+
}
|
|
37
|
+
async applyPatch(patchContent) {
|
|
38
|
+
await this.execWithInput(["am", "--3way"], patchContent);
|
|
39
|
+
}
|
|
40
|
+
async getTreeHash(commitSha) {
|
|
41
|
+
return (await this.exec(["rev-parse", `${commitSha}^{tree}`])).trim();
|
|
42
|
+
}
|
|
43
|
+
async showFile(treeish, filePath) {
|
|
44
|
+
try {
|
|
45
|
+
return await this.exec(["show", `${treeish}:${filePath}`]);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async getCommitInfo(commitSha) {
|
|
52
|
+
const format = "%H%x00%an%x00%ae%x00%s";
|
|
53
|
+
const output = await this.exec(["log", "-1", `--format=${format}`, commitSha]);
|
|
54
|
+
const [sha, authorName, authorEmail, message] = output.trim().split("\0");
|
|
55
|
+
return { sha, authorName, authorEmail, message };
|
|
56
|
+
}
|
|
57
|
+
async getCommitParents(commitSha) {
|
|
58
|
+
const output = await this.exec(["rev-parse", `${commitSha}^@`]);
|
|
59
|
+
return output.trim().split("\n").filter(Boolean);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Detect file renames between two tree hashes using git's rename detection.
|
|
63
|
+
* Returns an array of { from, to } pairs.
|
|
64
|
+
*/
|
|
65
|
+
async detectRenames(fromTree, toTree) {
|
|
66
|
+
try {
|
|
67
|
+
const output = await this.exec([
|
|
68
|
+
"diff", "--find-renames", "--name-status", fromTree, toTree,
|
|
69
|
+
]);
|
|
70
|
+
const renames = [];
|
|
71
|
+
for (const line of output.trim().split("\n")) {
|
|
72
|
+
if (!line)
|
|
73
|
+
continue;
|
|
74
|
+
// Rename lines look like: R095\told/path.ts\tnew/path.ts
|
|
75
|
+
if (line.startsWith("R")) {
|
|
76
|
+
const parts = line.split("\t");
|
|
77
|
+
if (parts.length >= 3) {
|
|
78
|
+
renames.push({ from: parts[1], to: parts[2] });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return renames;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Check whether a commit SHA exists in the local repository.
|
|
90
|
+
*/
|
|
91
|
+
async commitExists(sha) {
|
|
92
|
+
try {
|
|
93
|
+
const type = await this.exec(["cat-file", "-t", sha]);
|
|
94
|
+
return type.trim() === "commit";
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
getRepoPath() {
|
|
101
|
+
return this.repoPath;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=GitClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitClient.js","sourceRoot":"","sources":["../../src/git/GitClient.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type { GenerationLock, GenerationRecord, StoredPatch, CustomizationsConfig, MoveDeclaration, ReplayResult, FileResult, ConflictRegion, ConflictReason, ConflictMetadata, MergeResult, CommitInfo, ReplayConfig, } from "./types.js";
|
|
2
|
+
export { DEFAULT_REPLAY_CONFIG } from "./types.js";
|
|
3
|
+
export { GitClient } from "./git/GitClient.js";
|
|
4
|
+
export { isGenerationCommit, isReplayCommit, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, } from "./git/CommitDetection.js";
|
|
5
|
+
export { LockfileManager } from "./LockfileManager.js";
|
|
6
|
+
export { ReplayDetector } from "./ReplayDetector.js";
|
|
7
|
+
export { threeWayMerge } from "./ThreeWayMerge.js";
|
|
8
|
+
export { ReplayApplicator } from "./ReplayApplicator.js";
|
|
9
|
+
export { ReplayCommitter, type CommitOptions } from "./ReplayCommitter.js";
|
|
10
|
+
export { ReplayService, ReplayConflictError, type ReplayReport, type ReplayOptions, type ConflictDetail } from "./ReplayService.js";
|
|
11
|
+
export { resolveConflictMarkers, resolveContent, type ResolutionStrategy } from "./ConflictResolver.js";
|
|
12
|
+
export { isCI } from "./environment.js";
|
|
13
|
+
export { FernignoreMigrator, type MigrationAnalysis, type MigrationResult } from "./FernignoreMigrator.js";
|
|
14
|
+
export { bootstrap, type BootstrapOptions, type BootstrapResult, forget, type ForgetOptions, type ForgetResult, reset, type ResetOptions, type ResetResult, resolve, type ResolveOptions, type ResolveResult, status, type StatusResult, type StatusPatch, type StatusGeneration, } from "./commands/index.js";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACR,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,UAAU,EACV,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,YAAY,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACH,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpI,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACxG,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC3G,OAAO,EACH,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EACtD,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAC7C,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAC1C,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAChD,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,GACrE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { DEFAULT_REPLAY_CONFIG } from "./types.js";
|
|
2
|
+
export { GitClient } from "./git/GitClient.js";
|
|
3
|
+
export { isGenerationCommit, isReplayCommit, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, } from "./git/CommitDetection.js";
|
|
4
|
+
export { LockfileManager } from "./LockfileManager.js";
|
|
5
|
+
export { ReplayDetector } from "./ReplayDetector.js";
|
|
6
|
+
export { threeWayMerge } from "./ThreeWayMerge.js";
|
|
7
|
+
export { ReplayApplicator } from "./ReplayApplicator.js";
|
|
8
|
+
export { ReplayCommitter } from "./ReplayCommitter.js";
|
|
9
|
+
export { ReplayService, ReplayConflictError } from "./ReplayService.js";
|
|
10
|
+
export { resolveConflictMarkers, resolveContent } from "./ConflictResolver.js";
|
|
11
|
+
export { isCI } from "./environment.js";
|
|
12
|
+
export { FernignoreMigrator } from "./FernignoreMigrator.js";
|
|
13
|
+
export { bootstrap, forget, reset, resolve, status, } from "./commands/index.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACH,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAA8D,MAAM,oBAAoB,CAAC;AACpI,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAA2B,MAAM,uBAAuB,CAAC;AACxG,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAgD,MAAM,yBAAyB,CAAC;AAC3G,OAAO,EACH,SAAS,EACT,MAAM,EACN,KAAK,EACL,OAAO,EACP,MAAM,GACT,MAAM,qBAAqB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export interface GenerationLock {
|
|
2
|
+
version: "1.0";
|
|
3
|
+
generations: GenerationRecord[];
|
|
4
|
+
current_generation: string;
|
|
5
|
+
patches: StoredPatch[];
|
|
6
|
+
}
|
|
7
|
+
export interface GenerationRecord {
|
|
8
|
+
commit_sha: string;
|
|
9
|
+
tree_hash: string;
|
|
10
|
+
timestamp: string;
|
|
11
|
+
cli_version: string;
|
|
12
|
+
generator_versions: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
export interface StoredPatch {
|
|
15
|
+
id: string;
|
|
16
|
+
content_hash: string;
|
|
17
|
+
original_commit: string;
|
|
18
|
+
original_message: string;
|
|
19
|
+
original_author: string;
|
|
20
|
+
base_generation: string;
|
|
21
|
+
files: string[];
|
|
22
|
+
patch_content: string;
|
|
23
|
+
}
|
|
24
|
+
export interface CustomizationsConfig {
|
|
25
|
+
exclude?: string[];
|
|
26
|
+
moves?: MoveDeclaration[];
|
|
27
|
+
}
|
|
28
|
+
export interface MoveDeclaration {
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
}
|
|
32
|
+
export type ConflictReason = "same-line-edit" | "new-file-both" | "base-generation-mismatch" | "patch-apply-failed";
|
|
33
|
+
export interface ReplayResult {
|
|
34
|
+
patch: StoredPatch;
|
|
35
|
+
status: "applied" | "conflict" | "skipped";
|
|
36
|
+
method: "git-am" | "3way-merge";
|
|
37
|
+
fileResults?: FileResult[];
|
|
38
|
+
conflictReason?: ConflictReason;
|
|
39
|
+
}
|
|
40
|
+
export interface ConflictMetadata {
|
|
41
|
+
patchId: string;
|
|
42
|
+
patchMessage: string;
|
|
43
|
+
baseGeneration: string;
|
|
44
|
+
currentGeneration: string;
|
|
45
|
+
}
|
|
46
|
+
export interface FileResult {
|
|
47
|
+
file: string;
|
|
48
|
+
status: "merged" | "conflict" | "skipped";
|
|
49
|
+
reason?: string;
|
|
50
|
+
conflicts?: ConflictRegion[];
|
|
51
|
+
conflictReason?: ConflictReason;
|
|
52
|
+
conflictMetadata?: ConflictMetadata;
|
|
53
|
+
}
|
|
54
|
+
export interface ConflictRegion {
|
|
55
|
+
startLine: number;
|
|
56
|
+
endLine: number;
|
|
57
|
+
ours: string[];
|
|
58
|
+
theirs: string[];
|
|
59
|
+
}
|
|
60
|
+
export interface MergeResult {
|
|
61
|
+
content: string;
|
|
62
|
+
hasConflicts: boolean;
|
|
63
|
+
conflicts: ConflictRegion[];
|
|
64
|
+
}
|
|
65
|
+
export interface CommitInfo {
|
|
66
|
+
sha: string;
|
|
67
|
+
authorName: string;
|
|
68
|
+
authorEmail: string;
|
|
69
|
+
authorLogin?: string;
|
|
70
|
+
message: string;
|
|
71
|
+
}
|
|
72
|
+
export interface ReplayConfig {
|
|
73
|
+
enabled: boolean;
|
|
74
|
+
on_conflict?: {
|
|
75
|
+
ci?: "fail" | "create-pr" | "keep-mine" | "keep-generated";
|
|
76
|
+
local?: "prompt" | "keep-mine" | "keep-generated";
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export declare const DEFAULT_REPLAY_CONFIG: ReplayConfig;
|
|
80
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AA6FrD,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IAC/C,OAAO,EAAE,KAAK;IACd,WAAW,EAAE;QACT,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,QAAQ;KAClB;CACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fern-api/replay",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Automatically preserves SDK customizations across Fern regenerations",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"fern-replay": "./dist/cli.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"minimatch": "^9.0.0",
|
|
20
|
+
"node-diff3": "^3.1.0",
|
|
21
|
+
"simple-git": "^3.27.0",
|
|
22
|
+
"yaml": "^2.8.2"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^20.0.0",
|
|
26
|
+
"tsx": "^4.21.0",
|
|
27
|
+
"typescript": "^5.5.0",
|
|
28
|
+
"vitest": "^2.0.0"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/fern-api/fern-replay.git"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc",
|
|
40
|
+
"dev": "npx tsx src/cli.ts",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
44
|
+
}
|
|
45
|
+
}
|