@fern-api/generator-cli 0.9.49 → 0.9.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +94 -8
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -22214,7 +22214,7 @@ var init_diff3 = __esm({
|
|
|
22214
22214
|
}
|
|
22215
22215
|
});
|
|
22216
22216
|
|
|
22217
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.19.
|
|
22217
|
+
// ../../node_modules/.pnpm/@fern-api+replay@0.19.1/node_modules/@fern-api/replay/dist/index.js
|
|
22218
22218
|
var dist_exports = {};
|
|
22219
22219
|
__export(dist_exports, {
|
|
22220
22220
|
CREDENTIAL_PATTERNS: () => CREDENTIAL_PATTERNS,
|
|
@@ -23059,6 +23059,37 @@ async function buildMergePlan(args) {
|
|
|
23059
23059
|
conflictReasonHint
|
|
23060
23060
|
};
|
|
23061
23061
|
}
|
|
23062
|
+
function maskVersions(line) {
|
|
23063
|
+
return line.replace(VERSION_TOKEN, VERSION_MASK);
|
|
23064
|
+
}
|
|
23065
|
+
function containsPlaceholder(content) {
|
|
23066
|
+
if (!content) return false;
|
|
23067
|
+
return AUTOVERSION_PLACEHOLDERS.some((p2) => content.includes(p2));
|
|
23068
|
+
}
|
|
23069
|
+
function remapManagedLines(genBase, target, theirs) {
|
|
23070
|
+
if (!containsPlaceholder(genBase)) return theirs;
|
|
23071
|
+
const managedMasks = /* @__PURE__ */ new Set();
|
|
23072
|
+
for (const line of genBase.split("\n")) {
|
|
23073
|
+
if (AUTOVERSION_PLACEHOLDERS.some((p2) => line.includes(p2))) managedMasks.add(maskVersions(line));
|
|
23074
|
+
}
|
|
23075
|
+
if (managedMasks.size === 0) return theirs;
|
|
23076
|
+
const targetByMask = /* @__PURE__ */ new Map();
|
|
23077
|
+
for (const line of target.split("\n")) {
|
|
23078
|
+
const mask = maskVersions(line);
|
|
23079
|
+
if (managedMasks.has(mask) && !targetByMask.has(mask)) targetByMask.set(mask, line);
|
|
23080
|
+
}
|
|
23081
|
+
return theirs.split("\n").map((line) => {
|
|
23082
|
+
const mask = maskVersions(line);
|
|
23083
|
+
const replacement = managedMasks.has(mask) ? targetByMask.get(mask) : void 0;
|
|
23084
|
+
return replacement !== void 0 && replacement !== line ? replacement : line;
|
|
23085
|
+
}).join("\n");
|
|
23086
|
+
}
|
|
23087
|
+
function neutralizeAutoversionTheirs(genBase, theirs) {
|
|
23088
|
+
return remapManagedLines(genBase, genBase, theirs);
|
|
23089
|
+
}
|
|
23090
|
+
function alignAutoversionToOurs(genBase, ours, theirs) {
|
|
23091
|
+
return remapManagedLines(genBase, ours, theirs);
|
|
23092
|
+
}
|
|
23062
23093
|
async function runMergeAndRecord(args) {
|
|
23063
23094
|
const { plan, inputs, patch, accumulator } = args;
|
|
23064
23095
|
const { resolvedPath, metadata, oursPath, ours } = inputs;
|
|
@@ -23089,11 +23120,13 @@ async function runMergeAndRecord(args) {
|
|
|
23089
23120
|
accumulator.recordMerge(resolvedPath, merged2.content, patch.base_generation);
|
|
23090
23121
|
return { file: resolvedPath, status: "merged", ...unreachableFlag };
|
|
23091
23122
|
}
|
|
23092
|
-
const
|
|
23123
|
+
const mergeBase = inputs.base != null ? alignAutoversionToOurs(inputs.base, ours, plan.mergeBase) : plan.mergeBase;
|
|
23124
|
+
const theirs = inputs.base != null ? alignAutoversionToOurs(inputs.base, ours, plan.theirs) : plan.theirs;
|
|
23125
|
+
const merged = threeWayMerge(mergeBase, ours, theirs);
|
|
23093
23126
|
await (0, import_promises7.mkdir)((0, import_path12.dirname)(oursPath), { recursive: true });
|
|
23094
23127
|
await (0, import_promises7.writeFile)(oursPath, merged.content);
|
|
23095
23128
|
if (merged.hasConflicts) {
|
|
23096
|
-
accumulator.recordConflict(resolvedPath,
|
|
23129
|
+
accumulator.recordConflict(resolvedPath, theirs, patch.base_generation);
|
|
23097
23130
|
return {
|
|
23098
23131
|
file: resolvedPath,
|
|
23099
23132
|
status: "conflict",
|
|
@@ -23102,7 +23135,7 @@ async function runMergeAndRecord(args) {
|
|
|
23102
23135
|
conflictMetadata: metadata
|
|
23103
23136
|
};
|
|
23104
23137
|
}
|
|
23105
|
-
accumulator.recordMerge(resolvedPath,
|
|
23138
|
+
accumulator.recordMerge(resolvedPath, theirs, patch.base_generation);
|
|
23106
23139
|
return {
|
|
23107
23140
|
file: resolvedPath,
|
|
23108
23141
|
status: "merged",
|
|
@@ -24260,9 +24293,9 @@ function status(outputDir) {
|
|
|
24260
24293
|
legacyDismissedCount
|
|
24261
24294
|
};
|
|
24262
24295
|
}
|
|
24263
|
-
var import_promises4, import_os, import_path7, import_fs6, import_path8, import_yaml, import_crypto, import_path9, import_promises5, import_os2, import_path10, import_promises6, import_path11, import_promises7, import_path12, import_fs7, import_promises8, import_path13, import_fs8, import_path14, import_promises9, import_os3, import_path15, import_child_process3, import_crypto2, import_fs9, import_path16, import_yaml2, import_crypto3, import_fs10, import_path17, import_fs11, import_promises10, import_path18, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, HybridReconstruction_exports, init_HybridReconstruction, PatchApplyTheirs_exports, init_PatchApplyTheirs, CREDENTIAL_PATTERNS, SENSITIVE_FILE_PATTERNS, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileNotFoundError, LockfileManager, BINARY_EXTENSIONS, INFRASTRUCTURE_FILES, ReplayDetector, MergeAccumulator, CONFLICT_OPENER, CONFLICT_SEPARATOR, CONFLICT_CLOSER, ReplayApplicator, ReplayCommitter, FileOwnership, FirstGenerationFlow, SkipApplicationFlow, NoPatchesFlow, NormalRegenerationFlow, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, GITATTRIBUTES_ENTRIES, EMPTY_RESULT;
|
|
24296
|
+
var import_promises4, import_os, import_path7, import_fs6, import_path8, import_yaml, import_crypto, import_path9, import_promises5, import_os2, import_path10, import_promises6, import_path11, import_promises7, import_path12, import_fs7, import_promises8, import_path13, import_fs8, import_path14, import_promises9, import_os3, import_path15, import_child_process3, import_crypto2, import_fs9, import_path16, import_yaml2, import_crypto3, import_fs10, import_path17, import_fs11, import_promises10, import_path18, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, HybridReconstruction_exports, init_HybridReconstruction, PatchApplyTheirs_exports, init_PatchApplyTheirs, CREDENTIAL_PATTERNS, SENSITIVE_FILE_PATTERNS, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileNotFoundError, LockfileManager, BINARY_EXTENSIONS, INFRASTRUCTURE_FILES, ReplayDetector, MergeAccumulator, CONFLICT_OPENER, CONFLICT_SEPARATOR, CONFLICT_CLOSER, AUTOVERSION_PLACEHOLDERS, VERSION_TOKEN, VERSION_MASK, ReplayApplicator, ReplayCommitter, FileOwnership, FirstGenerationFlow, SkipApplicationFlow, NoPatchesFlow, NormalRegenerationFlow, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, GITATTRIBUTES_ENTRIES, EMPTY_RESULT;
|
|
24264
24297
|
var init_dist3 = __esm({
|
|
24265
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.19.
|
|
24298
|
+
"../../node_modules/.pnpm/@fern-api+replay@0.19.1/node_modules/@fern-api/replay/dist/index.js"() {
|
|
24266
24299
|
"use strict";
|
|
24267
24300
|
init_esm4();
|
|
24268
24301
|
import_promises4 = require("fs/promises");
|
|
@@ -25466,6 +25499,16 @@ var init_dist3 = __esm({
|
|
|
25466
25499
|
CONFLICT_OPENER = "<<<<<<< Generated";
|
|
25467
25500
|
CONFLICT_SEPARATOR = "=======";
|
|
25468
25501
|
CONFLICT_CLOSER = ">>>>>>> Your customization";
|
|
25502
|
+
AUTOVERSION_PLACEHOLDERS = [
|
|
25503
|
+
"v0.0.0-fern-placeholder",
|
|
25504
|
+
// Go -- a superstring of the default; check first
|
|
25505
|
+
"0.0.0-fern-placeholder",
|
|
25506
|
+
// TS/Java/C#/Ruby/PHP/Rust/default
|
|
25507
|
+
"0.0.0.dev0"
|
|
25508
|
+
// Python (PEP 440 -- Poetry rejects hyphens)
|
|
25509
|
+
];
|
|
25510
|
+
VERSION_TOKEN = /(?:v)?\d+\.\d+\.\d+[0-9A-Za-z.+-]*/g;
|
|
25511
|
+
VERSION_MASK = "@@FERN_VERSION@@";
|
|
25469
25512
|
ReplayApplicator = class {
|
|
25470
25513
|
git;
|
|
25471
25514
|
lockManager;
|
|
@@ -26852,7 +26895,9 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
26852
26895
|
if (baseChanged) repointed++;
|
|
26853
26896
|
continue;
|
|
26854
26897
|
}
|
|
26855
|
-
const
|
|
26898
|
+
const rawDiff = await this.git.exec(["diff", currentGenSha, "--", ...patch.files]).catch(() => null);
|
|
26899
|
+
const neutralizedRebase = rawDiff != null && containsPlaceholder(rawDiff) ? await this.computeAutoversionNeutralizedRebase(patch.files, currentGenSha) : null;
|
|
26900
|
+
const diff = neutralizedRebase ? neutralizedRebase.diff : rawDiff;
|
|
26856
26901
|
if (diff === null) continue;
|
|
26857
26902
|
if (!diff.trim()) {
|
|
26858
26903
|
if (hasProtectedFiles) {
|
|
@@ -26908,7 +26953,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
26908
26953
|
patch.base_generation = currentGenSha;
|
|
26909
26954
|
patch.patch_content = diff;
|
|
26910
26955
|
patch.content_hash = newContentHash;
|
|
26911
|
-
const snapshot = await this.readSnapshotFromDisk(patch.files);
|
|
26956
|
+
const snapshot = neutralizedRebase ? neutralizedRebase.snapshot : await this.readSnapshotFromDisk(patch.files);
|
|
26912
26957
|
const snapshotIsNonEmpty = Object.keys(snapshot).length > 0;
|
|
26913
26958
|
if (snapshotIsNonEmpty) {
|
|
26914
26959
|
patch.theirs_snapshot = snapshot;
|
|
@@ -26948,6 +26993,47 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
26948
26993
|
}
|
|
26949
26994
|
return snapshot;
|
|
26950
26995
|
}
|
|
26996
|
+
/**
|
|
26997
|
+
* Autoversion-aware replacement for the naive `git diff currentGen -- files`
|
|
26998
|
+
* + on-disk snapshot used when rebasing a cleanly-applied patch.
|
|
26999
|
+
*
|
|
27000
|
+
* The generation tree (BASE) still carries the placeholder on version lines
|
|
27001
|
+
* (autoversion runs after `[fern-generated]`), but the working tree holds
|
|
27002
|
+
* autoversion's resolved semver. A raw diff/snapshot would fold the
|
|
27003
|
+
* placeholder->semver swap into the customer's patch_content/theirs_snapshot,
|
|
27004
|
+
* pinning a stale version. This re-derives both against a version-neutralized
|
|
27005
|
+
* THEIRS so the pipeline-owned version line never enters the patch.
|
|
27006
|
+
*
|
|
27007
|
+
* Returns null when no file is under autoversion (fixed `--version`, i.e. no
|
|
27008
|
+
* placeholder in the generation tree) — callers keep their existing behavior.
|
|
27009
|
+
*/
|
|
27010
|
+
async computeAutoversionNeutralizedRebase(files, currentGenSha) {
|
|
27011
|
+
const genByFile = /* @__PURE__ */ new Map();
|
|
27012
|
+
let anyPlaceholder = false;
|
|
27013
|
+
for (const file of files) {
|
|
27014
|
+
const gen = await this.git.showFile(currentGenSha, file).catch(() => null);
|
|
27015
|
+
genByFile.set(file, gen);
|
|
27016
|
+
if (containsPlaceholder(gen)) anyPlaceholder = true;
|
|
27017
|
+
}
|
|
27018
|
+
if (!anyPlaceholder) return null;
|
|
27019
|
+
const snapshot = {};
|
|
27020
|
+
const fragments = [];
|
|
27021
|
+
for (const file of files) {
|
|
27022
|
+
if (isBinaryFile(file)) continue;
|
|
27023
|
+
const disk = await (0, import_promises8.readFile)((0, import_path13.join)(this.outputDir, file), "utf-8").catch(() => null);
|
|
27024
|
+
if (disk == null) continue;
|
|
27025
|
+
const gen = genByFile.get(file) ?? null;
|
|
27026
|
+
const neutralized = gen != null ? neutralizeAutoversionTheirs(gen, disk) : disk;
|
|
27027
|
+
snapshot[file] = neutralized;
|
|
27028
|
+
if (gen == null) {
|
|
27029
|
+
fragments.push(synthesizeNewFileDiff(file, neutralized));
|
|
27030
|
+
} else if (gen !== neutralized) {
|
|
27031
|
+
const fileDiff = await unifiedDiff(gen, neutralized, file);
|
|
27032
|
+
if (fileDiff.trim()) fragments.push(fileDiff);
|
|
27033
|
+
}
|
|
27034
|
+
}
|
|
27035
|
+
return { diff: fragments.join(""), snapshot };
|
|
27036
|
+
}
|
|
26951
27037
|
/**
|
|
26952
27038
|
* Detects autoversion contamination — returns true when a
|
|
26953
27039
|
* `[fern-autoversion]` commit between `fromSha` and `toSha` touched any
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fern-api/generator-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.50",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fern-api/fern.git",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@boundaryml/baml": "^0.219.0",
|
|
26
|
-
"@fern-api/replay": "0.19.
|
|
26
|
+
"@fern-api/replay": "0.19.1",
|
|
27
27
|
"@octokit/rest": "^22.0.1",
|
|
28
28
|
"es-toolkit": "^1.45.1",
|
|
29
29
|
"semver": "^7.6.3",
|