@fern-api/generator-cli 0.9.45 → 0.9.47
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 +139 -9
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -41355,7 +41355,8 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
41355
41355
|
}
|
|
41356
41356
|
await this.addSuffixToGoMod(goModPath, modulePath, suffix);
|
|
41357
41357
|
await this.addSuffixToGoFiles(workingDirectory, modulePath, suffix);
|
|
41358
|
-
this.
|
|
41358
|
+
await this.addSuffixToMarkdownFiles(workingDirectory, modulePath, suffix);
|
|
41359
|
+
this.logger.info(`Added ${suffix} to Go module path ${modulePath} across imports, headers, and docs`);
|
|
41359
41360
|
}
|
|
41360
41361
|
/**
|
|
41361
41362
|
* Extracts the major version number from a version string.
|
|
@@ -41436,15 +41437,16 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
41436
41437
|
return results;
|
|
41437
41438
|
}
|
|
41438
41439
|
/**
|
|
41439
|
-
* Adds a version suffix to import paths
|
|
41440
|
+
* Adds a version suffix to import paths and embedded module-path string
|
|
41441
|
+
* literals (e.g. the X-Fern-SDK-Name header value) in all .go files.
|
|
41440
41442
|
*/
|
|
41441
41443
|
async addSuffixToGoFiles(repoRoot, modulePath, suffix) {
|
|
41442
41444
|
const goFiles = await this.walkDirectory(repoRoot, (filePath) => (0, import_path22.extname)(filePath) === ".go");
|
|
41443
41445
|
await this.processInParallel(goFiles, (filePath) => this.addSuffixToGoFile(filePath, modulePath, suffix));
|
|
41444
41446
|
}
|
|
41445
41447
|
/**
|
|
41446
|
-
* Adds a version suffix to import paths
|
|
41447
|
-
*
|
|
41448
|
+
* Adds a version suffix to import paths and embedded module-path string
|
|
41449
|
+
* literals in a single .go file.
|
|
41448
41450
|
*/
|
|
41449
41451
|
async addSuffixToGoFile(filePath, modulePath, suffix) {
|
|
41450
41452
|
const content = await (0, import_promises14.readFile)(filePath, "utf-8");
|
|
@@ -41463,13 +41465,10 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
41463
41465
|
inImportBlock = false;
|
|
41464
41466
|
}
|
|
41465
41467
|
const isImportLine = inImportBlock || trimmed2.startsWith('import "') || trimmed2.startsWith('import "') || /^import\s+\w+\s+"/.test(trimmed2);
|
|
41466
|
-
if (!isImportLine) {
|
|
41467
|
-
continue;
|
|
41468
|
-
}
|
|
41469
41468
|
if (!line.includes(modulePath)) {
|
|
41470
41469
|
continue;
|
|
41471
41470
|
}
|
|
41472
|
-
const newLine = line.
|
|
41471
|
+
const newLine = isImportLine ? line.split(`"${modulePath}/`).join(`"${modulePath}${suffix}/`).split(`"${modulePath}"`).join(`"${modulePath}${suffix}"`) : line.split(`"${modulePath}"`).join(`"${modulePath}${suffix}"`);
|
|
41473
41472
|
if (newLine !== line) {
|
|
41474
41473
|
lines[i2] = newLine;
|
|
41475
41474
|
changed = true;
|
|
@@ -41480,6 +41479,45 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
41480
41479
|
this.logger.debug(`Updated Go imports in ${filePath}`);
|
|
41481
41480
|
}
|
|
41482
41481
|
}
|
|
41482
|
+
/**
|
|
41483
|
+
* Adds a version suffix to Go module references in all Markdown files
|
|
41484
|
+
* (e.g. README.md) in the repository, so documented install commands and
|
|
41485
|
+
* import samples resolve to the correct /vN module path when copy-pasted.
|
|
41486
|
+
*/
|
|
41487
|
+
async addSuffixToMarkdownFiles(repoRoot, modulePath, suffix) {
|
|
41488
|
+
const markdownFiles = await this.walkDirectory(
|
|
41489
|
+
repoRoot,
|
|
41490
|
+
(filePath) => (0, import_path22.extname)(filePath).toLowerCase() === ".md"
|
|
41491
|
+
);
|
|
41492
|
+
await this.processInParallel(
|
|
41493
|
+
markdownFiles,
|
|
41494
|
+
(filePath) => this.addSuffixToMarkdownFile(filePath, modulePath, suffix)
|
|
41495
|
+
);
|
|
41496
|
+
}
|
|
41497
|
+
/**
|
|
41498
|
+
* Adds a version suffix to Go module references in a single Markdown file.
|
|
41499
|
+
* Rewrites `go get`/`go install` install commands and quoted import paths in
|
|
41500
|
+
* code samples. Web URLs (e.g. `https://pkg.go.dev/<modulePath>`) are left
|
|
41501
|
+
* untouched because the module path there is neither quote-anchored nor
|
|
41502
|
+
* preceded by an install command.
|
|
41503
|
+
*/
|
|
41504
|
+
async addSuffixToMarkdownFile(filePath, modulePath, suffix) {
|
|
41505
|
+
const content = await (0, import_promises14.readFile)(filePath, "utf-8");
|
|
41506
|
+
if (!content.includes(modulePath)) {
|
|
41507
|
+
return;
|
|
41508
|
+
}
|
|
41509
|
+
let updated = content.split(`"${modulePath}/`).join(`"${modulePath}${suffix}/`).split(`"${modulePath}"`).join(`"${modulePath}${suffix}"`);
|
|
41510
|
+
const escapedModulePath = modulePath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
41511
|
+
const installCommandPattern = new RegExp(
|
|
41512
|
+
`(go (?:get|install)(?:\\s+-\\S+)*\\s+)${escapedModulePath}(?![\\w./-])`,
|
|
41513
|
+
"g"
|
|
41514
|
+
);
|
|
41515
|
+
updated = updated.replace(installCommandPattern, `$1${modulePath}${suffix}`);
|
|
41516
|
+
if (updated !== content) {
|
|
41517
|
+
await (0, import_promises14.writeFile)(filePath, updated, "utf-8");
|
|
41518
|
+
this.logger.debug(`Updated Go module path in ${filePath}`);
|
|
41519
|
+
}
|
|
41520
|
+
}
|
|
41483
41521
|
/**
|
|
41484
41522
|
* Extracts the file path from a diff file section.
|
|
41485
41523
|
* Parses the "diff --git a/path b/path" header line.
|
|
@@ -41656,7 +41694,8 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
41656
41694
|
}
|
|
41657
41695
|
async handleNormalFlow(params) {
|
|
41658
41696
|
const { prepared, service, language, mappedMagicVersion, previousGenerationSha } = params;
|
|
41659
|
-
const
|
|
41697
|
+
const diffBase = this.resolveReachableGenerationBase(previousGenerationSha, prepared.currentGenerationSha);
|
|
41698
|
+
const rawDiff = diffBase != null ? this.safeGitDiff(diffBase, prepared.currentGenerationSha) : "";
|
|
41660
41699
|
const previousVersion = await this.resolvePreviousVersion({
|
|
41661
41700
|
service,
|
|
41662
41701
|
rawDiff,
|
|
@@ -42079,6 +42118,97 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
42079
42118
|
maxBuffer: 256 * 1024 * 1024
|
|
42080
42119
|
});
|
|
42081
42120
|
}
|
|
42121
|
+
/**
|
|
42122
|
+
* Resolves a reachable base commit for the autoversion diff.
|
|
42123
|
+
*
|
|
42124
|
+
* `recordedSha` (the previous generation from replay.lock) is preferred when it exists
|
|
42125
|
+
* in this clone. When it doesn't — e.g. the signed-commit push recreated the
|
|
42126
|
+
* [fern-generated] commit under a new SHA, or the branch was squash-merged — we re-anchor
|
|
42127
|
+
* on the most recent reachable [fern-generated] commit in history. Returns null when no
|
|
42128
|
+
* generation baseline is reachable at all, in which case the caller resolves the previous
|
|
42129
|
+
* version from metadata/git-tags and still rewrites the placeholder.
|
|
42130
|
+
*/
|
|
42131
|
+
resolveReachableGenerationBase(recordedSha, currentGenerationSha) {
|
|
42132
|
+
if (this.commitExists(recordedSha)) {
|
|
42133
|
+
return recordedSha;
|
|
42134
|
+
}
|
|
42135
|
+
this.logger.warn(
|
|
42136
|
+
`AutoVersionStep: recorded previous generation ${recordedSha.slice(0, 7)} is unreachable in this clone; deriving the baseline from history.`
|
|
42137
|
+
);
|
|
42138
|
+
const derived = this.findPreviousGenerationFromHistory(currentGenerationSha);
|
|
42139
|
+
if (derived != null) {
|
|
42140
|
+
this.logger.info(`AutoVersionStep: re-anchored autoversion baseline on ${derived.slice(0, 7)}.`);
|
|
42141
|
+
return derived;
|
|
42142
|
+
}
|
|
42143
|
+
this.logger.warn(
|
|
42144
|
+
"AutoVersionStep: no reachable [fern-generated] baseline found; falling back to metadata/git-tags."
|
|
42145
|
+
);
|
|
42146
|
+
return null;
|
|
42147
|
+
}
|
|
42148
|
+
commitExists(sha) {
|
|
42149
|
+
if (!/^[0-9a-f]{7,40}$/.test(sha)) {
|
|
42150
|
+
return false;
|
|
42151
|
+
}
|
|
42152
|
+
try {
|
|
42153
|
+
(0, import_child_process4.execFileSync)("git", ["cat-file", "-e", `${sha}^{commit}`], {
|
|
42154
|
+
cwd: this.outputDir,
|
|
42155
|
+
stdio: "pipe"
|
|
42156
|
+
});
|
|
42157
|
+
return true;
|
|
42158
|
+
} catch {
|
|
42159
|
+
return false;
|
|
42160
|
+
}
|
|
42161
|
+
}
|
|
42162
|
+
/**
|
|
42163
|
+
* Walks first-parent history from the current generation commit and returns the most
|
|
42164
|
+
* recent prior [fern-generated] commit — the reachable equivalent of replay.lock's
|
|
42165
|
+
* recorded baseline. Mirrors @fern-api/replay's `findPreviousGenerationFromHistory`.
|
|
42166
|
+
*/
|
|
42167
|
+
findPreviousGenerationFromHistory(currentGenerationSha) {
|
|
42168
|
+
const start = this.commitExists(currentGenerationSha) ? currentGenerationSha : "HEAD";
|
|
42169
|
+
let log;
|
|
42170
|
+
try {
|
|
42171
|
+
log = (0, import_child_process4.execFileSync)("git", ["log", "--first-parent", "--format=%H%x00%s", start], {
|
|
42172
|
+
cwd: this.outputDir,
|
|
42173
|
+
encoding: "utf-8",
|
|
42174
|
+
stdio: "pipe",
|
|
42175
|
+
maxBuffer: 64 * 1024 * 1024
|
|
42176
|
+
});
|
|
42177
|
+
} catch (error) {
|
|
42178
|
+
this.logger.debug(`AutoVersionStep: git log history walk failed (${String(error)}); no baseline derived.`);
|
|
42179
|
+
return null;
|
|
42180
|
+
}
|
|
42181
|
+
for (const line of log.split("\n")) {
|
|
42182
|
+
if (line.trim().length === 0) {
|
|
42183
|
+
continue;
|
|
42184
|
+
}
|
|
42185
|
+
const [sha, subject = ""] = line.split("\0");
|
|
42186
|
+
if (sha == null || sha === currentGenerationSha) {
|
|
42187
|
+
continue;
|
|
42188
|
+
}
|
|
42189
|
+
if (subject.startsWith("[fern-generated]")) {
|
|
42190
|
+
return sha;
|
|
42191
|
+
}
|
|
42192
|
+
}
|
|
42193
|
+
return null;
|
|
42194
|
+
}
|
|
42195
|
+
/**
|
|
42196
|
+
* `gitDiff` that degrades to an empty diff instead of throwing. Both endpoints are
|
|
42197
|
+
* expected to be reachable (the base is resolved via resolveReachableGenerationBase and
|
|
42198
|
+
* `to` is this run's freshly-created HEAD), but we never want a `git diff` failure to
|
|
42199
|
+
* abort autoversion and leave the magic placeholder in the shipped SDK — the empty diff
|
|
42200
|
+
* routes version resolution to baseVersion/metadata/git-tags, which still rewrites it.
|
|
42201
|
+
*/
|
|
42202
|
+
safeGitDiff(from, to) {
|
|
42203
|
+
try {
|
|
42204
|
+
return this.gitDiff(from, to);
|
|
42205
|
+
} catch (error) {
|
|
42206
|
+
this.logger.warn(
|
|
42207
|
+
`AutoVersionStep: git diff ${from.slice(0, 7)}..${to.slice(0, 7)} failed (${error instanceof Error ? error.message : String(error)}); proceeding with an empty diff.`
|
|
42208
|
+
);
|
|
42209
|
+
return "";
|
|
42210
|
+
}
|
|
42211
|
+
}
|
|
42082
42212
|
gitDiff(from, to) {
|
|
42083
42213
|
return (0, import_child_process4.execFileSync)("git", ["diff", from, to, "--", ".", ":(exclude).fern/metadata.json"], {
|
|
42084
42214
|
cwd: this.outputDir,
|