@fern-api/fern-api-dev 5.45.3 → 5.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.cjs +290 -132
- package/package.json +1 -1
package/cli.cjs
CHANGED
|
@@ -422248,15 +422248,19 @@ var require_AutoVersionStep = __commonJS({
|
|
|
422248
422248
|
analysis: { versionBump: "PATCH", message: this.brandMessage("SDK regeneration") }
|
|
422249
422249
|
});
|
|
422250
422250
|
}
|
|
422251
|
-
const chunks = service.chunkDiff(cleanedDiff, index_1.MAX_AI_DIFF_BYTES);
|
|
422252
|
-
const cappedChunks = chunks.slice(0, index_1.MAX_CHUNKS);
|
|
422253
|
-
const skippedChunks = chunks.length - cappedChunks.length;
|
|
422254
|
-
if (chunks.length > 1) {
|
|
422255
|
-
this.logger.info(`AutoVersionStep: split diff into ${chunks.length} chunks` + (skippedChunks > 0 ? ` (capped at ${index_1.MAX_CHUNKS}, skipping ${skippedChunks})` : ""));
|
|
422256
|
-
}
|
|
422257
422251
|
let analysis;
|
|
422258
422252
|
try {
|
|
422259
|
-
|
|
422253
|
+
if (this.config.ai == null && this.config.fernToken != null) {
|
|
422254
|
+
analysis = await this.analyzeViaFaiService(cleanedDiff, language, previousVersion);
|
|
422255
|
+
} else {
|
|
422256
|
+
const chunks = service.chunkDiff(cleanedDiff, index_1.MAX_AI_DIFF_BYTES);
|
|
422257
|
+
const cappedChunks = chunks.slice(0, index_1.MAX_CHUNKS);
|
|
422258
|
+
const skippedChunks = chunks.length - cappedChunks.length;
|
|
422259
|
+
if (chunks.length > 1) {
|
|
422260
|
+
this.logger.info(`AutoVersionStep: split diff into ${chunks.length} chunks` + (skippedChunks > 0 ? ` (capped at ${index_1.MAX_CHUNKS}, skipping ${skippedChunks})` : ""));
|
|
422261
|
+
}
|
|
422262
|
+
analysis = cappedChunks.length <= 1 ? await this.analyzeSingle(cleanedDiff, language, previousVersion) : await this.analyzeChunks(cappedChunks, language, previousVersion);
|
|
422263
|
+
}
|
|
422260
422264
|
} catch (error50) {
|
|
422261
422265
|
this.logger.warn(`AutoVersionStep: FAI analysis failed (${String(error50)}); falling back to PATCH bump.`);
|
|
422262
422266
|
analysis = { versionBump: "PATCH", message: this.brandMessage("SDK regeneration") };
|
|
@@ -422518,6 +422522,47 @@ ${newBlock}${remainder}`;
|
|
|
422518
422522
|
};
|
|
422519
422523
|
}
|
|
422520
422524
|
}
|
|
422525
|
+
/**
|
|
422526
|
+
* Calls the hosted FAI service (`/sdks/analyze-commit-diff`) with the fern token.
|
|
422527
|
+
* Used when no BAML `ai` config is supplied (remote generation via fiddle). FAI
|
|
422528
|
+
* handles chunking, parallelism, and retries server-side. Returns null on
|
|
422529
|
+
* NO_CHANGE; throws on transport/HTTP errors so the caller's PATCH fallback applies.
|
|
422530
|
+
*/
|
|
422531
|
+
async analyzeViaFaiService(cleanedDiff, language, previousVersion) {
|
|
422532
|
+
const baseUrl = this.config.faiBaseUrl ?? "https://fai.buildwithfern.com";
|
|
422533
|
+
const response = await fetch(`${baseUrl}/sdks/analyze-commit-diff`, {
|
|
422534
|
+
method: "POST",
|
|
422535
|
+
headers: {
|
|
422536
|
+
Authorization: `Bearer ${this.config.fernToken}`,
|
|
422537
|
+
"Content-Type": "application/json"
|
|
422538
|
+
},
|
|
422539
|
+
body: JSON.stringify({
|
|
422540
|
+
diff: cleanedDiff,
|
|
422541
|
+
language,
|
|
422542
|
+
previous_version: previousVersion,
|
|
422543
|
+
prior_changelog: this.config.priorChangelog ?? void 0,
|
|
422544
|
+
spec_commit_message: this.config.specCommitMessage ?? void 0
|
|
422545
|
+
})
|
|
422546
|
+
});
|
|
422547
|
+
if (!response.ok) {
|
|
422548
|
+
const body = await response.text().catch(() => "");
|
|
422549
|
+
throw new Error(`FAI analyze-commit-diff failed with status ${response.status}: ${body.slice(0, 500)}`);
|
|
422550
|
+
}
|
|
422551
|
+
const parsed = await response.json();
|
|
422552
|
+
if (!isFaiAnalyzeResponse(parsed)) {
|
|
422553
|
+
throw new Error("FAI analyze-commit-diff returned an unexpected response shape");
|
|
422554
|
+
}
|
|
422555
|
+
if (parsed.version_bump === "NO_CHANGE") {
|
|
422556
|
+
return null;
|
|
422557
|
+
}
|
|
422558
|
+
return {
|
|
422559
|
+
versionBump: parsed.version_bump,
|
|
422560
|
+
message: this.brandMessage(parsed.message),
|
|
422561
|
+
changelogEntry: nonEmpty2(parsed.changelog_entry),
|
|
422562
|
+
prDescription: nonEmpty2(parsed.pr_description),
|
|
422563
|
+
versionBumpReason: nonEmpty2(parsed.version_bump_reason)
|
|
422564
|
+
};
|
|
422565
|
+
}
|
|
422521
422566
|
/**
|
|
422522
422567
|
* Dynamically imports @fern-api/cli-ai only when autoversion actually needs to
|
|
422523
422568
|
* call FAI. The package is ESM-only with extensionless internal imports, so
|
|
@@ -422560,6 +422605,20 @@ ${newBlock}${remainder}`;
|
|
|
422560
422605
|
}
|
|
422561
422606
|
};
|
|
422562
422607
|
exports2.AutoVersionStep = AutoVersionStep;
|
|
422608
|
+
var FAI_VERSION_BUMPS = ["MAJOR", "MINOR", "PATCH", "NO_CHANGE"];
|
|
422609
|
+
function isFaiAnalyzeResponse(value2) {
|
|
422610
|
+
if (typeof value2 !== "object" || value2 == null) {
|
|
422611
|
+
return false;
|
|
422612
|
+
}
|
|
422613
|
+
const candidate = value2;
|
|
422614
|
+
return typeof candidate.message === "string" && typeof candidate.version_bump === "string" && FAI_VERSION_BUMPS.includes(candidate.version_bump) && isStringOrAbsent(candidate.changelog_entry) && isStringOrAbsent(candidate.pr_description) && isStringOrAbsent(candidate.version_bump_reason);
|
|
422615
|
+
}
|
|
422616
|
+
function isStringOrAbsent(value2) {
|
|
422617
|
+
return value2 == null || typeof value2 === "string";
|
|
422618
|
+
}
|
|
422619
|
+
function nonEmpty2(value2) {
|
|
422620
|
+
return value2 != null && value2.trim().length > 0 ? value2 : void 0;
|
|
422621
|
+
}
|
|
422563
422622
|
}
|
|
422564
422623
|
});
|
|
422565
422624
|
|
|
@@ -669211,7 +669270,7 @@ var AccessTokenPosthogManager = class {
|
|
|
669211
669270
|
properties: {
|
|
669212
669271
|
...event,
|
|
669213
669272
|
...event.properties,
|
|
669214
|
-
version: "5.
|
|
669273
|
+
version: "5.46.0",
|
|
669215
669274
|
usingAccessToken: true,
|
|
669216
669275
|
...getRunIdProperties()
|
|
669217
669276
|
}
|
|
@@ -669275,7 +669334,7 @@ var UserPosthogManager = class {
|
|
|
669275
669334
|
distinctId: this.userId ?? await this.getPersistedDistinctId(),
|
|
669276
669335
|
event: "CLI",
|
|
669277
669336
|
properties: {
|
|
669278
|
-
version: "5.
|
|
669337
|
+
version: "5.46.0",
|
|
669279
669338
|
...event,
|
|
669280
669339
|
...event.properties,
|
|
669281
669340
|
usingAccessToken: false,
|
|
@@ -856646,7 +856705,7 @@ function createDocsConfigFileAstVisitorForRules({ relativeFilepath, allRulesWith
|
|
|
856646
856705
|
const ruleViolations = await visitFromRule(node4);
|
|
856647
856706
|
const severityOverride = severityOverrides?.get(ruleName);
|
|
856648
856707
|
addViolations(ruleViolations.map((violation) => ({
|
|
856649
|
-
name: violation.name,
|
|
856708
|
+
name: violation.name ?? ruleName,
|
|
856650
856709
|
severity: severityOverride ?? violation.severity,
|
|
856651
856710
|
relativeFilepath: violation.relativeFilepath ?? RelativeFilePath2.of(""),
|
|
856652
856711
|
nodePath: violation.nodePath ?? nodePath,
|
|
@@ -861013,7 +861072,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
|
|
|
861013
861072
|
var LOGS_FOLDER_NAME = "logs";
|
|
861014
861073
|
var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
|
|
861015
861074
|
function getCliSource() {
|
|
861016
|
-
const version7 = "5.
|
|
861075
|
+
const version7 = "5.46.0";
|
|
861017
861076
|
return `cli@${version7}`;
|
|
861018
861077
|
}
|
|
861019
861078
|
var DebugLogger = class {
|
|
@@ -892105,7 +892164,7 @@ var LegacyDocsPublisher = class {
|
|
|
892105
892164
|
previewId,
|
|
892106
892165
|
disableTemplates: void 0,
|
|
892107
892166
|
skipUpload,
|
|
892108
|
-
cliVersion: "5.
|
|
892167
|
+
cliVersion: "5.46.0",
|
|
892109
892168
|
loginCommand: "fern auth login"
|
|
892110
892169
|
});
|
|
892111
892170
|
if (taskContext.getResult() === TaskResult.Failure) {
|
|
@@ -917533,13 +917592,16 @@ var EndpointSnippetGenerator3 = class {
|
|
|
917533
917592
|
}
|
|
917534
917593
|
getBytesBodyRequestArg({ value: value2 }) {
|
|
917535
917594
|
const bytesValue = typeof value2 === "string" ? value2 : "";
|
|
917536
|
-
|
|
917537
|
-
|
|
917538
|
-
|
|
917539
|
-
|
|
917540
|
-
|
|
917541
|
-
|
|
917542
|
-
|
|
917595
|
+
if (this.context.customConfig?.useReaderForBytesRequest ?? true) {
|
|
917596
|
+
return go_exports.TypeInstantiation.reference(go_exports.invokeFunc({
|
|
917597
|
+
func: go_exports.typeReference({
|
|
917598
|
+
name: "NewReader",
|
|
917599
|
+
importPath: "bytes"
|
|
917600
|
+
}),
|
|
917601
|
+
arguments_: [go_exports.TypeInstantiation.bytes(bytesValue)]
|
|
917602
|
+
}));
|
|
917603
|
+
}
|
|
917604
|
+
return go_exports.TypeInstantiation.bytes(bytesValue);
|
|
917543
917605
|
}
|
|
917544
917606
|
getMethodArgsForInlinedRequest({ request: request7, snippet: snippet2 }) {
|
|
917545
917607
|
const otherArgs = [];
|
|
@@ -917659,7 +917721,7 @@ var EndpointSnippetGenerator3 = class {
|
|
|
917659
917721
|
getReferencedRequestBodyPropertyTypeInstantiation({ body, value: value2 }) {
|
|
917660
917722
|
switch (body.type) {
|
|
917661
917723
|
case "bytes":
|
|
917662
|
-
return
|
|
917724
|
+
return go_exports.TypeInstantiation.bytes(typeof value2 === "string" ? value2 : "");
|
|
917663
917725
|
case "typeReference":
|
|
917664
917726
|
return this.context.dynamicTypeInstantiationMapper.convert({ typeReference: body.value, value: value2 });
|
|
917665
917727
|
default:
|
|
@@ -943539,13 +943601,19 @@ function getGithubPublishConfig(githubPublishInfo) {
|
|
|
943539
943601
|
secretKeyEnvironmentVariable: (0, import_api50.EnvironmentVariable)(value2.signature.secretKey ?? "")
|
|
943540
943602
|
} : void 0
|
|
943541
943603
|
}),
|
|
943542
|
-
pypi: (value2) =>
|
|
943543
|
-
|
|
943544
|
-
|
|
943545
|
-
|
|
943546
|
-
|
|
943547
|
-
|
|
943548
|
-
|
|
943604
|
+
pypi: (value2) => {
|
|
943605
|
+
const password = (value2.credentials?.password ?? "").trim();
|
|
943606
|
+
const useOidc = password === "<USE_OIDC>" || password === "OIDC";
|
|
943607
|
+
const hasCredentials = value2.credentials != null;
|
|
943608
|
+
return import_generator_exec_sdk.FernGeneratorExec.GithubPublishInfo.pypi({
|
|
943609
|
+
registryUrl: value2.registryUrl,
|
|
943610
|
+
packageName: value2.packageName,
|
|
943611
|
+
usernameEnvironmentVariable: (0, import_api50.EnvironmentVariable)("PYPI_USERNAME"),
|
|
943612
|
+
passwordEnvironmentVariable: (0, import_api50.EnvironmentVariable)(useOidc ? "OIDC" : "PYPI_PASSWORD"),
|
|
943613
|
+
shouldGeneratePublishWorkflow: useOidc || hasCredentials,
|
|
943614
|
+
pypiMetadata: value2.pypiMetadata
|
|
943615
|
+
});
|
|
943616
|
+
},
|
|
943549
943617
|
rubygems: (value2) => import_generator_exec_sdk.FernGeneratorExec.GithubPublishInfo.rubygems({
|
|
943550
943618
|
registryUrl: value2.registryUrl,
|
|
943551
943619
|
packageName: value2.packageName,
|
|
@@ -943667,10 +943735,11 @@ function getGeneratorConfig({ generatorInvocation, customConfig, workspaceName,
|
|
|
943667
943735
|
});
|
|
943668
943736
|
}
|
|
943669
943737
|
});
|
|
943738
|
+
const publishConfig = getPublishConfigForGithubOidc(generatorInvocation, outputVersion);
|
|
943670
943739
|
return {
|
|
943671
943740
|
irFilepath: irPath,
|
|
943672
943741
|
output: output2,
|
|
943673
|
-
publish:
|
|
943742
|
+
publish: publishConfig,
|
|
943674
943743
|
customConfig,
|
|
943675
943744
|
workspaceName,
|
|
943676
943745
|
organization,
|
|
@@ -943861,6 +943930,42 @@ function getPublishTargetFromPublishModeV2(mode) {
|
|
|
943861
943930
|
_other: () => void 0
|
|
943862
943931
|
});
|
|
943863
943932
|
}
|
|
943933
|
+
function getPublishConfigForGithubOidc(generatorInvocation, version7) {
|
|
943934
|
+
const publishInfo = generatorInvocation.outputMode._visit({
|
|
943935
|
+
publish: () => void 0,
|
|
943936
|
+
publishV2: () => void 0,
|
|
943937
|
+
downloadFiles: () => void 0,
|
|
943938
|
+
github: (value2) => value2.publishInfo,
|
|
943939
|
+
githubV2: (value2) => value2._visit({
|
|
943940
|
+
push: (v9) => v9.publishInfo,
|
|
943941
|
+
commitAndRelease: (v9) => v9.publishInfo,
|
|
943942
|
+
pullRequest: (v9) => v9.publishInfo,
|
|
943943
|
+
_other: () => void 0
|
|
943944
|
+
}),
|
|
943945
|
+
_other: () => void 0
|
|
943946
|
+
});
|
|
943947
|
+
if (publishInfo == null || publishInfo.type !== "pypi") {
|
|
943948
|
+
return void 0;
|
|
943949
|
+
}
|
|
943950
|
+
const password = (publishInfo.credentials?.password ?? "").trim();
|
|
943951
|
+
if (password !== "OIDC" && password !== "<USE_OIDC>") {
|
|
943952
|
+
return void 0;
|
|
943953
|
+
}
|
|
943954
|
+
const registriesV2 = structuredClone(emptyRegistriesConfigV2);
|
|
943955
|
+
registriesV2.pypi = {
|
|
943956
|
+
registryUrl: publishInfo.registryUrl,
|
|
943957
|
+
username: "__token__",
|
|
943958
|
+
password: "OIDC",
|
|
943959
|
+
packageName: publishInfo.packageName,
|
|
943960
|
+
pypiMetadata: publishInfo.pypiMetadata
|
|
943961
|
+
};
|
|
943962
|
+
return {
|
|
943963
|
+
registries: structuredClone(emptyRegistriesConfig),
|
|
943964
|
+
registriesV2,
|
|
943965
|
+
publishTarget: void 0,
|
|
943966
|
+
version: version7
|
|
943967
|
+
};
|
|
943968
|
+
}
|
|
943864
943969
|
var emptyRegistriesConfig = {
|
|
943865
943970
|
maven: { registryUrl: "", username: "", password: "", group: "", signature: void 0 },
|
|
943866
943971
|
npm: { registryUrl: "", token: "", scope: "" }
|
|
@@ -944444,7 +944549,7 @@ var LocalTaskHandler = class {
|
|
|
944444
944549
|
const absolutePathToFernignore = AbsoluteFilePath2.of(join8(this.absolutePathToLocalOutput, RelativeFilePath2.of(FERNIGNORE_FILENAME)));
|
|
944445
944550
|
const fernIgnorePaths = await getFernIgnorePaths({ absolutePathToFernignore });
|
|
944446
944551
|
const pathsToPreserve = await this.getPathsToPreserve(fernIgnorePaths);
|
|
944447
|
-
await (0, import_promises129.cp)(this.absolutePathToLocalOutput, tmpOutputResolutionDir, { recursive: true });
|
|
944552
|
+
await (0, import_promises129.cp)(this.absolutePathToLocalOutput, tmpOutputResolutionDir, { recursive: true, verbatimSymlinks: true });
|
|
944448
944553
|
await this.runThrowawayGitCommand(["init"], tmpOutputResolutionDir);
|
|
944449
944554
|
await this.runThrowawayGitCommand(["config", "gc.auto", "0"], tmpOutputResolutionDir);
|
|
944450
944555
|
await this.runThrowawayGitCommand(["add", "."], tmpOutputResolutionDir);
|
|
@@ -944472,7 +944577,7 @@ var LocalTaskHandler = class {
|
|
|
944472
944577
|
retryDelay: 100
|
|
944473
944578
|
});
|
|
944474
944579
|
await (0, import_promises129.rm)(this.absolutePathToLocalOutput, { recursive: true });
|
|
944475
|
-
await (0, import_promises129.cp)(tmpOutputResolutionDir, this.absolutePathToLocalOutput, { recursive: true });
|
|
944580
|
+
await (0, import_promises129.cp)(tmpOutputResolutionDir, this.absolutePathToLocalOutput, { recursive: true, verbatimSymlinks: true });
|
|
944476
944581
|
}
|
|
944477
944582
|
async copyGeneratedFilesNoFernIgnorePreservingGit() {
|
|
944478
944583
|
const contents = await (0, import_promises129.readdir)(this.absolutePathToLocalOutput);
|
|
@@ -944500,10 +944605,10 @@ var LocalTaskHandler = class {
|
|
|
944500
944605
|
if (firstLocalOutputItem.endsWith(".zip")) {
|
|
944501
944606
|
await (0, import_decompress2.default)(join8(this.absolutePathToTmpOutputDirectory, RelativeFilePath2.of(firstLocalOutputItem)), outputPath);
|
|
944502
944607
|
for (const localOutputItem of remaininglocalOutputItems) {
|
|
944503
|
-
await (0, import_promises129.cp)(join8(this.absolutePathToTmpOutputDirectory, RelativeFilePath2.of(localOutputItem)), join8(outputPath, RelativeFilePath2.of(localOutputItem)), { recursive: true });
|
|
944608
|
+
await (0, import_promises129.cp)(join8(this.absolutePathToTmpOutputDirectory, RelativeFilePath2.of(localOutputItem)), join8(outputPath, RelativeFilePath2.of(localOutputItem)), { recursive: true, verbatimSymlinks: true });
|
|
944504
944609
|
}
|
|
944505
944610
|
} else {
|
|
944506
|
-
await (0, import_promises129.cp)(this.absolutePathToTmpOutputDirectory, outputPath, { recursive: true });
|
|
944611
|
+
await (0, import_promises129.cp)(this.absolutePathToTmpOutputDirectory, outputPath, { recursive: true, verbatimSymlinks: true });
|
|
944507
944612
|
}
|
|
944508
944613
|
}
|
|
944509
944614
|
async copySnippetJSON({ absolutePathToTmpSnippetJSON, absolutePathToLocalSnippetJSON }) {
|
|
@@ -957243,7 +957348,7 @@ function getAutomationContextFromEnv() {
|
|
|
957243
957348
|
config_branch: process.env.FERN_CONFIG_BRANCH,
|
|
957244
957349
|
config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
|
|
957245
957350
|
trigger: process.env.GITHUB_EVENT_NAME,
|
|
957246
|
-
cli_version: "5.
|
|
957351
|
+
cli_version: "5.46.0"
|
|
957247
957352
|
};
|
|
957248
957353
|
}
|
|
957249
957354
|
function isAutomationMode() {
|
|
@@ -958069,7 +958174,7 @@ var CliContext = class _CliContext {
|
|
|
958069
958174
|
if (false) {
|
|
958070
958175
|
this.logger.error("CLI_VERSION is not defined");
|
|
958071
958176
|
}
|
|
958072
|
-
return "5.
|
|
958177
|
+
return "5.46.0";
|
|
958073
958178
|
}
|
|
958074
958179
|
getCliName() {
|
|
958075
958180
|
if (false) {
|
|
@@ -972785,101 +972890,132 @@ async function validateWorkspaces({
|
|
|
972785
972890
|
const apiResults = [];
|
|
972786
972891
|
let docsResult;
|
|
972787
972892
|
let hasAnyErrors = false;
|
|
972893
|
+
let abortReason;
|
|
972788
972894
|
const apiWorkspacesToValidate = commandLineApiWorkspace != null ? project.apiWorkspaces.filter((workspace) => workspace.workspaceName === commandLineApiWorkspace) : project.apiWorkspaces;
|
|
972789
|
-
|
|
972790
|
-
|
|
972791
|
-
const
|
|
972792
|
-
|
|
972793
|
-
|
|
972794
|
-
|
|
972795
|
-
collected = await collectDocsWorkspaceViolations({
|
|
972796
|
-
workspace: docsWorkspace,
|
|
972797
|
-
context: context3,
|
|
972798
|
-
apiWorkspaces: project.apiWorkspaces,
|
|
972799
|
-
ossWorkspaces,
|
|
972800
|
-
errorOnBrokenLinks,
|
|
972801
|
-
excludeRules
|
|
972802
|
-
});
|
|
972803
|
-
});
|
|
972804
|
-
if (collected != null) {
|
|
972805
|
-
docsResult = {
|
|
972806
|
-
violations: collected.violations,
|
|
972807
|
-
elapsedMillis: collected.elapsedMillis
|
|
972808
|
-
};
|
|
972809
|
-
if (collected.hasErrors) {
|
|
972810
|
-
hasAnyErrors = true;
|
|
972811
|
-
}
|
|
972812
|
-
}
|
|
972813
|
-
}
|
|
972814
|
-
await Promise.all(
|
|
972815
|
-
apiWorkspacesToValidate.map(async (workspace) => {
|
|
972816
|
-
if (workspace.generatorsConfiguration?.groups.length === 0 && workspace.type !== "fern") {
|
|
972817
|
-
return;
|
|
972818
|
-
}
|
|
972819
|
-
if (workspace instanceof OSSWorkspace && directFromOpenapi) {
|
|
972820
|
-
await cliContext.runTaskForWorkspace(workspace, async (context3) => {
|
|
972821
|
-
await workspace.getIntermediateRepresentation({
|
|
972822
|
-
context: context3,
|
|
972823
|
-
audiences: { type: "all" },
|
|
972824
|
-
enableUniqueErrorsPerEndpoint: false,
|
|
972825
|
-
generateV1Examples: false,
|
|
972826
|
-
logWarnings
|
|
972827
|
-
});
|
|
972828
|
-
});
|
|
972829
|
-
return;
|
|
972830
|
-
}
|
|
972831
|
-
if (workspace instanceof LazyFernWorkspace) {
|
|
972832
|
-
const absolutePathToApiYml = join8(
|
|
972833
|
-
workspace.absoluteFilePath,
|
|
972834
|
-
RelativeFilePath2.of(DEFINITION_DIRECTORY),
|
|
972835
|
-
RelativeFilePath2.of(ROOT_API_FILENAME)
|
|
972836
|
-
);
|
|
972837
|
-
const apiYmlExists = await doesPathExist(absolutePathToApiYml);
|
|
972838
|
-
if (!apiYmlExists) {
|
|
972839
|
-
await cliContext.runTask(async (context3) => {
|
|
972840
|
-
context3.logger.error(`Missing file: ${ROOT_API_FILENAME}`);
|
|
972841
|
-
return context3.failAndThrow(void 0, void 0, { code: CliError.Code.ValidationError });
|
|
972842
|
-
});
|
|
972843
|
-
return;
|
|
972844
|
-
}
|
|
972845
|
-
}
|
|
972895
|
+
let hasErrors = false;
|
|
972896
|
+
try {
|
|
972897
|
+
const docsWorkspace = project.docsWorkspaces;
|
|
972898
|
+
if (docsWorkspace != null) {
|
|
972899
|
+
const excludeRules = brokenLinks || errorOnBrokenLinks ? [] : ["valid-markdown-links"];
|
|
972900
|
+
const ossWorkspaces = await filterOssWorkspaces(project);
|
|
972846
972901
|
let collected;
|
|
972847
|
-
await cliContext.runTaskForWorkspace(
|
|
972848
|
-
|
|
972849
|
-
|
|
972850
|
-
workspace: fernWorkspace,
|
|
972902
|
+
await cliContext.runTaskForWorkspace(docsWorkspace, async (context3) => {
|
|
972903
|
+
collected = await collectDocsWorkspaceViolations({
|
|
972904
|
+
workspace: docsWorkspace,
|
|
972851
972905
|
context: context3,
|
|
972852
|
-
|
|
972906
|
+
apiWorkspaces: project.apiWorkspaces,
|
|
972907
|
+
ossWorkspaces,
|
|
972908
|
+
errorOnBrokenLinks,
|
|
972909
|
+
excludeRules
|
|
972853
972910
|
});
|
|
972854
972911
|
});
|
|
972855
972912
|
if (collected != null) {
|
|
972856
|
-
|
|
972857
|
-
apiName: collected.apiName,
|
|
972913
|
+
docsResult = {
|
|
972858
972914
|
violations: collected.violations,
|
|
972859
972915
|
elapsedMillis: collected.elapsedMillis
|
|
972860
|
-
}
|
|
972916
|
+
};
|
|
972861
972917
|
if (collected.hasErrors) {
|
|
972862
972918
|
hasAnyErrors = true;
|
|
972863
972919
|
}
|
|
972864
972920
|
}
|
|
972865
|
-
}
|
|
972866
|
-
|
|
972867
|
-
|
|
972868
|
-
|
|
972869
|
-
|
|
972870
|
-
|
|
972871
|
-
|
|
972872
|
-
|
|
972873
|
-
|
|
972874
|
-
|
|
972875
|
-
|
|
972876
|
-
|
|
972877
|
-
|
|
972878
|
-
|
|
972921
|
+
}
|
|
972922
|
+
await Promise.all(
|
|
972923
|
+
apiWorkspacesToValidate.map(async (workspace) => {
|
|
972924
|
+
if (workspace.generatorsConfiguration?.groups.length === 0 && workspace.type !== "fern") {
|
|
972925
|
+
return;
|
|
972926
|
+
}
|
|
972927
|
+
if (workspace instanceof OSSWorkspace && directFromOpenapi) {
|
|
972928
|
+
await cliContext.runTaskForWorkspace(workspace, async (context3) => {
|
|
972929
|
+
await workspace.getIntermediateRepresentation({
|
|
972930
|
+
context: context3,
|
|
972931
|
+
audiences: { type: "all" },
|
|
972932
|
+
enableUniqueErrorsPerEndpoint: false,
|
|
972933
|
+
generateV1Examples: false,
|
|
972934
|
+
logWarnings
|
|
972935
|
+
});
|
|
972936
|
+
});
|
|
972937
|
+
return;
|
|
972938
|
+
}
|
|
972939
|
+
if (workspace instanceof LazyFernWorkspace) {
|
|
972940
|
+
const absolutePathToApiYml = join8(
|
|
972941
|
+
workspace.absoluteFilePath,
|
|
972942
|
+
RelativeFilePath2.of(DEFINITION_DIRECTORY),
|
|
972943
|
+
RelativeFilePath2.of(ROOT_API_FILENAME)
|
|
972944
|
+
);
|
|
972945
|
+
const apiYmlExists = await doesPathExist(absolutePathToApiYml);
|
|
972946
|
+
if (!apiYmlExists) {
|
|
972947
|
+
abortReason = "missing api.yml";
|
|
972948
|
+
await cliContext.runTask(async (context3) => {
|
|
972949
|
+
context3.logger.error(`Missing file: ${ROOT_API_FILENAME}`);
|
|
972950
|
+
return context3.failAndThrow(void 0, void 0, {
|
|
972951
|
+
code: CliError.Code.ValidationError
|
|
972952
|
+
});
|
|
972953
|
+
});
|
|
972954
|
+
return;
|
|
972955
|
+
}
|
|
972956
|
+
}
|
|
972957
|
+
let collected;
|
|
972958
|
+
await cliContext.runTaskForWorkspace(workspace, async (context3) => {
|
|
972959
|
+
const fernWorkspace = await workspace.toFernWorkspace({ context: context3 });
|
|
972960
|
+
collected = await collectAPIWorkspaceViolations({
|
|
972961
|
+
workspace: fernWorkspace,
|
|
972962
|
+
context: context3,
|
|
972963
|
+
ossWorkspace: workspace instanceof OSSWorkspace ? workspace : void 0
|
|
972964
|
+
});
|
|
972965
|
+
});
|
|
972966
|
+
if (collected != null) {
|
|
972967
|
+
apiResults.push({
|
|
972968
|
+
apiName: collected.apiName,
|
|
972969
|
+
violations: collected.violations,
|
|
972970
|
+
elapsedMillis: collected.elapsedMillis
|
|
972971
|
+
});
|
|
972972
|
+
if (collected.hasErrors) {
|
|
972973
|
+
hasAnyErrors = true;
|
|
972974
|
+
}
|
|
972975
|
+
}
|
|
972976
|
+
})
|
|
972879
972977
|
);
|
|
972880
|
-
|
|
972881
|
-
|
|
972882
|
-
|
|
972978
|
+
const reportResult = await cliContext.runTask((context3) => {
|
|
972979
|
+
return printCheckReport({
|
|
972980
|
+
apiResults,
|
|
972981
|
+
docsResult,
|
|
972982
|
+
logWarnings,
|
|
972983
|
+
context: context3
|
|
972984
|
+
});
|
|
972985
|
+
});
|
|
972986
|
+
hasErrors = reportResult.hasErrors;
|
|
972987
|
+
if (cliContext.isJsonMode) {
|
|
972988
|
+
const showApiNames = apiResults.length > 1;
|
|
972989
|
+
cliContext.writeJsonToStdout(
|
|
972990
|
+
buildCheckJsonResult({ apiResults, docsResult, hasErrors: hasErrors || hasAnyErrors, showApiNames })
|
|
972991
|
+
);
|
|
972992
|
+
}
|
|
972993
|
+
if (hasErrors || hasAnyErrors) {
|
|
972994
|
+
abortReason = "validation errors";
|
|
972995
|
+
cliContext.failAndThrow(void 0, void 0, { code: CliError.Code.ValidationError });
|
|
972996
|
+
}
|
|
972997
|
+
} catch (error50) {
|
|
972998
|
+
if (abortReason == null) {
|
|
972999
|
+
abortReason = error50 instanceof Error ? error50.message.slice(0, 100) : "unexpected error";
|
|
973000
|
+
}
|
|
973001
|
+
throw error50;
|
|
973002
|
+
} finally {
|
|
973003
|
+
const allViolations = [...apiResults.flatMap((r5) => r5.violations), ...docsResult?.violations ?? []];
|
|
973004
|
+
const firedRules = [
|
|
973005
|
+
...new Set(allViolations.map((v9) => v9.name).filter((name2) => name2 != null))
|
|
973006
|
+
];
|
|
973007
|
+
const numErrors = allViolations.filter((v9) => v9.severity === "fatal" || v9.severity === "error").length;
|
|
973008
|
+
const numWarnings = allViolations.filter((v9) => v9.severity === "warning").length;
|
|
973009
|
+
cliContext.instrumentPostHogEvent({
|
|
973010
|
+
command: "fern check",
|
|
973011
|
+
properties: {
|
|
973012
|
+
validationRules: firedRules,
|
|
973013
|
+
numErrors,
|
|
973014
|
+
numWarnings,
|
|
973015
|
+
passed: !hasErrors && !hasAnyErrors,
|
|
973016
|
+
abortReason
|
|
973017
|
+
}
|
|
973018
|
+
});
|
|
972883
973019
|
}
|
|
972884
973020
|
}
|
|
972885
973021
|
|
|
@@ -974233,24 +974369,46 @@ function addValidateCommand(cli, cliContext) {
|
|
|
974233
974369
|
default: false
|
|
974234
974370
|
}),
|
|
974235
974371
|
async (argv) => {
|
|
974236
|
-
|
|
974237
|
-
|
|
974238
|
-
|
|
974239
|
-
|
|
974240
|
-
|
|
974241
|
-
cliContext.failAndThrow(`API does not exist: ${argv.api}`, void 0, {
|
|
974242
|
-
code: CliError.Code.ConfigError
|
|
974372
|
+
let project;
|
|
974373
|
+
try {
|
|
974374
|
+
project = await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
|
|
974375
|
+
commandLineApiWorkspace: void 0,
|
|
974376
|
+
defaultToAllApiWorkspaces: true
|
|
974243
974377
|
});
|
|
974378
|
+
if (argv.api != null && !project.apiWorkspaces.some((ws5) => ws5.workspaceName === argv.api)) {
|
|
974379
|
+
cliContext.instrumentPostHogEvent({
|
|
974380
|
+
command: "fern check",
|
|
974381
|
+
properties: {
|
|
974382
|
+
passed: false,
|
|
974383
|
+
abortReason: `API does not exist: ${argv.api}`
|
|
974384
|
+
}
|
|
974385
|
+
});
|
|
974386
|
+
cliContext.failAndThrow(`API does not exist: ${argv.api}`, void 0, {
|
|
974387
|
+
code: CliError.Code.ConfigError
|
|
974388
|
+
});
|
|
974389
|
+
}
|
|
974390
|
+
await validateWorkspaces({
|
|
974391
|
+
project,
|
|
974392
|
+
cliContext,
|
|
974393
|
+
logWarnings: argv.warnings,
|
|
974394
|
+
brokenLinks: argv.brokenLinks,
|
|
974395
|
+
errorOnBrokenLinks: argv.strictBrokenLinks,
|
|
974396
|
+
directFromOpenapi: argv.fromOpenapi,
|
|
974397
|
+
commandLineApiWorkspace: argv.api
|
|
974398
|
+
});
|
|
974399
|
+
} catch (error50) {
|
|
974400
|
+
if (project == null) {
|
|
974401
|
+
const reason = error50 instanceof Error ? error50.message.slice(0, 100) : "project load failed";
|
|
974402
|
+
cliContext.instrumentPostHogEvent({
|
|
974403
|
+
command: "fern check",
|
|
974404
|
+
properties: {
|
|
974405
|
+
passed: false,
|
|
974406
|
+
abortReason: reason
|
|
974407
|
+
}
|
|
974408
|
+
});
|
|
974409
|
+
}
|
|
974410
|
+
throw error50;
|
|
974244
974411
|
}
|
|
974245
|
-
await validateWorkspaces({
|
|
974246
|
-
project,
|
|
974247
|
-
cliContext,
|
|
974248
|
-
logWarnings: argv.warnings,
|
|
974249
|
-
brokenLinks: argv.brokenLinks,
|
|
974250
|
-
errorOnBrokenLinks: argv.strictBrokenLinks,
|
|
974251
|
-
directFromOpenapi: argv.fromOpenapi,
|
|
974252
|
-
commandLineApiWorkspace: argv.api
|
|
974253
|
-
});
|
|
974254
974412
|
}
|
|
974255
974413
|
);
|
|
974256
974414
|
}
|
package/package.json
CHANGED