@fern-api/fern-api-dev 5.7.5 → 5.7.6-3-gd8ee8ddb229

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 +147 -73
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -427701,7 +427701,7 @@ var require_sync2 = __commonJS({
427701
427701
  "../../../node_modules/.pnpm/escalade@3.2.0/node_modules/escalade/sync/index.js"(exports2, module4) {
427702
427702
  "use strict";
427703
427703
  var { dirname: dirname22, resolve: resolve15 } = require("path");
427704
- var { readdirSync: readdirSync3, statSync: statSync5 } = require("fs");
427704
+ var { readdirSync: readdirSync4, statSync: statSync5 } = require("fs");
427705
427705
  module4.exports = function(start2, callback) {
427706
427706
  let dir = resolve15(".", start2);
427707
427707
  let tmp18, stats = statSync5(dir);
@@ -427709,7 +427709,7 @@ var require_sync2 = __commonJS({
427709
427709
  dir = dirname22(dir);
427710
427710
  }
427711
427711
  while (true) {
427712
- tmp18 = callback(dir, readdirSync3(dir));
427712
+ tmp18 = callback(dir, readdirSync4(dir));
427713
427713
  if (tmp18) return resolve15(dir, tmp18);
427714
427714
  dir = dirname22(tmp18 = dir);
427715
427715
  if (tmp18 === dir) break;
@@ -535141,7 +535141,7 @@ var ExampleTypeFactory = class _ExampleTypeFactory {
535141
535141
  if (example != null) {
535142
535142
  const allowed = schema2.values.map((v9) => v9.value);
535143
535143
  const exampleStr = _ExampleTypeFactory.truncateExample(example);
535144
- this.context.logger.warn(`Example value ${exampleStr} is not a valid enum value${options2.name != null ? ` for '${options2.name}'` : ""}. Allowed values: [${allowed.join(", ")}]. Using fallback value instead.`);
535144
+ this.context.logger.debug(`Example value ${exampleStr} is not a valid enum value${options2.name != null ? ` for '${options2.name}'` : ""}. Allowed values: [${allowed.join(", ")}]. Using fallback value instead.`);
535145
535145
  }
535146
535146
  return schema2.values[0] != null ? FullExample.enum(schema2.values[0]?.value) : void 0;
535147
535147
  case "literal":
@@ -535973,7 +535973,7 @@ var ExampleTypeFactory = class _ExampleTypeFactory {
535973
535973
  const fieldDesc = options2.name != null ? ` for '${options2.name}'` : "";
535974
535974
  const actualType = typeof example;
535975
535975
  const exampleStr = _ExampleTypeFactory.truncateExample(example);
535976
- this.context.logger.warn(`Invalid example${fieldDesc}: expected ${expected} but got ${actualType} (${exampleStr}). The provided example does not match the '${schemaType}' schema and will be replaced with a generated value.`);
535976
+ this.context.logger.debug(`Invalid example${fieldDesc}: expected ${expected} but got ${actualType} (${exampleStr}). The provided example does not match the '${schemaType}' schema and will be replaced with a generated value.`);
535977
535977
  }
535978
535978
  static truncateExample(example, maxLength = 100) {
535979
535979
  const str3 = JSON.stringify(example);
@@ -541476,7 +541476,6 @@ function replaceWithSchemaReference({ openapi, replaceReference, schemaReference
541476
541476
  // ../api-importers/openapi/openapi-ir-parser/lib/openapi/v3/generateIr.js
541477
541477
  function generateIr({ openApi, taskContext, options: options2, source: source2, namespace }) {
541478
541478
  openApi = runResolutions({ openapi: openApi });
541479
- validateOpenApiSpecForDocsCompat({ openApi, taskContext });
541480
541479
  resetTitleCollisionTracker();
541481
541480
  const tempContext = new OpenAPIV3ParserContext({
541482
541481
  document: openApi,
@@ -541911,35 +541910,6 @@ function getAllParentSchemaIds({ schema: schema2, schemas }) {
541911
541910
  function distinct(array3) {
541912
541911
  return [...new Set(array3)];
541913
541912
  }
541914
- var NON_ASCII_REGEX = new RegExp("[^\\x00-\\x7F]");
541915
- var FRONTMATTER_DELIMITER_REGEX = /(?:^|\n)\s*---\s*(?:\n|$)/;
541916
- function validateOpenApiSpecForDocsCompat({ openApi, taskContext }) {
541917
- for (const tag2 of openApi.tags ?? []) {
541918
- if (NON_ASCII_REGEX.test(tag2.name)) {
541919
- const nonAsciiChars = [...tag2.name].filter((c5) => NON_ASCII_REGEX.test(c5));
541920
- taskContext.logger.error(`Tag name "${tag2.name}" contains non-ASCII characters: ${nonAsciiChars.join(", ")}. Non-ASCII characters in tag names will be included in URL paths and HTTP headers, which only support ASCII characters. This will cause runtime errors (ERR_INVALID_CHAR). Remove non-ASCII characters from the tag name.`);
541921
- }
541922
- }
541923
- for (const [path106, pathItem] of Object.entries(openApi.paths ?? {})) {
541924
- if (pathItem == null) {
541925
- continue;
541926
- }
541927
- for (const method8 of ["get", "post", "put", "delete", "patch", "options", "head", "trace"]) {
541928
- const operation = pathItem[method8];
541929
- if (operation?.description != null && FRONTMATTER_DELIMITER_REGEX.test(operation.description)) {
541930
- taskContext.logger.error(`Description at paths.${path106}.${method8} contains "---" frontmatter delimiters which will cause YAML parsing failures in the generated docs site. Remove the "---" delimiters from the description.`);
541931
- }
541932
- if (operation?.tags != null && (openApi.tags == null || openApi.tags.length === 0)) {
541933
- for (const tag2 of operation.tags) {
541934
- if (NON_ASCII_REGEX.test(tag2)) {
541935
- const nonAsciiChars = [...tag2].filter((c5) => NON_ASCII_REGEX.test(c5));
541936
- taskContext.logger.error(`Tag name "${tag2}" at paths.${path106}.${method8} contains non-ASCII characters: ${nonAsciiChars.join(", ")}. Remove non-ASCII characters from the tag name.`);
541937
- }
541938
- }
541939
- }
541940
- }
541941
- }
541942
- }
541943
541913
  function getAudiences({ operation }) {
541944
541914
  let endpointAudiences = [];
541945
541915
  switch (operation.type) {
@@ -607103,23 +607073,23 @@ var ExampleValidator = class {
607103
607073
  };
607104
607074
 
607105
607075
  // ../api-importers/v3-importer-commons/lib/OpenApiSpecValidations.js
607106
- var NON_ASCII_REGEX2 = new RegExp("[^\\x00-\\x7F]");
607107
- var FRONTMATTER_DELIMITER_REGEX2 = /(?:^|\n)\s*---\s*(?:\n|$)/;
607076
+ var NON_ASCII_REGEX = new RegExp("[^\\x00-\\x7F]");
607077
+ var FRONTMATTER_DELIMITER_REGEX = /(?:^|\n)\s*---\s*(?:\n|$)/;
607108
607078
  function validateTagNames({ tags, errorCollector }) {
607109
607079
  for (const tag2 of tags) {
607110
- if (NON_ASCII_REGEX2.test(tag2.name)) {
607111
- const nonAsciiChars = [...tag2.name].filter((c5) => NON_ASCII_REGEX2.test(c5));
607080
+ if (NON_ASCII_REGEX.test(tag2.name)) {
607081
+ const nonAsciiChars = [...tag2.name].filter((c5) => NON_ASCII_REGEX.test(c5));
607112
607082
  errorCollector.collect({
607113
607083
  level: APIErrorLevel.ERROR,
607114
607084
  message: `Tag name "${tag2.name}" contains non-ASCII characters: ${nonAsciiChars.join(", ")}. Non-ASCII characters in tag names will be included in URL paths and HTTP headers, which only support ASCII characters. This will cause runtime errors (ERR_INVALID_CHAR).`,
607115
607085
  path: ["tags", tag2.name],
607116
- resolution: `Remove non-ASCII characters from the tag name. For example, rename "${tag2.name}" to "${tag2.name.replace(NON_ASCII_REGEX2, "").trim()}".`
607086
+ resolution: `Remove non-ASCII characters from the tag name. For example, rename "${tag2.name}" to "${tag2.name.replace(NON_ASCII_REGEX, "").trim()}".`
607117
607087
  });
607118
607088
  }
607119
607089
  }
607120
607090
  }
607121
607091
  function validateDescription({ description, path: path106, errorCollector }) {
607122
- if (FRONTMATTER_DELIMITER_REGEX2.test(description)) {
607092
+ if (FRONTMATTER_DELIMITER_REGEX.test(description)) {
607123
607093
  errorCollector.collect({
607124
607094
  level: APIErrorLevel.ERROR,
607125
607095
  message: `Description contains "---" frontmatter delimiters which will cause YAML parsing failures in the generated docs site. The docs renderer interprets content between "---" delimiters as YAML frontmatter, which will fail if the content is not valid YAML.`,
@@ -607156,14 +607126,14 @@ function validateOpenApiSpec({ spec, errorCollector }) {
607156
607126
  }
607157
607127
  if (Array.isArray(op4.tags) && !Array.isArray(spec.tags)) {
607158
607128
  for (const tag2 of op4.tags) {
607159
- if (typeof tag2 === "string" && !seenTags.has(tag2) && NON_ASCII_REGEX2.test(tag2)) {
607129
+ if (typeof tag2 === "string" && !seenTags.has(tag2) && NON_ASCII_REGEX.test(tag2)) {
607160
607130
  seenTags.add(tag2);
607161
- const nonAsciiChars = [...tag2].filter((c5) => NON_ASCII_REGEX2.test(c5));
607131
+ const nonAsciiChars = [...tag2].filter((c5) => NON_ASCII_REGEX.test(c5));
607162
607132
  errorCollector.collect({
607163
607133
  level: APIErrorLevel.ERROR,
607164
607134
  message: `Tag name "${tag2}" contains non-ASCII characters: ${nonAsciiChars.join(", ")}. Non-ASCII characters in tag names will be included in URL paths and HTTP headers, which only support ASCII characters. This will cause runtime errors (ERR_INVALID_CHAR).`,
607165
607135
  path: ["paths", path106, method8, "tags"],
607166
- resolution: `Remove non-ASCII characters from the tag name. For example, rename "${tag2}" to "${tag2.replace(NON_ASCII_REGEX2, "").trim()}".`
607136
+ resolution: `Remove non-ASCII characters from the tag name. For example, rename "${tag2}" to "${tag2.replace(NON_ASCII_REGEX, "").trim()}".`
607167
607137
  });
607168
607138
  }
607169
607139
  }
@@ -614844,7 +614814,7 @@ function audiencesIntersect(a3, b8) {
614844
614814
 
614845
614815
  // ../workspace/oss-validator/lib/rules/no-invalid-tag-names-or-frontmatter/no-invalid-tag-names-or-frontmatter.js
614846
614816
  init_lib6();
614847
- var NON_ASCII_REGEX3 = new RegExp("[^\\x00-\\x7F]");
614817
+ var NON_ASCII_REGEX2 = new RegExp("[^\\x00-\\x7F]");
614848
614818
  var FRONTMATTER_REGEX = /(?:^|\n)\s*---\s*(?:\n|$)/;
614849
614819
  var HTTP_METHODS = ["get", "post", "put", "delete", "patch", "options", "head", "trace"];
614850
614820
  var NoInvalidTagNamesOrFrontmatterRule = {
@@ -614865,8 +614835,8 @@ var NoInvalidTagNamesOrFrontmatterRule = {
614865
614835
  if (Array.isArray(apiDoc.tags)) {
614866
614836
  for (const tag2 of apiDoc.tags) {
614867
614837
  if (typeof tag2 === "object" && tag2 != null && typeof tag2.name === "string") {
614868
- if (NON_ASCII_REGEX3.test(tag2.name)) {
614869
- const nonAsciiChars = [...tag2.name].filter((c5) => NON_ASCII_REGEX3.test(c5));
614838
+ if (NON_ASCII_REGEX2.test(tag2.name)) {
614839
+ const nonAsciiChars = [...tag2.name].filter((c5) => NON_ASCII_REGEX2.test(c5));
614870
614840
  violations.push({
614871
614841
  name: "no-invalid-tag-names-or-frontmatter",
614872
614842
  severity: "error",
@@ -614902,9 +614872,9 @@ var NoInvalidTagNamesOrFrontmatterRule = {
614902
614872
  }
614903
614873
  if (Array.isArray(op4.tags) && !Array.isArray(apiDoc.tags)) {
614904
614874
  for (const tag2 of op4.tags) {
614905
- if (typeof tag2 === "string" && !seenInlineTags.has(tag2) && NON_ASCII_REGEX3.test(tag2)) {
614875
+ if (typeof tag2 === "string" && !seenInlineTags.has(tag2) && NON_ASCII_REGEX2.test(tag2)) {
614906
614876
  seenInlineTags.add(tag2);
614907
- const nonAsciiChars = [...tag2].filter((c5) => NON_ASCII_REGEX3.test(c5));
614877
+ const nonAsciiChars = [...tag2].filter((c5) => NON_ASCII_REGEX2.test(c5));
614908
614878
  violations.push({
614909
614879
  name: "no-invalid-tag-names-or-frontmatter",
614910
614880
  severity: "error",
@@ -622607,7 +622577,7 @@ var AccessTokenPosthogManager = class {
622607
622577
  properties: {
622608
622578
  ...event,
622609
622579
  ...event.properties,
622610
- version: "5.7.5",
622580
+ version: "5.7.6-3-gd8ee8ddb229",
622611
622581
  usingAccessToken: true
622612
622582
  }
622613
622583
  });
@@ -622661,7 +622631,7 @@ var UserPosthogManager = class {
622661
622631
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
622662
622632
  event: "CLI",
622663
622633
  properties: {
622664
- version: "5.7.5",
622634
+ version: "5.7.6-3-gd8ee8ddb229",
622665
622635
  ...event,
622666
622636
  ...event.properties,
622667
622637
  usingAccessToken: false,
@@ -847021,7 +846991,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
847021
846991
  var LOGS_FOLDER_NAME = "logs";
847022
846992
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
847023
846993
  function getCliSource() {
847024
- const version7 = "5.7.5";
846994
+ const version7 = "5.7.6-3-gd8ee8ddb229";
847025
846995
  return `cli@${version7}`;
847026
846996
  }
847027
846997
  var DebugLogger = class {
@@ -847450,6 +847420,7 @@ function resolveWindowsSymlinks(outputDir, symlinks, logger4, onProgress) {
847450
847420
  continue;
847451
847421
  }
847452
847422
  if (!(0, import_fs27.existsSync)(sourcePath)) {
847423
+ logger4.debug(`Symlink target not found: ${symlinkPath} -> ${linkname} (resolved: ${sourcePath})`);
847453
847424
  failed++;
847454
847425
  continue;
847455
847426
  }
@@ -847474,10 +847445,38 @@ function resolveWindowsSymlinks(outputDir, symlinks, logger4, onProgress) {
847474
847445
  }
847475
847446
  logger4.debug(`Symlink resolution: ${junctions} junctions, ${copies} file copies, ${alreadyExisted} pre-existing, ${failed} failed (${fallbackUsed} via fallback) out of ${symlinks.length}`);
847476
847447
  const standaloneNM = import_path58.default.join(outputDir, "standalone", "node_modules");
847477
- for (const dep of ["next", "react", "react-dom", "styled-jsx"]) {
847478
- if (!(0, import_fs27.existsSync)(import_path58.default.join(standaloneNM, dep))) {
847479
- logger4.warn(`${dep} is MISSING from standalone/node_modules/`);
847448
+ const criticalDeps = ["next", "react", "react-dom", "styled-jsx"];
847449
+ for (const dep of criticalDeps) {
847450
+ const depPath = import_path58.default.join(standaloneNM, dep);
847451
+ if ((0, import_fs27.existsSync)(depPath)) {
847452
+ continue;
847453
+ }
847454
+ logger4.warn(`${dep} is MISSING from standalone/node_modules/ \u2014 attempting recovery`);
847455
+ if ((0, import_fs27.existsSync)(rootPnpmStore)) {
847456
+ try {
847457
+ const pnpmDirs = (0, import_fs27.readdirSync)(rootPnpmStore);
847458
+ const matchingDir = pnpmDirs.find((d5) => d5 === dep || d5.startsWith(`${dep}@`));
847459
+ if (matchingDir != null) {
847460
+ const realPkgPath = import_path58.default.join(rootPnpmStore, matchingDir, "node_modules", dep);
847461
+ if ((0, import_fs27.existsSync)(realPkgPath)) {
847462
+ logger4.debug(`Found ${dep} in .pnpm store at ${realPkgPath}, copying...`);
847463
+ (0, import_fs27.mkdirSync)(import_path58.default.dirname(depPath), { recursive: true });
847464
+ (0, import_fs27.cpSync)(realPkgPath, depPath, { recursive: true });
847465
+ if ((0, import_fs27.existsSync)(depPath)) {
847466
+ logger4.info(`Recovered ${dep} via direct copy from .pnpm store`);
847467
+ continue;
847468
+ }
847469
+ }
847470
+ }
847471
+ } catch (recoverError) {
847472
+ logger4.debug(`Recovery scan for ${dep} failed: ${recoverError}`);
847473
+ }
847480
847474
  }
847475
+ const symlinkEntry = symlinks.find((s9) => s9.path === import_path58.default.join("standalone", "node_modules", dep).replace(/\\/g, "/") || s9.path.endsWith(`/node_modules/${dep}`));
847476
+ if (symlinkEntry != null) {
847477
+ logger4.debug(`${dep} was a symlink: ${symlinkEntry.path} -> ${symlinkEntry.linkname} but resolution failed`);
847478
+ }
847479
+ logger4.error(`${dep} could not be recovered and will be unavailable at runtime`);
847481
847480
  }
847482
847481
  }
847483
847482
  function getLocalStorageFolder() {
@@ -849035,7 +849034,9 @@ ${err.stack}`);
849035
849034
  let serverProcess = null;
849036
849035
  let actualPort = port;
849037
849036
  const startNextJsServer = () => {
849038
- return new Promise((resolve15) => {
849037
+ return new Promise((resolve15, reject) => {
849038
+ let settled = false;
849039
+ let fallbackTimer;
849039
849040
  serverProcess = runExeca(context3.logger, "node", [serverPath], {
849040
849041
  env: env5,
849041
849042
  doNotPipeOutput: true
@@ -849047,7 +849048,11 @@ ${err.stack}`);
849047
849048
  if (portMatch != null) {
849048
849049
  actualPort = Number(portMatch[1]);
849049
849050
  }
849050
- if (output2.includes("Ready in") || output2.includes("\u2713 Ready")) {
849051
+ if (!settled && (output2.includes("Ready in") || output2.includes("\u2713 Ready"))) {
849052
+ settled = true;
849053
+ if (fallbackTimer != null) {
849054
+ clearTimeout(fallbackTimer);
849055
+ }
849051
849056
  resolve15();
849052
849057
  }
849053
849058
  };
@@ -849057,23 +849062,44 @@ ${err.stack}`);
849057
849062
  });
849058
849063
  context3.logger.debug(`Next.js standalone server started with PID: ${serverProcess.pid}`);
849059
849064
  serverProcess.on("error", (err) => {
849060
- context3.logger.debug(`Server process error: ${err.message}`);
849065
+ context3.logger.error(`Server process error: ${err.message}`);
849066
+ if (!settled) {
849067
+ settled = true;
849068
+ if (fallbackTimer != null) {
849069
+ clearTimeout(fallbackTimer);
849070
+ }
849071
+ reject(new Error(`Server process failed to start: ${err.message}`));
849072
+ }
849061
849073
  });
849062
849074
  serverProcess.on("exit", (code5, signal) => {
849063
- if (code5) {
849064
- context3.logger.debug(`Server process exited with code: ${code5}`);
849075
+ if (code5 != null && code5 !== 0) {
849076
+ context3.logger.error(`Server process exited with code: ${code5}`);
849077
+ if (!settled) {
849078
+ settled = true;
849079
+ if (fallbackTimer != null) {
849080
+ clearTimeout(fallbackTimer);
849081
+ }
849082
+ reject(new Error(`Server process exited with code ${code5}. Check the debug logs above for details.`));
849083
+ }
849065
849084
  } else if (signal) {
849066
849085
  context3.logger.debug(`Server process killed with signal: ${signal}`);
849067
849086
  } else {
849068
849087
  context3.logger.debug("Server process exited");
849069
849088
  }
849070
849089
  });
849071
- setTimeout(() => {
849072
- resolve15();
849090
+ fallbackTimer = setTimeout(() => {
849091
+ if (!settled) {
849092
+ settled = true;
849093
+ resolve15();
849094
+ }
849073
849095
  }, 1e4);
849074
849096
  });
849075
849097
  };
849076
- await startNextJsServer();
849098
+ try {
849099
+ await startNextJsServer();
849100
+ } catch (err) {
849101
+ context3.failAndThrow(`Docs preview server failed to start: ${extractErrorMessage(err)}. Run with --log-level debug for more details.`, void 0, { code: CliError.Code.InternalError });
849102
+ }
849077
849103
  watcher.on("all", async (event, targetPath, _targetPathNext) => {
849078
849104
  if (targetPath.includes(".fern/logs/") || targetPath.includes(".fern\\logs\\")) {
849079
849105
  return;
@@ -849193,7 +849219,7 @@ ${err.stack}`);
849193
849219
  process.exit(1);
849194
849220
  });
849195
849221
  process.on("beforeExit", cleanup);
849196
- context3.logger.info(`Docs preview server ready on http://localhost:${port}`);
849222
+ context3.logger.info(`Docs preview server ready on http://localhost:${actualPort}`);
849197
849223
  await new Promise(() => {
849198
849224
  });
849199
849225
  }
@@ -859581,7 +859607,7 @@ var LegacyDocsPublisher = class {
859581
859607
  previewId,
859582
859608
  disableTemplates: void 0,
859583
859609
  skipUpload,
859584
- cliVersion: "5.7.5",
859610
+ cliVersion: "5.7.6-3-gd8ee8ddb229",
859585
859611
  loginCommand: "fern auth login"
859586
859612
  });
859587
859613
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -904911,6 +904937,11 @@ var Expression2 = class extends AstNode8 {
904911
904937
  case "string-literal":
904912
904938
  writer2.write(this.internalExpression.escape ? `"${escapeSwiftStringLiteralContent(this.internalExpression.value)}"` : `"${this.internalExpression.value}"`);
904913
904939
  break;
904940
+ case "raw-multi-line-string-literal":
904941
+ writer2.write(`#"""
904942
+ ${this.internalExpression.value}
904943
+ """#`);
904944
+ break;
904914
904945
  case "number-literal":
904915
904946
  writer2.write(this.internalExpression.value.toString());
904916
904947
  break;
@@ -905059,6 +905090,18 @@ var Expression2 = class extends AstNode8 {
905059
905090
  static escapedStringLiteral(value2) {
905060
905091
  return new this({ type: "string-literal", value: value2, escape: true });
905061
905092
  }
905093
+ /**
905094
+ * Emits `value` as a Swift raw multi-line string literal (`#"""..."""#`).
905095
+ * Inside a raw string literal, escape sequences such as `\n` are NOT
905096
+ * interpreted by the Swift compiler -- they remain as literal
905097
+ * backslash-n characters at runtime. Use this when `value` already
905098
+ * contains escape sequences that must survive verbatim into the
905099
+ * runtime `String` (e.g. JSON payloads where `\n` must reach the
905100
+ * JSON parser as `\n`, not as a real newline).
905101
+ */
905102
+ static rawMultiLineStringLiteral(value2) {
905103
+ return new this({ type: "raw-multi-line-string-literal", value: value2 });
905104
+ }
905062
905105
  static numberLiteral(value2) {
905063
905106
  return new this({ type: "number-literal", value: value2 });
905064
905107
  }
@@ -934006,7 +934049,7 @@ var CliContext = class _CliContext {
934006
934049
  if (false) {
934007
934050
  this.logger.error("CLI_VERSION is not defined");
934008
934051
  }
934009
- return "5.7.5";
934052
+ return "5.7.6-3-gd8ee8ddb229";
934010
934053
  }
934011
934054
  getCliName() {
934012
934055
  if (false) {
@@ -949099,6 +949142,7 @@ async function formatWorkspaces({
949099
949142
  // src/commands/generate/generateDocsWorkspace.ts
949100
949143
  init_lib4();
949101
949144
  init_js();
949145
+ init_lib6();
949102
949146
 
949103
949147
  // src/utils/environment.ts
949104
949148
  function detectCISource() {
@@ -949302,22 +949346,21 @@ ${source_default.yellow("?")} Are you sure you want to continue?`,
949302
949346
  const skippedWorkspacePaths = /* @__PURE__ */ new Set();
949303
949347
  const ossWorkspacesForValidation = await filterOssWorkspaces(project);
949304
949348
  for (const ossWorkspace of ossWorkspacesForValidation) {
949349
+ const apiName = ossWorkspace.workspaceName ?? basename3(ossWorkspace.absoluteFilePath);
949305
949350
  try {
949306
949351
  const violations = await validateOSSWorkspace(ossWorkspace, context3);
949307
949352
  const errors4 = violations.filter((v9) => v9.severity === "fatal" || v9.severity === "error");
949308
949353
  if (errors4.length > 0) {
949309
- for (const error50 of errors4) {
949310
- context3.logger.warn(`${error50.relativeFilepath}: ${error50.message}`);
949311
- }
949312
- context3.logger.warn(
949313
- `Skipping API workspace at ${ossWorkspace.absoluteFilePath} due to ${errors4.length} validation error${errors4.length !== 1 ? "s" : ""}. Run fern check for details.`
949354
+ const reasons = summarizeValidationErrors(errors4);
949355
+ const reasonList = reasons.map((r5) => ` - ${r5}`).join("\n");
949356
+ context3.logger.error(
949357
+ `Skipping API ${apiName} due to ${errors4.length} validation error${errors4.length !== 1 ? "s" : ""}:
949358
+ ${reasonList}`
949314
949359
  );
949315
949360
  skippedWorkspacePaths.add(ossWorkspace.absoluteFilePath);
949316
949361
  }
949317
949362
  } catch (error50) {
949318
- context3.logger.warn(
949319
- `Skipping API workspace at ${ossWorkspace.absoluteFilePath}: ${extractErrorMessage(error50)}`
949320
- );
949363
+ context3.logger.error(`Skipping API ${apiName}: ${extractErrorMessage(error50)}`);
949321
949364
  skippedWorkspacePaths.add(ossWorkspace.absoluteFilePath);
949322
949365
  }
949323
949366
  }
@@ -949357,6 +949400,37 @@ function getExcludeRules(brokenLinks, strictBrokenLinks) {
949357
949400
  }
949358
949401
  return excludeRules;
949359
949402
  }
949403
+ function summarizeValidationErrors(errors4) {
949404
+ const summaries = [];
949405
+ const frontmatterEndpoints = [];
949406
+ const nonAsciiTags = [];
949407
+ const otherErrors = [];
949408
+ for (const error50 of errors4) {
949409
+ if (error50.message.includes("---") && error50.message.includes("frontmatter")) {
949410
+ const methodPathMatch = error50.message.match(/for ((?:GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|TRACE) \S+)/);
949411
+ frontmatterEndpoints.push(methodPathMatch?.[1] ?? error50.nodePath.join("."));
949412
+ } else if (error50.message.includes("non-ASCII")) {
949413
+ const tagMatch = error50.message.match(/Tag name "([^"]+)"/);
949414
+ nonAsciiTags.push(tagMatch?.[1] ?? "unknown");
949415
+ } else {
949416
+ otherErrors.push(error50);
949417
+ }
949418
+ }
949419
+ if (frontmatterEndpoints.length > 0) {
949420
+ summaries.push(
949421
+ `${frontmatterEndpoints.length} endpoint${frontmatterEndpoints.length !== 1 ? "s" : ""} contain "---" frontmatter delimiters that will cause 500 errors on the docs site`
949422
+ );
949423
+ }
949424
+ if (nonAsciiTags.length > 0) {
949425
+ summaries.push(
949426
+ `${nonAsciiTags.length} tag${nonAsciiTags.length !== 1 ? "s" : ""} contain non-ASCII characters: ${nonAsciiTags.join(", ")}`
949427
+ );
949428
+ }
949429
+ for (const error50 of otherErrors) {
949430
+ summaries.push(`${error50.relativeFilepath}: ${error50.message}`);
949431
+ }
949432
+ return summaries;
949433
+ }
949360
949434
 
949361
949435
  // src/commands/generate-dynamic-ir/generateDynamicIrForWorkspaces.ts
949362
949436
  init_lib6();
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.7.5",
2
+ "version": "5.7.6-3-gd8ee8ddb229",
3
3
  "repository": {
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/fern-api/fern.git",