@fern-api/generator-cli 0.6.2 → 0.6.4

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 (4) hide show
  1. package/dist/api.js +7407 -22334
  2. package/dist/cli.js +1091 -1217
  3. package/package.json +9 -33
  4. package/lib/api.js +0 -9
package/dist/cli.js CHANGED
@@ -4867,18 +4867,18 @@ var require_build3 = __commonJS({
4867
4867
  var require_sync = __commonJS({
4868
4868
  "../../node_modules/.pnpm/escalade@3.2.0/node_modules/escalade/sync/index.js"(exports2, module2) {
4869
4869
  "use strict";
4870
- var { dirname: dirname6, resolve: resolve8 } = require("path");
4870
+ var { dirname: dirname4, resolve: resolve8 } = require("path");
4871
4871
  var { readdirSync: readdirSync2, statSync: statSync4 } = require("fs");
4872
4872
  module2.exports = function(start, callback) {
4873
4873
  let dir = resolve8(".", start);
4874
4874
  let tmp3, stats = statSync4(dir);
4875
4875
  if (!stats.isDirectory()) {
4876
- dir = dirname6(dir);
4876
+ dir = dirname4(dir);
4877
4877
  }
4878
4878
  while (true) {
4879
4879
  tmp3 = callback(dir, readdirSync2(dir));
4880
4880
  if (tmp3) return resolve8(dir, tmp3);
4881
- dir = dirname6(tmp3 = dir);
4881
+ dir = dirname4(tmp3 = dir);
4882
4882
  if (tmp3 === dir) break;
4883
4883
  }
4884
4884
  };
@@ -4914,9 +4914,9 @@ var require_require_directory = __commonJS({
4914
4914
  "../../node_modules/.pnpm/require-directory@2.1.1/node_modules/require-directory/index.js"(exports2, module2) {
4915
4915
  "use strict";
4916
4916
  var fs3 = require("fs");
4917
- var join11 = require("path").join;
4917
+ var join9 = require("path").join;
4918
4918
  var resolve8 = require("path").resolve;
4919
- var dirname6 = require("path").dirname;
4919
+ var dirname4 = require("path").dirname;
4920
4920
  var defaultOptions2 = {
4921
4921
  extensions: ["js", "json", "coffee"],
4922
4922
  recurse: true,
@@ -4949,9 +4949,9 @@ var require_require_directory = __commonJS({
4949
4949
  options[prop] = defaultOptions2[prop];
4950
4950
  }
4951
4951
  }
4952
- path5 = !path5 ? dirname6(m.filename) : resolve8(dirname6(m.filename), path5);
4952
+ path5 = !path5 ? dirname4(m.filename) : resolve8(dirname4(m.filename), path5);
4953
4953
  fs3.readdirSync(path5).forEach(function(filename) {
4954
- var joined = join11(path5, filename), files, key, obj;
4954
+ var joined = join9(path5, filename), files, key, obj;
4955
4955
  if (fs3.statSync(joined).isDirectory() && options.recurse) {
4956
4956
  files = requireDirectory(m, joined, options);
4957
4957
  if (Object.keys(files).length) {
@@ -6604,7 +6604,7 @@ var require_ms = __commonJS({
6604
6604
  options = options || {};
6605
6605
  var type = typeof val;
6606
6606
  if (type === "string" && val.length > 0) {
6607
- return parse4(val);
6607
+ return parse3(val);
6608
6608
  } else if (type === "number" && isFinite(val)) {
6609
6609
  return options.long ? fmtLong(val) : fmtShort(val);
6610
6610
  }
@@ -6612,7 +6612,7 @@ var require_ms = __commonJS({
6612
6612
  "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
6613
6613
  );
6614
6614
  };
6615
- function parse4(str) {
6615
+ function parse3(str) {
6616
6616
  str = String(str);
6617
6617
  if (str.length > 100) {
6618
6618
  return;
@@ -7387,11 +7387,11 @@ var require_src2 = __commonJS({
7387
7387
  var require_dist = __commonJS({
7388
7388
  "../../node_modules/.pnpm/@kwsites+file-exists@1.1.1/node_modules/@kwsites/file-exists/dist/index.js"(exports2) {
7389
7389
  "use strict";
7390
- function __export3(m) {
7390
+ function __export4(m) {
7391
7391
  for (var p in m) if (!exports2.hasOwnProperty(p)) exports2[p] = m[p];
7392
7392
  }
7393
7393
  Object.defineProperty(exports2, "__esModule", { value: true });
7394
- __export3(require_src2());
7394
+ __export4(require_src2());
7395
7395
  }
7396
7396
  });
7397
7397
 
@@ -7654,7 +7654,7 @@ function parseStringResponse(result, parsers12, texts, trim = true) {
7654
7654
  }
7655
7655
  return lines[i + offset];
7656
7656
  };
7657
- parsers12.some(({ parse: parse4 }) => parse4(line, result));
7657
+ parsers12.some(({ parse: parse3 }) => parse3(line, result));
7658
7658
  }
7659
7659
  });
7660
7660
  return result;
@@ -11898,7 +11898,7 @@ var require_fast_content_type_parse = __commonJS({
11898
11898
  var defaultContentType = { type: "", parameters: new NullObject() };
11899
11899
  Object.freeze(defaultContentType.parameters);
11900
11900
  Object.freeze(defaultContentType);
11901
- function parse4(header) {
11901
+ function parse3(header) {
11902
11902
  if (typeof header !== "string") {
11903
11903
  throw new TypeError("argument header is required and must be a string");
11904
11904
  }
@@ -11974,148 +11974,13 @@ var require_fast_content_type_parse = __commonJS({
11974
11974
  }
11975
11975
  return result;
11976
11976
  }
11977
- module2.exports.default = { parse: parse4, safeParse: safeParse2 };
11978
- module2.exports.parse = parse4;
11977
+ module2.exports.default = { parse: parse3, safeParse: safeParse2 };
11978
+ module2.exports.parse = parse3;
11979
11979
  module2.exports.safeParse = safeParse2;
11980
11980
  module2.exports.defaultContentType = defaultContentType;
11981
11981
  }
11982
11982
  });
11983
11983
 
11984
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/GitClient.js
11985
- var GitClient_exports = {};
11986
- __export(GitClient_exports, {
11987
- GitClient: () => GitClient
11988
- });
11989
- var GitClient;
11990
- var init_GitClient = __esm({
11991
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/GitClient.js"() {
11992
- "use strict";
11993
- init_esm4();
11994
- GitClient = class {
11995
- git;
11996
- repoPath;
11997
- constructor(repoPath) {
11998
- this.repoPath = repoPath;
11999
- this.git = simpleGit(repoPath);
12000
- }
12001
- async exec(args) {
12002
- return this.git.raw(args);
12003
- }
12004
- async execWithInput(args, input) {
12005
- const { spawn: spawn2 } = await import("child_process");
12006
- return new Promise((resolve8, reject) => {
12007
- const proc = spawn2("git", args, { cwd: this.repoPath });
12008
- let stdout = "";
12009
- let stderr = "";
12010
- proc.stdout.on("data", (data) => {
12011
- stdout += data.toString();
12012
- });
12013
- proc.stderr.on("data", (data) => {
12014
- stderr += data.toString();
12015
- });
12016
- proc.on("close", (code) => {
12017
- if (code === 0) {
12018
- resolve8(stdout);
12019
- } else {
12020
- reject(new Error(`git ${args.join(" ")} failed (code ${code}): ${stderr}`));
12021
- }
12022
- });
12023
- proc.stdin.write(input);
12024
- proc.stdin.end();
12025
- });
12026
- }
12027
- async formatPatch(commitSha) {
12028
- return this.exec(["format-patch", "-1", commitSha, "--stdout"]);
12029
- }
12030
- async applyPatch(patchContent) {
12031
- await this.execWithInput(["am", "--3way"], patchContent);
12032
- }
12033
- async getTreeHash(commitSha) {
12034
- return (await this.exec(["rev-parse", `${commitSha}^{tree}`])).trim();
12035
- }
12036
- async showFile(treeish, filePath) {
12037
- try {
12038
- return await this.exec(["show", `${treeish}:${filePath}`]);
12039
- } catch {
12040
- return null;
12041
- }
12042
- }
12043
- async getCommitInfo(commitSha) {
12044
- const format3 = "%H%x00%an%x00%ae%x00%s";
12045
- const output = await this.exec(["log", "-1", `--format=${format3}`, commitSha]);
12046
- const [sha, authorName, authorEmail, message] = output.trim().split("\0");
12047
- return { sha, authorName, authorEmail, message };
12048
- }
12049
- async getCommitParents(commitSha) {
12050
- const output = await this.exec(["rev-parse", `${commitSha}^@`]);
12051
- return output.trim().split("\n").filter(Boolean);
12052
- }
12053
- async detectRenames(fromTree, toTree) {
12054
- try {
12055
- const output = await this.exec(["diff", "--find-renames", "--name-status", fromTree, toTree]);
12056
- const renames = [];
12057
- for (const line of output.trim().split("\n")) {
12058
- if (!line)
12059
- continue;
12060
- if (line.startsWith("R")) {
12061
- const parts = line.split(" ");
12062
- if (parts.length >= 3) {
12063
- renames.push({ from: parts[1], to: parts[2] });
12064
- }
12065
- }
12066
- }
12067
- return renames;
12068
- } catch {
12069
- return [];
12070
- }
12071
- }
12072
- async isAncestor(commit, descendant) {
12073
- try {
12074
- const mergeBase = (await this.exec(["merge-base", commit, descendant])).trim();
12075
- return mergeBase === commit;
12076
- } catch {
12077
- return false;
12078
- }
12079
- }
12080
- async commitExists(sha) {
12081
- try {
12082
- const type = await this.exec(["cat-file", "-t", sha]);
12083
- return type.trim() === "commit";
12084
- } catch {
12085
- return false;
12086
- }
12087
- }
12088
- getRepoPath() {
12089
- return this.repoPath;
12090
- }
12091
- };
12092
- }
12093
- });
12094
-
12095
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/CommitDetection.js
12096
- function isGenerationCommit(commit) {
12097
- const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
12098
- const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN2 || commit.authorEmail === FERN_BOT_EMAIL2 || commit.authorName === FERN_BOT_NAME2);
12099
- const hasGenerationMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || // Squash merge of a Fern-generated PR uses the PR title as commit message.
12100
- // The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
12101
- // GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
12102
- commit.message.startsWith("SDK Generation");
12103
- return isBotAuthor || hasGenerationMarker;
12104
- }
12105
- function isReplayCommit(commit) {
12106
- return commit.message.startsWith("[fern-replay]");
12107
- }
12108
- var FERN_BOT_NAME2, FERN_BOT_EMAIL2, FERN_BOT_LOGIN2, FERN_SUPPORT_NAMES;
12109
- var init_CommitDetection = __esm({
12110
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/CommitDetection.js"() {
12111
- "use strict";
12112
- FERN_BOT_NAME2 = "fern-api";
12113
- FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
12114
- FERN_BOT_LOGIN2 = "fern-api[bot]";
12115
- FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
12116
- }
12117
- });
12118
-
12119
11984
  // ../../node_modules/.pnpm/yaml@2.3.3/node_modules/yaml/dist/nodes/identity.js
12120
11985
  var require_identity = __commonJS({
12121
11986
  "../../node_modules/.pnpm/yaml@2.3.3/node_modules/yaml/dist/nodes/identity.js"(exports2) {
@@ -19145,7 +19010,7 @@ var require_public_api = __commonJS({
19145
19010
  }
19146
19011
  return doc;
19147
19012
  }
19148
- function parse4(src, reviver, options) {
19013
+ function parse3(src, reviver, options) {
19149
19014
  let _reviver = void 0;
19150
19015
  if (typeof reviver === "function") {
19151
19016
  _reviver = reviver;
@@ -19184,7 +19049,7 @@ var require_public_api = __commonJS({
19184
19049
  }
19185
19050
  return new Document.Document(value, _replacer, options).toString(options);
19186
19051
  }
19187
- exports2.parse = parse4;
19052
+ exports2.parse = parse3;
19188
19053
  exports2.parseAllDocuments = parseAllDocuments;
19189
19054
  exports2.parseDocument = parseDocument;
19190
19055
  exports2.stringify = stringify3;
@@ -19243,485 +19108,259 @@ var require_dist3 = __commonJS({
19243
19108
  }
19244
19109
  });
19245
19110
 
19246
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/LockfileManager.js
19247
- var import_node_fs, import_node_path2, import_yaml, LOCKFILE_HEADER, LockfileManager;
19248
- var init_LockfileManager = __esm({
19249
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/LockfileManager.js"() {
19250
- "use strict";
19251
- import_node_fs = require("fs");
19252
- import_node_path2 = require("path");
19253
- import_yaml = __toESM(require_dist3(), 1);
19254
- LOCKFILE_HEADER = "# DO NOT EDIT MANUALLY - Managed by Fern Replay\n";
19255
- LockfileManager = class {
19256
- outputDir;
19257
- lock = null;
19258
- constructor(outputDir) {
19259
- this.outputDir = outputDir;
19260
- }
19261
- get lockfilePath() {
19262
- return (0, import_node_path2.join)(this.outputDir, ".fern", "replay.lock");
19263
- }
19264
- get customizationsPath() {
19265
- return (0, import_node_path2.join)(this.outputDir, ".fern", "replay.yml");
19266
- }
19267
- exists() {
19268
- return (0, import_node_fs.existsSync)(this.lockfilePath);
19269
- }
19270
- read() {
19271
- if (this.lock) {
19272
- return this.lock;
19273
- }
19274
- if (!this.exists()) {
19275
- throw new Error(`Lockfile not found: ${this.lockfilePath}`);
19111
+ // ../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs
19112
+ function LCS(buffer1, buffer2) {
19113
+ let equivalenceClasses = {};
19114
+ for (let j = 0; j < buffer2.length; j++) {
19115
+ const item = buffer2[j];
19116
+ if (equivalenceClasses[item]) {
19117
+ equivalenceClasses[item].push(j);
19118
+ } else {
19119
+ equivalenceClasses[item] = [j];
19120
+ }
19121
+ }
19122
+ const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };
19123
+ let candidates = [NULLRESULT];
19124
+ for (let i = 0; i < buffer1.length; i++) {
19125
+ const item = buffer1[i];
19126
+ const buffer2indices = equivalenceClasses[item] || [];
19127
+ let r = 0;
19128
+ let c = candidates[0];
19129
+ for (let jx = 0; jx < buffer2indices.length; jx++) {
19130
+ const j = buffer2indices[jx];
19131
+ let s;
19132
+ for (s = r; s < candidates.length; s++) {
19133
+ if (candidates[s].buffer2index < j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > j)) {
19134
+ break;
19276
19135
  }
19277
- const content = (0, import_node_fs.readFileSync)(this.lockfilePath, "utf-8");
19278
- this.lock = (0, import_yaml.parse)(content);
19279
- return this.lock;
19280
- }
19281
- initialize(firstGeneration) {
19282
- this.initializeInMemory(firstGeneration);
19283
- this.save();
19284
- }
19285
- /**
19286
- * Set up in-memory lock state without writing to disk.
19287
- * Useful for bootstrap dry-run where we need state for detection
19288
- * but don't want to persist anything.
19289
- */
19290
- initializeInMemory(firstGeneration) {
19291
- this.lock = {
19292
- version: "1.0",
19293
- generations: [firstGeneration],
19294
- current_generation: firstGeneration.commit_sha,
19295
- patches: []
19296
- };
19297
19136
  }
19298
- save() {
19299
- if (!this.lock) {
19300
- throw new Error("No lockfile data to save. Call read() or initialize() first.");
19137
+ if (s < candidates.length) {
19138
+ const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] };
19139
+ if (r === candidates.length) {
19140
+ candidates.push(c);
19141
+ } else {
19142
+ candidates[r] = c;
19301
19143
  }
19302
- const dir = (0, import_node_path2.dirname)(this.lockfilePath);
19303
- if (!(0, import_node_fs.existsSync)(dir)) {
19304
- (0, import_node_fs.mkdirSync)(dir, { recursive: true });
19144
+ r = s + 1;
19145
+ c = newCandidate;
19146
+ if (r === candidates.length) {
19147
+ break;
19305
19148
  }
19306
- const yaml = (0, import_yaml.stringify)(this.lock, {
19307
- lineWidth: 0,
19308
- blockQuote: "literal"
19309
- });
19310
- const content = LOCKFILE_HEADER + yaml;
19311
- const tmpPath = this.lockfilePath + ".tmp";
19312
- (0, import_node_fs.writeFileSync)(tmpPath, content, "utf-8");
19313
- (0, import_node_fs.renameSync)(tmpPath, this.lockfilePath);
19314
19149
  }
19315
- addGeneration(record2) {
19316
- this.ensureLoaded();
19317
- this.lock.generations.push(record2);
19318
- this.lock.current_generation = record2.commit_sha;
19150
+ }
19151
+ candidates[r] = c;
19152
+ }
19153
+ return candidates[candidates.length - 1];
19154
+ }
19155
+ function diffIndices(buffer1, buffer2) {
19156
+ const lcs = LCS(buffer1, buffer2);
19157
+ let result = [];
19158
+ let tail1 = buffer1.length;
19159
+ let tail2 = buffer2.length;
19160
+ for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {
19161
+ const mismatchLength1 = tail1 - candidate.buffer1index - 1;
19162
+ const mismatchLength2 = tail2 - candidate.buffer2index - 1;
19163
+ tail1 = candidate.buffer1index;
19164
+ tail2 = candidate.buffer2index;
19165
+ if (mismatchLength1 || mismatchLength2) {
19166
+ result.push({
19167
+ buffer1: [tail1 + 1, mismatchLength1],
19168
+ buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
19169
+ buffer2: [tail2 + 1, mismatchLength2],
19170
+ buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
19171
+ });
19172
+ }
19173
+ }
19174
+ result.reverse();
19175
+ return result;
19176
+ }
19177
+ function diff3MergeRegions(a, o, b) {
19178
+ let hunks = [];
19179
+ function addHunk(h, ab) {
19180
+ hunks.push({
19181
+ ab,
19182
+ oStart: h.buffer1[0],
19183
+ oLength: h.buffer1[1],
19184
+ abStart: h.buffer2[0],
19185
+ abLength: h.buffer2[1]
19186
+ });
19187
+ }
19188
+ diffIndices(o, a).forEach((item) => addHunk(item, "a"));
19189
+ diffIndices(o, b).forEach((item) => addHunk(item, "b"));
19190
+ hunks.sort((x, y) => x.oStart - y.oStart);
19191
+ let results = [];
19192
+ let currOffset = 0;
19193
+ function advanceTo(endOffset) {
19194
+ if (endOffset > currOffset) {
19195
+ results.push({
19196
+ stable: true,
19197
+ buffer: "o",
19198
+ bufferStart: currOffset,
19199
+ bufferLength: endOffset - currOffset,
19200
+ bufferContent: o.slice(currOffset, endOffset)
19201
+ });
19202
+ currOffset = endOffset;
19203
+ }
19204
+ }
19205
+ while (hunks.length) {
19206
+ let hunk = hunks.shift();
19207
+ let regionStart = hunk.oStart;
19208
+ let regionEnd = hunk.oStart + hunk.oLength;
19209
+ let regionHunks = [hunk];
19210
+ advanceTo(regionStart);
19211
+ while (hunks.length) {
19212
+ const nextHunk = hunks[0];
19213
+ const nextHunkStart = nextHunk.oStart;
19214
+ if (nextHunkStart > regionEnd)
19215
+ break;
19216
+ regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
19217
+ regionHunks.push(hunks.shift());
19218
+ }
19219
+ if (regionHunks.length === 1) {
19220
+ if (hunk.abLength > 0) {
19221
+ const buffer = hunk.ab === "a" ? a : b;
19222
+ results.push({
19223
+ stable: true,
19224
+ buffer: hunk.ab,
19225
+ bufferStart: hunk.abStart,
19226
+ bufferLength: hunk.abLength,
19227
+ bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
19228
+ });
19319
19229
  }
19320
- addPatch(patch) {
19321
- this.ensureLoaded();
19322
- this.lock.patches.push(patch);
19230
+ } else {
19231
+ let bounds = {
19232
+ a: [a.length, -1, o.length, -1],
19233
+ b: [b.length, -1, o.length, -1]
19234
+ };
19235
+ while (regionHunks.length) {
19236
+ hunk = regionHunks.shift();
19237
+ const oStart = hunk.oStart;
19238
+ const oEnd = oStart + hunk.oLength;
19239
+ const abStart = hunk.abStart;
19240
+ const abEnd = abStart + hunk.abLength;
19241
+ let b2 = bounds[hunk.ab];
19242
+ b2[0] = Math.min(abStart, b2[0]);
19243
+ b2[1] = Math.max(abEnd, b2[1]);
19244
+ b2[2] = Math.min(oStart, b2[2]);
19245
+ b2[3] = Math.max(oEnd, b2[3]);
19323
19246
  }
19324
- updatePatch(patchId, updates) {
19325
- this.ensureLoaded();
19326
- const patch = this.lock.patches.find((p) => p.id === patchId);
19327
- if (!patch) {
19328
- throw new Error(`Patch not found: ${patchId}`);
19329
- }
19330
- Object.assign(patch, updates);
19331
- }
19332
- removePatch(patchId) {
19333
- this.ensureLoaded();
19334
- this.lock.patches = this.lock.patches.filter((p) => p.id !== patchId);
19335
- }
19336
- clearPatches() {
19337
- this.ensureLoaded();
19338
- this.lock.patches = [];
19339
- }
19340
- getPatches() {
19341
- this.ensureLoaded();
19342
- return this.lock.patches;
19343
- }
19344
- setReplaySkippedAt(timestamp) {
19345
- this.ensureLoaded();
19346
- this.lock.replay_skipped_at = timestamp;
19347
- }
19348
- clearReplaySkippedAt() {
19349
- this.ensureLoaded();
19350
- delete this.lock.replay_skipped_at;
19351
- }
19352
- isReplaySkipped() {
19353
- this.ensureLoaded();
19354
- return this.lock.replay_skipped_at != null;
19355
- }
19356
- getGeneration(commitSha) {
19357
- this.ensureLoaded();
19358
- return this.lock.generations.find((g) => g.commit_sha === commitSha);
19359
- }
19360
- getCustomizationsConfig() {
19361
- if (!(0, import_node_fs.existsSync)(this.customizationsPath)) {
19362
- return {};
19363
- }
19364
- const content = (0, import_node_fs.readFileSync)(this.customizationsPath, "utf-8");
19365
- return (0, import_yaml.parse)(content) ?? {};
19366
- }
19367
- ensureLoaded() {
19368
- if (!this.lock) {
19369
- throw new Error("No lockfile loaded. Call read() or initialize() first.");
19370
- }
19371
- }
19372
- };
19247
+ const aStart = bounds.a[0] + (regionStart - bounds.a[2]);
19248
+ const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
19249
+ const bStart = bounds.b[0] + (regionStart - bounds.b[2]);
19250
+ const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
19251
+ let result = {
19252
+ stable: false,
19253
+ aStart,
19254
+ aLength: aEnd - aStart,
19255
+ aContent: a.slice(aStart, aEnd),
19256
+ oStart: regionStart,
19257
+ oLength: regionEnd - regionStart,
19258
+ oContent: o.slice(regionStart, regionEnd),
19259
+ bStart,
19260
+ bLength: bEnd - bStart,
19261
+ bContent: b.slice(bStart, bEnd)
19262
+ };
19263
+ results.push(result);
19264
+ }
19265
+ currOffset = regionEnd;
19373
19266
  }
19374
- });
19375
-
19376
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayDetector.js
19377
- var import_node_crypto, INFRASTRUCTURE_FILES, ReplayDetector;
19378
- var init_ReplayDetector = __esm({
19379
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayDetector.js"() {
19380
- "use strict";
19381
- import_node_crypto = require("crypto");
19382
- init_CommitDetection();
19383
- INFRASTRUCTURE_FILES = /* @__PURE__ */ new Set([".fernignore"]);
19384
- ReplayDetector = class {
19385
- git;
19386
- lockManager;
19387
- sdkOutputDir;
19388
- warnings = [];
19389
- constructor(git, lockManager, sdkOutputDir) {
19390
- this.git = git;
19391
- this.lockManager = lockManager;
19392
- this.sdkOutputDir = sdkOutputDir;
19393
- }
19394
- async detectNewPatches() {
19395
- const lock = this.lockManager.read();
19396
- const lastGen = this.getLastGeneration(lock);
19397
- if (!lastGen) {
19398
- return [];
19399
- }
19400
- const exists2 = await this.git.commitExists(lastGen.commit_sha);
19401
- if (!exists2) {
19402
- this.warnings.push(`Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Skipping new patch detection. Existing lockfile patches will still be applied.`);
19403
- return [];
19404
- }
19405
- const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
19406
- if (!isAncestor) {
19407
- return this.detectPatchesViaTreeDiff(lastGen);
19408
- }
19409
- const log = await this.git.exec([
19410
- "log",
19411
- "--format=%H%x00%an%x00%ae%x00%s",
19412
- `${lastGen.commit_sha}..HEAD`,
19413
- "--",
19414
- this.sdkOutputDir
19415
- ]);
19416
- if (!log.trim()) {
19417
- return [];
19418
- }
19419
- const commits = this.parseGitLog(log);
19420
- const newPatches = [];
19421
- for (const commit of commits) {
19422
- if (isGenerationCommit(commit)) {
19423
- continue;
19424
- }
19425
- const parents = await this.git.getCommitParents(commit.sha);
19426
- if (parents.length > 1) {
19427
- continue;
19428
- }
19429
- if (lock.patches.find((p) => p.original_commit === commit.sha)) {
19430
- continue;
19431
- }
19432
- const patchContent = await this.git.formatPatch(commit.sha);
19433
- const contentHash = this.computeContentHash(patchContent);
19434
- if (lock.patches.find((p) => p.content_hash === contentHash)) {
19435
- continue;
19436
- }
19437
- const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
19438
- const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f));
19439
- if (files.length === 0) {
19440
- continue;
19441
- }
19442
- newPatches.push({
19443
- id: `patch-${commit.sha.slice(0, 8)}`,
19444
- content_hash: contentHash,
19445
- original_commit: commit.sha,
19446
- original_message: commit.message,
19447
- original_author: `${commit.authorName} <${commit.authorEmail}>`,
19448
- base_generation: lastGen.commit_sha,
19449
- files,
19450
- patch_content: patchContent
19451
- });
19452
- }
19453
- return newPatches.reverse();
19454
- }
19455
- /**
19456
- * Compute content hash for deduplication.
19457
- * Removes commit SHA line and index lines before hashing,
19458
- * so rebased commits with same content produce the same hash.
19459
- */
19460
- computeContentHash(patchContent) {
19461
- const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
19462
- return `sha256:${(0, import_node_crypto.createHash)("sha256").update(normalized).digest("hex")}`;
19463
- }
19464
- /** Detect patches via tree diff for non-linear history. Returns a composite patch. */
19465
- async detectPatchesViaTreeDiff(lastGen) {
19466
- const filesOutput = await this.git.exec(["diff", "--name-only", lastGen.commit_sha, "HEAD"]);
19467
- const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f)).filter((f) => !f.startsWith(".fern/"));
19468
- if (files.length === 0)
19469
- return [];
19470
- const diff = await this.git.exec(["diff", lastGen.commit_sha, "HEAD", "--", ...files]);
19471
- if (!diff.trim())
19472
- return [];
19473
- const contentHash = this.computeContentHash(diff);
19474
- const lock = this.lockManager.read();
19475
- if (lock.patches.some((p) => p.content_hash === contentHash)) {
19476
- return [];
19477
- }
19478
- const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
19479
- return [
19480
- {
19481
- id: `patch-composite-${headSha.slice(0, 8)}`,
19482
- content_hash: contentHash,
19483
- original_commit: headSha,
19484
- original_message: "Customer customizations (composite)",
19485
- original_author: "composite",
19486
- base_generation: lastGen.commit_sha,
19487
- files,
19488
- patch_content: diff
19267
+ advanceTo(o.length);
19268
+ return results;
19269
+ }
19270
+ function diff3Merge(a, o, b, options) {
19271
+ let defaults3 = {
19272
+ excludeFalseConflicts: true,
19273
+ stringSeparator: /\s+/
19274
+ };
19275
+ options = Object.assign(defaults3, options);
19276
+ if (typeof a === "string")
19277
+ a = a.split(options.stringSeparator);
19278
+ if (typeof o === "string")
19279
+ o = o.split(options.stringSeparator);
19280
+ if (typeof b === "string")
19281
+ b = b.split(options.stringSeparator);
19282
+ let results = [];
19283
+ const regions = diff3MergeRegions(a, o, b);
19284
+ let okBuffer = [];
19285
+ function flushOk() {
19286
+ if (okBuffer.length) {
19287
+ results.push({ ok: okBuffer });
19288
+ }
19289
+ okBuffer = [];
19290
+ }
19291
+ function isFalseConflict(a2, b2) {
19292
+ if (a2.length !== b2.length)
19293
+ return false;
19294
+ for (let i = 0; i < a2.length; i++) {
19295
+ if (a2[i] !== b2[i])
19296
+ return false;
19297
+ }
19298
+ return true;
19299
+ }
19300
+ regions.forEach((region) => {
19301
+ if (region.stable) {
19302
+ okBuffer.push(...region.bufferContent);
19303
+ } else {
19304
+ if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
19305
+ okBuffer.push(...region.aContent);
19306
+ } else {
19307
+ flushOk();
19308
+ results.push({
19309
+ conflict: {
19310
+ a: region.aContent,
19311
+ aIndex: region.aStart,
19312
+ o: region.oContent,
19313
+ oIndex: region.oStart,
19314
+ b: region.bContent,
19315
+ bIndex: region.bStart
19489
19316
  }
19490
- ];
19491
- }
19492
- parseGitLog(log) {
19493
- return log.trim().split("\n").map((line) => {
19494
- const [sha, authorName, authorEmail, message] = line.split("\0");
19495
- return { sha, authorName, authorEmail, message };
19496
19317
  });
19497
19318
  }
19498
- getLastGeneration(lock) {
19499
- return lock.generations.find((g) => g.commit_sha === lock.current_generation);
19500
- }
19501
- };
19319
+ }
19320
+ });
19321
+ flushOk();
19322
+ return results;
19323
+ }
19324
+ var init_diff3 = __esm({
19325
+ "../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs"() {
19326
+ "use strict";
19502
19327
  }
19503
19328
  });
19504
19329
 
19505
- // ../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs
19506
- function LCS(buffer1, buffer2) {
19507
- let equivalenceClasses = {};
19508
- for (let j = 0; j < buffer2.length; j++) {
19509
- const item = buffer2[j];
19510
- if (equivalenceClasses[item]) {
19511
- equivalenceClasses[item].push(j);
19512
- } else {
19513
- equivalenceClasses[item] = [j];
19514
- }
19515
- }
19516
- const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };
19517
- let candidates = [NULLRESULT];
19518
- for (let i = 0; i < buffer1.length; i++) {
19519
- const item = buffer1[i];
19520
- const buffer2indices = equivalenceClasses[item] || [];
19521
- let r = 0;
19522
- let c = candidates[0];
19523
- for (let jx = 0; jx < buffer2indices.length; jx++) {
19524
- const j = buffer2indices[jx];
19525
- let s;
19526
- for (s = r; s < candidates.length; s++) {
19527
- if (candidates[s].buffer2index < j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > j)) {
19528
- break;
19529
- }
19530
- }
19531
- if (s < candidates.length) {
19532
- const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] };
19533
- if (r === candidates.length) {
19534
- candidates.push(c);
19535
- } else {
19536
- candidates[r] = c;
19537
- }
19538
- r = s + 1;
19539
- c = newCandidate;
19540
- if (r === candidates.length) {
19541
- break;
19542
- }
19543
- }
19544
- }
19545
- candidates[r] = c;
19546
- }
19547
- return candidates[candidates.length - 1];
19548
- }
19549
- function diffIndices(buffer1, buffer2) {
19550
- const lcs = LCS(buffer1, buffer2);
19551
- let result = [];
19552
- let tail1 = buffer1.length;
19553
- let tail2 = buffer2.length;
19554
- for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {
19555
- const mismatchLength1 = tail1 - candidate.buffer1index - 1;
19556
- const mismatchLength2 = tail2 - candidate.buffer2index - 1;
19557
- tail1 = candidate.buffer1index;
19558
- tail2 = candidate.buffer2index;
19559
- if (mismatchLength1 || mismatchLength2) {
19560
- result.push({
19561
- buffer1: [tail1 + 1, mismatchLength1],
19562
- buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
19563
- buffer2: [tail2 + 1, mismatchLength2],
19564
- buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
19565
- });
19566
- }
19567
- }
19568
- result.reverse();
19569
- return result;
19570
- }
19571
- function diff3MergeRegions(a, o, b) {
19572
- let hunks = [];
19573
- function addHunk(h, ab) {
19574
- hunks.push({
19575
- ab,
19576
- oStart: h.buffer1[0],
19577
- oLength: h.buffer1[1],
19578
- abStart: h.buffer2[0],
19579
- abLength: h.buffer2[1]
19580
- });
19581
- }
19582
- diffIndices(o, a).forEach((item) => addHunk(item, "a"));
19583
- diffIndices(o, b).forEach((item) => addHunk(item, "b"));
19584
- hunks.sort((x, y) => x.oStart - y.oStart);
19585
- let results = [];
19586
- let currOffset = 0;
19587
- function advanceTo(endOffset) {
19588
- if (endOffset > currOffset) {
19589
- results.push({
19590
- stable: true,
19591
- buffer: "o",
19592
- bufferStart: currOffset,
19593
- bufferLength: endOffset - currOffset,
19594
- bufferContent: o.slice(currOffset, endOffset)
19595
- });
19596
- currOffset = endOffset;
19597
- }
19598
- }
19599
- while (hunks.length) {
19600
- let hunk = hunks.shift();
19601
- let regionStart = hunk.oStart;
19602
- let regionEnd = hunk.oStart + hunk.oLength;
19603
- let regionHunks = [hunk];
19604
- advanceTo(regionStart);
19605
- while (hunks.length) {
19606
- const nextHunk = hunks[0];
19607
- const nextHunkStart = nextHunk.oStart;
19608
- if (nextHunkStart > regionEnd)
19609
- break;
19610
- regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
19611
- regionHunks.push(hunks.shift());
19612
- }
19613
- if (regionHunks.length === 1) {
19614
- if (hunk.abLength > 0) {
19615
- const buffer = hunk.ab === "a" ? a : b;
19616
- results.push({
19617
- stable: true,
19618
- buffer: hunk.ab,
19619
- bufferStart: hunk.abStart,
19620
- bufferLength: hunk.abLength,
19621
- bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
19622
- });
19623
- }
19624
- } else {
19625
- let bounds = {
19626
- a: [a.length, -1, o.length, -1],
19627
- b: [b.length, -1, o.length, -1]
19628
- };
19629
- while (regionHunks.length) {
19630
- hunk = regionHunks.shift();
19631
- const oStart = hunk.oStart;
19632
- const oEnd = oStart + hunk.oLength;
19633
- const abStart = hunk.abStart;
19634
- const abEnd = abStart + hunk.abLength;
19635
- let b2 = bounds[hunk.ab];
19636
- b2[0] = Math.min(abStart, b2[0]);
19637
- b2[1] = Math.max(abEnd, b2[1]);
19638
- b2[2] = Math.min(oStart, b2[2]);
19639
- b2[3] = Math.max(oEnd, b2[3]);
19640
- }
19641
- const aStart = bounds.a[0] + (regionStart - bounds.a[2]);
19642
- const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
19643
- const bStart = bounds.b[0] + (regionStart - bounds.b[2]);
19644
- const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
19645
- let result = {
19646
- stable: false,
19647
- aStart,
19648
- aLength: aEnd - aStart,
19649
- aContent: a.slice(aStart, aEnd),
19650
- oStart: regionStart,
19651
- oLength: regionEnd - regionStart,
19652
- oContent: o.slice(regionStart, regionEnd),
19653
- bStart,
19654
- bLength: bEnd - bStart,
19655
- bContent: b.slice(bStart, bEnd)
19656
- };
19657
- results.push(result);
19658
- }
19659
- currOffset = regionEnd;
19660
- }
19661
- advanceTo(o.length);
19662
- return results;
19330
+ // ../../node_modules/.pnpm/@fern-api+replay@0.6.1/node_modules/@fern-api/replay/dist/index.js
19331
+ var dist_exports = {};
19332
+ __export(dist_exports, {
19333
+ FERN_BOT_EMAIL: () => FERN_BOT_EMAIL2,
19334
+ FERN_BOT_LOGIN: () => FERN_BOT_LOGIN2,
19335
+ FERN_BOT_NAME: () => FERN_BOT_NAME2,
19336
+ FernignoreMigrator: () => FernignoreMigrator,
19337
+ GitClient: () => GitClient,
19338
+ LockfileManager: () => LockfileManager,
19339
+ ReplayApplicator: () => ReplayApplicator,
19340
+ ReplayCommitter: () => ReplayCommitter,
19341
+ ReplayDetector: () => ReplayDetector,
19342
+ ReplayService: () => ReplayService,
19343
+ bootstrap: () => bootstrap,
19344
+ forget: () => forget,
19345
+ isGenerationCommit: () => isGenerationCommit,
19346
+ isReplayCommit: () => isReplayCommit,
19347
+ reset: () => reset,
19348
+ resolve: () => resolve7,
19349
+ status: () => status,
19350
+ threeWayMerge: () => threeWayMerge
19351
+ });
19352
+ function isGenerationCommit(commit) {
19353
+ const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
19354
+ const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN2 || commit.authorEmail === FERN_BOT_EMAIL2 || commit.authorName === FERN_BOT_NAME2);
19355
+ const hasGenerationMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || // Squash merge of a Fern-generated PR uses the PR title as commit message.
19356
+ // The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
19357
+ // GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
19358
+ commit.message.startsWith("SDK Generation");
19359
+ return isBotAuthor || hasGenerationMarker;
19663
19360
  }
19664
- function diff3Merge(a, o, b, options) {
19665
- let defaults3 = {
19666
- excludeFalseConflicts: true,
19667
- stringSeparator: /\s+/
19668
- };
19669
- options = Object.assign(defaults3, options);
19670
- if (typeof a === "string")
19671
- a = a.split(options.stringSeparator);
19672
- if (typeof o === "string")
19673
- o = o.split(options.stringSeparator);
19674
- if (typeof b === "string")
19675
- b = b.split(options.stringSeparator);
19676
- let results = [];
19677
- const regions = diff3MergeRegions(a, o, b);
19678
- let okBuffer = [];
19679
- function flushOk() {
19680
- if (okBuffer.length) {
19681
- results.push({ ok: okBuffer });
19682
- }
19683
- okBuffer = [];
19684
- }
19685
- function isFalseConflict(a2, b2) {
19686
- if (a2.length !== b2.length)
19687
- return false;
19688
- for (let i = 0; i < a2.length; i++) {
19689
- if (a2[i] !== b2[i])
19690
- return false;
19691
- }
19692
- return true;
19693
- }
19694
- regions.forEach((region) => {
19695
- if (region.stable) {
19696
- okBuffer.push(...region.bufferContent);
19697
- } else {
19698
- if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
19699
- okBuffer.push(...region.aContent);
19700
- } else {
19701
- flushOk();
19702
- results.push({
19703
- conflict: {
19704
- a: region.aContent,
19705
- aIndex: region.aStart,
19706
- o: region.oContent,
19707
- oIndex: region.oStart,
19708
- b: region.bContent,
19709
- bIndex: region.bStart
19710
- }
19711
- });
19712
- }
19713
- }
19714
- });
19715
- flushOk();
19716
- return results;
19361
+ function isReplayCommit(commit) {
19362
+ return commit.message.startsWith("[fern-replay]");
19717
19363
  }
19718
- var init_diff3 = __esm({
19719
- "../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs"() {
19720
- "use strict";
19721
- }
19722
- });
19723
-
19724
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ThreeWayMerge.js
19725
19364
  function threeWayMerge(base, ours, theirs) {
19726
19365
  const baseLines = base.split("\n");
19727
19366
  const oursLines = ours.split("\n");
@@ -19757,54 +19396,702 @@ function threeWayMerge(base, ours, theirs) {
19757
19396
  conflicts: conflicts2
19758
19397
  };
19759
19398
  }
19760
- var init_ThreeWayMerge = __esm({
19761
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ThreeWayMerge.js"() {
19762
- "use strict";
19763
- init_diff3();
19764
- }
19765
- });
19766
-
19767
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayApplicator.js
19768
19399
  function isBinaryFile(filePath) {
19769
- const ext2 = (0, import_node_path3.extname)(filePath).toLowerCase();
19400
+ const ext2 = (0, import_path9.extname)(filePath).toLowerCase();
19770
19401
  return BINARY_EXTENSIONS.has(ext2);
19771
19402
  }
19772
19403
  function isDiffLineForFile(diffLine, filePath) {
19773
19404
  const match2 = diffLine.match(/^diff --git a\/.+ b\/(.+)$/);
19774
19405
  return match2 !== null && match2[1] === filePath;
19775
19406
  }
19776
- var import_promises4, import_node_os, import_node_path3, BINARY_EXTENSIONS, ReplayApplicator;
19777
- var init_ReplayApplicator = __esm({
19778
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayApplicator.js"() {
19779
- "use strict";
19780
- import_promises4 = require("fs/promises");
19781
- import_node_os = require("os");
19782
- import_node_path3 = require("path");
19783
- init_esm3();
19784
- init_ThreeWayMerge();
19785
- BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
19786
- ".png",
19787
- ".jpg",
19788
- ".jpeg",
19789
- ".gif",
19790
- ".bmp",
19791
- ".ico",
19792
- ".webp",
19793
- ".svg",
19794
- ".pdf",
19795
- ".doc",
19796
- ".docx",
19797
- ".xls",
19798
- ".xlsx",
19799
- ".ppt",
19800
- ".pptx",
19801
- ".zip",
19802
- ".gz",
19803
- ".tar",
19804
- ".bz2",
19805
- ".7z",
19806
- ".rar",
19807
- ".jar",
19407
+ async function bootstrap(outputDir, options) {
19408
+ const git = new GitClient(outputDir);
19409
+ const lockManager = new LockfileManager(outputDir);
19410
+ const maxCommits = options?.maxCommitsToScan ?? 500;
19411
+ const warnings = [];
19412
+ if (lockManager.exists() && !options?.force) {
19413
+ return {
19414
+ generationCommit: null,
19415
+ patchesDetected: 0,
19416
+ patchesCreated: 0,
19417
+ patches: [],
19418
+ fernignorePatterns: [],
19419
+ fernignoreUpdated: false,
19420
+ warnings: ["Replay lockfile already exists. Use --force to overwrite."],
19421
+ staleGenerationsSkipped: 0,
19422
+ scannedSinceGeneration: ""
19423
+ };
19424
+ }
19425
+ const genCommits = await findAllGenerationCommits(git, maxCommits);
19426
+ if (genCommits.length === 0) {
19427
+ return {
19428
+ generationCommit: null,
19429
+ patchesDetected: 0,
19430
+ patchesCreated: 0,
19431
+ patches: [],
19432
+ fernignorePatterns: [],
19433
+ fernignoreUpdated: false,
19434
+ warnings: [
19435
+ "No generation commits found in the last " + maxCommits + " commits. Run 'fern generate' first to establish a baseline."
19436
+ ],
19437
+ staleGenerationsSkipped: 0,
19438
+ scannedSinceGeneration: ""
19439
+ };
19440
+ }
19441
+ const latestGen = genCommits[0];
19442
+ const anchorSha = options?.importHistory ? latestGen.sha : (await git.exec(["rev-parse", "HEAD"])).trim();
19443
+ const treeHash = await git.getTreeHash(anchorSha);
19444
+ const genRecord = {
19445
+ commit_sha: anchorSha,
19446
+ tree_hash: treeHash,
19447
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
19448
+ cli_version: "unknown",
19449
+ generator_versions: {}
19450
+ };
19451
+ lockManager.initializeInMemory(genRecord);
19452
+ const patches = options?.importHistory ? await findAllUserPatches(git, genCommits) : [];
19453
+ const migrator = new FernignoreMigrator(git, lockManager, outputDir);
19454
+ const fernignorePatterns = migrator.readFernignorePatterns();
19455
+ let fernignoreAnalysis;
19456
+ if (options?.importHistory && migrator.fernignoreExists() && fernignorePatterns.length > 0) {
19457
+ fernignoreAnalysis = await migrator.analyzeMigration();
19458
+ if (fernignoreAnalysis.syntheticPatches.length > 0) {
19459
+ patches.push(...fernignoreAnalysis.syntheticPatches);
19460
+ }
19461
+ if (fernignoreAnalysis.fernignoreOnly.length > 0) {
19462
+ for (const file of fernignoreAnalysis.fernignoreOnly) {
19463
+ warnings.push(
19464
+ `${file}: in .fernignore but no recent commits found since last generation. File may be stale, matches generated output, or does not exist. No customization to track.`
19465
+ );
19466
+ }
19467
+ }
19468
+ }
19469
+ if (options?.dryRun) {
19470
+ return {
19471
+ generationCommit: latestGen,
19472
+ patchesDetected: patches.length,
19473
+ patchesCreated: 0,
19474
+ patches,
19475
+ fernignorePatterns,
19476
+ fernignoreAnalysis,
19477
+ fernignoreUpdated: false,
19478
+ warnings,
19479
+ staleGenerationsSkipped: genCommits.length - 1,
19480
+ scannedSinceGeneration: latestGen.sha
19481
+ };
19482
+ }
19483
+ for (const patch of patches) {
19484
+ lockManager.addPatch(patch);
19485
+ }
19486
+ lockManager.save();
19487
+ const fernignoreUpdated = ensureFernignoreEntries(outputDir);
19488
+ if (migrator.fernignoreExists() && fernignorePatterns.length > 0) {
19489
+ const action = options?.fernignoreAction ?? "skip";
19490
+ if (action === "migrate") {
19491
+ const patternsToExclude = fernignoreAnalysis?.fernignoreOnly ?? [];
19492
+ if (patternsToExclude.length > 0) {
19493
+ migrator.movePatternsToReplayYml(patternsToExclude);
19494
+ }
19495
+ }
19496
+ }
19497
+ return {
19498
+ generationCommit: latestGen,
19499
+ patchesDetected: patches.length,
19500
+ patchesCreated: patches.length,
19501
+ patches,
19502
+ fernignorePatterns,
19503
+ fernignoreAnalysis,
19504
+ fernignoreUpdated,
19505
+ warnings,
19506
+ staleGenerationsSkipped: genCommits.length - 1,
19507
+ scannedSinceGeneration: latestGen.sha
19508
+ };
19509
+ }
19510
+ async function findAllGenerationCommits(git, maxCommits) {
19511
+ const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `-${maxCommits}`]);
19512
+ if (!log.trim()) {
19513
+ return [];
19514
+ }
19515
+ const genCommits = [];
19516
+ for (const line of log.trim().split("\n")) {
19517
+ if (!line) continue;
19518
+ const [sha, authorName, authorEmail, message] = line.split("\0");
19519
+ const commit = { sha, authorName, authorEmail, message };
19520
+ if (isGenerationCommit(commit) && !isReplayCommit(commit)) {
19521
+ genCommits.push(commit);
19522
+ }
19523
+ }
19524
+ return genCommits;
19525
+ }
19526
+ async function findAllUserPatches(git, genCommits) {
19527
+ const patches = [];
19528
+ const seenHashes = /* @__PURE__ */ new Set();
19529
+ const latestGen = genCommits[0];
19530
+ const recentPatches = await extractUserPatches(git, latestGen.sha, "HEAD", latestGen.sha, seenHashes);
19531
+ patches.push(...recentPatches);
19532
+ return patches;
19533
+ }
19534
+ async function extractUserPatches(git, fromSha, toRef, baseGeneration, seenHashes) {
19535
+ const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `${fromSha}..${toRef}`]);
19536
+ if (!log.trim()) {
19537
+ return [];
19538
+ }
19539
+ const commits = parseGitLog(log);
19540
+ const patches = [];
19541
+ for (const commit of commits.reverse()) {
19542
+ if (isGenerationCommit(commit)) continue;
19543
+ const parents = await git.getCommitParents(commit.sha);
19544
+ if (parents.length > 1) continue;
19545
+ const patchContent = await git.formatPatch(commit.sha);
19546
+ const contentHash = computeContentHash(patchContent);
19547
+ if (seenHashes.has(contentHash)) continue;
19548
+ seenHashes.add(contentHash);
19549
+ const filesOutput = await git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
19550
+ patches.push({
19551
+ id: `patch-${commit.sha.slice(0, 8)}`,
19552
+ content_hash: contentHash,
19553
+ original_commit: commit.sha,
19554
+ original_message: commit.message,
19555
+ original_author: `${commit.authorName} <${commit.authorEmail}>`,
19556
+ base_generation: baseGeneration,
19557
+ files: filesOutput.trim().split("\n").filter(Boolean),
19558
+ patch_content: patchContent
19559
+ });
19560
+ }
19561
+ return patches;
19562
+ }
19563
+ function parseGitLog(log) {
19564
+ return log.trim().split("\n").filter(Boolean).map((line) => {
19565
+ const [sha, authorName, authorEmail, message] = line.split("\0");
19566
+ return { sha, authorName, authorEmail, message };
19567
+ });
19568
+ }
19569
+ function ensureFernignoreEntries(outputDir) {
19570
+ const fernignorePath = (0, import_path12.join)(outputDir, ".fernignore");
19571
+ let content = "";
19572
+ if ((0, import_fs9.existsSync)(fernignorePath)) {
19573
+ content = (0, import_fs9.readFileSync)(fernignorePath, "utf-8");
19574
+ }
19575
+ const lines = content.split("\n");
19576
+ const toAdd = [];
19577
+ for (const entry of REPLAY_FERNIGNORE_ENTRIES) {
19578
+ if (!lines.some((line) => line.trim() === entry)) {
19579
+ toAdd.push(entry);
19580
+ }
19581
+ }
19582
+ if (toAdd.length === 0) {
19583
+ return false;
19584
+ }
19585
+ if (content && !content.endsWith("\n")) {
19586
+ content += "\n";
19587
+ }
19588
+ content += toAdd.join("\n") + "\n";
19589
+ (0, import_fs9.writeFileSync)(fernignorePath, content, "utf-8");
19590
+ return true;
19591
+ }
19592
+ function computeContentHash(patchContent) {
19593
+ const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
19594
+ return `sha256:${(0, import_crypto3.createHash)("sha256").update(normalized).digest("hex")}`;
19595
+ }
19596
+ function forget(outputDir, filePattern, options) {
19597
+ const lockManager = new LockfileManager(outputDir);
19598
+ if (!lockManager.exists()) {
19599
+ return { removed: [], notFound: true };
19600
+ }
19601
+ const lock = lockManager.read();
19602
+ const matchingPatches = lock.patches.filter(
19603
+ (patch) => patch.files.some((file) => file === filePattern || minimatch(file, filePattern))
19604
+ );
19605
+ if (matchingPatches.length === 0) {
19606
+ return { removed: [], notFound: true };
19607
+ }
19608
+ const removed = matchingPatches.map((p) => ({
19609
+ id: p.id,
19610
+ message: p.original_message,
19611
+ files: p.files
19612
+ }));
19613
+ if (!options?.dryRun) {
19614
+ for (const patch of matchingPatches) {
19615
+ lockManager.removePatch(patch.id);
19616
+ }
19617
+ lockManager.save();
19618
+ }
19619
+ return { removed, notFound: false };
19620
+ }
19621
+ function reset(outputDir, options) {
19622
+ const lockManager = new LockfileManager(outputDir);
19623
+ if (!lockManager.exists()) {
19624
+ return {
19625
+ success: true,
19626
+ patchesRemoved: 0,
19627
+ lockfileDeleted: false,
19628
+ nothingToReset: true
19629
+ };
19630
+ }
19631
+ const lock = lockManager.read();
19632
+ const patchCount = lock.patches.length;
19633
+ if (!options?.dryRun) {
19634
+ (0, import_fs10.unlinkSync)(lockManager.lockfilePath);
19635
+ }
19636
+ return {
19637
+ success: true,
19638
+ patchesRemoved: patchCount,
19639
+ lockfileDeleted: true,
19640
+ nothingToReset: false
19641
+ };
19642
+ }
19643
+ async function resolve7(outputDir, options) {
19644
+ const lockManager = new LockfileManager(outputDir);
19645
+ if (!lockManager.exists()) {
19646
+ return { success: false, reason: "no-lockfile" };
19647
+ }
19648
+ const lock = lockManager.read();
19649
+ if (lock.patches.length === 0) {
19650
+ return { success: false, reason: "no-patches" };
19651
+ }
19652
+ const git = new GitClient(outputDir);
19653
+ if (options?.checkMarkers !== false) {
19654
+ const markerFiles = await git.exec(["grep", "-l", "<<<<<<<", "--", "."]).catch(() => "");
19655
+ if (markerFiles.trim()) {
19656
+ const files = markerFiles.trim().split("\n").filter(Boolean);
19657
+ return { success: false, reason: "unresolved-conflicts", unresolvedFiles: files };
19658
+ }
19659
+ }
19660
+ const committer = new ReplayCommitter(git, outputDir);
19661
+ await committer.stageAll();
19662
+ const commitSha = await committer.commitReplay(lock.patches.length, lock.patches);
19663
+ return { success: true, commitSha };
19664
+ }
19665
+ function status(outputDir) {
19666
+ const lockManager = new LockfileManager(outputDir);
19667
+ if (!lockManager.exists()) {
19668
+ return { initialized: false, patches: [], lastGeneration: void 0 };
19669
+ }
19670
+ const lock = lockManager.read();
19671
+ const patches = lock.patches.map((patch) => ({
19672
+ sha: patch.original_commit.slice(0, 7),
19673
+ author: patch.original_author.split("<")[0]?.trim() ?? "unknown",
19674
+ message: patch.original_message,
19675
+ files: patch.files
19676
+ }));
19677
+ let lastGeneration;
19678
+ const lastGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
19679
+ if (lastGen) {
19680
+ lastGeneration = {
19681
+ sha: lastGen.commit_sha,
19682
+ timestamp: lastGen.timestamp
19683
+ };
19684
+ }
19685
+ return { initialized: true, patches, lastGeneration };
19686
+ }
19687
+ 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;
19688
+ var init_dist = __esm({
19689
+ "../../node_modules/.pnpm/@fern-api+replay@0.6.1/node_modules/@fern-api/replay/dist/index.js"() {
19690
+ "use strict";
19691
+ init_esm4();
19692
+ import_fs6 = require("fs");
19693
+ import_path8 = require("path");
19694
+ import_yaml = __toESM(require_dist3(), 1);
19695
+ import_crypto = require("crypto");
19696
+ init_diff3();
19697
+ import_promises4 = require("fs/promises");
19698
+ import_os = require("os");
19699
+ import_path9 = require("path");
19700
+ init_esm3();
19701
+ import_fs7 = require("fs");
19702
+ import_path10 = require("path");
19703
+ init_esm3();
19704
+ import_crypto2 = require("crypto");
19705
+ import_fs8 = require("fs");
19706
+ import_path11 = require("path");
19707
+ init_esm3();
19708
+ import_yaml2 = __toESM(require_dist3(), 1);
19709
+ import_crypto3 = require("crypto");
19710
+ import_fs9 = require("fs");
19711
+ import_path12 = require("path");
19712
+ init_esm3();
19713
+ import_fs10 = require("fs");
19714
+ __defProp3 = Object.defineProperty;
19715
+ __getOwnPropNames3 = Object.getOwnPropertyNames;
19716
+ __esm3 = (fn, res) => function __init() {
19717
+ return fn && (res = (0, fn[__getOwnPropNames3(fn)[0]])(fn = 0)), res;
19718
+ };
19719
+ __export3 = (target, all) => {
19720
+ for (var name in all)
19721
+ __defProp3(target, name, { get: all[name], enumerable: true });
19722
+ };
19723
+ GitClient_exports = {};
19724
+ __export3(GitClient_exports, {
19725
+ GitClient: () => GitClient
19726
+ });
19727
+ init_GitClient = __esm3({
19728
+ "src/git/GitClient.ts"() {
19729
+ "use strict";
19730
+ GitClient = class {
19731
+ git;
19732
+ repoPath;
19733
+ constructor(repoPath) {
19734
+ this.repoPath = repoPath;
19735
+ this.git = simpleGit(repoPath);
19736
+ }
19737
+ async exec(args) {
19738
+ return this.git.raw(args);
19739
+ }
19740
+ async execWithInput(args, input) {
19741
+ const { spawn: spawn2 } = await import("child_process");
19742
+ return new Promise((resolve22, reject) => {
19743
+ const proc = spawn2("git", args, { cwd: this.repoPath });
19744
+ let stdout = "";
19745
+ let stderr = "";
19746
+ proc.stdout.on("data", (data) => {
19747
+ stdout += data.toString();
19748
+ });
19749
+ proc.stderr.on("data", (data) => {
19750
+ stderr += data.toString();
19751
+ });
19752
+ proc.on("close", (code) => {
19753
+ if (code === 0) {
19754
+ resolve22(stdout);
19755
+ } else {
19756
+ reject(new Error(`git ${args.join(" ")} failed (code ${code}): ${stderr}`));
19757
+ }
19758
+ });
19759
+ proc.stdin.write(input);
19760
+ proc.stdin.end();
19761
+ });
19762
+ }
19763
+ async formatPatch(commitSha) {
19764
+ return this.exec(["format-patch", "-1", commitSha, "--stdout"]);
19765
+ }
19766
+ async applyPatch(patchContent) {
19767
+ await this.execWithInput(["am", "--3way"], patchContent);
19768
+ }
19769
+ async getTreeHash(commitSha) {
19770
+ return (await this.exec(["rev-parse", `${commitSha}^{tree}`])).trim();
19771
+ }
19772
+ async showFile(treeish, filePath) {
19773
+ try {
19774
+ return await this.exec(["show", `${treeish}:${filePath}`]);
19775
+ } catch {
19776
+ return null;
19777
+ }
19778
+ }
19779
+ async getCommitInfo(commitSha) {
19780
+ const format3 = "%H%x00%an%x00%ae%x00%s";
19781
+ const output = await this.exec(["log", "-1", `--format=${format3}`, commitSha]);
19782
+ const [sha, authorName, authorEmail, message] = output.trim().split("\0");
19783
+ return { sha, authorName, authorEmail, message };
19784
+ }
19785
+ async getCommitParents(commitSha) {
19786
+ const output = await this.exec(["rev-parse", `${commitSha}^@`]);
19787
+ return output.trim().split("\n").filter(Boolean);
19788
+ }
19789
+ async detectRenames(fromTree, toTree) {
19790
+ try {
19791
+ const output = await this.exec(["diff", "--find-renames", "--name-status", fromTree, toTree]);
19792
+ const renames = [];
19793
+ for (const line of output.trim().split("\n")) {
19794
+ if (!line) continue;
19795
+ if (line.startsWith("R")) {
19796
+ const parts = line.split(" ");
19797
+ if (parts.length >= 3) {
19798
+ renames.push({ from: parts[1], to: parts[2] });
19799
+ }
19800
+ }
19801
+ }
19802
+ return renames;
19803
+ } catch {
19804
+ return [];
19805
+ }
19806
+ }
19807
+ async isAncestor(commit, descendant) {
19808
+ try {
19809
+ const mergeBase = (await this.exec(["merge-base", commit, descendant])).trim();
19810
+ return mergeBase === commit;
19811
+ } catch {
19812
+ return false;
19813
+ }
19814
+ }
19815
+ async commitExists(sha) {
19816
+ try {
19817
+ const type = await this.exec(["cat-file", "-t", sha]);
19818
+ return type.trim() === "commit";
19819
+ } catch {
19820
+ return false;
19821
+ }
19822
+ }
19823
+ getRepoPath() {
19824
+ return this.repoPath;
19825
+ }
19826
+ };
19827
+ }
19828
+ });
19829
+ init_GitClient();
19830
+ FERN_BOT_NAME2 = "fern-api";
19831
+ FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
19832
+ FERN_BOT_LOGIN2 = "fern-api[bot]";
19833
+ FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
19834
+ LOCKFILE_HEADER = "# DO NOT EDIT MANUALLY - Managed by Fern Replay\n";
19835
+ LockfileManager = class {
19836
+ outputDir;
19837
+ lock = null;
19838
+ constructor(outputDir) {
19839
+ this.outputDir = outputDir;
19840
+ }
19841
+ get lockfilePath() {
19842
+ return (0, import_path8.join)(this.outputDir, ".fern", "replay.lock");
19843
+ }
19844
+ get customizationsPath() {
19845
+ return (0, import_path8.join)(this.outputDir, ".fern", "replay.yml");
19846
+ }
19847
+ exists() {
19848
+ return (0, import_fs6.existsSync)(this.lockfilePath);
19849
+ }
19850
+ read() {
19851
+ if (this.lock) {
19852
+ return this.lock;
19853
+ }
19854
+ if (!this.exists()) {
19855
+ throw new Error(`Lockfile not found: ${this.lockfilePath}`);
19856
+ }
19857
+ const content = (0, import_fs6.readFileSync)(this.lockfilePath, "utf-8");
19858
+ this.lock = (0, import_yaml.parse)(content);
19859
+ return this.lock;
19860
+ }
19861
+ initialize(firstGeneration) {
19862
+ this.initializeInMemory(firstGeneration);
19863
+ this.save();
19864
+ }
19865
+ /**
19866
+ * Set up in-memory lock state without writing to disk.
19867
+ * Useful for bootstrap dry-run where we need state for detection
19868
+ * but don't want to persist anything.
19869
+ */
19870
+ initializeInMemory(firstGeneration) {
19871
+ this.lock = {
19872
+ version: "1.0",
19873
+ generations: [firstGeneration],
19874
+ current_generation: firstGeneration.commit_sha,
19875
+ patches: []
19876
+ };
19877
+ }
19878
+ save() {
19879
+ if (!this.lock) {
19880
+ throw new Error("No lockfile data to save. Call read() or initialize() first.");
19881
+ }
19882
+ const dir = (0, import_path8.dirname)(this.lockfilePath);
19883
+ if (!(0, import_fs6.existsSync)(dir)) {
19884
+ (0, import_fs6.mkdirSync)(dir, { recursive: true });
19885
+ }
19886
+ const yaml = (0, import_yaml.stringify)(this.lock, {
19887
+ lineWidth: 0,
19888
+ blockQuote: "literal"
19889
+ });
19890
+ const content = LOCKFILE_HEADER + yaml;
19891
+ const tmpPath = this.lockfilePath + ".tmp";
19892
+ (0, import_fs6.writeFileSync)(tmpPath, content, "utf-8");
19893
+ (0, import_fs6.renameSync)(tmpPath, this.lockfilePath);
19894
+ }
19895
+ addGeneration(record2) {
19896
+ this.ensureLoaded();
19897
+ this.lock.generations.push(record2);
19898
+ this.lock.current_generation = record2.commit_sha;
19899
+ }
19900
+ addPatch(patch) {
19901
+ this.ensureLoaded();
19902
+ this.lock.patches.push(patch);
19903
+ }
19904
+ updatePatch(patchId, updates) {
19905
+ this.ensureLoaded();
19906
+ const patch = this.lock.patches.find((p) => p.id === patchId);
19907
+ if (!patch) {
19908
+ throw new Error(`Patch not found: ${patchId}`);
19909
+ }
19910
+ Object.assign(patch, updates);
19911
+ }
19912
+ removePatch(patchId) {
19913
+ this.ensureLoaded();
19914
+ this.lock.patches = this.lock.patches.filter((p) => p.id !== patchId);
19915
+ }
19916
+ clearPatches() {
19917
+ this.ensureLoaded();
19918
+ this.lock.patches = [];
19919
+ }
19920
+ getPatches() {
19921
+ this.ensureLoaded();
19922
+ return this.lock.patches;
19923
+ }
19924
+ setReplaySkippedAt(timestamp) {
19925
+ this.ensureLoaded();
19926
+ this.lock.replay_skipped_at = timestamp;
19927
+ }
19928
+ clearReplaySkippedAt() {
19929
+ this.ensureLoaded();
19930
+ delete this.lock.replay_skipped_at;
19931
+ }
19932
+ isReplaySkipped() {
19933
+ this.ensureLoaded();
19934
+ return this.lock.replay_skipped_at != null;
19935
+ }
19936
+ getGeneration(commitSha) {
19937
+ this.ensureLoaded();
19938
+ return this.lock.generations.find((g) => g.commit_sha === commitSha);
19939
+ }
19940
+ getCustomizationsConfig() {
19941
+ if (!(0, import_fs6.existsSync)(this.customizationsPath)) {
19942
+ return {};
19943
+ }
19944
+ const content = (0, import_fs6.readFileSync)(this.customizationsPath, "utf-8");
19945
+ return (0, import_yaml.parse)(content) ?? {};
19946
+ }
19947
+ ensureLoaded() {
19948
+ if (!this.lock) {
19949
+ throw new Error("No lockfile loaded. Call read() or initialize() first.");
19950
+ }
19951
+ }
19952
+ };
19953
+ INFRASTRUCTURE_FILES = /* @__PURE__ */ new Set([".fernignore"]);
19954
+ ReplayDetector = class {
19955
+ git;
19956
+ lockManager;
19957
+ sdkOutputDir;
19958
+ warnings = [];
19959
+ constructor(git, lockManager, sdkOutputDir) {
19960
+ this.git = git;
19961
+ this.lockManager = lockManager;
19962
+ this.sdkOutputDir = sdkOutputDir;
19963
+ }
19964
+ async detectNewPatches() {
19965
+ const lock = this.lockManager.read();
19966
+ const lastGen = this.getLastGeneration(lock);
19967
+ if (!lastGen) {
19968
+ return [];
19969
+ }
19970
+ const exists2 = await this.git.commitExists(lastGen.commit_sha);
19971
+ if (!exists2) {
19972
+ this.warnings.push(
19973
+ `Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Skipping new patch detection. Existing lockfile patches will still be applied.`
19974
+ );
19975
+ return [];
19976
+ }
19977
+ const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
19978
+ if (!isAncestor) {
19979
+ return this.detectPatchesViaTreeDiff(lastGen);
19980
+ }
19981
+ const log = await this.git.exec([
19982
+ "log",
19983
+ "--format=%H%x00%an%x00%ae%x00%s",
19984
+ `${lastGen.commit_sha}..HEAD`,
19985
+ "--",
19986
+ this.sdkOutputDir
19987
+ ]);
19988
+ if (!log.trim()) {
19989
+ return [];
19990
+ }
19991
+ const commits = this.parseGitLog(log);
19992
+ const newPatches = [];
19993
+ for (const commit of commits) {
19994
+ if (isGenerationCommit(commit)) {
19995
+ continue;
19996
+ }
19997
+ const parents = await this.git.getCommitParents(commit.sha);
19998
+ if (parents.length > 1) {
19999
+ continue;
20000
+ }
20001
+ if (lock.patches.find((p) => p.original_commit === commit.sha)) {
20002
+ continue;
20003
+ }
20004
+ const patchContent = await this.git.formatPatch(commit.sha);
20005
+ const contentHash = this.computeContentHash(patchContent);
20006
+ if (lock.patches.find((p) => p.content_hash === contentHash)) {
20007
+ continue;
20008
+ }
20009
+ const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
20010
+ const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f));
20011
+ if (files.length === 0) {
20012
+ continue;
20013
+ }
20014
+ newPatches.push({
20015
+ id: `patch-${commit.sha.slice(0, 8)}`,
20016
+ content_hash: contentHash,
20017
+ original_commit: commit.sha,
20018
+ original_message: commit.message,
20019
+ original_author: `${commit.authorName} <${commit.authorEmail}>`,
20020
+ base_generation: lastGen.commit_sha,
20021
+ files,
20022
+ patch_content: patchContent
20023
+ });
20024
+ }
20025
+ return newPatches.reverse();
20026
+ }
20027
+ /**
20028
+ * Compute content hash for deduplication.
20029
+ * Removes commit SHA line and index lines before hashing,
20030
+ * so rebased commits with same content produce the same hash.
20031
+ */
20032
+ computeContentHash(patchContent) {
20033
+ const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
20034
+ return `sha256:${(0, import_crypto.createHash)("sha256").update(normalized).digest("hex")}`;
20035
+ }
20036
+ /** Detect patches via tree diff for non-linear history. Returns a composite patch. */
20037
+ async detectPatchesViaTreeDiff(lastGen) {
20038
+ const filesOutput = await this.git.exec(["diff", "--name-only", lastGen.commit_sha, "HEAD"]);
20039
+ const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f)).filter((f) => !f.startsWith(".fern/"));
20040
+ if (files.length === 0) return [];
20041
+ const diff = await this.git.exec(["diff", lastGen.commit_sha, "HEAD", "--", ...files]);
20042
+ if (!diff.trim()) return [];
20043
+ const contentHash = this.computeContentHash(diff);
20044
+ const lock = this.lockManager.read();
20045
+ if (lock.patches.some((p) => p.content_hash === contentHash)) {
20046
+ return [];
20047
+ }
20048
+ const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
20049
+ return [
20050
+ {
20051
+ id: `patch-composite-${headSha.slice(0, 8)}`,
20052
+ content_hash: contentHash,
20053
+ original_commit: headSha,
20054
+ original_message: "Customer customizations (composite)",
20055
+ original_author: "composite",
20056
+ base_generation: lastGen.commit_sha,
20057
+ files,
20058
+ patch_content: diff
20059
+ }
20060
+ ];
20061
+ }
20062
+ parseGitLog(log) {
20063
+ return log.trim().split("\n").map((line) => {
20064
+ const [sha, authorName, authorEmail, message] = line.split("\0");
20065
+ return { sha, authorName, authorEmail, message };
20066
+ });
20067
+ }
20068
+ getLastGeneration(lock) {
20069
+ return lock.generations.find((g) => g.commit_sha === lock.current_generation);
20070
+ }
20071
+ };
20072
+ BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
20073
+ ".png",
20074
+ ".jpg",
20075
+ ".jpeg",
20076
+ ".gif",
20077
+ ".bmp",
20078
+ ".ico",
20079
+ ".webp",
20080
+ ".svg",
20081
+ ".pdf",
20082
+ ".doc",
20083
+ ".docx",
20084
+ ".xls",
20085
+ ".xlsx",
20086
+ ".ppt",
20087
+ ".pptx",
20088
+ ".zip",
20089
+ ".gz",
20090
+ ".tar",
20091
+ ".bz2",
20092
+ ".7z",
20093
+ ".rar",
20094
+ ".jar",
19808
20095
  ".war",
19809
20096
  ".ear",
19810
20097
  ".class",
@@ -19869,9 +20156,8 @@ var init_ReplayApplicator = __esm({
19869
20156
  }
19870
20157
  /** Populate accumulator after git apply succeeds. */
19871
20158
  async populateAccumulatorForPatch(patch, baseGen, currentTreeHash) {
19872
- if (!baseGen)
19873
- return;
19874
- const tempDir = await (0, import_promises4.mkdtemp)((0, import_node_path3.join)((0, import_node_os.tmpdir)(), "replay-acc-"));
20159
+ if (!baseGen) return;
20160
+ const tempDir = await (0, import_promises4.mkdtemp)((0, import_path9.join)((0, import_os.tmpdir)(), "replay-acc-"));
19875
20161
  const { GitClient: GitClient2 } = await Promise.resolve().then(() => (init_GitClient(), GitClient_exports));
19876
20162
  const tempGit = new GitClient2(tempDir);
19877
20163
  await tempGit.exec(["init"]);
@@ -19879,8 +20165,7 @@ var init_ReplayApplicator = __esm({
19879
20165
  await tempGit.exec(["config", "user.name", "Fern Replay"]);
19880
20166
  try {
19881
20167
  for (const filePath of patch.files) {
19882
- if (isBinaryFile(filePath))
19883
- continue;
20168
+ if (isBinaryFile(filePath)) continue;
19884
20169
  const resolvedPath = await this.resolveFilePath(filePath, baseGen.tree_hash, currentTreeHash);
19885
20170
  const base = await this.git.showFile(baseGen.tree_hash, filePath);
19886
20171
  const theirs = await this.applyPatchToContent(base, patch.patch_content, filePath, tempGit, tempDir);
@@ -19901,12 +20186,13 @@ var init_ReplayApplicator = __esm({
19901
20186
  const lock = this.lockManager.read();
19902
20187
  const currentGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
19903
20188
  const currentTreeHash = currentGen?.tree_hash ?? baseGen?.tree_hash ?? "";
19904
- const needsAccumulation = await Promise.all(patch.files.map(async (f) => {
19905
- if (!baseGen)
19906
- return false;
19907
- const resolved = await this.resolveFilePath(f, baseGen.tree_hash, currentTreeHash);
19908
- return this.fileTheirsAccumulator.has(resolved);
19909
- })).then((results) => results.some(Boolean));
20189
+ const needsAccumulation = await Promise.all(
20190
+ patch.files.map(async (f) => {
20191
+ if (!baseGen) return false;
20192
+ const resolved = await this.resolveFilePath(f, baseGen.tree_hash, currentTreeHash);
20193
+ return this.fileTheirsAccumulator.has(resolved);
20194
+ })
20195
+ ).then((results) => results.some(Boolean));
19910
20196
  if (!needsAccumulation) {
19911
20197
  const snapshots = /* @__PURE__ */ new Map();
19912
20198
  const resolvedFiles = {};
@@ -19915,7 +20201,7 @@ var init_ReplayApplicator = __esm({
19915
20201
  if (resolvedPath !== filePath) {
19916
20202
  resolvedFiles[filePath] = resolvedPath;
19917
20203
  }
19918
- const fullPath = (0, import_node_path3.join)(this.outputDir, resolvedPath);
20204
+ const fullPath = (0, import_path9.join)(this.outputDir, resolvedPath);
19919
20205
  snapshots.set(resolvedPath, await (0, import_promises4.readFile)(fullPath, "utf-8").catch(() => null));
19920
20206
  }
19921
20207
  try {
@@ -19930,7 +20216,7 @@ var init_ReplayApplicator = __esm({
19930
20216
  } catch {
19931
20217
  for (const [resolvedPath, content] of snapshots) {
19932
20218
  if (content != null) {
19933
- await (0, import_promises4.writeFile)((0, import_node_path3.join)(this.outputDir, resolvedPath), content);
20219
+ await (0, import_promises4.writeFile)((0, import_path9.join)(this.outputDir, resolvedPath), content);
19934
20220
  }
19935
20221
  }
19936
20222
  }
@@ -19940,7 +20226,7 @@ var init_ReplayApplicator = __esm({
19940
20226
  async applyWithThreeWayMerge(patch) {
19941
20227
  const fileResults = [];
19942
20228
  const resolvedFiles = {};
19943
- const tempDir = await (0, import_promises4.mkdtemp)((0, import_node_path3.join)((0, import_node_os.tmpdir)(), "replay-"));
20229
+ const tempDir = await (0, import_promises4.mkdtemp)((0, import_path9.join)((0, import_os.tmpdir)(), "replay-"));
19944
20230
  const { GitClient: GitClient2 } = await Promise.resolve().then(() => (init_GitClient(), GitClient_exports));
19945
20231
  const tempGit = new GitClient2(tempDir);
19946
20232
  await tempGit.exec(["init"]);
@@ -20003,13 +20289,26 @@ var init_ReplayApplicator = __esm({
20003
20289
  renameSourcePath = renameSource;
20004
20290
  }
20005
20291
  }
20006
- const oursPath = (0, import_node_path3.join)(this.outputDir, resolvedPath);
20292
+ const oursPath = (0, import_path9.join)(this.outputDir, resolvedPath);
20007
20293
  const ours = await (0, import_promises4.readFile)(oursPath, "utf-8").catch(() => null);
20008
- let theirs = await this.applyPatchToContent(base, patch.patch_content, filePath, tempGit, tempDir, renameSourcePath);
20294
+ let theirs = await this.applyPatchToContent(
20295
+ base,
20296
+ patch.patch_content,
20297
+ filePath,
20298
+ tempGit,
20299
+ tempDir,
20300
+ renameSourcePath
20301
+ );
20009
20302
  let useAccumulatorAsMergeBase = false;
20010
20303
  const accumulatorEntry = this.fileTheirsAccumulator.get(resolvedPath);
20011
20304
  if (!theirs && base && accumulatorEntry) {
20012
- theirs = await this.applyPatchToContent(accumulatorEntry.content, patch.patch_content, filePath, tempGit, tempDir);
20305
+ theirs = await this.applyPatchToContent(
20306
+ accumulatorEntry.content,
20307
+ patch.patch_content,
20308
+ filePath,
20309
+ tempGit,
20310
+ tempDir
20311
+ );
20013
20312
  if (theirs) {
20014
20313
  useAccumulatorAsMergeBase = true;
20015
20314
  }
@@ -20033,14 +20332,14 @@ var init_ReplayApplicator = __esm({
20033
20332
  }
20034
20333
  }
20035
20334
  if (!base && !ours && effective_theirs) {
20036
- const outDir2 = (0, import_node_path3.dirname)(oursPath);
20335
+ const outDir2 = (0, import_path9.dirname)(oursPath);
20037
20336
  await (0, import_promises4.mkdir)(outDir2, { recursive: true });
20038
20337
  await (0, import_promises4.writeFile)(oursPath, effective_theirs);
20039
20338
  return { file: resolvedPath, status: "merged", reason: "new-file" };
20040
20339
  }
20041
20340
  if (!base && ours && effective_theirs) {
20042
20341
  const merged2 = threeWayMerge("", ours, effective_theirs);
20043
- const outDir2 = (0, import_node_path3.dirname)(oursPath);
20342
+ const outDir2 = (0, import_path9.dirname)(oursPath);
20044
20343
  await (0, import_promises4.mkdir)(outDir2, { recursive: true });
20045
20344
  await (0, import_promises4.writeFile)(oursPath, merged2.content);
20046
20345
  if (merged2.hasConflicts) {
@@ -20070,7 +20369,7 @@ var init_ReplayApplicator = __esm({
20070
20369
  }
20071
20370
  const mergeBase = useAccumulatorAsMergeBase && accumulatorEntry ? accumulatorEntry.content : base;
20072
20371
  const merged = threeWayMerge(mergeBase, ours, effective_theirs);
20073
- const outDir = (0, import_node_path3.dirname)(oursPath);
20372
+ const outDir = (0, import_path9.dirname)(oursPath);
20074
20373
  await (0, import_promises4.mkdir)(outDir, { recursive: true });
20075
20374
  await (0, import_promises4.writeFile)(oursPath, merged.content);
20076
20375
  if (effective_theirs && base) {
@@ -20099,8 +20398,7 @@ var init_ReplayApplicator = __esm({
20099
20398
  }
20100
20399
  isExcluded(patch) {
20101
20400
  const config = this.lockManager.getCustomizationsConfig();
20102
- if (!config.exclude)
20103
- return false;
20401
+ if (!config.exclude) return false;
20104
20402
  return patch.files.some((file) => config.exclude.some((pattern) => minimatch(file, pattern)));
20105
20403
  }
20106
20404
  async resolveFilePath(filePath, baseTreeHash, currentTreeHash) {
@@ -20136,12 +20434,11 @@ var init_ReplayApplicator = __esm({
20136
20434
  return this.extractNewFileFromPatch(patchContent, filePath);
20137
20435
  }
20138
20436
  const fileDiff = this.extractFileDiff(patchContent, filePath);
20139
- if (!fileDiff)
20140
- return null;
20437
+ if (!fileDiff) return null;
20141
20438
  try {
20142
20439
  if (sourceFilePath) {
20143
- const tempSourcePath = (0, import_node_path3.join)(tempDir, sourceFilePath);
20144
- await (0, import_promises4.mkdir)((0, import_node_path3.dirname)(tempSourcePath), { recursive: true });
20440
+ const tempSourcePath = (0, import_path9.join)(tempDir, sourceFilePath);
20441
+ await (0, import_promises4.mkdir)((0, import_path9.dirname)(tempSourcePath), { recursive: true });
20145
20442
  await (0, import_promises4.writeFile)(tempSourcePath, base);
20146
20443
  await tempGit.exec(["add", sourceFilePath]);
20147
20444
  await tempGit.exec([
@@ -20151,11 +20448,11 @@ var init_ReplayApplicator = __esm({
20151
20448
  "--allow-empty"
20152
20449
  ]);
20153
20450
  await tempGit.execWithInput(["apply", "--allow-empty"], fileDiff);
20154
- const tempTargetPath = (0, import_node_path3.join)(tempDir, filePath);
20451
+ const tempTargetPath = (0, import_path9.join)(tempDir, filePath);
20155
20452
  return await (0, import_promises4.readFile)(tempTargetPath, "utf-8");
20156
20453
  }
20157
- const tempFilePath = (0, import_node_path3.join)(tempDir, filePath);
20158
- await (0, import_promises4.mkdir)((0, import_node_path3.dirname)(tempFilePath), { recursive: true });
20454
+ const tempFilePath = (0, import_path9.join)(tempDir, filePath);
20455
+ await (0, import_promises4.mkdir)((0, import_path9.dirname)(tempFilePath), { recursive: true });
20159
20456
  await (0, import_promises4.writeFile)(tempFilePath, base);
20160
20457
  await tempGit.exec(["add", filePath]);
20161
20458
  await tempGit.exec(["commit", "-m", `base for ${filePath}`, "--allow-empty"]);
@@ -20191,15 +20488,12 @@ var init_ReplayApplicator = __esm({
20191
20488
  let inTargetFile = false;
20192
20489
  for (const line of lines) {
20193
20490
  if (line.startsWith("diff --git")) {
20194
- if (inTargetFile)
20195
- break;
20491
+ if (inTargetFile) break;
20196
20492
  inTargetFile = isDiffLineForFile(line, targetFilePath);
20197
20493
  continue;
20198
20494
  }
20199
- if (!inTargetFile)
20200
- continue;
20201
- if (line.startsWith("@@"))
20202
- break;
20495
+ if (!inTargetFile) continue;
20496
+ if (line.startsWith("@@")) break;
20203
20497
  if (line.startsWith("rename from ")) {
20204
20498
  return line.slice("rename from ".length);
20205
20499
  }
@@ -20214,20 +20508,17 @@ var init_ReplayApplicator = __esm({
20214
20508
  let noTrailingNewline = false;
20215
20509
  for (const line of lines) {
20216
20510
  if (line.startsWith("diff --git")) {
20217
- if (inTargetFile)
20218
- break;
20511
+ if (inTargetFile) break;
20219
20512
  inTargetFile = isDiffLineForFile(line, filePath);
20220
20513
  inHunk = false;
20221
20514
  continue;
20222
20515
  }
20223
- if (!inTargetFile)
20224
- continue;
20516
+ if (!inTargetFile) continue;
20225
20517
  if (line.startsWith("@@")) {
20226
20518
  inHunk = true;
20227
20519
  continue;
20228
20520
  }
20229
- if (!inHunk)
20230
- continue;
20521
+ if (!inHunk) continue;
20231
20522
  if (line === "\") {
20232
20523
  noTrailingNewline = true;
20233
20524
  continue;
@@ -20236,19 +20527,10 @@ var init_ReplayApplicator = __esm({
20236
20527
  addedLines.push(line.slice(1));
20237
20528
  }
20238
20529
  }
20239
- if (addedLines.length === 0)
20240
- return null;
20530
+ if (addedLines.length === 0) return null;
20241
20531
  return addedLines.join("\n") + (noTrailingNewline ? "" : "\n");
20242
20532
  }
20243
20533
  };
20244
- }
20245
- });
20246
-
20247
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayCommitter.js
20248
- var ReplayCommitter;
20249
- var init_ReplayCommitter = __esm({
20250
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayCommitter.js"() {
20251
- "use strict";
20252
20534
  ReplayCommitter = class {
20253
20535
  git;
20254
20536
  outputDir;
@@ -20317,22 +20599,7 @@ CLI Version: ${options.cliVersion}`;
20317
20599
  return this.git.getTreeHash(commitSha);
20318
20600
  }
20319
20601
  };
20320
- }
20321
- });
20322
-
20323
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayService.js
20324
- var import_node_fs2, import_node_path4, ReplayService;
20325
- var init_ReplayService = __esm({
20326
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayService.js"() {
20327
- "use strict";
20328
- import_node_fs2 = require("fs");
20329
- import_node_path4 = require("path");
20330
- init_esm3();
20331
20602
  init_GitClient();
20332
- init_LockfileManager();
20333
- init_ReplayApplicator();
20334
- init_ReplayCommitter();
20335
- init_ReplayDetector();
20336
20603
  ReplayService = class {
20337
20604
  git;
20338
20605
  detector;
@@ -20578,7 +20845,15 @@ var init_ReplayService = __esm({
20578
20845
  await this.committer.commitReplay(appliedCount, allPatches);
20579
20846
  }
20580
20847
  }
20581
- return this.buildReport("normal-regeneration", allPatches, results, options, warnings, rebaseCounts, preRebaseCounts);
20848
+ return this.buildReport(
20849
+ "normal-regeneration",
20850
+ allPatches,
20851
+ results,
20852
+ options,
20853
+ warnings,
20854
+ rebaseCounts,
20855
+ preRebaseCounts
20856
+ );
20582
20857
  }
20583
20858
  /**
20584
20859
  * Rebase cleanly applied patches so they are relative to the current generation.
@@ -20608,23 +20883,23 @@ var init_ReplayService = __esm({
20608
20883
  await this.trimAbsorbedFiles(result, currentGenSha);
20609
20884
  continue;
20610
20885
  }
20611
- if (result.status !== "applied")
20612
- continue;
20886
+ if (result.status !== "applied") continue;
20613
20887
  const patch = result.patch;
20614
- if (patch.base_generation === currentGenSha)
20615
- continue;
20888
+ if (patch.base_generation === currentGenSha) continue;
20616
20889
  try {
20617
20890
  const fernignorePatterns = this.readFernignorePatterns();
20618
- const isUserOwned = await Promise.all(patch.files.map(async (file) => {
20619
- if (file === ".fernignore") {
20620
- return true;
20621
- }
20622
- if (fernignorePatterns.some((p) => file === p || minimatch(file, p))) {
20623
- return true;
20624
- }
20625
- const content = await this.git.showFile(currentGenSha, file);
20626
- return content === null;
20627
- }));
20891
+ const isUserOwned = await Promise.all(
20892
+ patch.files.map(async (file) => {
20893
+ if (file === ".fernignore") {
20894
+ return true;
20895
+ }
20896
+ if (fernignorePatterns.some((p) => file === p || minimatch(file, p))) {
20897
+ return true;
20898
+ }
20899
+ const content = await this.git.showFile(currentGenSha, file);
20900
+ return content === null;
20901
+ })
20902
+ );
20628
20903
  const hasUserOwnedFiles = isUserOwned.some(Boolean);
20629
20904
  if (hasUserOwnedFiles) {
20630
20905
  this.lockManager.updatePatch(patch.id, {
@@ -20670,23 +20945,18 @@ var init_ReplayService = __esm({
20670
20945
  */
20671
20946
  async trimAbsorbedFiles(result, currentGenSha) {
20672
20947
  const cleanFiles = result.fileResults.filter((f) => f.status === "merged").map((f) => f.file);
20673
- if (cleanFiles.length === 0)
20674
- return;
20948
+ if (cleanFiles.length === 0) return;
20675
20949
  const patch = result.patch;
20676
20950
  const fernignorePatterns = this.readFernignorePatterns();
20677
20951
  const generatorCleanFiles = [];
20678
20952
  for (const file of cleanFiles) {
20679
- if (file === ".fernignore")
20680
- continue;
20681
- if (fernignorePatterns.some((p) => file === p || minimatch(file, p)))
20682
- continue;
20953
+ if (file === ".fernignore") continue;
20954
+ if (fernignorePatterns.some((p) => file === p || minimatch(file, p))) continue;
20683
20955
  const content = await this.git.showFile(currentGenSha, file);
20684
- if (content === null)
20685
- continue;
20956
+ if (content === null) continue;
20686
20957
  generatorCleanFiles.push(file);
20687
20958
  }
20688
- if (generatorCleanFiles.length === 0)
20689
- return;
20959
+ if (generatorCleanFiles.length === 0) return;
20690
20960
  const absorbedFiles = /* @__PURE__ */ new Set();
20691
20961
  for (const file of generatorCleanFiles) {
20692
20962
  try {
@@ -20697,11 +20967,9 @@ var init_ReplayService = __esm({
20697
20967
  } catch {
20698
20968
  }
20699
20969
  }
20700
- if (absorbedFiles.size === 0)
20701
- return;
20970
+ if (absorbedFiles.size === 0) return;
20702
20971
  const remainingFiles = patch.files.filter((f) => !absorbedFiles.has(f));
20703
- if (remainingFiles.length === patch.files.length)
20704
- return;
20972
+ if (remainingFiles.length === patch.files.length) return;
20705
20973
  try {
20706
20974
  this.lockManager.updatePatch(patch.id, { files: remainingFiles });
20707
20975
  } catch {
@@ -20726,8 +20994,7 @@ var init_ReplayService = __esm({
20726
20994
  if (patch.base_generation === currentGen) {
20727
20995
  try {
20728
20996
  const diff = await this.git.exec(["diff", currentGen, "HEAD", "--", ...patch.files]).catch(() => null);
20729
- if (diff === null)
20730
- continue;
20997
+ if (diff === null) continue;
20731
20998
  if (!diff.trim()) {
20732
20999
  this.lockManager.removePatch(patch.id);
20733
21000
  contentRefreshed++;
@@ -20754,11 +21021,9 @@ var init_ReplayService = __esm({
20754
21021
  }
20755
21022
  try {
20756
21023
  const markerFiles = await this.git.exec(["grep", "-l", "<<<<<<<", "HEAD", "--", ...patch.files]).catch(() => "");
20757
- if (markerFiles.trim())
20758
- continue;
21024
+ if (markerFiles.trim()) continue;
20759
21025
  const diff = await this.git.exec(["diff", currentGen, "HEAD", "--", ...patch.files]).catch(() => null);
20760
- if (diff === null)
20761
- continue;
21026
+ if (diff === null) continue;
20762
21027
  if (!diff.trim()) {
20763
21028
  this.lockManager.removePatch(patch.id);
20764
21029
  conflictAbsorbed++;
@@ -20777,10 +21042,9 @@ var init_ReplayService = __esm({
20777
21042
  return { conflictResolved, conflictAbsorbed, contentRefreshed };
20778
21043
  }
20779
21044
  readFernignorePatterns() {
20780
- const fernignorePath = (0, import_node_path4.join)(this.outputDir, ".fernignore");
20781
- if (!(0, import_node_fs2.existsSync)(fernignorePath))
20782
- return [];
20783
- return (0, import_node_fs2.readFileSync)(fernignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
21045
+ const fernignorePath = (0, import_path10.join)(this.outputDir, ".fernignore");
21046
+ if (!(0, import_fs7.existsSync)(fernignorePath)) return [];
21047
+ return (0, import_fs7.readFileSync)(fernignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
20784
21048
  }
20785
21049
  buildReport(flow, patches, results, options, warnings, rebaseCounts, preRebaseCounts) {
20786
21050
  const conflictResults = results.filter((r) => r.status === "conflict");
@@ -20816,20 +21080,6 @@ var init_ReplayService = __esm({
20816
21080
  };
20817
21081
  }
20818
21082
  };
20819
- }
20820
- });
20821
-
20822
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/FernignoreMigrator.js
20823
- var import_node_crypto2, import_node_fs3, import_node_path5, import_yaml2, FernignoreMigrator;
20824
- var init_FernignoreMigrator = __esm({
20825
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/FernignoreMigrator.js"() {
20826
- "use strict";
20827
- import_node_crypto2 = require("crypto");
20828
- import_node_fs3 = require("fs");
20829
- import_node_path5 = require("path");
20830
- init_esm3();
20831
- import_yaml2 = __toESM(require_dist3(), 1);
20832
- init_ReplayDetector();
20833
21083
  FernignoreMigrator = class {
20834
21084
  git;
20835
21085
  lockManager;
@@ -20840,14 +21090,14 @@ var init_FernignoreMigrator = __esm({
20840
21090
  this.outputDir = outputDir;
20841
21091
  }
20842
21092
  fernignoreExists() {
20843
- return (0, import_node_fs3.existsSync)((0, import_node_path5.join)(this.outputDir, ".fernignore"));
21093
+ return (0, import_fs8.existsSync)((0, import_path11.join)(this.outputDir, ".fernignore"));
20844
21094
  }
20845
21095
  readFernignorePatterns() {
20846
- const fernignorePath = (0, import_node_path5.join)(this.outputDir, ".fernignore");
20847
- if (!(0, import_node_fs3.existsSync)(fernignorePath)) {
21096
+ const fernignorePath = (0, import_path11.join)(this.outputDir, ".fernignore");
21097
+ if (!(0, import_fs8.existsSync)(fernignorePath)) {
20848
21098
  return [];
20849
21099
  }
20850
- const content = (0, import_node_fs3.readFileSync)(fernignorePath, "utf-8");
21100
+ const content = (0, import_fs8.readFileSync)(fernignorePath, "utf-8");
20851
21101
  return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
20852
21102
  }
20853
21103
  /** Analyze .fernignore patterns vs git history. Creates synthetic patches for files differing from pristine generation. */
@@ -20894,9 +21144,9 @@ var init_FernignoreMigrator = __esm({
20894
21144
  }
20895
21145
  if (patchFiles.length > 0) {
20896
21146
  const patchContent = diffParts.join("\n");
20897
- const contentHash = `sha256:${(0, import_node_crypto2.createHash)("sha256").update(patchContent).digest("hex")}`;
21147
+ const contentHash = `sha256:${(0, import_crypto2.createHash)("sha256").update(patchContent).digest("hex")}`;
20898
21148
  syntheticPatches.push({
20899
- id: `patch-fernignore-${(0, import_node_crypto2.createHash)("sha256").update(pattern).digest("hex").slice(0, 8)}`,
21149
+ id: `patch-fernignore-${(0, import_crypto2.createHash)("sha256").update(pattern).digest("hex").slice(0, 8)}`,
20900
21150
  content_hash: contentHash,
20901
21151
  original_commit: currentGen.commit_sha,
20902
21152
  original_message: `[fernignore-migration] Customizations for ${pattern}`,
@@ -20928,22 +21178,24 @@ var init_FernignoreMigrator = __esm({
20928
21178
  const allFiles = (await this.git.exec(["ls-files"])).trim().split("\n").filter(Boolean);
20929
21179
  const results = [];
20930
21180
  for (const pattern of patterns) {
20931
- const matching = allFiles.filter((f) => minimatch(f, pattern) || f === pattern || f.startsWith(pattern + "/"));
21181
+ const matching = allFiles.filter(
21182
+ (f) => minimatch(f, pattern) || f === pattern || f.startsWith(pattern + "/")
21183
+ );
20932
21184
  results.push({ pattern, files: matching.length > 0 ? matching : [pattern] });
20933
21185
  }
20934
21186
  return results;
20935
21187
  }
20936
21188
  readFileContent(filePath) {
20937
- const fullPath = (0, import_node_path5.join)(this.outputDir, filePath);
20938
- if (!(0, import_node_fs3.existsSync)(fullPath)) {
21189
+ const fullPath = (0, import_path11.join)(this.outputDir, filePath);
21190
+ if (!(0, import_fs8.existsSync)(fullPath)) {
20939
21191
  return null;
20940
21192
  }
20941
21193
  try {
20942
- const stat = (0, import_node_fs3.statSync)(fullPath);
21194
+ const stat = (0, import_fs8.statSync)(fullPath);
20943
21195
  if (stat.isDirectory()) {
20944
21196
  return null;
20945
21197
  }
20946
- return (0, import_node_fs3.readFileSync)(fullPath, "utf-8");
21198
+ return (0, import_fs8.readFileSync)(fullPath, "utf-8");
20947
21199
  } catch {
20948
21200
  return null;
20949
21201
  }
@@ -20981,421 +21233,43 @@ var init_FernignoreMigrator = __esm({
20981
21233
  const warnings = [];
20982
21234
  let patchesCreated = 0;
20983
21235
  for (const patch of patches) {
20984
- this.lockManager.addPatch(patch);
20985
- patchesCreated++;
20986
- }
20987
- if (patchesCreated > 0) {
20988
- this.lockManager.save();
20989
- }
20990
- for (const file of analysis.fernignoreOnly) {
20991
- warnings.push(`${file}: in .fernignore but no commit history found. Commit this file or keep in .fernignore as fallback.`);
20992
- }
20993
- return {
20994
- patchesCreated,
20995
- filesSkipped: analysis.fernignoreOnly,
20996
- warnings
20997
- };
20998
- }
20999
- movePatternsToReplayYml(patterns) {
21000
- const replayYmlPath = (0, import_node_path5.join)(this.outputDir, ".fern", "replay.yml");
21001
- let config = {};
21002
- if ((0, import_node_fs3.existsSync)(replayYmlPath)) {
21003
- const content = (0, import_node_fs3.readFileSync)(replayYmlPath, "utf-8");
21004
- config = (0, import_yaml2.parse)(content) ?? {};
21005
- }
21006
- const existing = config.exclude ?? [];
21007
- const merged = [.../* @__PURE__ */ new Set([...existing, ...patterns])];
21008
- config.exclude = merged;
21009
- const dir = (0, import_node_path5.dirname)(replayYmlPath);
21010
- if (!(0, import_node_fs3.existsSync)(dir)) {
21011
- (0, import_node_fs3.mkdirSync)(dir, { recursive: true });
21012
- }
21013
- (0, import_node_fs3.writeFileSync)(replayYmlPath, (0, import_yaml2.stringify)(config, { lineWidth: 0 }), "utf-8");
21014
- }
21015
- };
21016
- }
21017
- });
21018
-
21019
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/bootstrap.js
21020
- async function bootstrap(outputDir, options) {
21021
- const git = new GitClient(outputDir);
21022
- const lockManager = new LockfileManager(outputDir);
21023
- const maxCommits = options?.maxCommitsToScan ?? 500;
21024
- const warnings = [];
21025
- if (lockManager.exists() && !options?.force) {
21026
- return {
21027
- generationCommit: null,
21028
- patchesDetected: 0,
21029
- patchesCreated: 0,
21030
- patches: [],
21031
- fernignorePatterns: [],
21032
- fernignoreUpdated: false,
21033
- warnings: ["Replay lockfile already exists. Use --force to overwrite."],
21034
- staleGenerationsSkipped: 0,
21035
- scannedSinceGeneration: ""
21036
- };
21037
- }
21038
- const genCommits = await findAllGenerationCommits(git, maxCommits);
21039
- if (genCommits.length === 0) {
21040
- return {
21041
- generationCommit: null,
21042
- patchesDetected: 0,
21043
- patchesCreated: 0,
21044
- patches: [],
21045
- fernignorePatterns: [],
21046
- fernignoreUpdated: false,
21047
- warnings: [
21048
- "No generation commits found in the last " + maxCommits + " commits. Run 'fern generate' first to establish a baseline."
21049
- ],
21050
- staleGenerationsSkipped: 0,
21051
- scannedSinceGeneration: ""
21052
- };
21053
- }
21054
- const latestGen = genCommits[0];
21055
- const anchorSha = options?.importHistory ? latestGen.sha : (await git.exec(["rev-parse", "HEAD"])).trim();
21056
- const treeHash = await git.getTreeHash(anchorSha);
21057
- const genRecord = {
21058
- commit_sha: anchorSha,
21059
- tree_hash: treeHash,
21060
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
21061
- cli_version: "unknown",
21062
- generator_versions: {}
21063
- };
21064
- lockManager.initializeInMemory(genRecord);
21065
- const patches = options?.importHistory ? await findAllUserPatches(git, genCommits) : [];
21066
- const migrator = new FernignoreMigrator(git, lockManager, outputDir);
21067
- const fernignorePatterns = migrator.readFernignorePatterns();
21068
- let fernignoreAnalysis;
21069
- if (options?.importHistory && migrator.fernignoreExists() && fernignorePatterns.length > 0) {
21070
- fernignoreAnalysis = await migrator.analyzeMigration();
21071
- if (fernignoreAnalysis.syntheticPatches.length > 0) {
21072
- patches.push(...fernignoreAnalysis.syntheticPatches);
21073
- }
21074
- if (fernignoreAnalysis.fernignoreOnly.length > 0) {
21075
- for (const file of fernignoreAnalysis.fernignoreOnly) {
21076
- warnings.push(`${file}: in .fernignore but no recent commits found since last generation. File may be stale, matches generated output, or does not exist. No customization to track.`);
21077
- }
21078
- }
21079
- }
21080
- if (options?.dryRun) {
21081
- return {
21082
- generationCommit: latestGen,
21083
- patchesDetected: patches.length,
21084
- patchesCreated: 0,
21085
- patches,
21086
- fernignorePatterns,
21087
- fernignoreAnalysis,
21088
- fernignoreUpdated: false,
21089
- warnings,
21090
- staleGenerationsSkipped: genCommits.length - 1,
21091
- scannedSinceGeneration: latestGen.sha
21092
- };
21093
- }
21094
- for (const patch of patches) {
21095
- lockManager.addPatch(patch);
21096
- }
21097
- lockManager.save();
21098
- const fernignoreUpdated = ensureFernignoreEntries(outputDir);
21099
- if (migrator.fernignoreExists() && fernignorePatterns.length > 0) {
21100
- const action = options?.fernignoreAction ?? "skip";
21101
- if (action === "migrate") {
21102
- const patternsToExclude = fernignoreAnalysis?.fernignoreOnly ?? [];
21103
- if (patternsToExclude.length > 0) {
21104
- migrator.movePatternsToReplayYml(patternsToExclude);
21236
+ this.lockManager.addPatch(patch);
21237
+ patchesCreated++;
21238
+ }
21239
+ if (patchesCreated > 0) {
21240
+ this.lockManager.save();
21241
+ }
21242
+ for (const file of analysis.fernignoreOnly) {
21243
+ warnings.push(
21244
+ `${file}: in .fernignore but no commit history found. Commit this file or keep in .fernignore as fallback.`
21245
+ );
21246
+ }
21247
+ return {
21248
+ patchesCreated,
21249
+ filesSkipped: analysis.fernignoreOnly,
21250
+ warnings
21251
+ };
21252
+ }
21253
+ movePatternsToReplayYml(patterns) {
21254
+ const replayYmlPath = (0, import_path11.join)(this.outputDir, ".fern", "replay.yml");
21255
+ let config = {};
21256
+ if ((0, import_fs8.existsSync)(replayYmlPath)) {
21257
+ const content = (0, import_fs8.readFileSync)(replayYmlPath, "utf-8");
21258
+ config = (0, import_yaml2.parse)(content) ?? {};
21259
+ }
21260
+ const existing = config.exclude ?? [];
21261
+ const merged = [.../* @__PURE__ */ new Set([...existing, ...patterns])];
21262
+ config.exclude = merged;
21263
+ const dir = (0, import_path11.dirname)(replayYmlPath);
21264
+ if (!(0, import_fs8.existsSync)(dir)) {
21265
+ (0, import_fs8.mkdirSync)(dir, { recursive: true });
21266
+ }
21267
+ (0, import_fs8.writeFileSync)(replayYmlPath, (0, import_yaml2.stringify)(config, { lineWidth: 0 }), "utf-8");
21105
21268
  }
21106
- }
21107
- }
21108
- return {
21109
- generationCommit: latestGen,
21110
- patchesDetected: patches.length,
21111
- patchesCreated: patches.length,
21112
- patches,
21113
- fernignorePatterns,
21114
- fernignoreAnalysis,
21115
- fernignoreUpdated,
21116
- warnings,
21117
- staleGenerationsSkipped: genCommits.length - 1,
21118
- scannedSinceGeneration: latestGen.sha
21119
- };
21120
- }
21121
- async function findAllGenerationCommits(git, maxCommits) {
21122
- const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `-${maxCommits}`]);
21123
- if (!log.trim()) {
21124
- return [];
21125
- }
21126
- const genCommits = [];
21127
- for (const line of log.trim().split("\n")) {
21128
- if (!line)
21129
- continue;
21130
- const [sha, authorName, authorEmail, message] = line.split("\0");
21131
- const commit = { sha, authorName, authorEmail, message };
21132
- if (isGenerationCommit(commit) && !isReplayCommit(commit)) {
21133
- genCommits.push(commit);
21134
- }
21135
- }
21136
- return genCommits;
21137
- }
21138
- async function findAllUserPatches(git, genCommits) {
21139
- const patches = [];
21140
- const seenHashes = /* @__PURE__ */ new Set();
21141
- const latestGen = genCommits[0];
21142
- const recentPatches = await extractUserPatches(git, latestGen.sha, "HEAD", latestGen.sha, seenHashes);
21143
- patches.push(...recentPatches);
21144
- return patches;
21145
- }
21146
- async function extractUserPatches(git, fromSha, toRef, baseGeneration, seenHashes) {
21147
- const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `${fromSha}..${toRef}`]);
21148
- if (!log.trim()) {
21149
- return [];
21150
- }
21151
- const commits = parseGitLog(log);
21152
- const patches = [];
21153
- for (const commit of commits.reverse()) {
21154
- if (isGenerationCommit(commit))
21155
- continue;
21156
- const parents = await git.getCommitParents(commit.sha);
21157
- if (parents.length > 1)
21158
- continue;
21159
- const patchContent = await git.formatPatch(commit.sha);
21160
- const contentHash = computeContentHash(patchContent);
21161
- if (seenHashes.has(contentHash))
21162
- continue;
21163
- seenHashes.add(contentHash);
21164
- const filesOutput = await git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
21165
- patches.push({
21166
- id: `patch-${commit.sha.slice(0, 8)}`,
21167
- content_hash: contentHash,
21168
- original_commit: commit.sha,
21169
- original_message: commit.message,
21170
- original_author: `${commit.authorName} <${commit.authorEmail}>`,
21171
- base_generation: baseGeneration,
21172
- files: filesOutput.trim().split("\n").filter(Boolean),
21173
- patch_content: patchContent
21174
- });
21175
- }
21176
- return patches;
21177
- }
21178
- function parseGitLog(log) {
21179
- return log.trim().split("\n").filter(Boolean).map((line) => {
21180
- const [sha, authorName, authorEmail, message] = line.split("\0");
21181
- return { sha, authorName, authorEmail, message };
21182
- });
21183
- }
21184
- function ensureFernignoreEntries(outputDir) {
21185
- const fernignorePath = (0, import_node_path6.join)(outputDir, ".fernignore");
21186
- let content = "";
21187
- if ((0, import_node_fs4.existsSync)(fernignorePath)) {
21188
- content = (0, import_node_fs4.readFileSync)(fernignorePath, "utf-8");
21189
- }
21190
- const lines = content.split("\n");
21191
- const toAdd = [];
21192
- for (const entry of REPLAY_FERNIGNORE_ENTRIES) {
21193
- if (!lines.some((line) => line.trim() === entry)) {
21194
- toAdd.push(entry);
21195
- }
21196
- }
21197
- if (toAdd.length === 0) {
21198
- return false;
21199
- }
21200
- if (content && !content.endsWith("\n")) {
21201
- content += "\n";
21202
- }
21203
- content += toAdd.join("\n") + "\n";
21204
- (0, import_node_fs4.writeFileSync)(fernignorePath, content, "utf-8");
21205
- return true;
21206
- }
21207
- function computeContentHash(patchContent) {
21208
- const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
21209
- return `sha256:${(0, import_node_crypto3.createHash)("sha256").update(normalized).digest("hex")}`;
21210
- }
21211
- var import_node_crypto3, import_node_fs4, import_node_path6, REPLAY_FERNIGNORE_ENTRIES;
21212
- var init_bootstrap = __esm({
21213
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/bootstrap.js"() {
21214
- "use strict";
21215
- import_node_crypto3 = require("crypto");
21216
- import_node_fs4 = require("fs");
21217
- import_node_path6 = require("path");
21218
- init_FernignoreMigrator();
21219
- init_CommitDetection();
21220
- init_GitClient();
21221
- init_LockfileManager();
21222
- REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml"];
21223
- }
21224
- });
21225
-
21226
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/forget.js
21227
- function forget(outputDir, filePattern, options) {
21228
- const lockManager = new LockfileManager(outputDir);
21229
- if (!lockManager.exists()) {
21230
- return { removed: [], notFound: true };
21231
- }
21232
- const lock = lockManager.read();
21233
- const matchingPatches = lock.patches.filter((patch) => patch.files.some((file) => file === filePattern || minimatch(file, filePattern)));
21234
- if (matchingPatches.length === 0) {
21235
- return { removed: [], notFound: true };
21236
- }
21237
- const removed = matchingPatches.map((p) => ({
21238
- id: p.id,
21239
- message: p.original_message,
21240
- files: p.files
21241
- }));
21242
- if (!options?.dryRun) {
21243
- for (const patch of matchingPatches) {
21244
- lockManager.removePatch(patch.id);
21245
- }
21246
- lockManager.save();
21247
- }
21248
- return { removed, notFound: false };
21249
- }
21250
- var init_forget = __esm({
21251
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/forget.js"() {
21252
- "use strict";
21253
- init_esm3();
21254
- init_LockfileManager();
21255
- }
21256
- });
21257
-
21258
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/reset.js
21259
- function reset(outputDir, options) {
21260
- const lockManager = new LockfileManager(outputDir);
21261
- if (!lockManager.exists()) {
21262
- return {
21263
- success: true,
21264
- patchesRemoved: 0,
21265
- lockfileDeleted: false,
21266
- nothingToReset: true
21267
21269
  };
21268
- }
21269
- const lock = lockManager.read();
21270
- const patchCount = lock.patches.length;
21271
- if (!options?.dryRun) {
21272
- (0, import_node_fs5.unlinkSync)(lockManager.lockfilePath);
21273
- }
21274
- return {
21275
- success: true,
21276
- patchesRemoved: patchCount,
21277
- lockfileDeleted: true,
21278
- nothingToReset: false
21279
- };
21280
- }
21281
- var import_node_fs5;
21282
- var init_reset2 = __esm({
21283
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/reset.js"() {
21284
- "use strict";
21285
- import_node_fs5 = require("fs");
21286
- init_LockfileManager();
21287
- }
21288
- });
21289
-
21290
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/resolve.js
21291
- async function resolve7(outputDir, options) {
21292
- const lockManager = new LockfileManager(outputDir);
21293
- if (!lockManager.exists()) {
21294
- return { success: false, reason: "no-lockfile" };
21295
- }
21296
- const lock = lockManager.read();
21297
- if (lock.patches.length === 0) {
21298
- return { success: false, reason: "no-patches" };
21299
- }
21300
- const git = new GitClient(outputDir);
21301
- if (options?.checkMarkers !== false) {
21302
- const markerFiles = await git.exec(["grep", "-l", "<<<<<<<", "--", "."]).catch(() => "");
21303
- if (markerFiles.trim()) {
21304
- const files = markerFiles.trim().split("\n").filter(Boolean);
21305
- return { success: false, reason: "unresolved-conflicts", unresolvedFiles: files };
21306
- }
21307
- }
21308
- const committer = new ReplayCommitter(git, outputDir);
21309
- await committer.stageAll();
21310
- const commitSha = await committer.commitReplay(lock.patches.length, lock.patches);
21311
- return { success: true, commitSha };
21312
- }
21313
- var init_resolve = __esm({
21314
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/resolve.js"() {
21315
- "use strict";
21316
21270
  init_GitClient();
21317
- init_LockfileManager();
21318
- init_ReplayCommitter();
21319
- }
21320
- });
21321
-
21322
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/status.js
21323
- function status(outputDir) {
21324
- const lockManager = new LockfileManager(outputDir);
21325
- if (!lockManager.exists()) {
21326
- return { initialized: false, patches: [], lastGeneration: void 0 };
21327
- }
21328
- const lock = lockManager.read();
21329
- const patches = lock.patches.map((patch) => ({
21330
- sha: patch.original_commit.slice(0, 7),
21331
- author: patch.original_author.split("<")[0]?.trim() ?? "unknown",
21332
- message: patch.original_message,
21333
- files: patch.files
21334
- }));
21335
- let lastGeneration;
21336
- const lastGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
21337
- if (lastGen) {
21338
- lastGeneration = {
21339
- sha: lastGen.commit_sha,
21340
- timestamp: lastGen.timestamp
21341
- };
21342
- }
21343
- return { initialized: true, patches, lastGeneration };
21344
- }
21345
- var init_status2 = __esm({
21346
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/status.js"() {
21347
- "use strict";
21348
- init_LockfileManager();
21349
- }
21350
- });
21351
-
21352
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/index.js
21353
- var init_commands = __esm({
21354
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/index.js"() {
21355
- "use strict";
21356
- init_bootstrap();
21357
- init_forget();
21358
- init_reset2();
21359
- init_resolve();
21360
- init_status2();
21361
- }
21362
- });
21363
-
21364
- // ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/index.js
21365
- var dist_exports = {};
21366
- __export(dist_exports, {
21367
- FERN_BOT_EMAIL: () => FERN_BOT_EMAIL2,
21368
- FERN_BOT_LOGIN: () => FERN_BOT_LOGIN2,
21369
- FERN_BOT_NAME: () => FERN_BOT_NAME2,
21370
- FernignoreMigrator: () => FernignoreMigrator,
21371
- GitClient: () => GitClient,
21372
- LockfileManager: () => LockfileManager,
21373
- ReplayApplicator: () => ReplayApplicator,
21374
- ReplayCommitter: () => ReplayCommitter,
21375
- ReplayDetector: () => ReplayDetector,
21376
- ReplayService: () => ReplayService,
21377
- bootstrap: () => bootstrap,
21378
- forget: () => forget,
21379
- isGenerationCommit: () => isGenerationCommit,
21380
- isReplayCommit: () => isReplayCommit,
21381
- reset: () => reset,
21382
- resolve: () => resolve7,
21383
- status: () => status,
21384
- threeWayMerge: () => threeWayMerge
21385
- });
21386
- var init_dist = __esm({
21387
- "../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/index.js"() {
21388
- "use strict";
21271
+ REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml"];
21389
21272
  init_GitClient();
21390
- init_CommitDetection();
21391
- init_LockfileManager();
21392
- init_ReplayDetector();
21393
- init_ThreeWayMerge();
21394
- init_ReplayApplicator();
21395
- init_ReplayCommitter();
21396
- init_ReplayService();
21397
- init_FernignoreMigrator();
21398
- init_commands();
21399
21273
  }
21400
21274
  });
21401
21275
 
@@ -21433,9 +21307,9 @@ function resolve(...paths) {
21433
21307
  }
21434
21308
 
21435
21309
  // src/cli.ts
21436
- var import_fs9 = __toESM(require("fs"));
21310
+ var import_fs14 = __toESM(require("fs"));
21437
21311
  var import_promises9 = require("fs/promises");
21438
- var import_path11 = __toESM(require("path"));
21312
+ var import_path16 = __toESM(require("path"));
21439
21313
 
21440
21314
  // ../../node_modules/.pnpm/yargs@17.7.2/node_modules/yargs/build/lib/yerror.js
21441
21315
  var YError = class _YError extends Error {
@@ -31705,16 +31579,16 @@ function sleep(ms) {
31705
31579
  // src/replay/replay-run.ts
31706
31580
  init_dist();
31707
31581
  var import_child_process3 = require("child_process");
31708
- var import_fs7 = require("fs");
31709
- var import_path9 = require("path");
31582
+ var import_fs12 = require("fs");
31583
+ var import_path14 = require("path");
31710
31584
 
31711
31585
  // src/replay/fernignore.ts
31712
- var import_fs6 = require("fs");
31586
+ var import_fs11 = require("fs");
31713
31587
  var import_promises5 = require("fs/promises");
31714
- var import_path8 = require("path");
31588
+ var import_path13 = require("path");
31715
31589
  var REPLAY_FERNIGNORE_ENTRIES2 = [".fern/replay.lock", ".fern/replay.yml"];
31716
31590
  async function ensureReplayFernignoreEntries(outputDir) {
31717
- const fernignorePath = (0, import_path8.join)(outputDir, ".fernignore");
31591
+ const fernignorePath = (0, import_path13.join)(outputDir, ".fernignore");
31718
31592
  let content = "";
31719
31593
  try {
31720
31594
  content = await (0, import_promises5.readFile)(fernignorePath, "utf-8");
@@ -31730,16 +31604,16 @@ async function ensureReplayFernignoreEntries(outputDir) {
31730
31604
  return false;
31731
31605
  }
31732
31606
  function ensureReplayFernignoreEntriesSync(outputDir) {
31733
- const fernignorePath = (0, import_path8.join)(outputDir, ".fernignore");
31607
+ const fernignorePath = (0, import_path13.join)(outputDir, ".fernignore");
31734
31608
  let content = "";
31735
- if ((0, import_fs6.existsSync)(fernignorePath)) {
31736
- content = (0, import_fs6.readFileSync)(fernignorePath, "utf-8");
31609
+ if ((0, import_fs11.existsSync)(fernignorePath)) {
31610
+ content = (0, import_fs11.readFileSync)(fernignorePath, "utf-8");
31737
31611
  }
31738
31612
  const lines = content.split("\n");
31739
31613
  const toAdd = REPLAY_FERNIGNORE_ENTRIES2.filter((entry) => !lines.some((line) => line.trim() === entry));
31740
31614
  if (toAdd.length > 0) {
31741
31615
  const suffix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
31742
- (0, import_fs6.writeFileSync)(fernignorePath, content + suffix + toAdd.join("\n") + "\n", "utf-8");
31616
+ (0, import_fs11.writeFileSync)(fernignorePath, content + suffix + toAdd.join("\n") + "\n", "utf-8");
31743
31617
  }
31744
31618
  }
31745
31619
 
@@ -31754,8 +31628,8 @@ async function replayRun(params) {
31754
31628
  skipApplication,
31755
31629
  logger
31756
31630
  } = params;
31757
- const lockfilePath = (0, import_path9.join)(outputDir, ".fern", "replay.lock");
31758
- if (!(0, import_fs7.existsSync)(lockfilePath)) {
31631
+ const lockfilePath = (0, import_path14.join)(outputDir, ".fern", "replay.lock");
31632
+ if (!(0, import_fs12.existsSync)(lockfilePath)) {
31759
31633
  return {
31760
31634
  report: null,
31761
31635
  fernignoreUpdated: false,
@@ -32017,8 +31891,8 @@ var PostGenerationPipeline = class {
32017
31891
 
32018
31892
  // src/replay/replay-init.ts
32019
31893
  init_dist();
32020
- var import_fs8 = require("fs");
32021
- var import_path10 = require("path");
31894
+ var import_fs13 = require("fs");
31895
+ var import_path15 = require("path");
32022
31896
  var import_tmp_promise2 = __toESM(require_tmp_promise());
32023
31897
  async function replayInit(params) {
32024
31898
  const { githubRepo, token, dryRun } = params;
@@ -32049,7 +31923,7 @@ async function replayInit(params) {
32049
31923
  Tracked ${bootstrapResult.patchesCreated} customization patch(es).
32050
31924
  Base generation: ${bootstrapResult.generationCommit.sha.slice(0, 7)}`;
32051
31925
  const filesToAdd = [".fern/replay.lock", ".fern/replay.yml", ".fernignore"].filter(
32052
- (f) => (0, import_fs8.existsSync)((0, import_path10.join)(repoPath, f))
31926
+ (f) => (0, import_fs13.existsSync)((0, import_path15.join)(repoPath, f))
32053
31927
  );
32054
31928
  const branchName = `fern-replay/init-${Date.now()}`;
32055
31929
  await repository.checkoutOrCreateLocal(branchName);
@@ -32385,8 +32259,8 @@ void yargs_default(hideBin(process.argv)).scriptName(process.env.CLI_NAME ?? "ge
32385
32259
  const result = await pipeline.run();
32386
32260
  if (argv["result-file"] != null) {
32387
32261
  const resultPath = resolve(wd, argv["result-file"]);
32388
- await (0, import_promises9.mkdir)(import_path11.default.dirname(resultPath), { recursive: true });
32389
- await import_fs9.default.promises.writeFile(resultPath, JSON.stringify(result, null, 2));
32262
+ await (0, import_promises9.mkdir)(import_path16.default.dirname(resultPath), { recursive: true });
32263
+ await import_fs14.default.promises.writeFile(resultPath, JSON.stringify(result, null, 2));
32390
32264
  }
32391
32265
  process.stderr.write(`Pipeline ${result.success ? "succeeded" : "failed"}
32392
32266
  `);
@@ -32592,9 +32466,9 @@ async function createWriteStream(outputPath) {
32592
32466
  }
32593
32467
  async function createWriteStreamFromFile(filepath) {
32594
32468
  if (!await doesPathExist(filepath)) {
32595
- await (0, import_promises9.mkdir)(import_path11.default.dirname(filepath), { recursive: true });
32469
+ await (0, import_promises9.mkdir)(import_path16.default.dirname(filepath), { recursive: true });
32596
32470
  }
32597
- return import_fs9.default.createWriteStream(filepath);
32471
+ return import_fs14.default.createWriteStream(filepath);
32598
32472
  }
32599
32473
  /*! Bundled license information:
32600
32474