@fern-api/fern-api-dev 5.28.0 → 5.28.2

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 (2) hide show
  1. package/cli.cjs +123 -269
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -360342,9 +360342,9 @@ var require_diff3 = __commonJS({
360342
360342
  }
360343
360343
  });
360344
360344
 
360345
- // ../../../node_modules/.pnpm/@fern-api+replay@0.15.2/node_modules/@fern-api/replay/dist/index.cjs
360345
+ // ../../../node_modules/.pnpm/@fern-api+replay@0.16.0/node_modules/@fern-api/replay/dist/index.cjs
360346
360346
  var require_dist14 = __commonJS({
360347
- "../../../node_modules/.pnpm/@fern-api+replay@0.15.2/node_modules/@fern-api/replay/dist/index.cjs"(exports2, module4) {
360347
+ "../../../node_modules/.pnpm/@fern-api+replay@0.16.0/node_modules/@fern-api/replay/dist/index.cjs"(exports2, module4) {
360348
360348
  "use strict";
360349
360349
  var __defProp4 = Object.defineProperty;
360350
360350
  var __getOwnPropDesc4 = Object.getOwnPropertyDescriptor;
@@ -360880,9 +360880,22 @@ var require_dist14 = __commonJS({
360880
360880
  const hasGenerationMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.startsWith("[fern-autoversion]") || 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.
360881
360881
  // The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
360882
360882
  // GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
360883
- commit.message.startsWith("SDK Generation");
360883
+ commit.message.startsWith("SDK Generation") || // Merge commit (GitHub's "Create a merge commit" option) of a fern-bot
360884
+ // regen PR. First-parent walking lands on this commit, not on the
360885
+ // generation commit on the side branch, so the classifier must treat
360886
+ // it as a generation boundary. GitHub's default subject is
360887
+ // "Merge pull request #N from <owner>/<branch>"; fern-bot branches are
360888
+ // named "<owner>/fern-bot/<...>".
360889
+ /^Merge pull request #\d+ from [^/]+\/fern-bot\//.test(commit.message);
360884
360890
  return isBotAuthor || hasGenerationMarker;
360885
360891
  }
360892
+ function isGenerationBoundary(commit) {
360893
+ const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
360894
+ const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN || commit.authorEmail === FERN_BOT_EMAIL || commit.authorName === FERN_BOT_NAME);
360895
+ const isAutoversion = commit.message.startsWith("[fern-autoversion]");
360896
+ const hasBoundaryMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || commit.message.startsWith("SDK Generation");
360897
+ return isBotAuthor && !isAutoversion || hasBoundaryMarker;
360898
+ }
360886
360899
  function isReplayCommit(commit) {
360887
360900
  return commit.message.startsWith("[fern-replay]");
360888
360901
  }
@@ -361202,8 +361215,48 @@ var require_dist14 = __commonJS({
361202
361215
  this.lockManager = lockManager;
361203
361216
  this.sdkOutputDir = sdkOutputDir;
361204
361217
  }
361218
+ /**
361219
+ * Derive the previous-generation SHA from git history instead of trusting
361220
+ * `lock.current_generation`.
361221
+ *
361222
+ * Walks `git log HEAD --first-parent` and returns the SHA of the most recent
361223
+ * commit that `isGenerationBoundary` classifies as a customization-baseline
361224
+ * boundary, or null if no such commit is reachable from HEAD on the mainline.
361225
+ *
361226
+ * `isGenerationBoundary` is intentionally narrower than `isGenerationCommit`:
361227
+ * it excludes `[fern-autoversion]` (lightweight bumps that don't reset the
361228
+ * baseline) and the GitHub merge-commit subject for fern-bot regen PRs
361229
+ * (which sits on first-parent but where the customer fix-up commits live
361230
+ * on second-parent — stopping at the merge would hide them).
361231
+ *
361232
+ * See docs/adr/0001-derived-scan-boundary.md.
361233
+ */
361234
+ async findPreviousGenerationFromHistory() {
361235
+ let log4;
361236
+ try {
361237
+ log4 = await this.git.exec([
361238
+ "log",
361239
+ "--first-parent",
361240
+ "--format=%H%x00%an%x00%ae%x00%s",
361241
+ "HEAD"
361242
+ ]);
361243
+ } catch {
361244
+ return null;
361245
+ }
361246
+ for (const commit of this.parseGitLog(log4)) {
361247
+ if (isGenerationBoundary(commit)) {
361248
+ return commit.sha;
361249
+ }
361250
+ }
361251
+ return null;
361252
+ }
361205
361253
  async detectNewPatches() {
361206
361254
  const lock = this.lockManager.read();
361255
+ const derivedSha = await this.findPreviousGenerationFromHistory();
361256
+ if (derivedSha !== null) {
361257
+ const derivedRecord = await this.synthesizeGenerationRecord(derivedSha);
361258
+ return this.detectPatchesInRange(derivedSha, derivedRecord, lock);
361259
+ }
361207
361260
  const lastGen = this.getLastGeneration(lock);
361208
361261
  if (!lastGen) {
361209
361262
  return { patches: [], revertedPatchIds: [] };
@@ -361211,7 +361264,7 @@ var require_dist14 = __commonJS({
361211
361264
  const exists2 = await this.git.commitExists(lastGen.commit_sha);
361212
361265
  if (!exists2) {
361213
361266
  this.warnings.push(
361214
- `Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Falling back to alternate detection.`
361267
+ `Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Falling back to tree-diff detection (likely a shallow clone).`
361215
361268
  );
361216
361269
  return this.detectPatchesViaTreeDiff(
361217
361270
  lastGen,
@@ -361219,44 +361272,8 @@ var require_dist14 = __commonJS({
361219
361272
  true
361220
361273
  );
361221
361274
  }
361222
- const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
361223
- if (!isAncestor) {
361224
- return this.detectPatchesViaMergeBase(lastGen, lock);
361225
- }
361226
361275
  return this.detectPatchesInRange(lastGen.commit_sha, lastGen, lock);
361227
361276
  }
361228
- /**
361229
- * Non-linear-history detection via `merge-base(prevGen, HEAD)`.
361230
- *
361231
- * After a squash-merge of a Fern-bot PR, `lastGen.commit_sha` (the previous
361232
- * `[fern-generated]`) is orphaned but still in git's object database. The
361233
- * merge-base is the commit on main from which the bot's branch was created —
361234
- * a reachable ancestor of HEAD. Walking that range and classifying each
361235
- * commit via `isGenerationCommit` mirrors the linear path and eliminates
361236
- * the bug class where pipeline-driven changes (autoversion, replay,
361237
- * generation) get bundled as customer customizations.
361238
- *
361239
- * Falls through to the legacy composite path when no common ancestor exists
361240
- * (truly disjoint history — orphan branches with no shared root).
361241
- */
361242
- async detectPatchesViaMergeBase(lastGen, lock) {
361243
- let mergeBase = "";
361244
- try {
361245
- mergeBase = (await this.git.exec(["merge-base", lastGen.commit_sha, "HEAD"])).trim();
361246
- } catch {
361247
- }
361248
- if (!mergeBase) {
361249
- this.warnings.push(
361250
- `No common ancestor between previous generation ${lastGen.commit_sha.slice(0, 7)} and HEAD. Falling back to composite tree-diff detection.`
361251
- );
361252
- return this.detectPatchesViaTreeDiff(
361253
- lastGen,
361254
- /* commitKnownMissing */
361255
- false
361256
- );
361257
- }
361258
- return this.detectPatchesInRange(mergeBase, lastGen, lock);
361259
- }
361260
361277
  /**
361261
361278
  * Walk `${rangeStart}..HEAD`, classify each commit, emit one
361262
361279
  * `StoredPatch` per customer commit. Body shared by the linear path
@@ -361692,6 +361709,26 @@ var require_dist14 = __commonJS({
361692
361709
  getLastGeneration(lock) {
361693
361710
  return lock.generations.find((g8) => g8.commit_sha === lock.current_generation);
361694
361711
  }
361712
+ /**
361713
+ * Build a transient `GenerationRecord` from a SHA derived by walking git
361714
+ * history. Only `commit_sha` (and `tree_hash` when needed downstream) is
361715
+ * load-bearing here; the rest are filled with defensible placeholders.
361716
+ * This record is consumed by `detectPatchesInRange` and is never persisted.
361717
+ */
361718
+ async synthesizeGenerationRecord(sha) {
361719
+ let tree_hash = "";
361720
+ try {
361721
+ tree_hash = await this.git.getTreeHash(sha);
361722
+ } catch {
361723
+ }
361724
+ return {
361725
+ commit_sha: sha,
361726
+ tree_hash,
361727
+ timestamp: (/* @__PURE__ */ new Date(0)).toISOString(),
361728
+ cli_version: "",
361729
+ generator_versions: {}
361730
+ };
361731
+ }
361695
361732
  };
361696
361733
  var import_node_diff3 = require_diff3();
361697
361734
  function threeWayMerge(base4, ours, theirs) {
@@ -362813,8 +362850,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
362813
362850
  tree_hash: treeHash,
362814
362851
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
362815
362852
  cli_version: options2?.cliVersion ?? "unknown",
362816
- generator_versions: options2?.generatorVersions ?? {},
362817
- base_branch_head: options2?.baseBranchHead
362853
+ generator_versions: options2?.generatorVersions ?? {}
362818
362854
  };
362819
362855
  }
362820
362856
  async stageAll() {
@@ -363193,7 +363229,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363193
363229
  flow: "first-generation",
363194
363230
  previousGenerationSha: null,
363195
363231
  currentGenerationSha: headSha,
363196
- baseBranchHead: options2.baseBranchHead ?? null,
363197
363232
  _prepared: {
363198
363233
  kind: "terminal",
363199
363234
  flow: "first-generation",
@@ -363203,8 +363238,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363203
363238
  }
363204
363239
  const commitOpts = options2 ? {
363205
363240
  cliVersion: options2.cliVersion ?? "unknown",
363206
- generatorVersions: options2.generatorVersions ?? {},
363207
- baseBranchHead: options2.baseBranchHead
363241
+ generatorVersions: options2.generatorVersions ?? {}
363208
363242
  } : void 0;
363209
363243
  await this.service.committer.commitGeneration("Initial SDK generation", commitOpts);
363210
363244
  const genRecord = await this.service.committer.createGenerationRecord(commitOpts);
@@ -363213,7 +363247,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363213
363247
  flow: "first-generation",
363214
363248
  previousGenerationSha: null,
363215
363249
  currentGenerationSha: genRecord.commit_sha,
363216
- baseBranchHead: options2?.baseBranchHead ?? null,
363217
363250
  _prepared: {
363218
363251
  kind: "active",
363219
363252
  flow: "first-generation",
@@ -363248,8 +363281,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363248
363281
  async prepare(options2) {
363249
363282
  const commitOpts = options2 ? {
363250
363283
  cliVersion: options2.cliVersion ?? "unknown",
363251
- generatorVersions: options2.generatorVersions ?? {},
363252
- baseBranchHead: options2.baseBranchHead
363284
+ generatorVersions: options2.generatorVersions ?? {}
363253
363285
  } : void 0;
363254
363286
  await this.service.committer.commitGeneration("Update SDK (replay skipped)", commitOpts);
363255
363287
  await this.service.cleanupStaleConflictMarkers();
@@ -363271,7 +363303,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363271
363303
  flow: "skip-application",
363272
363304
  previousGenerationSha,
363273
363305
  currentGenerationSha: genRecord.commit_sha,
363274
- baseBranchHead: options2?.baseBranchHead ?? null,
363275
363306
  _prepared: {
363276
363307
  kind: "active",
363277
363308
  flow: "skip-application",
@@ -363330,7 +363361,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363330
363361
  flow: "no-patches",
363331
363362
  previousGenerationSha,
363332
363363
  currentGenerationSha: headSha,
363333
- baseBranchHead: options2.baseBranchHead ?? null,
363334
363364
  _prepared: {
363335
363365
  kind: "terminal",
363336
363366
  flow: "no-patches",
@@ -363362,8 +363392,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363362
363392
  }
363363
363393
  const commitOpts = options2 ? {
363364
363394
  cliVersion: options2.cliVersion ?? "unknown",
363365
- generatorVersions: options2.generatorVersions ?? {},
363366
- baseBranchHead: options2.baseBranchHead
363395
+ generatorVersions: options2.generatorVersions ?? {}
363367
363396
  } : void 0;
363368
363397
  await this.service.committer.commitGeneration("Update SDK", commitOpts);
363369
363398
  await this.service.cleanupStaleConflictMarkers();
@@ -363373,7 +363402,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363373
363402
  flow: "no-patches",
363374
363403
  previousGenerationSha,
363375
363404
  currentGenerationSha: genRecord.commit_sha,
363376
- baseBranchHead: options2?.baseBranchHead ?? null,
363377
363405
  _prepared: {
363378
363406
  kind: "active",
363379
363407
  flow: "no-patches",
@@ -363461,7 +363489,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363461
363489
  flow: "normal-regeneration",
363462
363490
  previousGenerationSha,
363463
363491
  currentGenerationSha: headSha,
363464
- baseBranchHead: options2.baseBranchHead ?? null,
363465
363492
  _prepared: {
363466
363493
  kind: "terminal",
363467
363494
  flow: "normal-regeneration",
@@ -363479,14 +363506,16 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363479
363506
  existingPatches = this.service.lockManager.getPatches();
363480
363507
  const seenHashes = /* @__PURE__ */ new Map();
363481
363508
  for (const p14 of existingPatches) {
363482
- const priorPatchId = seenHashes.get(p14.content_hash);
363483
- if (priorPatchId !== void 0) {
363484
- this.service.lockManager.removePatch(p14.id);
363485
- this.service.warnings.push(
363486
- `Consolidated patch ${p14.id} (commit ${(p14.original_commit || "<missing>").slice(0, 7)}) into prior patch ${priorPatchId}: byte-identical patch_content. Per-commit attribution preserved in git log; lockfile collapsed to avoid duplicate-apply corruption on next regen.`
363487
- );
363488
- } else {
363489
- seenHashes.set(p14.content_hash, p14.id);
363509
+ if (!p14.original_commit || p14.original_commit === "") {
363510
+ const priorPatchId = seenHashes.get(p14.content_hash);
363511
+ if (priorPatchId !== void 0) {
363512
+ this.service.lockManager.removePatch(p14.id);
363513
+ this.service.warnings.push(
363514
+ `Consolidated patch ${p14.id} into prior patch ${priorPatchId}: byte-identical patch_content. Lockfile collapsed to avoid duplicate-apply corruption on next regen.`
363515
+ );
363516
+ } else {
363517
+ seenHashes.set(p14.content_hash, p14.id);
363518
+ }
363490
363519
  }
363491
363520
  }
363492
363521
  existingPatches = this.service.lockManager.getPatches();
@@ -363515,8 +363544,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363515
363544
  const allPatches = [...existingPatches, ...newPatches];
363516
363545
  const commitOpts = options2 ? {
363517
363546
  cliVersion: options2.cliVersion ?? "unknown",
363518
- generatorVersions: options2.generatorVersions ?? {},
363519
- baseBranchHead: options2.baseBranchHead
363547
+ generatorVersions: options2.generatorVersions ?? {}
363520
363548
  } : void 0;
363521
363549
  await this.service.committer.commitGeneration("Update SDK", commitOpts);
363522
363550
  await this.service.cleanupStaleConflictMarkers();
@@ -363526,7 +363554,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363526
363554
  flow: "normal-regeneration",
363527
363555
  previousGenerationSha,
363528
363556
  currentGenerationSha: genRecord.commit_sha,
363529
- baseBranchHead: options2?.baseBranchHead ?? null,
363530
363557
  _prepared: {
363531
363558
  kind: "active",
363532
363559
  flow: "normal-regeneration",
@@ -363717,68 +363744,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
363717
363744
  const prep = await this.prepareReplay(options2);
363718
363745
  return this.applyPreparedReplay(prep, options2);
363719
363746
  }
363720
- /**
363721
- * Sync the lockfile after a divergent PR was squash-merged.
363722
- * Call this BEFORE runReplay() when the CLI detects a merged divergent PR.
363723
- *
363724
- * After updating the generation record, re-detects customer patches via
363725
- * tree diff between the generation tag (pure generation tree) and HEAD
363726
- * (which includes customer customizations after squash merge). This ensures
363727
- * patches survive the squash merge → regenerate cycle even when the lockfile
363728
- * was restored from the base branch during conflict PR creation.
363729
- */
363730
- async syncFromDivergentMerge(generationCommitSha, options2) {
363731
- const treeHash = await this.git.getTreeHash(generationCommitSha);
363732
- const timestamp2 = (await this.git.exec(["log", "-1", "--format=%aI", generationCommitSha])).trim();
363733
- const record23 = {
363734
- commit_sha: generationCommitSha,
363735
- tree_hash: treeHash,
363736
- timestamp: timestamp2,
363737
- cli_version: options2?.cliVersion ?? "unknown",
363738
- generator_versions: options2?.generatorVersions ?? {},
363739
- base_branch_head: options2?.baseBranchHead
363740
- };
363741
- let resolvedPatches;
363742
- if (!this.lockManager.exists()) {
363743
- this.lockManager.initializeInMemory(record23);
363744
- } else {
363745
- this.lockManager.read();
363746
- const unresolvedPatches = [
363747
- ...this.lockManager.getUnresolvedPatches(),
363748
- ...this.lockManager.getResolvingPatches()
363749
- ];
363750
- resolvedPatches = this.lockManager.getPatches().filter((p14) => p14.status == null);
363751
- this.lockManager.addGeneration(record23);
363752
- this.lockManager.clearPatches();
363753
- for (const patch5 of unresolvedPatches) {
363754
- this.lockManager.addPatch(patch5);
363755
- }
363756
- }
363757
- try {
363758
- const { patches: redetectedPatches } = await this.detector.detectNewPatches();
363759
- if (redetectedPatches.length > 0) {
363760
- const redetectedFiles = new Set(redetectedPatches.flatMap((p14) => p14.files));
363761
- const currentPatches = this.lockManager.getPatches();
363762
- for (const patch5 of currentPatches) {
363763
- if (patch5.status != null && patch5.files.some((f4) => redetectedFiles.has(f4))) {
363764
- this.lockManager.removePatch(patch5.id);
363765
- }
363766
- }
363767
- for (const patch5 of redetectedPatches) {
363768
- this.lockManager.addPatch(patch5);
363769
- }
363770
- }
363771
- } catch (error50) {
363772
- for (const patch5 of resolvedPatches ?? []) {
363773
- this.lockManager.addPatch(patch5);
363774
- }
363775
- this.detector.warnings.push(
363776
- `Patch re-detection failed after divergent merge sync. ${(resolvedPatches ?? []).length} previously resolved patch(es) preserved. Error: ${error50 instanceof Error ? error50.message : String(error50)}`
363777
- );
363778
- }
363779
- this.lockManager.save();
363780
- this.detector.warnings.push(...this.lockManager.warnings);
363781
- }
363782
363747
  determineFlow() {
363783
363748
  try {
363784
363749
  const lock = this.lockManager.read();
@@ -365476,14 +365441,12 @@ var require_replay_run = __commonJS({
365476
365441
  exports2.replayPrepare = replayPrepare;
365477
365442
  exports2.replayApply = replayApply;
365478
365443
  exports2.replayRun = replayRun;
365479
- exports2.isTagMergedIntoHead = isTagMergedIntoHead;
365480
365444
  var replay_1 = require_dist14();
365481
- var child_process_1 = require("child_process");
365482
365445
  var fs_1 = require("fs");
365483
365446
  var path_1 = require("path");
365484
365447
  var fernignore_1 = require_fernignore();
365485
365448
  async function replayPrepare(params2, state) {
365486
- const { outputDir, cliVersion, generatorVersions, stageOnly = false, generatorName, skipApplication, logger: logger4 } = params2;
365449
+ const { outputDir, cliVersion, generatorVersions, stageOnly = false, skipApplication, logger: logger4 } = params2;
365487
365450
  const lockfilePath = (0, path_1.join)(outputDir, ".fern", "replay.lock");
365488
365451
  let autoBootstrapped = false;
365489
365452
  let bootstrapAttempted = false;
@@ -365516,57 +365479,6 @@ var require_replay_run = __commonJS({
365516
365479
  return null;
365517
365480
  }
365518
365481
  }
365519
- const baseBranchHead = gitRevParse(outputDir, "HEAD");
365520
- let previousGenerationSha = null;
365521
- let prevBaseBranchHead = null;
365522
- try {
365523
- const lockManager = new replay_1.LockfileManager(outputDir);
365524
- if (lockManager.exists()) {
365525
- const lock = lockManager.read();
365526
- previousGenerationSha = lock.current_generation;
365527
- const latestGen = lock.generations.find((g8) => g8.commit_sha === lock.current_generation);
365528
- prevBaseBranchHead = latestGen?.base_branch_head ?? null;
365529
- }
365530
- } catch {
365531
- }
365532
- if (previousGenerationSha != null) {
365533
- const sanitizedName = generatorName?.replace(/\//g, "--");
365534
- const namespacedTag = sanitizedName != null ? `fern-generation-base--${sanitizedName}` : null;
365535
- const tagSha = (namespacedTag != null ? gitRevParse(outputDir, namespacedTag) : null) ?? gitRevParse(outputDir, "fern-generation-base");
365536
- let shouldSync = false;
365537
- if (tagSha != null) {
365538
- const tagParent = gitRevParse(outputDir, `${tagSha}^`);
365539
- if (tagParent === prevBaseBranchHead || tagParent === previousGenerationSha) {
365540
- const tagDistance = gitDiffNameOnly(outputDir, tagSha, "HEAD").length;
365541
- const lockDistance = gitDiffNameOnly(outputDir, prevBaseBranchHead ?? previousGenerationSha, "HEAD").length;
365542
- shouldSync = tagDistance < lockDistance;
365543
- }
365544
- }
365545
- if (shouldSync && tagSha != null) {
365546
- if (!isTagMergedIntoHead(outputDir, tagSha)) {
365547
- logger4?.warn(`fern-generation-base tag ${tagSha} is not reachable from HEAD \u2014 skipping divergent-merge sync. The tag likely points at an unmerged generation (PR closed without merge).`);
365548
- } else {
365549
- try {
365550
- const syncService = new replay_1.ReplayService(outputDir, { enabled: true });
365551
- await syncService.syncFromDivergentMerge(tagSha, {
365552
- cliVersion,
365553
- generatorVersions,
365554
- baseBranchHead: baseBranchHead ?? void 0
365555
- });
365556
- } catch (error50) {
365557
- logger4?.warn("Replay divergent-merge sync failed, continuing without sync: " + String(error50));
365558
- throw new ReplayPrepareError(String(error50), error50);
365559
- }
365560
- try {
365561
- const freshLockManager = new replay_1.LockfileManager(outputDir);
365562
- if (freshLockManager.exists()) {
365563
- previousGenerationSha = freshLockManager.read().current_generation;
365564
- }
365565
- } catch {
365566
- }
365567
- }
365568
- }
365569
- }
365570
365482
  const service = new replay_1.ReplayService(outputDir, { enabled: true });
365571
365483
  let preparation;
365572
365484
  try {
@@ -365574,8 +365486,7 @@ var require_replay_run = __commonJS({
365574
365486
  cliVersion,
365575
365487
  generatorVersions,
365576
365488
  stageOnly,
365577
- skipApplication,
365578
- baseBranchHead: baseBranchHead ?? void 0
365489
+ skipApplication
365579
365490
  });
365580
365491
  } catch (error50) {
365581
365492
  logger4?.warn("Replay prepare failed, continuing without replay: " + String(error50));
@@ -365586,9 +365497,8 @@ var require_replay_run = __commonJS({
365586
365497
  _preparation: preparation,
365587
365498
  outputDir,
365588
365499
  flow: preparation.flow,
365589
- previousGenerationSha,
365500
+ previousGenerationSha: preparation.previousGenerationSha,
365590
365501
  currentGenerationSha: preparation.currentGenerationSha,
365591
- baseBranchHead,
365592
365502
  autoBootstrapped,
365593
365503
  bootstrapAttempted
365594
365504
  };
@@ -365605,24 +365515,11 @@ var require_replay_run = __commonJS({
365605
365515
  fernignoreUpdated: false,
365606
365516
  previousGenerationSha: prepared.previousGenerationSha,
365607
365517
  currentGenerationSha: prepared.currentGenerationSha,
365608
- baseBranchHead: prepared.baseBranchHead,
365609
365518
  autoBootstrapped: prepared.autoBootstrapped,
365610
365519
  bootstrapAttempted: prepared.bootstrapAttempted,
365611
365520
  failureReason: String(error50)
365612
365521
  };
365613
365522
  }
365614
- let resolvedBaseBranchHead = prepared.baseBranchHead;
365615
- try {
365616
- const freshLockManager = new replay_1.LockfileManager(prepared.outputDir);
365617
- if (freshLockManager.exists()) {
365618
- const freshLock = freshLockManager.read();
365619
- const latestGen = freshLock.generations.find((g8) => g8.commit_sha === freshLock.current_generation);
365620
- if (latestGen?.base_branch_head) {
365621
- resolvedBaseBranchHead = latestGen.base_branch_head;
365622
- }
365623
- }
365624
- } catch {
365625
- }
365626
365523
  const fernignoreUpdated = await (0, fernignore_1.ensureReplayFernignoreEntries)(prepared.outputDir);
365627
365524
  await (0, fernignore_1.ensureGitattributesEntries)(prepared.outputDir);
365628
365525
  return {
@@ -365630,7 +365527,6 @@ var require_replay_run = __commonJS({
365630
365527
  fernignoreUpdated,
365631
365528
  previousGenerationSha: prepared.previousGenerationSha,
365632
365529
  currentGenerationSha: prepared.currentGenerationSha,
365633
- baseBranchHead: resolvedBaseBranchHead,
365634
365530
  autoBootstrapped: prepared.autoBootstrapped,
365635
365531
  bootstrapAttempted: prepared.bootstrapAttempted
365636
365532
  };
@@ -365646,7 +365542,6 @@ var require_replay_run = __commonJS({
365646
365542
  fernignoreUpdated: false,
365647
365543
  previousGenerationSha: null,
365648
365544
  currentGenerationSha: null,
365649
- baseBranchHead: null,
365650
365545
  autoBootstrapped: false,
365651
365546
  bootstrapAttempted: prepareState.bootstrapAttempted,
365652
365547
  failureReason: error50 instanceof ReplayPrepareError ? error50.reason : String(error50)
@@ -365658,7 +365553,6 @@ var require_replay_run = __commonJS({
365658
365553
  fernignoreUpdated: false,
365659
365554
  previousGenerationSha: null,
365660
365555
  currentGenerationSha: null,
365661
- baseBranchHead: null,
365662
365556
  autoBootstrapped: false,
365663
365557
  bootstrapAttempted: prepareState.bootstrapAttempted
365664
365558
  };
@@ -365678,53 +365572,6 @@ var require_replay_run = __commonJS({
365678
365572
  }
365679
365573
  };
365680
365574
  exports2.ReplayPrepareError = ReplayPrepareError;
365681
- function isTagMergedIntoHead(cwd2, tagSha) {
365682
- try {
365683
- (0, child_process_1.execFileSync)("git", ["merge-base", "--is-ancestor", tagSha, "HEAD"], {
365684
- cwd: cwd2,
365685
- stdio: "pipe"
365686
- });
365687
- return true;
365688
- } catch {
365689
- }
365690
- const tagTree = gitRevParse(cwd2, `${tagSha}^{tree}`);
365691
- if (tagTree == null) {
365692
- return false;
365693
- }
365694
- try {
365695
- const trees = (0, child_process_1.execFileSync)("git", ["log", "HEAD", "--format=%T", "--max-count=500"], {
365696
- cwd: cwd2,
365697
- encoding: "utf-8",
365698
- stdio: "pipe"
365699
- });
365700
- return trees.split("\n").some((t3) => t3.trim() === tagTree);
365701
- } catch {
365702
- return false;
365703
- }
365704
- }
365705
- function gitRevParse(cwd2, rev) {
365706
- try {
365707
- return (0, child_process_1.execFileSync)("git", ["rev-parse", "--verify", rev], {
365708
- cwd: cwd2,
365709
- encoding: "utf-8",
365710
- stdio: "pipe"
365711
- }).trim();
365712
- } catch {
365713
- return null;
365714
- }
365715
- }
365716
- function gitDiffNameOnly(cwd2, from4, to10) {
365717
- try {
365718
- const output2 = (0, child_process_1.execFileSync)("git", ["diff", "--name-only", from4, to10], {
365719
- cwd: cwd2,
365720
- encoding: "utf-8",
365721
- stdio: "pipe"
365722
- });
365723
- return output2.trim().split("\n").filter(Boolean);
365724
- } catch {
365725
- return [];
365726
- }
365727
- }
365728
365575
  }
365729
365576
  });
365730
365577
 
@@ -365741,14 +365588,12 @@ var require_GenerationCommitStep = __commonJS({
365741
365588
  config;
365742
365589
  cliVersion;
365743
365590
  generatorVersions;
365744
- generatorName;
365745
365591
  name = "generationCommit";
365746
- constructor(outputDir, logger4, config5, cliVersion, generatorVersions, generatorName) {
365592
+ constructor(outputDir, logger4, config5, cliVersion, generatorVersions) {
365747
365593
  super(outputDir, logger4);
365748
365594
  this.config = config5;
365749
365595
  this.cliVersion = cliVersion;
365750
365596
  this.generatorVersions = generatorVersions;
365751
- this.generatorName = generatorName;
365752
365597
  }
365753
365598
  async execute(_context) {
365754
365599
  const headBeforePrepare = tryRevParse(this.outputDir, "HEAD");
@@ -365759,7 +365604,6 @@ var require_GenerationCommitStep = __commonJS({
365759
365604
  outputDir: this.outputDir,
365760
365605
  cliVersion: this.cliVersion,
365761
365606
  generatorVersions: this.generatorVersions,
365762
- generatorName: this.generatorName,
365763
365607
  skipApplication: this.config.skipApplication,
365764
365608
  logger: this.logger
365765
365609
  }, prepareState);
@@ -365796,7 +365640,6 @@ var require_GenerationCommitStep = __commonJS({
365796
365640
  preparedReplay: prepared,
365797
365641
  previousGenerationSha: prepared.previousGenerationSha ?? void 0,
365798
365642
  currentGenerationSha: prepared.currentGenerationSha,
365799
- baseBranchHead: prepared.baseBranchHead ?? void 0,
365800
365643
  flow: prepared.flow,
365801
365644
  bootstrapAttempted: prepareState.bootstrapAttempted
365802
365645
  };
@@ -370467,14 +370310,12 @@ var require_ReplayStep = __commonJS({
370467
370310
  config;
370468
370311
  cliVersion;
370469
370312
  generatorVersions;
370470
- generatorName;
370471
370313
  name = "replay";
370472
- constructor(outputDir, logger4, config5, cliVersion, generatorVersions, generatorName) {
370314
+ constructor(outputDir, logger4, config5, cliVersion, generatorVersions) {
370473
370315
  super(outputDir, logger4);
370474
370316
  this.config = config5;
370475
370317
  this.cliVersion = cliVersion;
370476
370318
  this.generatorVersions = generatorVersions;
370477
- this.generatorName = generatorName;
370478
370319
  }
370479
370320
  async execute(context3) {
370480
370321
  const generationCommit = context3.previousStepResults.generationCommit;
@@ -370513,7 +370354,6 @@ var require_ReplayStep = __commonJS({
370513
370354
  cliVersion: this.cliVersion,
370514
370355
  generatorVersions: this.generatorVersions,
370515
370356
  stageOnly: this.config.stageOnly ?? false,
370516
- generatorName: this.generatorName,
370517
370357
  skipApplication: this.config.skipApplication,
370518
370358
  logger: this.logger
370519
370359
  });
@@ -370525,7 +370365,6 @@ var require_ReplayStep = __commonJS({
370525
370365
  errorMessage: result.failureReason,
370526
370366
  previousGenerationSha: result.previousGenerationSha ?? void 0,
370527
370367
  currentGenerationSha: result.currentGenerationSha ?? void 0,
370528
- baseBranchHead: result.baseBranchHead ?? void 0,
370529
370368
  autoBootstrapped: result.autoBootstrapped,
370530
370369
  bootstrapAttempted: result.bootstrapAttempted,
370531
370370
  flow: "normal-regeneration",
@@ -370540,7 +370379,6 @@ var require_ReplayStep = __commonJS({
370540
370379
  success: true,
370541
370380
  previousGenerationSha: result.previousGenerationSha ?? void 0,
370542
370381
  currentGenerationSha: result.currentGenerationSha ?? void 0,
370543
- baseBranchHead: result.baseBranchHead ?? void 0,
370544
370382
  autoBootstrapped: result.autoBootstrapped,
370545
370383
  bootstrapAttempted: result.bootstrapAttempted,
370546
370384
  flow: "first-generation",
@@ -370555,7 +370393,6 @@ var require_ReplayStep = __commonJS({
370555
370393
  success: true,
370556
370394
  previousGenerationSha: result.previousGenerationSha ?? void 0,
370557
370395
  currentGenerationSha: result.currentGenerationSha ?? void 0,
370558
- baseBranchHead: result.baseBranchHead ?? void 0,
370559
370396
  autoBootstrapped: result.autoBootstrapped,
370560
370397
  bootstrapAttempted: result.bootstrapAttempted,
370561
370398
  flow: report.flow,
@@ -370948,13 +370785,13 @@ var require_PostGenerationPipeline = __commonJS({
370948
370785
  autoVersionEnabled = false;
370949
370786
  }
370950
370787
  if (replayEnabled && config5.replay != null) {
370951
- this.steps.push(new GenerationCommitStep_1.GenerationCommitStep(config5.outputDir, this.logger, { enabled: true, skipApplication: config5.replay.skipApplication }, config5.cliVersion, config5.generatorVersions, config5.generatorName));
370788
+ this.steps.push(new GenerationCommitStep_1.GenerationCommitStep(config5.outputDir, this.logger, { enabled: true, skipApplication: config5.replay.skipApplication }, config5.cliVersion, config5.generatorVersions));
370952
370789
  }
370953
370790
  if (autoVersionEnabled && config5.autoVersion != null) {
370954
370791
  this.steps.push(new AutoVersionStep_1.AutoVersionStep(config5.outputDir, this.logger, config5.autoVersion));
370955
370792
  }
370956
370793
  if (replayEnabled && config5.replay != null) {
370957
- this.steps.push(new ReplayStep_1.ReplayStep(config5.outputDir, this.logger, config5.replay, config5.cliVersion, config5.generatorVersions, config5.generatorName));
370794
+ this.steps.push(new ReplayStep_1.ReplayStep(config5.outputDir, this.logger, config5.replay, config5.cliVersion, config5.generatorVersions));
370958
370795
  }
370959
370796
  if (config5.verify?.enabled) {
370960
370797
  this.steps.push(new VerificationStep_1.VerificationStep(config5.outputDir, this.logger, config5.verify, config5.generatorName, config5.generatorVersions));
@@ -668113,7 +667950,7 @@ var AccessTokenPosthogManager = class {
668113
667950
  properties: {
668114
667951
  ...event,
668115
667952
  ...event.properties,
668116
- version: "5.28.0",
667953
+ version: "5.28.2",
668117
667954
  usingAccessToken: true,
668118
667955
  ...getRunIdProperties()
668119
667956
  }
@@ -668177,7 +668014,7 @@ var UserPosthogManager = class {
668177
668014
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
668178
668015
  event: "CLI",
668179
668016
  properties: {
668180
- version: "5.28.0",
668017
+ version: "5.28.2",
668181
668018
  ...event,
668182
668019
  ...event.properties,
668183
668020
  usingAccessToken: false,
@@ -825352,6 +825189,7 @@ function convertAvailability5(availability) {
825352
825189
  }
825353
825190
 
825354
825191
  // ../docs-resolver/lib/stitchGlobalTheme.js
825192
+ init_lib4();
825355
825193
  init_lib8();
825356
825194
  init_lib6();
825357
825195
  var import_promises66 = require("fs/promises");
@@ -825486,6 +825324,18 @@ async function resolveThemeFileUrls(themeConfig, tmpDir) {
825486
825324
  }
825487
825325
  return cfg;
825488
825326
  }
825327
+ function deepMergeGlobalWins(local, global3) {
825328
+ const result = { ...local };
825329
+ for (const [key2, globalValue] of Object.entries(global3)) {
825330
+ const localValue = local[key2];
825331
+ if (isPlainObject4(globalValue) && isPlainObject4(localValue)) {
825332
+ result[key2] = deepMergeGlobalWins(localValue, globalValue);
825333
+ } else {
825334
+ result[key2] = globalValue;
825335
+ }
825336
+ }
825337
+ return result;
825338
+ }
825489
825339
  var THEME_FIELD_POLICIES = {
825490
825340
  logo: "global",
825491
825341
  favicon: "global",
@@ -825539,7 +825389,11 @@ function mergeThemeOverride(local, themeOverride) {
825539
825389
  const localHasValue = localValue !== void 0 && localValue !== null;
825540
825390
  if (policy === "global") {
825541
825391
  if (themeHasValue) {
825542
- merged[key2] = themeValue;
825392
+ if (isPlainObject4(themeValue) && isPlainObject4(localValue)) {
825393
+ merged[key2] = deepMergeGlobalWins(localValue, themeValue);
825394
+ } else {
825395
+ merged[key2] = themeValue;
825396
+ }
825543
825397
  }
825544
825398
  } else {
825545
825399
  if (localHasValue) {
@@ -859851,7 +859705,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
859851
859705
  var LOGS_FOLDER_NAME = "logs";
859852
859706
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
859853
859707
  function getCliSource() {
859854
- const version7 = "5.28.0";
859708
+ const version7 = "5.28.2";
859855
859709
  return `cli@${version7}`;
859856
859710
  }
859857
859711
  var DebugLogger = class {
@@ -873860,7 +873714,7 @@ var LegacyDocsPublisher = class {
873860
873714
  previewId,
873861
873715
  disableTemplates: void 0,
873862
873716
  skipUpload,
873863
- cliVersion: "5.28.0",
873717
+ cliVersion: "5.28.2",
873864
873718
  loginCommand: "fern auth login"
873865
873719
  });
873866
873720
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -948265,7 +948119,7 @@ function getAutomationContextFromEnv() {
948265
948119
  config_branch: process.env.FERN_CONFIG_BRANCH,
948266
948120
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
948267
948121
  trigger: process.env.GITHUB_EVENT_NAME,
948268
- cli_version: "5.28.0"
948122
+ cli_version: "5.28.2"
948269
948123
  };
948270
948124
  }
948271
948125
  function isAutomationMode() {
@@ -949091,7 +948945,7 @@ var CliContext = class _CliContext {
949091
948945
  if (false) {
949092
948946
  this.logger.error("CLI_VERSION is not defined");
949093
948947
  }
949094
- return "5.28.0";
948948
+ return "5.28.2";
949095
948949
  }
949096
948950
  getCliName() {
949097
948951
  if (false) {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.28.0",
2
+ "version": "5.28.2",
3
3
  "repository": {
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/fern-api/fern.git",