@fern-api/fern-api-dev 3.27.2 → 3.28.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 +582 -17
- package/package.json +1 -1
package/cli.cjs
CHANGED
|
@@ -1413817,7 +1413817,7 @@ var AccessTokenPosthogManager = class {
|
|
|
1413817
1413817
|
properties: {
|
|
1413818
1413818
|
...event,
|
|
1413819
1413819
|
...event.properties,
|
|
1413820
|
-
version: "3.
|
|
1413820
|
+
version: "3.28.0",
|
|
1413821
1413821
|
usingAccessToken: true
|
|
1413822
1413822
|
}
|
|
1413823
1413823
|
});
|
|
@@ -1413916,7 +1413916,7 @@ var UserPosthogManager = class {
|
|
|
1413916
1413916
|
distinctId: this.userId ?? await this.getPersistedDistinctId(),
|
|
1413917
1413917
|
event: "CLI",
|
|
1413918
1413918
|
properties: {
|
|
1413919
|
-
version: "3.
|
|
1413919
|
+
version: "3.28.0",
|
|
1413920
1413920
|
...event,
|
|
1413921
1413921
|
...event.properties,
|
|
1413922
1413922
|
usingAccessToken: false,
|
|
@@ -1493982,7 +1493982,7 @@ var CliContext = class {
|
|
|
1493982
1493982
|
if (false) {
|
|
1493983
1493983
|
this.logger.error("CLI_VERSION is not defined");
|
|
1493984
1493984
|
}
|
|
1493985
|
-
return "3.
|
|
1493985
|
+
return "3.28.0";
|
|
1493986
1493986
|
}
|
|
1493987
1493987
|
getCliName() {
|
|
1493988
1493988
|
if (false) {
|
|
@@ -1588481,7 +1588481,7 @@ var import_path35 = __toESM(require("path"), 1);
|
|
|
1588481
1588481
|
var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
|
|
1588482
1588482
|
var LOGS_FOLDER_NAME = "logs";
|
|
1588483
1588483
|
function getCliSource() {
|
|
1588484
|
-
const version6 = "3.
|
|
1588484
|
+
const version6 = "3.28.0";
|
|
1588485
1588485
|
return `cli@${version6}`;
|
|
1588486
1588486
|
}
|
|
1588487
1588487
|
var DebugLogger = class {
|
|
@@ -1604996,7 +1604996,8 @@ function logViolationsGroup({
|
|
|
1604996
1604996
|
if (title5 === "") {
|
|
1604997
1604997
|
title5 = violation.relativeFilepath;
|
|
1604998
1604998
|
}
|
|
1604999
|
-
|
|
1604999
|
+
const severityLabel = getSeverityLabel(violation.severity);
|
|
1605000
|
+
return `${severityLabel} ${violation.message}`;
|
|
1605000
1605001
|
}).filter((message) => message != null).join("\n");
|
|
1605001
1605002
|
context2.logger.log(
|
|
1605002
1605003
|
getLogLevelForSeverity(severity),
|
|
@@ -1605032,6 +1605033,18 @@ function getLogLevelForSeverity(severity) {
|
|
|
1605032
1605033
|
assertNever(severity);
|
|
1605033
1605034
|
}
|
|
1605034
1605035
|
}
|
|
1605036
|
+
function getSeverityLabel(severity) {
|
|
1605037
|
+
switch (severity) {
|
|
1605038
|
+
case "fatal":
|
|
1605039
|
+
return source_default.red("[error]");
|
|
1605040
|
+
case "error":
|
|
1605041
|
+
return source_default.red("[error]");
|
|
1605042
|
+
case "warning":
|
|
1605043
|
+
return source_default.yellow("[warning]");
|
|
1605044
|
+
default:
|
|
1605045
|
+
assertNever(severity);
|
|
1605046
|
+
}
|
|
1605047
|
+
}
|
|
1605035
1605048
|
function logViolationsSummary({
|
|
1605036
1605049
|
stats,
|
|
1605037
1605050
|
context: context2,
|
|
@@ -1605079,6 +1605092,39 @@ function getViolationStats(violations) {
|
|
|
1605079
1605092
|
}
|
|
1605080
1605093
|
|
|
1605081
1605094
|
// src/commands/validate/validateDocsWorkspaceAndLogIssues.ts
|
|
1605095
|
+
async function collectDocsWorkspaceViolations({
|
|
1605096
|
+
workspace,
|
|
1605097
|
+
apiWorkspaces,
|
|
1605098
|
+
ossWorkspaces,
|
|
1605099
|
+
context: context2,
|
|
1605100
|
+
errorOnBrokenLinks,
|
|
1605101
|
+
excludeRules
|
|
1605102
|
+
}) {
|
|
1605103
|
+
if (workspace.config.settings?.substituteEnvVars) {
|
|
1605104
|
+
workspace.config = replaceEnvVariables(workspace.config, {
|
|
1605105
|
+
onError: (e6) => context2.failAndThrow(e6)
|
|
1605106
|
+
});
|
|
1605107
|
+
}
|
|
1605108
|
+
const startTime = performance.now();
|
|
1605109
|
+
const violations = await validateDocsWorkspace(
|
|
1605110
|
+
workspace,
|
|
1605111
|
+
context2,
|
|
1605112
|
+
apiWorkspaces,
|
|
1605113
|
+
ossWorkspaces,
|
|
1605114
|
+
false,
|
|
1605115
|
+
excludeRules
|
|
1605116
|
+
);
|
|
1605117
|
+
const elapsedMillis = performance.now() - startTime;
|
|
1605118
|
+
let hasErrors = violations.some((v21) => v21.severity === "fatal" || v21.severity === "error");
|
|
1605119
|
+
if (errorOnBrokenLinks) {
|
|
1605120
|
+
hasErrors = hasErrors || violations.some((violation) => violation.name === "valid-markdown-links");
|
|
1605121
|
+
}
|
|
1605122
|
+
return {
|
|
1605123
|
+
violations,
|
|
1605124
|
+
elapsedMillis,
|
|
1605125
|
+
hasErrors
|
|
1605126
|
+
};
|
|
1605127
|
+
}
|
|
1605082
1605128
|
async function validateDocsWorkspaceWithoutExiting({
|
|
1605083
1605129
|
workspace,
|
|
1605084
1605130
|
apiWorkspaces,
|
|
@@ -1627884,13 +1627930,33 @@ async function publishDocs({ token, organization, docsWorkspace, domain: domain2
|
|
|
1627884
1627930
|
apiDefinition = await enhanceExamplesWithAI(apiDefinition, aiEnhancerConfig, context2, token, organization, sourceFilePath);
|
|
1627885
1627931
|
}
|
|
1627886
1627932
|
let dynamicIRsByLanguage;
|
|
1627933
|
+
let languagesWithExistingSdkDynamicIr = /* @__PURE__ */ new Set();
|
|
1627887
1627934
|
if (useDynamicSnippets) {
|
|
1627888
|
-
|
|
1627935
|
+
const existingSdkDynamicIrs = await checkAndDownloadExistingSdkDynamicIRs({
|
|
1627936
|
+
fdr,
|
|
1627889
1627937
|
workspace,
|
|
1627890
1627938
|
organization,
|
|
1627891
1627939
|
context: context2,
|
|
1627892
1627940
|
snippetsConfig
|
|
1627893
1627941
|
});
|
|
1627942
|
+
if (existingSdkDynamicIrs && Object.keys(existingSdkDynamicIrs).length > 0) {
|
|
1627943
|
+
dynamicIRsByLanguage = existingSdkDynamicIrs;
|
|
1627944
|
+
languagesWithExistingSdkDynamicIr = new Set(Object.keys(existingSdkDynamicIrs));
|
|
1627945
|
+
context2.logger.debug(`Using existing SDK dynamic IRs for: ${Object.keys(existingSdkDynamicIrs).join(", ")}`);
|
|
1627946
|
+
}
|
|
1627947
|
+
const generatedDynamicIRs = await generateLanguageSpecificDynamicIRs({
|
|
1627948
|
+
workspace,
|
|
1627949
|
+
organization,
|
|
1627950
|
+
context: context2,
|
|
1627951
|
+
snippetsConfig,
|
|
1627952
|
+
skipLanguages: languagesWithExistingSdkDynamicIr
|
|
1627953
|
+
});
|
|
1627954
|
+
if (generatedDynamicIRs) {
|
|
1627955
|
+
dynamicIRsByLanguage = {
|
|
1627956
|
+
...dynamicIRsByLanguage,
|
|
1627957
|
+
...generatedDynamicIRs
|
|
1627958
|
+
};
|
|
1627959
|
+
}
|
|
1627894
1627960
|
}
|
|
1627895
1627961
|
const response = await fdr.api.v1.register.registerApiDefinition({
|
|
1627896
1627962
|
orgId: FdrAPI_exports.OrgId(organization),
|
|
@@ -1628060,7 +1628126,203 @@ function parseBasePath(domain2) {
|
|
|
1628060
1628126
|
return void 0;
|
|
1628061
1628127
|
}
|
|
1628062
1628128
|
}
|
|
1628063
|
-
async function
|
|
1628129
|
+
async function checkAndDownloadExistingSdkDynamicIRs({ fdr, workspace, organization, context: context2, snippetsConfig }) {
|
|
1628130
|
+
if (!workspace) {
|
|
1628131
|
+
return void 0;
|
|
1628132
|
+
}
|
|
1628133
|
+
const snippetConfigWithVersions = await buildSnippetConfigurationWithVersions({
|
|
1628134
|
+
fdr,
|
|
1628135
|
+
workspace,
|
|
1628136
|
+
snippetsConfig,
|
|
1628137
|
+
context: context2
|
|
1628138
|
+
});
|
|
1628139
|
+
if (Object.keys(snippetConfigWithVersions).length === 0) {
|
|
1628140
|
+
context2.logger.debug(`[SDK Dynamic IR] No snippet configs with versions found, skipping S3 check`);
|
|
1628141
|
+
return void 0;
|
|
1628142
|
+
}
|
|
1628143
|
+
try {
|
|
1628144
|
+
const response = await fdr.api.v1.register.checkSdkDynamicIrExists({
|
|
1628145
|
+
orgId: FdrAPI_exports.OrgId(organization),
|
|
1628146
|
+
snippetConfiguration: snippetConfigWithVersions
|
|
1628147
|
+
});
|
|
1628148
|
+
if (!response.ok || !response.body) {
|
|
1628149
|
+
context2.logger.debug(`[SDK Dynamic IR] API call failed or returned empty body`);
|
|
1628150
|
+
return void 0;
|
|
1628151
|
+
}
|
|
1628152
|
+
const existingDynamicIrs = response.body.existingDynamicIrs;
|
|
1628153
|
+
if (Object.keys(existingDynamicIrs).length === 0) {
|
|
1628154
|
+
context2.logger.debug("[SDK Dynamic IR] No existing SDK dynamic IRs found in S3");
|
|
1628155
|
+
return void 0;
|
|
1628156
|
+
}
|
|
1628157
|
+
const result = {};
|
|
1628158
|
+
for (const [language, sdkDynamicIrDownload] of Object.entries(existingDynamicIrs)) {
|
|
1628159
|
+
try {
|
|
1628160
|
+
context2.logger.debug(`Downloading existing SDK dynamic IR for ${language}...`);
|
|
1628161
|
+
const downloadResponse = await fetch(sdkDynamicIrDownload.downloadUrl);
|
|
1628162
|
+
if (downloadResponse.ok) {
|
|
1628163
|
+
const dynamicIR = await downloadResponse.json();
|
|
1628164
|
+
result[language] = { dynamicIR };
|
|
1628165
|
+
context2.logger.debug(`Successfully downloaded SDK dynamic IR for ${language}`);
|
|
1628166
|
+
} else {
|
|
1628167
|
+
context2.logger.warn(`Failed to download SDK dynamic IR for ${language}: ${downloadResponse.status}`);
|
|
1628168
|
+
}
|
|
1628169
|
+
} catch (error2) {
|
|
1628170
|
+
context2.logger.warn(`Error downloading SDK dynamic IR for ${language}: ${error2}`);
|
|
1628171
|
+
}
|
|
1628172
|
+
}
|
|
1628173
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
1628174
|
+
} catch (error2) {
|
|
1628175
|
+
context2.logger.debug(`Error checking for existing SDK dynamic IRs: ${error2}`);
|
|
1628176
|
+
return void 0;
|
|
1628177
|
+
}
|
|
1628178
|
+
}
|
|
1628179
|
+
async function buildSnippetConfigurationWithVersions({ fdr, workspace, snippetsConfig, context: context2 }) {
|
|
1628180
|
+
const result = {};
|
|
1628181
|
+
const snippetConfigs = [
|
|
1628182
|
+
{
|
|
1628183
|
+
language: "typescript",
|
|
1628184
|
+
snippetName: snippetsConfig.typescriptSdk?.package,
|
|
1628185
|
+
explicitVersion: snippetsConfig.typescriptSdk?.version
|
|
1628186
|
+
},
|
|
1628187
|
+
{
|
|
1628188
|
+
language: "python",
|
|
1628189
|
+
snippetName: snippetsConfig.pythonSdk?.package,
|
|
1628190
|
+
explicitVersion: snippetsConfig.pythonSdk?.version
|
|
1628191
|
+
},
|
|
1628192
|
+
{
|
|
1628193
|
+
language: "java",
|
|
1628194
|
+
snippetName: snippetsConfig.javaSdk?.coordinate,
|
|
1628195
|
+
explicitVersion: snippetsConfig.javaSdk?.version
|
|
1628196
|
+
},
|
|
1628197
|
+
{
|
|
1628198
|
+
language: "go",
|
|
1628199
|
+
snippetName: snippetsConfig.goSdk?.githubRepo,
|
|
1628200
|
+
explicitVersion: snippetsConfig.goSdk?.version
|
|
1628201
|
+
},
|
|
1628202
|
+
{
|
|
1628203
|
+
language: "csharp",
|
|
1628204
|
+
snippetName: snippetsConfig.csharpSdk?.package,
|
|
1628205
|
+
explicitVersion: snippetsConfig.csharpSdk?.version
|
|
1628206
|
+
},
|
|
1628207
|
+
{
|
|
1628208
|
+
language: "ruby",
|
|
1628209
|
+
snippetName: snippetsConfig.rubySdk?.gem,
|
|
1628210
|
+
explicitVersion: snippetsConfig.rubySdk?.version
|
|
1628211
|
+
},
|
|
1628212
|
+
{
|
|
1628213
|
+
language: "php",
|
|
1628214
|
+
snippetName: snippetsConfig.phpSdk?.package,
|
|
1628215
|
+
explicitVersion: snippetsConfig.phpSdk?.version
|
|
1628216
|
+
},
|
|
1628217
|
+
{
|
|
1628218
|
+
language: "swift",
|
|
1628219
|
+
snippetName: snippetsConfig.swiftSdk?.package,
|
|
1628220
|
+
explicitVersion: snippetsConfig.swiftSdk?.version
|
|
1628221
|
+
},
|
|
1628222
|
+
{
|
|
1628223
|
+
language: "rust",
|
|
1628224
|
+
snippetName: snippetsConfig.rustSdk?.package,
|
|
1628225
|
+
explicitVersion: snippetsConfig.rustSdk?.version
|
|
1628226
|
+
}
|
|
1628227
|
+
];
|
|
1628228
|
+
for (const config2 of snippetConfigs) {
|
|
1628229
|
+
if (!config2.snippetName) {
|
|
1628230
|
+
continue;
|
|
1628231
|
+
}
|
|
1628232
|
+
let version6 = config2.explicitVersion;
|
|
1628233
|
+
if (!version6) {
|
|
1628234
|
+
const versionResult = await computeSemanticVersionForLanguage({
|
|
1628235
|
+
fdr,
|
|
1628236
|
+
workspace,
|
|
1628237
|
+
language: config2.language,
|
|
1628238
|
+
snippetName: config2.snippetName,
|
|
1628239
|
+
context: context2
|
|
1628240
|
+
});
|
|
1628241
|
+
version6 = versionResult?.version;
|
|
1628242
|
+
}
|
|
1628243
|
+
if (version6) {
|
|
1628244
|
+
result[config2.language] = { packageName: config2.snippetName, version: version6 };
|
|
1628245
|
+
} else {
|
|
1628246
|
+
context2.logger.debug(`[SDK Dynamic IR] ${config2.language}: skipping S3 check (no version available)`);
|
|
1628247
|
+
}
|
|
1628248
|
+
}
|
|
1628249
|
+
return result;
|
|
1628250
|
+
}
|
|
1628251
|
+
async function computeSemanticVersionForLanguage({ fdr, workspace, language, snippetName, context: context2 }) {
|
|
1628252
|
+
let fdrLanguage;
|
|
1628253
|
+
switch (language) {
|
|
1628254
|
+
case "csharp":
|
|
1628255
|
+
fdrLanguage = "Csharp";
|
|
1628256
|
+
break;
|
|
1628257
|
+
case "go":
|
|
1628258
|
+
fdrLanguage = "Go";
|
|
1628259
|
+
break;
|
|
1628260
|
+
case "java":
|
|
1628261
|
+
fdrLanguage = "Java";
|
|
1628262
|
+
break;
|
|
1628263
|
+
case "python":
|
|
1628264
|
+
fdrLanguage = "Python";
|
|
1628265
|
+
break;
|
|
1628266
|
+
case "ruby":
|
|
1628267
|
+
fdrLanguage = "Ruby";
|
|
1628268
|
+
break;
|
|
1628269
|
+
case "typescript":
|
|
1628270
|
+
fdrLanguage = "TypeScript";
|
|
1628271
|
+
break;
|
|
1628272
|
+
case "php":
|
|
1628273
|
+
fdrLanguage = "Php";
|
|
1628274
|
+
break;
|
|
1628275
|
+
case "swift":
|
|
1628276
|
+
fdrLanguage = "Swift";
|
|
1628277
|
+
break;
|
|
1628278
|
+
default:
|
|
1628279
|
+
return void 0;
|
|
1628280
|
+
}
|
|
1628281
|
+
let githubRepository;
|
|
1628282
|
+
let generatorPackage;
|
|
1628283
|
+
let matchedGeneratorName;
|
|
1628284
|
+
if (workspace.generatorsConfiguration?.groups) {
|
|
1628285
|
+
const candidatePackages = [];
|
|
1628286
|
+
for (const group of workspace.generatorsConfiguration.groups) {
|
|
1628287
|
+
for (const generatorInvocation of group.generators) {
|
|
1628288
|
+
if (generatorInvocation.language === language) {
|
|
1628289
|
+
const pkgName = generators_yml_exports.getPackageName({ generatorInvocation });
|
|
1628290
|
+
if (pkgName) {
|
|
1628291
|
+
candidatePackages.push(pkgName);
|
|
1628292
|
+
}
|
|
1628293
|
+
if (!generatorPackage && pkgName) {
|
|
1628294
|
+
generatorPackage = pkgName;
|
|
1628295
|
+
matchedGeneratorName = generatorInvocation.name;
|
|
1628296
|
+
if (generatorInvocation.outputMode.type === "githubV2") {
|
|
1628297
|
+
githubRepository = `${generatorInvocation.outputMode.githubV2.owner}/${generatorInvocation.outputMode.githubV2.repo}`;
|
|
1628298
|
+
}
|
|
1628299
|
+
}
|
|
1628300
|
+
}
|
|
1628301
|
+
}
|
|
1628302
|
+
}
|
|
1628303
|
+
}
|
|
1628304
|
+
if (!generatorPackage) {
|
|
1628305
|
+
context2.logger.debug(`[SDK Dynamic IR] ${language}: no generator found with a package name`);
|
|
1628306
|
+
return void 0;
|
|
1628307
|
+
}
|
|
1628308
|
+
try {
|
|
1628309
|
+
const response = await fdr.sdks.versions.computeSemanticVersion({
|
|
1628310
|
+
githubRepository,
|
|
1628311
|
+
language: fdrLanguage,
|
|
1628312
|
+
package: generatorPackage
|
|
1628313
|
+
});
|
|
1628314
|
+
if (!response.ok) {
|
|
1628315
|
+
context2.logger.debug(`[SDK Dynamic IR] ${language}: version computation failed for package "${generatorPackage}"`);
|
|
1628316
|
+
return void 0;
|
|
1628317
|
+
}
|
|
1628318
|
+
context2.logger.debug(`[SDK Dynamic IR] ${language}: computed version ${response.body.version} for package "${generatorPackage}"`);
|
|
1628319
|
+
return { version: response.body.version, generatorPackage };
|
|
1628320
|
+
} catch (error2) {
|
|
1628321
|
+
context2.logger.debug(`[SDK Dynamic IR] ${language}: error computing version: ${error2}`);
|
|
1628322
|
+
return void 0;
|
|
1628323
|
+
}
|
|
1628324
|
+
}
|
|
1628325
|
+
async function generateLanguageSpecificDynamicIRs({ workspace, organization, context: context2, snippetsConfig, skipLanguages = /* @__PURE__ */ new Set() }) {
|
|
1628064
1628326
|
let languageSpecificIRs = {};
|
|
1628065
1628327
|
if (!workspace) {
|
|
1628066
1628328
|
return void 0;
|
|
@@ -1628118,6 +1628380,10 @@ async function generateLanguageSpecificDynamicIRs({ workspace, organization, con
|
|
|
1628118
1628380
|
if (!generatorInvocation.language) {
|
|
1628119
1628381
|
continue;
|
|
1628120
1628382
|
}
|
|
1628383
|
+
if (skipLanguages.has(generatorInvocation.language)) {
|
|
1628384
|
+
context2.logger.debug(`Skipping dynamic IR generation for ${generatorInvocation.language} (using existing SDK dynamic IR)`);
|
|
1628385
|
+
continue;
|
|
1628386
|
+
}
|
|
1628121
1628387
|
if (generatorInvocation.language && snippetConfiguration[generatorInvocation.language] === packageName) {
|
|
1628122
1628388
|
const irForDynamicSnippets = generateIntermediateRepresentation({
|
|
1628123
1628389
|
workspace,
|
|
@@ -1628158,7 +1628424,7 @@ async function generateLanguageSpecificDynamicIRs({ workspace, organization, con
|
|
|
1628158
1628424
|
}
|
|
1628159
1628425
|
}
|
|
1628160
1628426
|
for (const [language, packageName] of Object.entries(snippetConfiguration)) {
|
|
1628161
|
-
if (language && packageName && !Object.keys(languageSpecificIRs).includes(language)) {
|
|
1628427
|
+
if (language && packageName && !Object.keys(languageSpecificIRs).includes(language) && !skipLanguages.has(language)) {
|
|
1628162
1628428
|
context2.logger.warn();
|
|
1628163
1628429
|
context2.logger.warn(`Failed to upload ${language} SDK snippets because of unknown package \`${packageName}\`.`);
|
|
1628164
1628430
|
context2.logger.warn(`Please make sure your ${workspace.workspaceName ? `${workspace.workspaceName}/` : ""}generators.yml has a generator that publishes a ${packageName} package.`);
|
|
@@ -1637803,6 +1638069,30 @@ async function runRulesOnOSSWorkspace({ workspace, context: context2, rules }) {
|
|
|
1637803
1638069
|
|
|
1637804
1638070
|
// src/commands/validate/validateAPIWorkspaceAndLogIssues.ts
|
|
1637805
1638071
|
var import_validate_npm_package_name = __toESM(require_lib20(), 1);
|
|
1638072
|
+
async function collectAPIWorkspaceViolations({
|
|
1638073
|
+
workspace,
|
|
1638074
|
+
context: context2,
|
|
1638075
|
+
ossWorkspace
|
|
1638076
|
+
}) {
|
|
1638077
|
+
if (!(0, import_validate_npm_package_name.default)(workspace.definition.rootApiFile.contents.name).validForNewPackages) {
|
|
1638078
|
+
context2.failAndThrow("API name is not valid.");
|
|
1638079
|
+
}
|
|
1638080
|
+
const startTime = performance.now();
|
|
1638081
|
+
const apiViolations = validateFernWorkspace(workspace, context2.logger);
|
|
1638082
|
+
const generatorViolations = await validateGeneratorsWorkspace(workspace, context2.logger);
|
|
1638083
|
+
const violations = [...apiViolations, ...generatorViolations];
|
|
1638084
|
+
if (ossWorkspace) {
|
|
1638085
|
+
violations.push(...await validateOSSWorkspace(ossWorkspace, context2));
|
|
1638086
|
+
}
|
|
1638087
|
+
const elapsedMillis = performance.now() - startTime;
|
|
1638088
|
+
const hasErrors = violations.some((v21) => v21.severity === "fatal" || v21.severity === "error");
|
|
1638089
|
+
return {
|
|
1638090
|
+
apiName: workspace.definition.rootApiFile.contents.name,
|
|
1638091
|
+
violations,
|
|
1638092
|
+
elapsedMillis,
|
|
1638093
|
+
hasErrors
|
|
1638094
|
+
};
|
|
1638095
|
+
}
|
|
1637806
1638096
|
async function validateAPIWorkspaceWithoutExiting({
|
|
1637807
1638097
|
workspace,
|
|
1637808
1638098
|
context: context2,
|
|
@@ -1643592,6 +1643882,230 @@ async function validateDocsBrokenLinks({
|
|
|
1643592
1643882
|
});
|
|
1643593
1643883
|
}
|
|
1643594
1643884
|
|
|
1643885
|
+
// src/commands/validate/printCheckReport.ts
|
|
1643886
|
+
function printCheckReport({ apiResults, docsResult, logWarnings, context: context2 }) {
|
|
1643887
|
+
const startTime = performance.now();
|
|
1643888
|
+
let hasErrors = false;
|
|
1643889
|
+
const apiResultsWithViolations = apiResults.filter((result) => {
|
|
1643890
|
+
const stats = getViolationStats2(result.violations);
|
|
1643891
|
+
return stats.numErrors > 0 || logWarnings && stats.numWarnings > 0;
|
|
1643892
|
+
});
|
|
1643893
|
+
if (apiResultsWithViolations.length > 0) {
|
|
1643894
|
+
const totalSdkStats = getTotalStats(apiResults.map((r23) => r23.violations).flat());
|
|
1643895
|
+
const showApiNesting = apiResults.length > 1;
|
|
1643896
|
+
if (showApiNesting) {
|
|
1643897
|
+
context2.logger.info(source_default.cyan(source_default.bold("[sdk]")));
|
|
1643898
|
+
for (const apiResult of apiResults) {
|
|
1643899
|
+
const stats = getViolationStats2(apiResult.violations);
|
|
1643900
|
+
if (stats.numErrors > 0 || logWarnings && stats.numWarnings > 0) {
|
|
1643901
|
+
hasErrors = hasErrors || stats.numErrors > 0;
|
|
1643902
|
+
printApiSection({
|
|
1643903
|
+
apiName: apiResult.apiName,
|
|
1643904
|
+
violations: apiResult.violations,
|
|
1643905
|
+
stats,
|
|
1643906
|
+
logWarnings,
|
|
1643907
|
+
context: context2,
|
|
1643908
|
+
indent: " "
|
|
1643909
|
+
});
|
|
1643910
|
+
}
|
|
1643911
|
+
}
|
|
1643912
|
+
} else {
|
|
1643913
|
+
hasErrors = hasErrors || totalSdkStats.numErrors > 0;
|
|
1643914
|
+
printSdkSectionFlat({
|
|
1643915
|
+
violations: apiResults[0]?.violations ?? [],
|
|
1643916
|
+
stats: totalSdkStats,
|
|
1643917
|
+
logWarnings,
|
|
1643918
|
+
context: context2
|
|
1643919
|
+
});
|
|
1643920
|
+
}
|
|
1643921
|
+
}
|
|
1643922
|
+
if (docsResult != null) {
|
|
1643923
|
+
const docsStats = getViolationStats2(docsResult.violations);
|
|
1643924
|
+
if (docsStats.numErrors > 0 || logWarnings && docsStats.numWarnings > 0) {
|
|
1643925
|
+
hasErrors = hasErrors || docsStats.numErrors > 0;
|
|
1643926
|
+
printDocsSection({
|
|
1643927
|
+
violations: docsResult.violations,
|
|
1643928
|
+
stats: docsStats,
|
|
1643929
|
+
logWarnings,
|
|
1643930
|
+
context: context2
|
|
1643931
|
+
});
|
|
1643932
|
+
}
|
|
1643933
|
+
}
|
|
1643934
|
+
const totalElapsedMillis = performance.now() - startTime;
|
|
1643935
|
+
const allViolations = [...apiResults.map((r23) => r23.violations).flat(), ...docsResult?.violations ?? []];
|
|
1643936
|
+
const totalStats = getViolationStats2(allViolations);
|
|
1643937
|
+
printSummary({
|
|
1643938
|
+
stats: totalStats,
|
|
1643939
|
+
logWarnings,
|
|
1643940
|
+
elapsedMillis: totalElapsedMillis,
|
|
1643941
|
+
context: context2
|
|
1643942
|
+
});
|
|
1643943
|
+
return { hasErrors };
|
|
1643944
|
+
}
|
|
1643945
|
+
function printSdkSectionFlat({
|
|
1643946
|
+
violations,
|
|
1643947
|
+
stats,
|
|
1643948
|
+
logWarnings,
|
|
1643949
|
+
context: context2
|
|
1643950
|
+
}) {
|
|
1643951
|
+
const statsStr = formatStats(stats, logWarnings);
|
|
1643952
|
+
context2.logger.info(source_default.cyan(source_default.bold(`[sdk]`)) + ` ${statsStr}`);
|
|
1643953
|
+
printViolationsByType({
|
|
1643954
|
+
violations,
|
|
1643955
|
+
logWarnings,
|
|
1643956
|
+
context: context2,
|
|
1643957
|
+
indent: " "
|
|
1643958
|
+
});
|
|
1643959
|
+
}
|
|
1643960
|
+
function printApiSection({
|
|
1643961
|
+
apiName,
|
|
1643962
|
+
violations,
|
|
1643963
|
+
stats,
|
|
1643964
|
+
logWarnings,
|
|
1643965
|
+
context: context2,
|
|
1643966
|
+
indent: indent3
|
|
1643967
|
+
}) {
|
|
1643968
|
+
const statsStr = formatStats(stats, logWarnings);
|
|
1643969
|
+
context2.logger.info(`${indent3}${source_default.bold(`[${apiName}]`)} ${statsStr}`);
|
|
1643970
|
+
printViolationsByType({
|
|
1643971
|
+
violations,
|
|
1643972
|
+
logWarnings,
|
|
1643973
|
+
context: context2,
|
|
1643974
|
+
indent: indent3 + " "
|
|
1643975
|
+
});
|
|
1643976
|
+
}
|
|
1643977
|
+
function printDocsSection({
|
|
1643978
|
+
violations,
|
|
1643979
|
+
stats,
|
|
1643980
|
+
logWarnings,
|
|
1643981
|
+
context: context2
|
|
1643982
|
+
}) {
|
|
1643983
|
+
const statsStr = formatStats(stats, logWarnings);
|
|
1643984
|
+
context2.logger.info(source_default.magenta(source_default.bold(`[docs]`)) + ` ${statsStr}`);
|
|
1643985
|
+
printViolationsByType({
|
|
1643986
|
+
violations,
|
|
1643987
|
+
logWarnings,
|
|
1643988
|
+
context: context2,
|
|
1643989
|
+
indent: " "
|
|
1643990
|
+
});
|
|
1643991
|
+
}
|
|
1643992
|
+
function printViolationsByType({
|
|
1643993
|
+
violations,
|
|
1643994
|
+
logWarnings,
|
|
1643995
|
+
context: context2,
|
|
1643996
|
+
indent: indent3
|
|
1643997
|
+
}) {
|
|
1643998
|
+
const errors4 = violations.filter((v21) => v21.severity === "fatal" || v21.severity === "error");
|
|
1643999
|
+
const warnings = violations.filter((v21) => v21.severity === "warning");
|
|
1644000
|
+
if (logWarnings) {
|
|
1644001
|
+
for (const violation of warnings.sort(sortViolations)) {
|
|
1644002
|
+
printViolation({ violation, context: context2, indent: indent3 });
|
|
1644003
|
+
}
|
|
1644004
|
+
}
|
|
1644005
|
+
for (const violation of errors4.sort(sortViolations)) {
|
|
1644006
|
+
printViolation({ violation, context: context2, indent: indent3 });
|
|
1644007
|
+
}
|
|
1644008
|
+
}
|
|
1644009
|
+
function printViolation({
|
|
1644010
|
+
violation,
|
|
1644011
|
+
context: context2,
|
|
1644012
|
+
indent: indent3
|
|
1644013
|
+
}) {
|
|
1644014
|
+
const severityLabel = getSeverityLabel2(violation.severity);
|
|
1644015
|
+
const path68 = formatViolationPath(violation);
|
|
1644016
|
+
if (path68 === "") {
|
|
1644017
|
+
context2.logger.info(`${indent3}${severityLabel} ${violation.message}`);
|
|
1644018
|
+
} else {
|
|
1644019
|
+
context2.logger.info(`${indent3}${severityLabel}`);
|
|
1644020
|
+
context2.logger.info(`${indent3} path: ${source_default.blue(path68)}`);
|
|
1644021
|
+
context2.logger.info(`${indent3} issue: ${violation.message}`);
|
|
1644022
|
+
}
|
|
1644023
|
+
context2.logger.info("");
|
|
1644024
|
+
}
|
|
1644025
|
+
function formatViolationPath(violation) {
|
|
1644026
|
+
const parts = [];
|
|
1644027
|
+
if (violation.relativeFilepath !== "") {
|
|
1644028
|
+
parts.push(violation.relativeFilepath);
|
|
1644029
|
+
}
|
|
1644030
|
+
for (const nodePathItem of violation.nodePath) {
|
|
1644031
|
+
let itemStr = typeof nodePathItem === "string" ? nodePathItem : nodePathItem.key;
|
|
1644032
|
+
if (typeof nodePathItem !== "string" && nodePathItem.arrayIndex != null) {
|
|
1644033
|
+
itemStr += `[${nodePathItem.arrayIndex}]`;
|
|
1644034
|
+
}
|
|
1644035
|
+
parts.push(itemStr);
|
|
1644036
|
+
}
|
|
1644037
|
+
return parts.join(" -> ");
|
|
1644038
|
+
}
|
|
1644039
|
+
function getSeverityLabel2(severity) {
|
|
1644040
|
+
switch (severity) {
|
|
1644041
|
+
case "fatal":
|
|
1644042
|
+
return source_default.red("[error]");
|
|
1644043
|
+
case "error":
|
|
1644044
|
+
return source_default.red("[error]");
|
|
1644045
|
+
case "warning":
|
|
1644046
|
+
return source_default.yellow("[warning]");
|
|
1644047
|
+
default:
|
|
1644048
|
+
assertNever(severity);
|
|
1644049
|
+
}
|
|
1644050
|
+
}
|
|
1644051
|
+
function formatStats(stats, logWarnings) {
|
|
1644052
|
+
const parts = [];
|
|
1644053
|
+
if (stats.numErrors > 0) {
|
|
1644054
|
+
parts.push(`${stats.numErrors} error${stats.numErrors !== 1 ? "s" : ""}`);
|
|
1644055
|
+
}
|
|
1644056
|
+
if (logWarnings && stats.numWarnings > 0) {
|
|
1644057
|
+
parts.push(`${stats.numWarnings} warning${stats.numWarnings !== 1 ? "s" : ""}`);
|
|
1644058
|
+
}
|
|
1644059
|
+
return parts.join(", ");
|
|
1644060
|
+
}
|
|
1644061
|
+
function getViolationStats2(violations) {
|
|
1644062
|
+
let numErrors = 0;
|
|
1644063
|
+
let numWarnings = 0;
|
|
1644064
|
+
for (const violation of violations) {
|
|
1644065
|
+
switch (violation.severity) {
|
|
1644066
|
+
case "fatal":
|
|
1644067
|
+
case "error":
|
|
1644068
|
+
numErrors += 1;
|
|
1644069
|
+
break;
|
|
1644070
|
+
case "warning":
|
|
1644071
|
+
numWarnings += 1;
|
|
1644072
|
+
break;
|
|
1644073
|
+
default:
|
|
1644074
|
+
assertNever(violation.severity);
|
|
1644075
|
+
}
|
|
1644076
|
+
}
|
|
1644077
|
+
return { numErrors, numWarnings };
|
|
1644078
|
+
}
|
|
1644079
|
+
function getTotalStats(violations) {
|
|
1644080
|
+
return getViolationStats2(violations);
|
|
1644081
|
+
}
|
|
1644082
|
+
function sortViolations(a10, b18) {
|
|
1644083
|
+
const pathCompare = a10.relativeFilepath.localeCompare(b18.relativeFilepath);
|
|
1644084
|
+
if (pathCompare !== 0) {
|
|
1644085
|
+
return pathCompare;
|
|
1644086
|
+
}
|
|
1644087
|
+
return JSON.stringify(a10.nodePath).localeCompare(JSON.stringify(b18.nodePath));
|
|
1644088
|
+
}
|
|
1644089
|
+
function printSummary({
|
|
1644090
|
+
stats,
|
|
1644091
|
+
logWarnings,
|
|
1644092
|
+
elapsedMillis,
|
|
1644093
|
+
context: context2
|
|
1644094
|
+
}) {
|
|
1644095
|
+
const suffix = elapsedMillis > 0 ? ` in ${(elapsedMillis / 1e3).toFixed(3)} seconds.` : ".";
|
|
1644096
|
+
let message = `Found ${stats.numErrors} error${stats.numErrors !== 1 ? "s" : ""} and ${stats.numWarnings} warning${stats.numWarnings !== 1 ? "s" : ""}` + suffix;
|
|
1644097
|
+
if (!logWarnings && stats.numWarnings > 0) {
|
|
1644098
|
+
message += " Run fern check --warnings to print out the warnings not shown.";
|
|
1644099
|
+
}
|
|
1644100
|
+
if (stats.numErrors > 0) {
|
|
1644101
|
+
context2.logger.error(message);
|
|
1644102
|
+
} else if (stats.numWarnings > 0) {
|
|
1644103
|
+
context2.logger.warn(message);
|
|
1644104
|
+
} else {
|
|
1644105
|
+
context2.logger.info(source_default.green("All checks passed"));
|
|
1644106
|
+
}
|
|
1644107
|
+
}
|
|
1644108
|
+
|
|
1643595
1644109
|
// src/commands/validate/validateWorkspaces.ts
|
|
1643596
1644110
|
async function validateWorkspaces({
|
|
1643597
1644111
|
project,
|
|
@@ -1643602,28 +1644116,41 @@ async function validateWorkspaces({
|
|
|
1643602
1644116
|
isLocal,
|
|
1643603
1644117
|
directFromOpenapi
|
|
1643604
1644118
|
}) {
|
|
1644119
|
+
const apiResults = [];
|
|
1644120
|
+
let docsResult;
|
|
1644121
|
+
let hasAnyErrors = false;
|
|
1643605
1644122
|
const docsWorkspace = project.docsWorkspaces;
|
|
1643606
1644123
|
if (docsWorkspace != null) {
|
|
1644124
|
+
const excludeRules = brokenLinks || errorOnBrokenLinks ? [] : ["valid-markdown-links"];
|
|
1644125
|
+
const ossWorkspaces = await filterOssWorkspaces(project);
|
|
1644126
|
+
let collected;
|
|
1643607
1644127
|
await cliContext.runTaskForWorkspace(docsWorkspace, async (context2) => {
|
|
1643608
|
-
|
|
1643609
|
-
await validateDocsWorkspaceAndLogIssues({
|
|
1644128
|
+
collected = await collectDocsWorkspaceViolations({
|
|
1643610
1644129
|
workspace: docsWorkspace,
|
|
1643611
1644130
|
context: context2,
|
|
1643612
|
-
logWarnings,
|
|
1643613
1644131
|
apiWorkspaces: project.apiWorkspaces,
|
|
1643614
|
-
ossWorkspaces
|
|
1644132
|
+
ossWorkspaces,
|
|
1643615
1644133
|
errorOnBrokenLinks,
|
|
1643616
1644134
|
excludeRules
|
|
1643617
1644135
|
});
|
|
1643618
1644136
|
});
|
|
1644137
|
+
if (collected != null) {
|
|
1644138
|
+
docsResult = {
|
|
1644139
|
+
violations: collected.violations,
|
|
1644140
|
+
elapsedMillis: collected.elapsedMillis
|
|
1644141
|
+
};
|
|
1644142
|
+
if (collected.hasErrors) {
|
|
1644143
|
+
hasAnyErrors = true;
|
|
1644144
|
+
}
|
|
1644145
|
+
}
|
|
1643619
1644146
|
}
|
|
1643620
1644147
|
await Promise.all(
|
|
1643621
1644148
|
project.apiWorkspaces.map(async (workspace) => {
|
|
1643622
|
-
if (workspace.generatorsConfiguration?.groups.length === 0 && workspace.type
|
|
1644149
|
+
if (workspace.generatorsConfiguration?.groups.length === 0 && workspace.type !== "fern") {
|
|
1643623
1644150
|
return;
|
|
1643624
1644151
|
}
|
|
1643625
|
-
|
|
1643626
|
-
|
|
1644152
|
+
if (workspace instanceof OSSWorkspace && directFromOpenapi) {
|
|
1644153
|
+
await cliContext.runTaskForWorkspace(workspace, async (context2) => {
|
|
1643627
1644154
|
await workspace.getIntermediateRepresentation({
|
|
1643628
1644155
|
context: context2,
|
|
1643629
1644156
|
audiences: { type: "all" },
|
|
@@ -1643631,18 +1644158,56 @@ async function validateWorkspaces({
|
|
|
1643631
1644158
|
generateV1Examples: false,
|
|
1643632
1644159
|
logWarnings
|
|
1643633
1644160
|
});
|
|
1644161
|
+
});
|
|
1644162
|
+
return;
|
|
1644163
|
+
}
|
|
1644164
|
+
if (workspace instanceof LazyFernWorkspace) {
|
|
1644165
|
+
const absolutePathToApiYml = join2(
|
|
1644166
|
+
workspace.absoluteFilePath,
|
|
1644167
|
+
RelativeFilePath2.of(DEFINITION_DIRECTORY),
|
|
1644168
|
+
RelativeFilePath2.of(ROOT_API_FILENAME)
|
|
1644169
|
+
);
|
|
1644170
|
+
const apiYmlExists = await doesPathExist(absolutePathToApiYml);
|
|
1644171
|
+
if (!apiYmlExists) {
|
|
1644172
|
+
await cliContext.runTask(async (context2) => {
|
|
1644173
|
+
context2.logger.error(`Missing file: ${ROOT_API_FILENAME}`);
|
|
1644174
|
+
return context2.failAndThrow();
|
|
1644175
|
+
});
|
|
1643634
1644176
|
return;
|
|
1643635
1644177
|
}
|
|
1644178
|
+
}
|
|
1644179
|
+
let collected;
|
|
1644180
|
+
await cliContext.runTaskForWorkspace(workspace, async (context2) => {
|
|
1643636
1644181
|
const fernWorkspace = await workspace.toFernWorkspace({ context: context2 });
|
|
1643637
|
-
await
|
|
1644182
|
+
collected = await collectAPIWorkspaceViolations({
|
|
1643638
1644183
|
workspace: fernWorkspace,
|
|
1643639
1644184
|
context: context2,
|
|
1643640
|
-
logWarnings,
|
|
1643641
1644185
|
ossWorkspace: workspace instanceof OSSWorkspace ? workspace : void 0
|
|
1643642
1644186
|
});
|
|
1643643
1644187
|
});
|
|
1644188
|
+
if (collected != null) {
|
|
1644189
|
+
apiResults.push({
|
|
1644190
|
+
apiName: collected.apiName,
|
|
1644191
|
+
violations: collected.violations,
|
|
1644192
|
+
elapsedMillis: collected.elapsedMillis
|
|
1644193
|
+
});
|
|
1644194
|
+
if (collected.hasErrors) {
|
|
1644195
|
+
hasAnyErrors = true;
|
|
1644196
|
+
}
|
|
1644197
|
+
}
|
|
1643644
1644198
|
})
|
|
1643645
1644199
|
);
|
|
1644200
|
+
const { hasErrors } = await cliContext.runTask((context2) => {
|
|
1644201
|
+
return printCheckReport({
|
|
1644202
|
+
apiResults,
|
|
1644203
|
+
docsResult,
|
|
1644204
|
+
logWarnings,
|
|
1644205
|
+
context: context2
|
|
1644206
|
+
});
|
|
1644207
|
+
});
|
|
1644208
|
+
if (hasErrors || hasAnyErrors) {
|
|
1644209
|
+
cliContext.failAndThrow();
|
|
1644210
|
+
}
|
|
1643646
1644211
|
}
|
|
1643647
1644212
|
|
|
1643648
1644213
|
// src/commands/write-definition/writeDefinitionForWorkspaces.ts
|
package/package.json
CHANGED