@fern-api/generator-cli 0.8.1 → 0.9.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/api.d.ts +17 -3
- package/dist/api.js +42 -26
- package/dist/cli.js +321 -43
- package/package.json +2 -2
package/dist/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BootstrapResult, ResolveResult, ReplayReport } from '@fern-api/replay';
|
|
2
|
-
export { ConflictDetail, ReplayReport, ResolveResult } from '@fern-api/replay';
|
|
1
|
+
import { ForgetOptions, ForgetResult, BootstrapResult, ResolveResult, ReplayReport, StatusResult } from '@fern-api/replay';
|
|
2
|
+
export { ConflictDetail, DiffStat, ForgetOptions, ForgetResult, MatchedPatch, ReplayReport, ResolveResult, StatusGeneration, StatusPatch, StatusResult } from '@fern-api/replay';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -614,6 +614,14 @@ declare function formatReplayPrBody(result: ReplayStepResult | undefined, option
|
|
|
614
614
|
repoUri?: string;
|
|
615
615
|
}): string | undefined;
|
|
616
616
|
|
|
617
|
+
interface ReplayForgetParams {
|
|
618
|
+
/** Directory containing the SDK (where .fern/replay.lock lives) */
|
|
619
|
+
outputDir: string;
|
|
620
|
+
/** Options controlling which patches to forget */
|
|
621
|
+
options?: ForgetOptions;
|
|
622
|
+
}
|
|
623
|
+
declare function replayForget(params: ReplayForgetParams): ForgetResult;
|
|
624
|
+
|
|
617
625
|
interface ReplayInitParams {
|
|
618
626
|
/** GitHub repo URI (e.g., "fern-demo/fern-replay-testbed-java-sdk") */
|
|
619
627
|
githubRepo: string;
|
|
@@ -699,4 +707,10 @@ interface ReplayRunResult {
|
|
|
699
707
|
}
|
|
700
708
|
declare function replayRun(params: ReplayRunParams): Promise<ReplayRunResult>;
|
|
701
709
|
|
|
702
|
-
|
|
710
|
+
interface ReplayStatusParams {
|
|
711
|
+
/** Directory containing the SDK (where .fern/replay.lock lives) */
|
|
712
|
+
outputDir: string;
|
|
713
|
+
}
|
|
714
|
+
declare function replayStatus(params: ReplayStatusParams): StatusResult;
|
|
715
|
+
|
|
716
|
+
export { type BootstrapLogEntry, type GenerateReadmeParams, type GenerateReadmeToStreamParams, type GenerateReferenceParams, type GenerateReferenceToStreamParams, type GithubPrParams, type GithubPushParams, type GithubReleaseParams, type GithubStepConfig, type GithubStepResult, type PipelineConfig, type PipelineContext, type PipelineLogger, type PipelineResult, PostGenerationPipeline, type ReplayForgetParams, type ReplayInitParams, type ReplayInitResult, type ReplayResolveParams, type ReplayRunParams, type ReplayRunResult, type ReplayStatusParams, type ReplayStepResult, consolePipelineLogger, formatBootstrapSummary, formatReplayPrBody, generateReadme, generateReadmeToStream, generateReference, generateReferenceToStream, githubPr, githubPush, githubRelease, logReplaySummary, replayForget, replayInit, replayResolve, replayRun, replayStatus };
|
package/dist/api.js
CHANGED
|
@@ -844,7 +844,7 @@ var require_dist2 = __commonJS({
|
|
|
844
844
|
function deferred2() {
|
|
845
845
|
let done;
|
|
846
846
|
let fail;
|
|
847
|
-
let
|
|
847
|
+
let status2 = "pending";
|
|
848
848
|
const promise = new Promise((_done, _fail) => {
|
|
849
849
|
done = _done;
|
|
850
850
|
fail = _fail;
|
|
@@ -852,22 +852,22 @@ var require_dist2 = __commonJS({
|
|
|
852
852
|
return {
|
|
853
853
|
promise,
|
|
854
854
|
done(result) {
|
|
855
|
-
if (
|
|
856
|
-
|
|
855
|
+
if (status2 === "pending") {
|
|
856
|
+
status2 = "resolved";
|
|
857
857
|
done(result);
|
|
858
858
|
}
|
|
859
859
|
},
|
|
860
860
|
fail(error) {
|
|
861
|
-
if (
|
|
862
|
-
|
|
861
|
+
if (status2 === "pending") {
|
|
862
|
+
status2 = "rejected";
|
|
863
863
|
fail(error);
|
|
864
864
|
}
|
|
865
865
|
},
|
|
866
866
|
get fulfilled() {
|
|
867
|
-
return
|
|
867
|
+
return status2 !== "pending";
|
|
868
868
|
},
|
|
869
869
|
get status() {
|
|
870
|
-
return
|
|
870
|
+
return status2;
|
|
871
871
|
}
|
|
872
872
|
};
|
|
873
873
|
}
|
|
@@ -892,9 +892,11 @@ __export(api_exports2, {
|
|
|
892
892
|
githubPush: () => githubPush,
|
|
893
893
|
githubRelease: () => githubRelease,
|
|
894
894
|
logReplaySummary: () => logReplaySummary,
|
|
895
|
+
replayForget: () => replayForget,
|
|
895
896
|
replayInit: () => replayInit,
|
|
896
897
|
replayResolve: () => replayResolve,
|
|
897
|
-
replayRun: () => replayRun
|
|
898
|
+
replayRun: () => replayRun,
|
|
899
|
+
replayStatus: () => replayStatus
|
|
898
900
|
});
|
|
899
901
|
module.exports = __toCommonJS(api_exports2);
|
|
900
902
|
|
|
@@ -2827,7 +2829,7 @@ var init_parse_diff_summary = __esm({
|
|
|
2827
2829
|
nameStatusParser = [
|
|
2828
2830
|
new LineParser(
|
|
2829
2831
|
/([ACDMRTUXB])([0-9]{0,3})\t(.[^\t]*)(\t(.[^\t]*))?$/,
|
|
2830
|
-
(result, [
|
|
2832
|
+
(result, [status2, similarity, from, _to, to]) => {
|
|
2831
2833
|
result.changed++;
|
|
2832
2834
|
result.files.push({
|
|
2833
2835
|
file: to ?? from,
|
|
@@ -2835,7 +2837,7 @@ var init_parse_diff_summary = __esm({
|
|
|
2835
2837
|
insertions: 0,
|
|
2836
2838
|
deletions: 0,
|
|
2837
2839
|
binary: false,
|
|
2838
|
-
status: orVoid(isDiffNameStatus(
|
|
2840
|
+
status: orVoid(isDiffNameStatus(status2) && status2),
|
|
2839
2841
|
from: orVoid(!!to && from !== to && from),
|
|
2840
2842
|
similarity: asNumber(similarity)
|
|
2841
2843
|
});
|
|
@@ -3361,10 +3363,10 @@ var init_merge = __esm({
|
|
|
3361
3363
|
init_task();
|
|
3362
3364
|
}
|
|
3363
3365
|
});
|
|
3364
|
-
function pushResultPushedItem(local, remote,
|
|
3365
|
-
const deleted =
|
|
3366
|
-
const tag =
|
|
3367
|
-
const alreadyUpdated = !
|
|
3366
|
+
function pushResultPushedItem(local, remote, status2) {
|
|
3367
|
+
const deleted = status2.includes("deleted");
|
|
3368
|
+
const tag = status2.includes("tag") || /^refs\/tags/.test(local);
|
|
3369
|
+
const alreadyUpdated = !status2.includes("new");
|
|
3368
3370
|
return {
|
|
3369
3371
|
deleted,
|
|
3370
3372
|
tag,
|
|
@@ -3678,7 +3680,7 @@ var init_StatusSummary = __esm({
|
|
|
3678
3680
|
]);
|
|
3679
3681
|
parseStatusSummary = function(text) {
|
|
3680
3682
|
const lines = text.split(NULL);
|
|
3681
|
-
const
|
|
3683
|
+
const status2 = new StatusSummary();
|
|
3682
3684
|
for (let i = 0, l = lines.length; i < l; ) {
|
|
3683
3685
|
let line = lines[i++].trim();
|
|
3684
3686
|
if (!line) {
|
|
@@ -3687,9 +3689,9 @@ var init_StatusSummary = __esm({
|
|
|
3687
3689
|
if (line.charAt(0) === "R") {
|
|
3688
3690
|
line += NULL + (lines[i++] || "");
|
|
3689
3691
|
}
|
|
3690
|
-
splitLine(
|
|
3692
|
+
splitLine(status2, line);
|
|
3691
3693
|
}
|
|
3692
|
-
return
|
|
3694
|
+
return status2;
|
|
3693
3695
|
};
|
|
3694
3696
|
}
|
|
3695
3697
|
});
|
|
@@ -4116,15 +4118,15 @@ var init_BranchSummary = __esm({
|
|
|
4116
4118
|
this.current = "";
|
|
4117
4119
|
this.detached = false;
|
|
4118
4120
|
}
|
|
4119
|
-
push(
|
|
4120
|
-
if (
|
|
4121
|
+
push(status2, detached, name, commit, label) {
|
|
4122
|
+
if (status2 === "*") {
|
|
4121
4123
|
this.detached = detached;
|
|
4122
4124
|
this.current = name;
|
|
4123
4125
|
}
|
|
4124
4126
|
this.all.push(name);
|
|
4125
4127
|
this.branches[name] = {
|
|
4126
|
-
current:
|
|
4127
|
-
linkedWorkTree:
|
|
4128
|
+
current: status2 === "*",
|
|
4129
|
+
linkedWorkTree: status2 === "+",
|
|
4128
4130
|
name,
|
|
4129
4131
|
commit,
|
|
4130
4132
|
label
|
|
@@ -10488,8 +10490,14 @@ var PostGenerationPipeline = class {
|
|
|
10488
10490
|
}
|
|
10489
10491
|
};
|
|
10490
10492
|
|
|
10491
|
-
// src/replay/replay-
|
|
10493
|
+
// src/replay/replay-forget.ts
|
|
10492
10494
|
var import_replay2 = require("@fern-api/replay");
|
|
10495
|
+
function replayForget(params) {
|
|
10496
|
+
return (0, import_replay2.forget)(params.outputDir, params.options);
|
|
10497
|
+
}
|
|
10498
|
+
|
|
10499
|
+
// src/replay/replay-init.ts
|
|
10500
|
+
var import_replay3 = require("@fern-api/replay");
|
|
10493
10501
|
var import_fs4 = require("fs");
|
|
10494
10502
|
var import_path6 = require("path");
|
|
10495
10503
|
var import_tmp_promise2 = __toESM(require("tmp-promise"));
|
|
@@ -10502,7 +10510,7 @@ async function replayInit(params) {
|
|
|
10502
10510
|
installationToken: token,
|
|
10503
10511
|
targetDirectory: repoPath
|
|
10504
10512
|
});
|
|
10505
|
-
const bootstrapResult = await (0,
|
|
10513
|
+
const bootstrapResult = await (0, import_replay3.bootstrap)(repoPath, {
|
|
10506
10514
|
dryRun,
|
|
10507
10515
|
fernignoreAction: "skip",
|
|
10508
10516
|
maxCommitsToScan: params.maxCommitsToScan,
|
|
@@ -10635,12 +10643,18 @@ function buildPrBody(result) {
|
|
|
10635
10643
|
}
|
|
10636
10644
|
|
|
10637
10645
|
// src/replay/replay-resolve.ts
|
|
10638
|
-
var
|
|
10646
|
+
var import_replay4 = require("@fern-api/replay");
|
|
10639
10647
|
async function replayResolve(params) {
|
|
10640
|
-
return (0,
|
|
10648
|
+
return (0, import_replay4.resolve)(params.outputDir, {
|
|
10641
10649
|
checkMarkers: params.checkMarkers
|
|
10642
10650
|
});
|
|
10643
10651
|
}
|
|
10652
|
+
|
|
10653
|
+
// src/replay/replay-status.ts
|
|
10654
|
+
var import_replay5 = require("@fern-api/replay");
|
|
10655
|
+
function replayStatus(params) {
|
|
10656
|
+
return (0, import_replay5.status)(params.outputDir);
|
|
10657
|
+
}
|
|
10644
10658
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10645
10659
|
0 && (module.exports = {
|
|
10646
10660
|
PostGenerationPipeline,
|
|
@@ -10655,7 +10669,9 @@ async function replayResolve(params) {
|
|
|
10655
10669
|
githubPush,
|
|
10656
10670
|
githubRelease,
|
|
10657
10671
|
logReplaySummary,
|
|
10672
|
+
replayForget,
|
|
10658
10673
|
replayInit,
|
|
10659
10674
|
replayResolve,
|
|
10660
|
-
replayRun
|
|
10675
|
+
replayRun,
|
|
10676
|
+
replayStatus
|
|
10661
10677
|
});
|
package/dist/cli.js
CHANGED
|
@@ -19759,7 +19759,7 @@ var init_diff3 = __esm({
|
|
|
19759
19759
|
}
|
|
19760
19760
|
});
|
|
19761
19761
|
|
|
19762
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.
|
|
19762
|
+
// ../../node_modules/.pnpm/@fern-api+replay@0.9.0/node_modules/@fern-api/replay/dist/index.js
|
|
19763
19763
|
var dist_exports = {};
|
|
19764
19764
|
__export(dist_exports, {
|
|
19765
19765
|
FERN_BOT_EMAIL: () => FERN_BOT_EMAIL2,
|
|
@@ -19797,7 +19797,7 @@ function isReplayCommit(commit) {
|
|
|
19797
19797
|
return commit.message.startsWith("[fern-replay]");
|
|
19798
19798
|
}
|
|
19799
19799
|
function isRevertCommit(message) {
|
|
19800
|
-
return
|
|
19800
|
+
return /^Revert ".+"$/.test(message);
|
|
19801
19801
|
}
|
|
19802
19802
|
function parseRevertedSha(fullBody) {
|
|
19803
19803
|
const match2 = fullBody.match(/This reverts commit ([0-9a-f]{40})\./);
|
|
@@ -19842,14 +19842,6 @@ function threeWayMerge(base, ours, theirs) {
|
|
|
19842
19842
|
conflicts: conflicts2
|
|
19843
19843
|
};
|
|
19844
19844
|
}
|
|
19845
|
-
function isBinaryFile(filePath) {
|
|
19846
|
-
const ext2 = (0, import_path9.extname)(filePath).toLowerCase();
|
|
19847
|
-
return BINARY_EXTENSIONS.has(ext2);
|
|
19848
|
-
}
|
|
19849
|
-
function isDiffLineForFile(diffLine, filePath) {
|
|
19850
|
-
const match2 = diffLine.match(/^diff --git a\/.+ b\/(.+)$/);
|
|
19851
|
-
return match2 !== null && match2[1] === filePath;
|
|
19852
|
-
}
|
|
19853
19845
|
function stripConflictMarkers(content) {
|
|
19854
19846
|
const lines = content.split("\n");
|
|
19855
19847
|
const result = [];
|
|
@@ -19876,6 +19868,14 @@ function stripConflictMarkers(content) {
|
|
|
19876
19868
|
}
|
|
19877
19869
|
return result.join("\n");
|
|
19878
19870
|
}
|
|
19871
|
+
function isBinaryFile(filePath) {
|
|
19872
|
+
const ext2 = (0, import_path9.extname)(filePath).toLowerCase();
|
|
19873
|
+
return BINARY_EXTENSIONS.has(ext2);
|
|
19874
|
+
}
|
|
19875
|
+
function isDiffLineForFile(diffLine, filePath) {
|
|
19876
|
+
const match2 = diffLine.match(/^diff --git a\/.+ b\/(.+)$/);
|
|
19877
|
+
return match2 !== null && match2[1] === filePath;
|
|
19878
|
+
}
|
|
19879
19879
|
async function bootstrap(outputDir, options) {
|
|
19880
19880
|
const git = new GitClient(outputDir);
|
|
19881
19881
|
const lockManager = new LockfileManager(outputDir);
|
|
@@ -20065,30 +20065,136 @@ function computeContentHash(patchContent) {
|
|
|
20065
20065
|
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
20066
20066
|
return `sha256:${(0, import_crypto3.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
20067
20067
|
}
|
|
20068
|
-
function
|
|
20068
|
+
function parseDiffStat(patchContent) {
|
|
20069
|
+
let additions = 0;
|
|
20070
|
+
let deletions = 0;
|
|
20071
|
+
let inDiffHunk = false;
|
|
20072
|
+
for (const line of patchContent.split("\n")) {
|
|
20073
|
+
if (line.startsWith("diff --git ")) {
|
|
20074
|
+
inDiffHunk = true;
|
|
20075
|
+
continue;
|
|
20076
|
+
}
|
|
20077
|
+
if (!inDiffHunk) continue;
|
|
20078
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
20079
|
+
additions++;
|
|
20080
|
+
} else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
20081
|
+
deletions++;
|
|
20082
|
+
}
|
|
20083
|
+
}
|
|
20084
|
+
return { additions, deletions };
|
|
20085
|
+
}
|
|
20086
|
+
function toMatchedPatch(patch) {
|
|
20087
|
+
return {
|
|
20088
|
+
id: patch.id,
|
|
20089
|
+
message: patch.original_message,
|
|
20090
|
+
files: patch.files,
|
|
20091
|
+
diffstat: parseDiffStat(patch.patch_content),
|
|
20092
|
+
...patch.status ? { status: patch.status } : {}
|
|
20093
|
+
};
|
|
20094
|
+
}
|
|
20095
|
+
function matchesPatch(patch, pattern) {
|
|
20096
|
+
const fileMatch = patch.files.some(
|
|
20097
|
+
(file) => file === pattern || minimatch(file, pattern)
|
|
20098
|
+
);
|
|
20099
|
+
if (fileMatch) return true;
|
|
20100
|
+
return patch.original_message.toLowerCase().includes(pattern.toLowerCase());
|
|
20101
|
+
}
|
|
20102
|
+
function buildWarnings(patches) {
|
|
20103
|
+
const warnings = [];
|
|
20104
|
+
for (const patch of patches) {
|
|
20105
|
+
if (patch.status === "resolving") {
|
|
20106
|
+
warnings.push(
|
|
20107
|
+
`patch ${patch.id} has conflict markers in these files: ${patch.files.join(", ")}. Run \`git checkout -- <files>\` to restore the generated versions.`
|
|
20108
|
+
);
|
|
20109
|
+
} else if (patch.status === "unresolved") {
|
|
20110
|
+
warnings.push(
|
|
20111
|
+
`patch ${patch.id} had unresolved conflicts (files: ${patch.files.join(", ")}).`
|
|
20112
|
+
);
|
|
20113
|
+
}
|
|
20114
|
+
}
|
|
20115
|
+
return warnings;
|
|
20116
|
+
}
|
|
20117
|
+
function forget(outputDir, options) {
|
|
20069
20118
|
const lockManager = new LockfileManager(outputDir);
|
|
20070
20119
|
if (!lockManager.exists()) {
|
|
20071
|
-
return {
|
|
20120
|
+
return { ...EMPTY_RESULT };
|
|
20072
20121
|
}
|
|
20073
20122
|
const lock = lockManager.read();
|
|
20074
|
-
const
|
|
20075
|
-
|
|
20076
|
-
|
|
20077
|
-
|
|
20078
|
-
|
|
20123
|
+
const totalPatches = lock.patches.length;
|
|
20124
|
+
if (options?.all) {
|
|
20125
|
+
const removed = lock.patches.map(toMatchedPatch);
|
|
20126
|
+
const warnings = buildWarnings(lock.patches);
|
|
20127
|
+
if (!options.dryRun) {
|
|
20128
|
+
for (const patch of lock.patches) {
|
|
20129
|
+
lockManager.addForgottenHash(patch.content_hash);
|
|
20130
|
+
}
|
|
20131
|
+
lockManager.clearPatches();
|
|
20132
|
+
lockManager.save();
|
|
20133
|
+
}
|
|
20134
|
+
return {
|
|
20135
|
+
initialized: true,
|
|
20136
|
+
removed,
|
|
20137
|
+
remaining: 0,
|
|
20138
|
+
notFound: false,
|
|
20139
|
+
alreadyForgotten: [],
|
|
20140
|
+
totalPatches,
|
|
20141
|
+
warnings
|
|
20142
|
+
};
|
|
20079
20143
|
}
|
|
20080
|
-
|
|
20081
|
-
|
|
20082
|
-
|
|
20083
|
-
|
|
20084
|
-
|
|
20085
|
-
|
|
20086
|
-
|
|
20087
|
-
|
|
20144
|
+
if (options?.patchIds && options.patchIds.length > 0) {
|
|
20145
|
+
const removed = [];
|
|
20146
|
+
const alreadyForgotten = [];
|
|
20147
|
+
const patchesToRemove = [];
|
|
20148
|
+
for (const id of options.patchIds) {
|
|
20149
|
+
const patch = lock.patches.find((p) => p.id === id);
|
|
20150
|
+
if (patch) {
|
|
20151
|
+
removed.push(toMatchedPatch(patch));
|
|
20152
|
+
patchesToRemove.push(patch);
|
|
20153
|
+
} else {
|
|
20154
|
+
alreadyForgotten.push(id);
|
|
20155
|
+
}
|
|
20088
20156
|
}
|
|
20089
|
-
|
|
20157
|
+
const warnings = buildWarnings(patchesToRemove);
|
|
20158
|
+
if (!options.dryRun) {
|
|
20159
|
+
for (const patch of patchesToRemove) {
|
|
20160
|
+
lockManager.addForgottenHash(patch.content_hash);
|
|
20161
|
+
lockManager.removePatch(patch.id);
|
|
20162
|
+
}
|
|
20163
|
+
lockManager.save();
|
|
20164
|
+
}
|
|
20165
|
+
return {
|
|
20166
|
+
initialized: true,
|
|
20167
|
+
removed,
|
|
20168
|
+
remaining: totalPatches - removed.length,
|
|
20169
|
+
notFound: removed.length === 0 && alreadyForgotten.length > 0,
|
|
20170
|
+
alreadyForgotten,
|
|
20171
|
+
totalPatches,
|
|
20172
|
+
warnings
|
|
20173
|
+
};
|
|
20174
|
+
}
|
|
20175
|
+
if (options?.pattern) {
|
|
20176
|
+
const matched = lock.patches.filter((p) => matchesPatch(p, options.pattern)).map(toMatchedPatch);
|
|
20177
|
+
return {
|
|
20178
|
+
initialized: true,
|
|
20179
|
+
removed: [],
|
|
20180
|
+
remaining: totalPatches,
|
|
20181
|
+
notFound: matched.length === 0,
|
|
20182
|
+
alreadyForgotten: [],
|
|
20183
|
+
totalPatches,
|
|
20184
|
+
warnings: [],
|
|
20185
|
+
matched
|
|
20186
|
+
};
|
|
20090
20187
|
}
|
|
20091
|
-
return {
|
|
20188
|
+
return {
|
|
20189
|
+
initialized: true,
|
|
20190
|
+
removed: [],
|
|
20191
|
+
remaining: totalPatches,
|
|
20192
|
+
notFound: totalPatches === 0,
|
|
20193
|
+
alreadyForgotten: [],
|
|
20194
|
+
totalPatches,
|
|
20195
|
+
warnings: [],
|
|
20196
|
+
matched: lock.patches.map(toMatchedPatch)
|
|
20197
|
+
};
|
|
20092
20198
|
}
|
|
20093
20199
|
function reset(outputDir, options) {
|
|
20094
20200
|
const lockManager = new LockfileManager(outputDir);
|
|
@@ -20202,28 +20308,53 @@ async function getChangedFiles(git, currentGen, files) {
|
|
|
20202
20308
|
function status(outputDir) {
|
|
20203
20309
|
const lockManager = new LockfileManager(outputDir);
|
|
20204
20310
|
if (!lockManager.exists()) {
|
|
20205
|
-
return {
|
|
20311
|
+
return {
|
|
20312
|
+
initialized: false,
|
|
20313
|
+
generationCount: 0,
|
|
20314
|
+
lastGeneration: void 0,
|
|
20315
|
+
patches: [],
|
|
20316
|
+
unresolvedCount: 0,
|
|
20317
|
+
excludePatterns: []
|
|
20318
|
+
};
|
|
20206
20319
|
}
|
|
20207
20320
|
const lock = lockManager.read();
|
|
20208
20321
|
const patches = lock.patches.map((patch) => ({
|
|
20209
|
-
|
|
20210
|
-
|
|
20322
|
+
id: patch.id,
|
|
20323
|
+
type: patch.patch_content.includes("new file mode") ? "added" : "modified",
|
|
20211
20324
|
message: patch.original_message,
|
|
20212
|
-
|
|
20325
|
+
author: patch.original_author.split("<")[0]?.trim() || "unknown",
|
|
20326
|
+
sha: patch.original_commit.slice(0, 7),
|
|
20327
|
+
files: patch.files,
|
|
20328
|
+
fileCount: patch.files.length,
|
|
20329
|
+
...patch.status ? { status: patch.status } : {}
|
|
20213
20330
|
}));
|
|
20331
|
+
const unresolvedCount = lock.patches.filter(
|
|
20332
|
+
(p) => p.status === "unresolved" || p.status === "resolving"
|
|
20333
|
+
).length;
|
|
20214
20334
|
let lastGeneration;
|
|
20215
20335
|
const lastGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
|
|
20216
20336
|
if (lastGen) {
|
|
20217
20337
|
lastGeneration = {
|
|
20218
|
-
sha: lastGen.commit_sha,
|
|
20219
|
-
timestamp: lastGen.timestamp
|
|
20338
|
+
sha: lastGen.commit_sha.slice(0, 7),
|
|
20339
|
+
timestamp: lastGen.timestamp,
|
|
20340
|
+
cliVersion: lastGen.cli_version,
|
|
20341
|
+
generatorVersions: lastGen.generator_versions
|
|
20220
20342
|
};
|
|
20221
20343
|
}
|
|
20222
|
-
|
|
20344
|
+
const config = lockManager.getCustomizationsConfig();
|
|
20345
|
+
const excludePatterns = config.exclude ?? [];
|
|
20346
|
+
return {
|
|
20347
|
+
initialized: true,
|
|
20348
|
+
generationCount: lock.generations.length,
|
|
20349
|
+
lastGeneration,
|
|
20350
|
+
patches,
|
|
20351
|
+
unresolvedCount,
|
|
20352
|
+
excludePatterns
|
|
20353
|
+
};
|
|
20223
20354
|
}
|
|
20224
|
-
var import_fs6, import_path8, import_yaml, import_crypto, import_promises4, import_os, import_path9, import_fs7, import_path10, import_crypto2, import_fs8, import_path11, import_yaml2, import_crypto3, import_fs9, import_path12, import_fs10, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, FERN_BOT_NAME2, FERN_BOT_EMAIL2, FERN_BOT_LOGIN2, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileManager, INFRASTRUCTURE_FILES, ReplayDetector, BINARY_EXTENSIONS, ReplayApplicator, ReplayCommitter, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES;
|
|
20355
|
+
var import_fs6, import_path8, import_yaml, import_crypto, import_promises4, import_os, import_path9, import_fs7, import_path10, import_crypto2, import_fs8, import_path11, import_yaml2, import_crypto3, import_fs9, import_path12, import_fs10, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, FERN_BOT_NAME2, FERN_BOT_EMAIL2, FERN_BOT_LOGIN2, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileManager, INFRASTRUCTURE_FILES, ReplayDetector, BINARY_EXTENSIONS, ReplayApplicator, ReplayCommitter, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, EMPTY_RESULT;
|
|
20225
20356
|
var init_dist = __esm({
|
|
20226
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.
|
|
20357
|
+
"../../node_modules/.pnpm/@fern-api+replay@0.9.0/node_modules/@fern-api/replay/dist/index.js"() {
|
|
20227
20358
|
"use strict";
|
|
20228
20359
|
init_esm4();
|
|
20229
20360
|
import_fs6 = require("fs");
|
|
@@ -20457,6 +20588,15 @@ var init_dist = __esm({
|
|
|
20457
20588
|
this.ensureLoaded();
|
|
20458
20589
|
this.lock.patches = [];
|
|
20459
20590
|
}
|
|
20591
|
+
addForgottenHash(hash) {
|
|
20592
|
+
this.ensureLoaded();
|
|
20593
|
+
if (!this.lock.forgotten_hashes) {
|
|
20594
|
+
this.lock.forgotten_hashes = [];
|
|
20595
|
+
}
|
|
20596
|
+
if (!this.lock.forgotten_hashes.includes(hash)) {
|
|
20597
|
+
this.lock.forgotten_hashes.push(hash);
|
|
20598
|
+
}
|
|
20599
|
+
}
|
|
20460
20600
|
getUnresolvedPatches() {
|
|
20461
20601
|
this.ensureLoaded();
|
|
20462
20602
|
return this.lock.patches.filter((p) => p.status === "unresolved");
|
|
@@ -20550,6 +20690,7 @@ var init_dist = __esm({
|
|
|
20550
20690
|
}
|
|
20551
20691
|
const commits = this.parseGitLog(log);
|
|
20552
20692
|
const newPatches = [];
|
|
20693
|
+
const forgottenHashes = new Set(lock.forgotten_hashes ?? []);
|
|
20553
20694
|
for (const commit of commits) {
|
|
20554
20695
|
if (isGenerationCommit(commit)) {
|
|
20555
20696
|
continue;
|
|
@@ -20563,7 +20704,7 @@ var init_dist = __esm({
|
|
|
20563
20704
|
}
|
|
20564
20705
|
const patchContent = await this.git.formatPatch(commit.sha);
|
|
20565
20706
|
const contentHash = this.computeContentHash(patchContent);
|
|
20566
|
-
if (lock.patches.find((p) => p.content_hash === contentHash)) {
|
|
20707
|
+
if (lock.patches.find((p) => p.content_hash === contentHash) || forgottenHashes.has(contentHash)) {
|
|
20567
20708
|
continue;
|
|
20568
20709
|
}
|
|
20569
20710
|
const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
|
|
@@ -20633,6 +20774,9 @@ var init_dist = __esm({
|
|
|
20633
20774
|
revertIndicesToRemove.add(idx);
|
|
20634
20775
|
}
|
|
20635
20776
|
}
|
|
20777
|
+
if (!matchedExisting && !matchedNew) {
|
|
20778
|
+
revertIndicesToRemove.add(i);
|
|
20779
|
+
}
|
|
20636
20780
|
}
|
|
20637
20781
|
const filteredPatches = newPatches.filter((_, i) => !revertIndicesToRemove.has(i));
|
|
20638
20782
|
return { patches: filteredPatches, revertedPatchIds: [...revertedPatchIdSet] };
|
|
@@ -20659,7 +20803,7 @@ var init_dist = __esm({
|
|
|
20659
20803
|
if (!diff.trim()) return { patches: [], revertedPatchIds: [] };
|
|
20660
20804
|
const contentHash = this.computeContentHash(diff);
|
|
20661
20805
|
const lock = this.lockManager.read();
|
|
20662
|
-
if (lock.patches.some((p) => p.content_hash === contentHash)) {
|
|
20806
|
+
if (lock.patches.some((p) => p.content_hash === contentHash) || (lock.forgotten_hashes ?? []).includes(contentHash)) {
|
|
20663
20807
|
return { patches: [], revertedPatchIds: [] };
|
|
20664
20808
|
}
|
|
20665
20809
|
const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
|
|
@@ -20756,7 +20900,8 @@ var init_dist = __esm({
|
|
|
20756
20900
|
async applyPatches(patches) {
|
|
20757
20901
|
this.resetAccumulator();
|
|
20758
20902
|
const results = [];
|
|
20759
|
-
for (
|
|
20903
|
+
for (let i = 0; i < patches.length; i++) {
|
|
20904
|
+
const patch = patches[i];
|
|
20760
20905
|
if (this.isExcluded(patch)) {
|
|
20761
20906
|
results.push({
|
|
20762
20907
|
patch,
|
|
@@ -20767,6 +20912,33 @@ var init_dist = __esm({
|
|
|
20767
20912
|
}
|
|
20768
20913
|
const result = await this.applyPatchWithFallback(patch);
|
|
20769
20914
|
results.push(result);
|
|
20915
|
+
if (result.status === "conflict" && result.fileResults) {
|
|
20916
|
+
const laterFiles = /* @__PURE__ */ new Set();
|
|
20917
|
+
for (let j = i + 1; j < patches.length; j++) {
|
|
20918
|
+
for (const f of patches[j].files) {
|
|
20919
|
+
laterFiles.add(f);
|
|
20920
|
+
}
|
|
20921
|
+
}
|
|
20922
|
+
const resolvedToOriginal = /* @__PURE__ */ new Map();
|
|
20923
|
+
if (result.resolvedFiles) {
|
|
20924
|
+
for (const [orig, resolved] of Object.entries(result.resolvedFiles)) {
|
|
20925
|
+
resolvedToOriginal.set(resolved, orig);
|
|
20926
|
+
}
|
|
20927
|
+
}
|
|
20928
|
+
for (const fileResult of result.fileResults) {
|
|
20929
|
+
if (fileResult.status !== "conflict") continue;
|
|
20930
|
+
const originalPath = resolvedToOriginal.get(fileResult.file) ?? fileResult.file;
|
|
20931
|
+
if (laterFiles.has(fileResult.file) || laterFiles.has(originalPath)) {
|
|
20932
|
+
const filePath = (0, import_path9.join)(this.outputDir, fileResult.file);
|
|
20933
|
+
try {
|
|
20934
|
+
const content = await (0, import_promises4.readFile)(filePath, "utf-8");
|
|
20935
|
+
const stripped = stripConflictMarkers(content);
|
|
20936
|
+
await (0, import_promises4.writeFile)(filePath, stripped);
|
|
20937
|
+
} catch {
|
|
20938
|
+
}
|
|
20939
|
+
}
|
|
20940
|
+
}
|
|
20941
|
+
}
|
|
20770
20942
|
}
|
|
20771
20943
|
return results;
|
|
20772
20944
|
}
|
|
@@ -20785,7 +20957,7 @@ var init_dist = __esm({
|
|
|
20785
20957
|
const resolvedPath = await this.resolveFilePath(filePath, baseGen.tree_hash, currentTreeHash);
|
|
20786
20958
|
const base = await this.git.showFile(baseGen.tree_hash, filePath);
|
|
20787
20959
|
const theirs = await this.applyPatchToContent(base, patch.patch_content, filePath, tempGit, tempDir);
|
|
20788
|
-
if (theirs
|
|
20960
|
+
if (theirs) {
|
|
20789
20961
|
this.fileTheirsAccumulator.set(resolvedPath, {
|
|
20790
20962
|
content: theirs,
|
|
20791
20963
|
baseGeneration: patch.base_generation
|
|
@@ -20917,7 +21089,7 @@ var init_dist = __esm({
|
|
|
20917
21089
|
);
|
|
20918
21090
|
let useAccumulatorAsMergeBase = false;
|
|
20919
21091
|
const accumulatorEntry = this.fileTheirsAccumulator.get(resolvedPath);
|
|
20920
|
-
if (!theirs &&
|
|
21092
|
+
if (!theirs && accumulatorEntry) {
|
|
20921
21093
|
theirs = await this.applyPatchToContent(
|
|
20922
21094
|
accumulatorEntry.content,
|
|
20923
21095
|
patch.patch_content,
|
|
@@ -20976,7 +21148,7 @@ var init_dist = __esm({
|
|
|
20976
21148
|
reason: "missing-content"
|
|
20977
21149
|
};
|
|
20978
21150
|
}
|
|
20979
|
-
if (!base || !ours) {
|
|
21151
|
+
if (!base && !useAccumulatorAsMergeBase || !ours) {
|
|
20980
21152
|
return {
|
|
20981
21153
|
file: resolvedPath,
|
|
20982
21154
|
status: "skipped",
|
|
@@ -20984,11 +21156,18 @@ var init_dist = __esm({
|
|
|
20984
21156
|
};
|
|
20985
21157
|
}
|
|
20986
21158
|
const mergeBase = useAccumulatorAsMergeBase && accumulatorEntry ? accumulatorEntry.content : base;
|
|
21159
|
+
if (mergeBase == null) {
|
|
21160
|
+
return {
|
|
21161
|
+
file: resolvedPath,
|
|
21162
|
+
status: "skipped",
|
|
21163
|
+
reason: "missing-content"
|
|
21164
|
+
};
|
|
21165
|
+
}
|
|
20987
21166
|
const merged = threeWayMerge(mergeBase, ours, effective_theirs);
|
|
20988
21167
|
const outDir = (0, import_path9.dirname)(oursPath);
|
|
20989
21168
|
await (0, import_promises4.mkdir)(outDir, { recursive: true });
|
|
20990
21169
|
await (0, import_promises4.writeFile)(oursPath, merged.content);
|
|
20991
|
-
if (effective_theirs
|
|
21170
|
+
if (effective_theirs) {
|
|
20992
21171
|
this.fileTheirsAccumulator.set(resolvedPath, {
|
|
20993
21172
|
content: effective_theirs,
|
|
20994
21173
|
baseGeneration: patch.base_generation
|
|
@@ -21979,6 +22158,15 @@ CLI Version: ${options.cliVersion}`;
|
|
|
21979
22158
|
};
|
|
21980
22159
|
init_GitClient();
|
|
21981
22160
|
REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml"];
|
|
22161
|
+
EMPTY_RESULT = {
|
|
22162
|
+
initialized: false,
|
|
22163
|
+
removed: [],
|
|
22164
|
+
remaining: 0,
|
|
22165
|
+
notFound: false,
|
|
22166
|
+
alreadyForgotten: [],
|
|
22167
|
+
totalPatches: 0,
|
|
22168
|
+
warnings: []
|
|
22169
|
+
};
|
|
21982
22170
|
init_GitClient();
|
|
21983
22171
|
}
|
|
21984
22172
|
});
|
|
@@ -32328,6 +32516,12 @@ var PostGenerationPipeline = class {
|
|
|
32328
32516
|
}
|
|
32329
32517
|
};
|
|
32330
32518
|
|
|
32519
|
+
// src/replay/replay-forget.ts
|
|
32520
|
+
init_dist();
|
|
32521
|
+
function replayForget(params) {
|
|
32522
|
+
return forget(params.outputDir, params.options);
|
|
32523
|
+
}
|
|
32524
|
+
|
|
32331
32525
|
// src/replay/replay-init.ts
|
|
32332
32526
|
init_dist();
|
|
32333
32527
|
var import_fs13 = require("fs");
|
|
@@ -32477,6 +32671,12 @@ function buildPrBody(result) {
|
|
|
32477
32671
|
// src/replay/replay-resolve.ts
|
|
32478
32672
|
init_dist();
|
|
32479
32673
|
|
|
32674
|
+
// src/replay/replay-status.ts
|
|
32675
|
+
init_dist();
|
|
32676
|
+
function replayStatus(params) {
|
|
32677
|
+
return status(params.outputDir);
|
|
32678
|
+
}
|
|
32679
|
+
|
|
32480
32680
|
// src/configuration/loadGitHubConfig.ts
|
|
32481
32681
|
var import_promises6 = require("fs/promises");
|
|
32482
32682
|
async function loadGitHubConfig({
|
|
@@ -32853,6 +33053,84 @@ Bootstrap complete! Lockfile saved to ${outputDir}/.fern/replay.lock
|
|
|
32853
33053
|
} catch (error) {
|
|
32854
33054
|
const errorMessage = extractErrorMessage(error);
|
|
32855
33055
|
process.stderr.write(`Bootstrap failed: ${errorMessage}
|
|
33056
|
+
`);
|
|
33057
|
+
process.exit(1);
|
|
33058
|
+
}
|
|
33059
|
+
}
|
|
33060
|
+
).command(
|
|
33061
|
+
"status [directory]",
|
|
33062
|
+
false,
|
|
33063
|
+
// hidden from --help
|
|
33064
|
+
(subYargs) => {
|
|
33065
|
+
return subYargs.positional("directory", {
|
|
33066
|
+
type: "string",
|
|
33067
|
+
default: ".",
|
|
33068
|
+
description: "SDK directory containing .fern/replay.lock"
|
|
33069
|
+
});
|
|
33070
|
+
},
|
|
33071
|
+
(argv) => {
|
|
33072
|
+
try {
|
|
33073
|
+
const outputDir = resolve(cwd(), argv.directory ?? ".");
|
|
33074
|
+
const result = replayStatus({ outputDir });
|
|
33075
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
33076
|
+
process.exit(0);
|
|
33077
|
+
} catch (error) {
|
|
33078
|
+
const errorMessage = extractErrorMessage(error);
|
|
33079
|
+
process.stderr.write(`Replay status failed: ${errorMessage}
|
|
33080
|
+
`);
|
|
33081
|
+
process.exit(1);
|
|
33082
|
+
}
|
|
33083
|
+
}
|
|
33084
|
+
).command(
|
|
33085
|
+
"forget [args..]",
|
|
33086
|
+
false,
|
|
33087
|
+
// hidden from --help
|
|
33088
|
+
(subYargs) => {
|
|
33089
|
+
return subYargs.positional("args", {
|
|
33090
|
+
type: "string",
|
|
33091
|
+
array: true,
|
|
33092
|
+
description: "Patch IDs or search pattern"
|
|
33093
|
+
}).option("dry-run", {
|
|
33094
|
+
type: "boolean",
|
|
33095
|
+
default: false,
|
|
33096
|
+
description: "Show what would be removed without actually removing"
|
|
33097
|
+
}).option("all", {
|
|
33098
|
+
type: "boolean",
|
|
33099
|
+
default: false,
|
|
33100
|
+
description: "Remove all tracked patches"
|
|
33101
|
+
}).option("pattern", {
|
|
33102
|
+
type: "string",
|
|
33103
|
+
description: "Search pattern (file path, glob, or commit message substring)"
|
|
33104
|
+
});
|
|
33105
|
+
},
|
|
33106
|
+
(argv) => {
|
|
33107
|
+
try {
|
|
33108
|
+
const outputDir = resolve(cwd(), ".");
|
|
33109
|
+
const args = argv.args ?? [];
|
|
33110
|
+
const dryRun = argv["dry-run"];
|
|
33111
|
+
let result;
|
|
33112
|
+
if (argv.all) {
|
|
33113
|
+
result = replayForget({ outputDir, options: { all: true, dryRun } });
|
|
33114
|
+
} else if (argv.pattern) {
|
|
33115
|
+
result = replayForget({ outputDir, options: { pattern: argv.pattern, dryRun } });
|
|
33116
|
+
} else if (args.length > 0) {
|
|
33117
|
+
const allPatchIds = args.every((a) => a.startsWith("patch-"));
|
|
33118
|
+
if (allPatchIds) {
|
|
33119
|
+
result = replayForget({ outputDir, options: { patchIds: args, dryRun } });
|
|
33120
|
+
} else {
|
|
33121
|
+
result = replayForget({
|
|
33122
|
+
outputDir,
|
|
33123
|
+
options: { pattern: args[0], dryRun }
|
|
33124
|
+
});
|
|
33125
|
+
}
|
|
33126
|
+
} else {
|
|
33127
|
+
result = replayForget({ outputDir, options: { dryRun } });
|
|
33128
|
+
}
|
|
33129
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
33130
|
+
process.exit(0);
|
|
33131
|
+
} catch (error) {
|
|
33132
|
+
const errorMessage = extractErrorMessage(error);
|
|
33133
|
+
process.stderr.write(`Replay forget failed: ${errorMessage}
|
|
32856
33134
|
`);
|
|
32857
33135
|
process.exit(1);
|
|
32858
33136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fern-api/generator-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fern-api/fern.git",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"**"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@fern-api/replay": "^0.
|
|
25
|
+
"@fern-api/replay": "^0.9.0",
|
|
26
26
|
"@octokit/rest": "^22.0.1",
|
|
27
27
|
"es-toolkit": "^1.45.1",
|
|
28
28
|
"tmp-promise": "^3.0.3"
|