@fern-api/fern-api-dev 5.111.0 → 5.112.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.
Files changed (2) hide show
  1. package/cli.cjs +1031 -236
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -101341,9 +101341,9 @@ var require_graceful_fs = __commonJS({
101341
101341
  }
101342
101342
  }
101343
101343
  var fs$readdir = fs35.readdir;
101344
- fs35.readdir = readdir23;
101344
+ fs35.readdir = readdir24;
101345
101345
  var noReaddirOptionVersions = /^v[0-5]\./;
101346
- function readdir23(path122, options2, cb) {
101346
+ function readdir24(path122, options2, cb) {
101347
101347
  if (typeof options2 === "function")
101348
101348
  cb = options2, options2 = null;
101349
101349
  var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path123, options3, cb2, startTime) {
@@ -200410,6 +200410,13 @@ var init_openapi = __esm({
200410
200410
  }
200411
200411
  });
200412
200412
 
200413
+ // ../../commons/api-workspace-commons/lib/RawSpecs.js
200414
+ var init_RawSpecs = __esm({
200415
+ "../../commons/api-workspace-commons/lib/RawSpecs.js"() {
200416
+ "use strict";
200417
+ }
200418
+ });
200419
+
200413
200420
  // ../../commons/api-workspace-commons/lib/Source.js
200414
200421
  var init_Source5 = __esm({
200415
200422
  "../../commons/api-workspace-commons/lib/Source.js"() {
@@ -200568,6 +200575,7 @@ var init_lib17 = __esm({
200568
200575
  init_getFilesystemPublishTarget();
200569
200576
  init_getOriginGitCommit();
200570
200577
  init_openapi();
200578
+ init_RawSpecs();
200571
200579
  init_Source5();
200572
200580
  init_Spec();
200573
200581
  init_utils11();
@@ -374265,6 +374273,7 @@ var init_OSSWorkspace = __esm({
374265
374273
  init_lib31();
374266
374274
  init_lib21();
374267
374275
  init_lib12();
374276
+ init_lib20();
374268
374277
  init_lib4();
374269
374278
  init_lib8();
374270
374279
  init_lib9();
@@ -374666,6 +374675,13 @@ var init_OSSWorkspace = __esm({
374666
374675
  sources: this.sources
374667
374676
  });
374668
374677
  }
374678
+ async getAllSpecsForGenerator(specsOverride) {
374679
+ if (specsOverride == null) {
374680
+ return this.allSpecs;
374681
+ }
374682
+ const overrideSpecs = await this.convertSpecsOverrideToSpecs(specsOverride);
374683
+ return overrideSpecs.filter((spec) => spec.type !== "protobuf" || !spec.fromOpenAPI);
374684
+ }
374669
374685
  async createWorkspaceWithSpecsOverride({ context: context3 }, specsOverride, settings) {
374670
374686
  const overrideSpecs = await this.convertSpecsOverrideToSpecs(specsOverride);
374671
374687
  const overrideAllSpecs = overrideSpecs.filter((spec) => spec.type !== "protobuf" || !spec.fromOpenAPI);
@@ -374724,8 +374740,9 @@ var init_OSSWorkspace = __esm({
374724
374740
  absoluteFilepath,
374725
374741
  absoluteFilepathToOverrides,
374726
374742
  absoluteFilepathToOverlays,
374727
- // Use default settings from existing specs for compatibility
374728
- settings: this.specs.length > 0 ? this.specs[0]?.settings : void 0,
374743
+ settings: getOpenAPISettings({
374744
+ options: mergeSettings(this.generatorsConfiguration?.api?.settings ?? parseOpenApiDefinitionSettingsSchema(void 0), parseOpenApiDefinitionSettingsSchema(spec.settings))
374745
+ }),
374729
374746
  source: {
374730
374747
  type: "openapi",
374731
374748
  file: absoluteFilepath
@@ -494571,9 +494588,9 @@ var require_graceful_fs2 = __commonJS({
494571
494588
  }
494572
494589
  }
494573
494590
  var fs$readdir = fs35.readdir;
494574
- fs35.readdir = readdir23;
494591
+ fs35.readdir = readdir24;
494575
494592
  var noReaddirOptionVersions = /^v[0-5]\./;
494576
- function readdir23(path122, options2, cb) {
494593
+ function readdir24(path122, options2, cb) {
494577
494594
  if (typeof options2 === "function")
494578
494595
  cb = options2, options2 = null;
494579
494596
  var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path123, options3, cb2, startTime) {
@@ -503426,10 +503443,10 @@ var require_make_dir = __commonJS({
503426
503443
  module4.exports = (input3, opts) => Promise.resolve().then(() => {
503427
503444
  checkPath(input3);
503428
503445
  opts = Object.assign({}, defaults3, opts);
503429
- const mkdir49 = pify(opts.fs.mkdir);
503446
+ const mkdir50 = pify(opts.fs.mkdir);
503430
503447
  const stat8 = pify(opts.fs.stat);
503431
503448
  const make = (pth) => {
503432
- return mkdir49(pth, opts.mode).then(() => pth).catch((err) => {
503449
+ return mkdir50(pth, opts.mode).then(() => pth).catch((err) => {
503433
503450
  if (err.code === "ENOENT") {
503434
503451
  if (err.message.includes("null bytes") || path122.dirname(pth) === pth) {
503435
503452
  throw err;
@@ -637453,14 +637470,14 @@ var require_empty2 = __commonJS({
637453
637470
  var u5 = require_universalify().fromPromise;
637454
637471
  var fs34 = require_fs();
637455
637472
  var path122 = require("path");
637456
- var mkdir49 = require_mkdirs();
637473
+ var mkdir50 = require_mkdirs();
637457
637474
  var remove3 = require_remove3();
637458
637475
  var emptyDir = u5(async function emptyDir2(dir) {
637459
637476
  let items;
637460
637477
  try {
637461
637478
  items = await fs34.readdir(dir);
637462
637479
  } catch {
637463
- return mkdir49.mkdirs(dir);
637480
+ return mkdir50.mkdirs(dir);
637464
637481
  }
637465
637482
  return Promise.all(items.map((item) => remove3.remove(path122.join(dir, item))));
637466
637483
  });
@@ -637469,7 +637486,7 @@ var require_empty2 = __commonJS({
637469
637486
  try {
637470
637487
  items = fs34.readdirSync(dir);
637471
637488
  } catch {
637472
- return mkdir49.mkdirsSync(dir);
637489
+ return mkdir50.mkdirsSync(dir);
637473
637490
  }
637474
637491
  items.forEach((item) => {
637475
637492
  item = path122.join(dir, item);
@@ -637492,7 +637509,7 @@ var require_file2 = __commonJS({
637492
637509
  var u5 = require_universalify().fromPromise;
637493
637510
  var path122 = require("path");
637494
637511
  var fs34 = require_fs();
637495
- var mkdir49 = require_mkdirs();
637512
+ var mkdir50 = require_mkdirs();
637496
637513
  async function createFile(file4) {
637497
637514
  let stats;
637498
637515
  try {
@@ -637506,7 +637523,7 @@ var require_file2 = __commonJS({
637506
637523
  dirStats = await fs34.stat(dir);
637507
637524
  } catch (err) {
637508
637525
  if (err.code === "ENOENT") {
637509
- await mkdir49.mkdirs(dir);
637526
+ await mkdir50.mkdirs(dir);
637510
637527
  await fs34.writeFile(file4, "");
637511
637528
  return;
637512
637529
  } else {
@@ -637532,7 +637549,7 @@ var require_file2 = __commonJS({
637532
637549
  fs34.readdirSync(dir);
637533
637550
  }
637534
637551
  } catch (err) {
637535
- if (err && err.code === "ENOENT") mkdir49.mkdirsSync(dir);
637552
+ if (err && err.code === "ENOENT") mkdir50.mkdirsSync(dir);
637536
637553
  else throw err;
637537
637554
  }
637538
637555
  fs34.writeFileSync(file4, "");
@@ -637551,7 +637568,7 @@ var require_link = __commonJS({
637551
637568
  var u5 = require_universalify().fromPromise;
637552
637569
  var path122 = require("path");
637553
637570
  var fs34 = require_fs();
637554
- var mkdir49 = require_mkdirs();
637571
+ var mkdir50 = require_mkdirs();
637555
637572
  var { pathExists: pathExists2 } = require_path_exists();
637556
637573
  var { areIdentical } = require_stat();
637557
637574
  async function createLink(srcpath, dstpath) {
@@ -637571,7 +637588,7 @@ var require_link = __commonJS({
637571
637588
  const dir = path122.dirname(dstpath);
637572
637589
  const dirExists = await pathExists2(dir);
637573
637590
  if (!dirExists) {
637574
- await mkdir49.mkdirs(dir);
637591
+ await mkdir50.mkdirs(dir);
637575
637592
  }
637576
637593
  await fs34.link(srcpath, dstpath);
637577
637594
  }
@@ -637591,7 +637608,7 @@ var require_link = __commonJS({
637591
637608
  const dir = path122.dirname(dstpath);
637592
637609
  const dirExists = fs34.existsSync(dir);
637593
637610
  if (dirExists) return fs34.linkSync(srcpath, dstpath);
637594
- mkdir49.mkdirsSync(dir);
637611
+ mkdir50.mkdirsSync(dir);
637595
637612
  return fs34.linkSync(srcpath, dstpath);
637596
637613
  }
637597
637614
  module4.exports = {
@@ -637927,19 +637944,19 @@ var require_output_file = __commonJS({
637927
637944
  var u5 = require_universalify().fromPromise;
637928
637945
  var fs34 = require_fs();
637929
637946
  var path122 = require("path");
637930
- var mkdir49 = require_mkdirs();
637947
+ var mkdir50 = require_mkdirs();
637931
637948
  var pathExists2 = require_path_exists().pathExists;
637932
637949
  async function outputFile(file4, data2, encoding = "utf-8") {
637933
637950
  const dir = path122.dirname(file4);
637934
637951
  if (!await pathExists2(dir)) {
637935
- await mkdir49.mkdirs(dir);
637952
+ await mkdir50.mkdirs(dir);
637936
637953
  }
637937
637954
  return fs34.writeFile(file4, data2, encoding);
637938
637955
  }
637939
637956
  function outputFileSync(file4, ...args) {
637940
637957
  const dir = path122.dirname(file4);
637941
637958
  if (!fs34.existsSync(dir)) {
637942
- mkdir49.mkdirsSync(dir);
637959
+ mkdir50.mkdirsSync(dir);
637943
637960
  }
637944
637961
  fs34.writeFileSync(file4, ...args);
637945
637962
  }
@@ -705504,7 +705521,7 @@ var AccessTokenPosthogManager = class {
705504
705521
  properties: {
705505
705522
  ...event,
705506
705523
  ...event.properties,
705507
- version: "5.111.0",
705524
+ version: "5.112.0",
705508
705525
  usingAccessToken: true,
705509
705526
  ...getRunIdProperties()
705510
705527
  }
@@ -705570,7 +705587,7 @@ var UserPosthogManager = class {
705570
705587
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
705571
705588
  event: "CLI",
705572
705589
  properties: {
705573
- version: "5.111.0",
705590
+ version: "5.112.0",
705574
705591
  ...event,
705575
705592
  ...event.properties,
705576
705593
  usingAccessToken: false,
@@ -887246,7 +887263,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
887246
887263
  var LOGS_FOLDER_NAME = "logs";
887247
887264
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
887248
887265
  function getCliSource() {
887249
- const version7 = "5.111.0";
887266
+ const version7 = "5.112.0";
887250
887267
  return `cli@${version7}`;
887251
887268
  }
887252
887269
  var DebugLogger = class {
@@ -908903,6 +908920,28 @@ function getGeneratorLanguage(generatorId) {
908903
908920
  return getGeneratorPolicy(generatorId)?.language;
908904
908921
  }
908905
908922
  function validateGeneratorConfigCompatibility(input3) {
908923
+ const route = selectGeneratorConfigRoute(input3);
908924
+ const receivedConfigKind = input3.configKind;
908925
+ if (!isGenerationConfigKind(receivedConfigKind)) {
908926
+ throw compatibilityError(input3, {
908927
+ code: "INVALID_CONFIG_KIND",
908928
+ message: "Configuration kind must be legacy-fern or sdk-config-v1",
908929
+ cutoverVersion: route.cutoverVersion,
908930
+ expectedLanguage: route.language,
908931
+ expectedConfigKind: route.configKind,
908932
+ recommendedAction: "USE_SUPPORTED_CONFIG_KIND"
908933
+ }, receivedConfigKind);
908934
+ }
908935
+ if (receivedConfigKind !== route.configKind) {
908936
+ const policy = getGeneratorPolicy(input3.generatorId);
908937
+ if (policy === void 0) {
908938
+ throw new Error(`Missing validated generator policy for ${input3.generatorId}`);
908939
+ }
908940
+ throw configKindError(input3, policy, route.configKind, receivedConfigKind);
908941
+ }
908942
+ return route;
908943
+ }
908944
+ function selectGeneratorConfigRoute(input3) {
908906
908945
  const policy = getGeneratorPolicy(input3.generatorId);
908907
908946
  if (policy === void 0) {
908908
908947
  throw compatibilityError(input3, {
@@ -908937,27 +908976,13 @@ function validateGeneratorConfigCompatibility(input3) {
908937
908976
  }
908938
908977
  const isBeforeCutover = compareSemver(requestedVersion, policy.parsedCutoverVersion) < 0;
908939
908978
  const expectedConfigKind = isBeforeCutover ? "legacy-fern" : "sdk-config-v1";
908940
- const receivedConfigKind = input3.configKind;
908941
- if (!isGenerationConfigKind(receivedConfigKind)) {
908942
- throw compatibilityError(input3, {
908943
- code: "INVALID_CONFIG_KIND",
908944
- message: "Configuration kind must be legacy-fern or sdk-config-v1",
908945
- cutoverVersion: policy.cutoverVersion,
908946
- expectedLanguage: policy.language,
908947
- expectedConfigKind,
908948
- recommendedAction: "USE_SUPPORTED_CONFIG_KIND"
908949
- }, receivedConfigKind);
908950
- }
908951
- if (receivedConfigKind !== expectedConfigKind) {
908952
- throw configKindError(input3, policy, expectedConfigKind, receivedConfigKind);
908953
- }
908954
908979
  return {
908955
908980
  generatorId: input3.generatorId,
908956
908981
  language: policy.language,
908957
908982
  requestedVersion: input3.requestedVersion,
908958
908983
  cutoverVersion: policy.cutoverVersion,
908959
- configKind: receivedConfigKind,
908960
- payloadKind: isBeforeCutover ? "fern-runtime-bundle" : "sdk-config-ir-v1"
908984
+ configKind: expectedConfigKind,
908985
+ payloadKind: isBeforeCutover ? "fern-runtime-bundle" : "sdk-config-v1"
908961
908986
  };
908962
908987
  }
908963
908988
  function compatibilityError(input3, details, receivedConfigKind = input3.configKind) {
@@ -908988,13 +909013,15 @@ function isGenerationConfigKind(value2) {
908988
909013
  var POLL_INTERVAL_MS2 = 2e3;
908989
909014
  var POLL_TIMEOUT_MS2 = 15 * 60 * 1e3;
908990
909015
  var REQUEST_TIMEOUT_MS = 6e4;
908991
- var MAX_BUNDLES = 64;
909016
+ var MAX_PAYLOADS = 64;
908992
909017
  var MAX_SOURCE_COMPRESSED_BYTES = 25 * 1024 * 1024;
908993
909018
  var MAX_SOURCE_DECOMPRESSED_BYTES = 25 * 1024 * 1024;
908994
- var MAX_BUNDLE_COMPRESSED_BYTES = 5 * 1024 * 1024;
908995
- var MAX_BUNDLE_DECOMPRESSED_BYTES = 25 * 1024 * 1024;
908996
- var MAX_TOTAL_BUNDLE_COMPRESSED_BYTES = 25 * 1024 * 1024;
908997
- var MAX_TOTAL_BUNDLE_DECOMPRESSED_BYTES = 100 * 1024 * 1024;
909019
+ var MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES = 5 * 1024 * 1024;
909020
+ var MAX_PAYLOAD_BYTES = 25 * 1024 * 1024;
909021
+ var MAX_TOTAL_RUNTIME_BUNDLE_COMPRESSED_BYTES = 25 * 1024 * 1024;
909022
+ var MAX_TOTAL_PAYLOAD_BYTES = 100 * 1024 * 1024;
909023
+ var MAX_TOTAL_UPLOAD_FILE_BYTES = 50 * 1024 * 1024;
909024
+ var MAX_REQUEST_FIELD_BYTES = 1024 * 1024;
908998
909025
  var MAX_MULTIPART_BODY_BYTES = 60 * 1024 * 1024;
908999
909026
  var LOOPBACK_HOSTNAMES2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
909000
909027
  var TARGET_ID_SEED_COLLATOR = new Intl.Collator("en", { numeric: true });
@@ -909025,6 +909052,18 @@ function getFernSdkGenApiOrigin() {
909025
909052
  function getFernSdkGenApiLanguage(generatorName) {
909026
909053
  return getGeneratorLanguage(generatorName);
909027
909054
  }
909055
+ function selectFernSdkGenApiRoute(generatorInvocation) {
909056
+ const language = getFernSdkGenApiLanguage(generatorInvocation.name);
909057
+ if (language == null) {
909058
+ return void 0;
909059
+ }
909060
+ return validateGeneratorConfigCompatibility({
909061
+ generatorId: generatorInvocation.name,
909062
+ language: generatorInvocation.language ?? language,
909063
+ requestedVersion: generatorInvocation.version,
909064
+ configKind: "legacy-fern"
909065
+ });
909066
+ }
909028
909067
  function mapFernSdkGenApiOutput(generatorInvocation) {
909029
909068
  const outputMode = generatorInvocation.outputMode;
909030
909069
  switch (outputMode.type) {
@@ -909226,6 +909265,7 @@ function isEligibleForFernSdkGenApi(candidate) {
909226
909265
  var FernSdkGenApiBatch = class {
909227
909266
  expectedTargets;
909228
909267
  participants = [];
909268
+ removedTargetIds = /* @__PURE__ */ new Set();
909229
909269
  terminalError;
909230
909270
  dispatched = false;
909231
909271
  constructor(expectedTargets) {
@@ -909238,6 +909278,9 @@ var FernSdkGenApiBatch = class {
909238
909278
  if (this.terminalError != null) {
909239
909279
  return Promise.reject(this.terminalError);
909240
909280
  }
909281
+ if (parameters2.targetIdSeed != null && this.removedTargetIds.has(parameters2.targetIdSeed)) {
909282
+ return Promise.reject(new Error(`Fern sdk-gen-api target ${parameters2.targetIdSeed} was removed`));
909283
+ }
909241
909284
  if (this.dispatched) {
909242
909285
  return Promise.reject(new Error("The Fern sdk-gen-api batch was already dispatched"));
909243
909286
  }
@@ -909254,6 +909297,22 @@ var FernSdkGenApiBatch = class {
909254
909297
  this.expectedTargets -= 1;
909255
909298
  this.dispatchIfReady();
909256
909299
  }
909300
+ /** Removes one failed automation target while preserving undispatched siblings. */
909301
+ remove(targetIdSeed, error50) {
909302
+ if (this.dispatched || this.terminalError != null) {
909303
+ return false;
909304
+ }
909305
+ if (this.removedTargetIds.has(targetIdSeed)) {
909306
+ return false;
909307
+ }
909308
+ this.removedTargetIds.add(targetIdSeed);
909309
+ const participantIndex = this.participants.findIndex((participant2) => participant2.targetIdSeed === targetIdSeed);
909310
+ const [participant] = participantIndex >= 0 ? this.participants.splice(participantIndex, 1) : [];
909311
+ participant?.reject(error50);
909312
+ this.expectedTargets -= 1;
909313
+ this.dispatchIfReady();
909314
+ return true;
909315
+ }
909257
909316
  /** Prevents siblings waiting at the batch barrier from hanging if preparation of one fails. */
909258
909317
  cancel(error50) {
909259
909318
  if (this.dispatched || this.terminalError != null) {
@@ -909265,7 +909324,7 @@ var FernSdkGenApiBatch = class {
909265
909324
  }
909266
909325
  }
909267
909326
  dispatchIfReady() {
909268
- if (this.dispatched || this.terminalError != null || this.participants.length !== this.expectedTargets) {
909327
+ if (this.dispatched || this.terminalError != null || this.expectedTargets === 0 || this.participants.length !== this.expectedTargets) {
909269
909328
  return;
909270
909329
  }
909271
909330
  this.dispatched = true;
@@ -909291,6 +909350,72 @@ var FernSdkGenApiBatch = class {
909291
909350
  }
909292
909351
  }
909293
909352
  };
909353
+ var FernSdkGenApiPreparationBatch = class {
909354
+ expectedTargetIds;
909355
+ settledTargetIds = /* @__PURE__ */ new Set();
909356
+ waiters = [];
909357
+ preflightParticipants = [];
909358
+ terminalError;
909359
+ didRunPreflight = false;
909360
+ constructor(targetIds) {
909361
+ this.expectedTargetIds = new Set(targetIds);
909362
+ if (this.expectedTargetIds.size !== targetIds.length) {
909363
+ throw new Error("Fern sdk-gen-api preparation target IDs must be unique");
909364
+ }
909365
+ }
909366
+ ready(targetId, preflightParameters) {
909367
+ this.assertExpected(targetId);
909368
+ if (this.settledTargetIds.has(targetId)) {
909369
+ throw new Error(`Fern sdk-gen-api target ${targetId} prepared more than once`);
909370
+ }
909371
+ this.settledTargetIds.add(targetId);
909372
+ if (preflightParameters != null) {
909373
+ this.preflightParticipants.push(preflightParameters);
909374
+ }
909375
+ return new Promise((resolve15, reject) => {
909376
+ this.waiters.push({ resolve: resolve15, reject });
909377
+ this.finishIfSettled();
909378
+ });
909379
+ }
909380
+ /** Returns true only when this call newly settles a target that failed before preparation. */
909381
+ fail(targetId, error50, isolateFailure) {
909382
+ this.assertExpected(targetId);
909383
+ if (this.settledTargetIds.has(targetId)) {
909384
+ return false;
909385
+ }
909386
+ this.settledTargetIds.add(targetId);
909387
+ if (!isolateFailure) {
909388
+ this.terminalError = error50;
909389
+ }
909390
+ this.finishIfSettled();
909391
+ return true;
909392
+ }
909393
+ assertExpected(targetId) {
909394
+ if (!this.expectedTargetIds.has(targetId)) {
909395
+ throw new Error(`Unexpected Fern sdk-gen-api preparation target ${targetId}`);
909396
+ }
909397
+ }
909398
+ finishIfSettled() {
909399
+ if (this.settledTargetIds.size !== this.expectedTargetIds.size) {
909400
+ return;
909401
+ }
909402
+ if (!this.didRunPreflight && this.terminalError == null && this.preflightParticipants.length > 0) {
909403
+ this.didRunPreflight = true;
909404
+ try {
909405
+ prepareFernSdkGenApiSubmission(this.preflightParticipants);
909406
+ } catch (error50) {
909407
+ this.terminalError = error50;
909408
+ }
909409
+ }
909410
+ for (const waiter of this.waiters) {
909411
+ if (this.terminalError != null) {
909412
+ waiter.reject(this.terminalError);
909413
+ } else {
909414
+ waiter.resolve();
909415
+ }
909416
+ }
909417
+ }
909418
+ };
909294
909419
  async function runFernSdkGenApiBuild(parameters2) {
909295
909420
  const [result] = await executeFernSdkGenApiBuild([parameters2]);
909296
909421
  if (result?.status === "fulfilled") {
@@ -909298,7 +909423,12 @@ async function runFernSdkGenApiBuild(parameters2) {
909298
909423
  }
909299
909424
  throw result?.reason ?? new Error("sdk-gen-api did not return the requested target");
909300
909425
  }
909301
- async function executeFernSdkGenApiBuild(participants) {
909426
+ function validateFernSdkGenApiTargetCount(targetCount) {
909427
+ if (targetCount > MAX_PAYLOADS) {
909428
+ throw new Error(`sdk-gen-api supports at most ${MAX_PAYLOADS} target payloads per build; received ${targetCount}`);
909429
+ }
909430
+ }
909431
+ function prepareFernSdkGenApiSubmission(participants) {
909302
909432
  const first3 = participants[0];
909303
909433
  if (first3 == null) {
909304
909434
  throw new Error("Cannot submit an empty Fern sdk-gen-api build");
@@ -909325,13 +909455,20 @@ async function executeFernSdkGenApiBuild(participants) {
909325
909455
  targets: participants.map((participant) => ({
909326
909456
  generatorInvocation: participant.generatorInvocation,
909327
909457
  sdkVersion: participant.sdkVersion,
909458
+ apiVersion: participant.apiVersion,
909328
909459
  targetIdSeed: participant.targetIdSeed,
909460
+ sourceSpecIndexes: participant.sourceSpecIndexes,
909329
909461
  audiences: participant.audiences,
909330
- runtimeBundle: participant.runtimeBundle
909462
+ payload: participant.payload
909331
909463
  }))
909332
909464
  });
909465
+ const serializedRequest = JSON.stringify(request7);
909466
+ const serializedRequestBytes = Buffer.byteLength(serializedRequest, "utf8");
909467
+ if (serializedRequestBytes > MAX_REQUEST_FIELD_BYTES) {
909468
+ return first3.context.failAndThrow(`sdk-gen-api serialized request field is ${formatMiB(serializedRequestBytes)}, exceeding the 1 MiB UTF-8 field limit; reduce generator customConfig, readme, settings, or API override metadata`, void 0, { code: CliError.Code.ConfigError });
909469
+ }
909333
909470
  const form = new import_form_data4.default();
909334
- form.append("request", JSON.stringify(request7));
909471
+ form.append("request", serializedRequest);
909335
909472
  form.append("sources", first3.specsTarGzBuffer, {
909336
909473
  filename: "specs.tar.gz",
909337
909474
  contentType: "application/gzip"
@@ -909339,17 +909476,22 @@ async function executeFernSdkGenApiBuild(participants) {
909339
909476
  participants.forEach((participant, index3) => {
909340
909477
  const target = request7.targets[index3];
909341
909478
  if (target == null) {
909342
- throw new Error(`Cannot pair sdk-gen-api runtime bundle at index ${index3} with a target`);
909479
+ throw new Error(`Cannot pair sdk-gen-api payload at index ${index3} with a target`);
909343
909480
  }
909344
- form.append("bundles", participant.runtimeBundle, {
909345
- filename: `${target.targetId}.json.gz`,
909346
- contentType: "application/gzip"
909481
+ const isRuntimeBundle = participant.payload.payloadKind === "fern-runtime-bundle";
909482
+ form.append("payloads", participant.payload.body, {
909483
+ filename: `${target.targetId}.json${isRuntimeBundle ? ".gz" : ""}`,
909484
+ contentType: isRuntimeBundle ? "application/gzip" : "application/json"
909347
909485
  });
909348
909486
  });
909349
909487
  const multipartBodyLength = form.getLengthSync();
909350
909488
  if (multipartBodyLength > MAX_MULTIPART_BODY_BYTES) {
909351
- return first3.context.failAndThrow(`sdk-gen-api multipart request is ${formatMiB(multipartBodyLength)}, exceeding the 60 MiB limit; reduce source or target bundle size`, void 0, { code: CliError.Code.ConfigError });
909489
+ return first3.context.failAndThrow(`sdk-gen-api multipart request is ${formatMiB(multipartBodyLength)}, exceeding the 60 MiB limit; reduce source or target payload size`, void 0, { code: CliError.Code.ConfigError });
909352
909490
  }
909491
+ return { first: first3, origin: origin2, request: request7, form };
909492
+ }
909493
+ async function executeFernSdkGenApiBuild(participants) {
909494
+ const { first: first3, origin: origin2, request: request7, form } = prepareFernSdkGenApiSubmission(participants);
909353
909495
  let buildId;
909354
909496
  try {
909355
909497
  const response = await axios_default.post(`${origin2}/v1/fern/build`, form, {
@@ -909427,7 +909569,7 @@ function assertGeneratorConfigCompatibility(participants) {
909427
909569
  generatorId: generatorInvocation.name,
909428
909570
  language,
909429
909571
  requestedVersion: generatorInvocation.version,
909430
- configKind: "legacy-fern"
909572
+ configKind: participant.payload.payloadKind === "fern-runtime-bundle" ? "legacy-fern" : "sdk-config-v1"
909431
909573
  });
909432
909574
  } catch (error50) {
909433
909575
  if (!(error50 instanceof GeneratorConfigCompatibilityError)) {
@@ -909452,8 +909594,8 @@ function formatGeneratorConfigCompatibilityError(error50) {
909452
909594
  `retryable=${error50.retryable}`,
909453
909595
  `recommendedAction=${error50.recommendedAction}`
909454
909596
  ].join("; ");
909455
- const remediation = error50.code === "SDK_CONFIG_V1_REQUIRED" ? " Run `fern sdk-config migrate` to create SDK Config v1 for this target." : "";
909456
- return `Cannot submit SDK generation to sdk-gen-api: ${error50.message} [${diagnostic}].${remediation}`;
909597
+ const migrationHint = error50.recommendedAction === "USE_SDK_CONFIG_V1" ? " Run `fern sdk migrate --output <path>` to migrate this SDK configuration before using this generator version." : "";
909598
+ return `Cannot submit SDK generation to sdk-gen-api: ${error50.message} [${diagnostic}].${migrationHint}`;
909457
909599
  }
909458
909600
  function compareFernSdkGenApiParticipants(left3, right3) {
909459
909601
  const seedComparison = TARGET_ID_SEED_COLLATOR.compare(left3.targetIdSeed ?? "", right3.targetIdSeed ?? "");
@@ -909471,20 +909613,25 @@ function compareFernSdkGenApiParticipants(left3, right3) {
909471
909613
  return left3.sdkVersion.localeCompare(right3.sdkVersion);
909472
909614
  }
909473
909615
  function validateProtocolInputs(participants, first3) {
909474
- if (participants.length > MAX_BUNDLES) {
909475
- first3.context.failAndThrow(`sdk-gen-api supports at most ${MAX_BUNDLES} runtime bundles per build; received ${participants.length}`, void 0, { code: CliError.Code.ConfigError });
909616
+ if (participants.length > MAX_PAYLOADS) {
909617
+ first3.context.failAndThrow(`sdk-gen-api supports at most ${MAX_PAYLOADS} target payloads per build; received ${participants.length}`, void 0, { code: CliError.Code.ConfigError });
909476
909618
  }
909477
909619
  if (first3.specsTarGzBuffer.length > MAX_SOURCE_COMPRESSED_BYTES) {
909478
909620
  first3.context.failAndThrow(`sdk-gen-api source archive is ${formatMiB(first3.specsTarGzBuffer.length)}, exceeding the 25 MiB compressed limit`, void 0, { code: CliError.Code.ConfigError });
909479
909621
  }
909480
- const oversizedBundleIndex = participants.findIndex((participant) => participant.runtimeBundle.length > MAX_BUNDLE_COMPRESSED_BYTES);
909481
- if (oversizedBundleIndex >= 0) {
909482
- const participant = participants[oversizedBundleIndex];
909483
- first3.context.failAndThrow(`sdk-gen-api runtime bundle ${participant?.targetIdSeed ?? oversizedBundleIndex.toString()} is ${formatMiB(participant?.runtimeBundle.length ?? 0)}, exceeding the 5 MiB compressed limit`, void 0, { code: CliError.Code.ConfigError });
909622
+ const oversizedPayloadIndex = participants.findIndex((participant) => participant.payload.body.length > (participant.payload.payloadKind === "fern-runtime-bundle" ? MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES : MAX_PAYLOAD_BYTES));
909623
+ if (oversizedPayloadIndex >= 0) {
909624
+ const participant = participants[oversizedPayloadIndex];
909625
+ const maxBytes = participant?.payload.payloadKind === "fern-runtime-bundle" ? MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES : MAX_PAYLOAD_BYTES;
909626
+ first3.context.failAndThrow(`sdk-gen-api ${payloadLabel(participant, oversizedPayloadIndex)} is ${formatMiB(participant?.payload.body.length ?? 0)}, exceeding the ${formatMiB(maxBytes)} upload limit`, void 0, { code: CliError.Code.ConfigError });
909484
909627
  }
909485
- const totalBundleBytes = participants.reduce((total, participant) => total + participant.runtimeBundle.length, 0);
909486
- if (totalBundleBytes > MAX_TOTAL_BUNDLE_COMPRESSED_BYTES) {
909487
- first3.context.failAndThrow(`sdk-gen-api runtime bundles total ${formatMiB(totalBundleBytes)}, exceeding the 25 MiB compressed limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909628
+ const totalUploadFileBytes = participants.reduce((total, participant) => total + participant.payload.body.length, first3.specsTarGzBuffer.length);
909629
+ if (totalUploadFileBytes > MAX_TOTAL_UPLOAD_FILE_BYTES) {
909630
+ first3.context.failAndThrow(`sdk-gen-api source archive and target payloads total ${formatMiB(totalUploadFileBytes)}, exceeding the 50 MiB in-memory upload limit; reduce the source archive size, target payload size, or number of targets`, void 0, { code: CliError.Code.ConfigError });
909631
+ }
909632
+ const totalRuntimeBundleBytes = participants.reduce((total, participant) => participant.payload.payloadKind === "fern-runtime-bundle" ? total + participant.payload.body.length : total, 0);
909633
+ if (totalRuntimeBundleBytes > MAX_TOTAL_RUNTIME_BUNDLE_COMPRESSED_BYTES) {
909634
+ first3.context.failAndThrow(`sdk-gen-api runtime bundles total ${formatMiB(totalRuntimeBundleBytes)}, exceeding the 25 MiB compressed limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909488
909635
  }
909489
909636
  getBoundedGzipSize({
909490
909637
  buffer: first3.specsTarGzBuffer,
@@ -909492,19 +909639,23 @@ function validateProtocolInputs(participants, first3) {
909492
909639
  label: "source archive",
909493
909640
  context: first3.context
909494
909641
  });
909495
- let totalDecompressedBundleBytes = 0;
909642
+ let totalPayloadBytes = 0;
909496
909643
  for (const [index3, participant] of participants.entries()) {
909497
- totalDecompressedBundleBytes += getBoundedGzipSize({
909498
- buffer: participant.runtimeBundle,
909499
- maxBytes: MAX_BUNDLE_DECOMPRESSED_BYTES,
909500
- label: `runtime bundle ${participant.targetIdSeed ?? index3.toString()}`,
909644
+ totalPayloadBytes += participant.payload.payloadKind === "fern-runtime-bundle" ? getBoundedGzipSize({
909645
+ buffer: participant.payload.body,
909646
+ maxBytes: MAX_PAYLOAD_BYTES,
909647
+ label: payloadLabel(participant, index3),
909501
909648
  context: first3.context
909502
- });
909503
- if (totalDecompressedBundleBytes > MAX_TOTAL_BUNDLE_DECOMPRESSED_BYTES) {
909504
- first3.context.failAndThrow(`sdk-gen-api runtime bundles total ${formatMiB(totalDecompressedBundleBytes)} decompressed, exceeding the 100 MiB decompressed limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909649
+ }) : participant.payload.body.length;
909650
+ if (totalPayloadBytes > MAX_TOTAL_PAYLOAD_BYTES) {
909651
+ first3.context.failAndThrow(`sdk-gen-api target payloads total ${formatMiB(totalPayloadBytes)}, exceeding the 100 MiB decoded limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909505
909652
  }
909506
909653
  }
909507
909654
  }
909655
+ function payloadLabel(participant, index3) {
909656
+ const kind = participant?.payload.payloadKind ?? "target payload";
909657
+ return `${kind} ${participant?.targetIdSeed ?? index3.toString()}`;
909658
+ }
909508
909659
  function getBoundedGzipSize({ buffer, maxBytes, label, context: context3 }) {
909509
909660
  let decompressed;
909510
909661
  try {
@@ -909587,23 +909738,41 @@ function createFernSdkGenApiBatchRequest({ apiName, organization, cliVersion, sp
909587
909738
  if (targets2.length === 0) {
909588
909739
  throw new Error("Cannot create an empty Fern sdk-gen-api request");
909589
909740
  }
909590
- const requestTargets = targets2.map(({ generatorInvocation, sdkVersion, targetIdSeed, audiences }, index3) => {
909741
+ const apiInputs = [];
909742
+ const apiInputIds = targets2.map(({ targetIdSeed, sourceSpecIndexes }, index3) => {
909743
+ if (sourceSpecIndexes == null) {
909744
+ if (!apiInputs.some((input3) => input3.id === "default")) {
909745
+ apiInputs.push({ id: "default", specIndexes: "all" });
909746
+ }
909747
+ return "default";
909748
+ }
909749
+ const id = `target-${targetIdSeed ?? index3.toString()}`;
909750
+ apiInputs.push({ id, specIndexes: sourceSpecIndexes });
909751
+ return id;
909752
+ });
909753
+ const requestTargets = targets2.map(({ generatorInvocation, sdkVersion, apiVersion, targetIdSeed, audiences, payload }, index3) => {
909591
909754
  const language = getFernSdkGenApiLanguage(generatorInvocation.name);
909592
909755
  if (language == null) {
909593
909756
  throw new Error(`Unsupported Fern SDK generator: ${generatorInvocation.name}`);
909594
909757
  }
909595
909758
  const output2 = mapFernSdkGenApiOutput(generatorInvocation);
909759
+ const packageConfig = payload.package ?? output2.package;
909596
909760
  const targetId = (0, import_crypto10.createHash)("sha256").update(`${apiName}:${generatorInvocation.name}:${generatorInvocation.version}:${targetIdSeed ?? index3.toString()}`).digest("hex").slice(0, 20);
909597
909761
  return {
909598
909762
  targetId,
909599
- apiInputId: "default",
909763
+ apiInputId: apiInputIds[index3] ?? "default",
909600
909764
  language,
909601
- sdk: { name: apiName, version: sdkVersion },
909765
+ sdk: {
909766
+ name: apiName,
909767
+ version: sdkVersion,
909768
+ ...apiVersion != null ? { apiVersion } : {}
909769
+ },
909602
909770
  fernGenerator: {
909603
909771
  id: generatorInvocation.name,
909604
909772
  version: generatorInvocation.version
909605
909773
  },
909606
- ...output2.package != null ? { package: output2.package } : {},
909774
+ payloadKind: payload.payloadKind,
909775
+ ...packageConfig != null ? { package: packageConfig } : {},
909607
909776
  invocation: {
909608
909777
  customConfig: stripCliConfigKeys(generatorInvocation.config) ?? {},
909609
909778
  keywords: generatorInvocation.keywords ?? [],
@@ -909622,15 +909791,14 @@ function createFernSdkGenApiBatchRequest({ apiName, organization, cliVersion, sp
909622
909791
  requestedOutput: output2.requestedOutput
909623
909792
  };
909624
909793
  });
909625
- const apiInputs = [{ id: "default", specIndexes: "all" }];
909626
- const runtimeBundleHashes = targets2.map((target) => (0, import_crypto10.createHash)("sha256").update(target.runtimeBundle).digest("hex"));
909794
+ const payloadHashes = targets2.map((target) => (0, import_crypto10.createHash)("sha256").update(target.payload.body).digest("hex"));
909627
909795
  const idempotencyKey = (0, import_crypto10.createHash)("sha256").update(specsTarGzBuffer).update(JSON.stringify({
909628
909796
  protocolVersion: 2,
909629
909797
  organization,
909630
909798
  apiName,
909631
909799
  apiInputs,
909632
909800
  targets: requestTargets,
909633
- runtimeBundleHashes
909801
+ payloadHashes
909634
909802
  })).digest("hex");
909635
909803
  return {
909636
909804
  protocolVersion: 2,
@@ -910758,6 +910926,33 @@ async function downloadFileForTask({ s3PreSignedReadUrl, absolutePathToLocalOutp
910758
910926
  await (0, import_promises122.pipeline)(request7.data, (0, import_fs37.createWriteStream)(absolutePathToLocalOutput));
910759
910927
  }
910760
910928
 
910929
+ // ../generation/remote-generation/remote-workspace-runner/lib/fernSdkGenApiSourceArchive.js
910930
+ function validateFernSdkGenApiSourceCompatibility(route, sourceArchive) {
910931
+ if (route.payloadKind !== "sdk-config-v1" || route.configKind !== "sdk-config-v1") {
910932
+ return;
910933
+ }
910934
+ if (sourceArchive.specIndexes.length === 0) {
910935
+ throw new Error("SDK Config v1 requires at least one effective Fern source spec");
910936
+ }
910937
+ const seenIndexes = /* @__PURE__ */ new Set();
910938
+ for (const manifestIndex of sourceArchive.specIndexes) {
910939
+ if (seenIndexes.has(manifestIndex)) {
910940
+ throw new Error(`Fern target source selection contains duplicate manifest index ${manifestIndex}`);
910941
+ }
910942
+ seenIndexes.add(manifestIndex);
910943
+ const source2 = sourceArchive.manifest.specs[manifestIndex];
910944
+ if (source2 == null) {
910945
+ throw new Error(`Fern source manifest does not contain selected index ${manifestIndex}`);
910946
+ }
910947
+ if (!isSupportedSourceType(source2.type)) {
910948
+ throw new Error(`Generator ${route.generatorId} ${route.requestedVersion} requires SDK Config v1, but selected source ${manifestIndex} cannot be represented downstream: SDK Config generation does not support Fern source type ${source2.type} (${source2.specPath}). Use an OpenAPI, AsyncAPI, or GraphQL source for this generator version.`);
910949
+ }
910950
+ }
910951
+ }
910952
+ function isSupportedSourceType(type7) {
910953
+ return type7 === "openapi" || type7 === "asyncapi" || type7 === "graphql";
910954
+ }
910955
+
910761
910956
  // ../generation/remote-generation/remote-workspace-runner/lib/resolveAutoDiscoveredFernignorePath.js
910762
910957
  init_lib12();
910763
910958
  init_lib8();
@@ -911317,26 +911512,25 @@ var SourceUploader = class {
911317
911512
  };
911318
911513
 
911319
911514
  // ../generation/remote-generation/remote-workspace-runner/lib/runRemoteGenerationForGenerator.js
911320
- async function runRemoteGenerationForGenerator({ projectConfig, organization, workspace, interactiveTaskContext, generatorInvocation, version: version7, audiences, shouldLogS3Url, token, whitelabel, replay, irVersionOverride, absolutePathToPreview, isPreview: isPreviewOverride, fiddlePreview, pushPreviewBranch, readme, fernignorePath, skipFernignore, dynamicIrOnly, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, loginCommand, specsTarGzBuffer, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject }) {
911515
+ async function runRemoteGenerationForGenerator({ projectConfig, organization, workspace, interactiveTaskContext, generatorInvocation, version: version7, audiences, shouldLogS3Url, token, whitelabel, replay, irVersionOverride, absolutePathToPreview, isPreview: isPreviewOverride, fiddlePreview, pushPreviewBranch, readme, fernignorePath, skipFernignore, dynamicIrOnly, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, loginCommand, specsTarGzBuffer, sdkGenApiSourceArchive, sdkGenApiRoute, sdkGenApiPreparationBatch, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject }) {
911321
911516
  const fdr = createFdrService({ token: token.value });
911322
911517
  const fdrOrigin = "https://registry-dev2.buildwithfern.com";
911323
911518
  const isAirGapped = await detectAirGappedMode(`${fdrOrigin}/health`, interactiveTaskContext.logger);
911324
911519
  const packageName = generators_yml_exports.getPackageName({ generatorInvocation }) ?? (generatorInvocation.outputMode.type === "downloadFiles" ? getPackageNameFromGeneratorConfig(generatorInvocation) : void 0);
911325
911520
  const isPreview = isPreviewOverride ?? absolutePathToPreview != null;
911326
- const substituteEnvVars = (stringOrObject) => replaceEnvVariables(stringOrObject, {
911327
- onError: (e2) => {
911521
+ const resolvedWhitelabel = whitelabel == null ? void 0 : replaceEnvVariables(whitelabel, {
911522
+ onError: (error50) => {
911328
911523
  if (!isPreview && requireEnvVars) {
911329
- interactiveTaskContext.failAndThrow(void 0, e2, {
911524
+ interactiveTaskContext.failAndThrow(void 0, error50, {
911330
911525
  code: CliError.Code.EnvironmentError
911331
911526
  });
911332
911527
  }
911333
911528
  }
911334
911529
  }, { substituteAsEmpty: isPreview });
911335
- const generatorInvocationWithEnvVarSubstitutions = substituteEnvVars(generatorInvocation);
911336
911530
  const dynamicGeneratorConfig = getDynamicGeneratorConfig({
911337
911531
  apiName: workspace.definition.rootApiFile.contents.name,
911338
911532
  organization,
911339
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions
911533
+ generatorInvocation
911340
911534
  });
911341
911535
  const resolvedVersion = version7 ?? await computeSemanticVersion({ packageName, generatorInvocation });
911342
911536
  if (version7 != null) {
@@ -911387,10 +911581,43 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911387
911581
  ciProvider: detectCiProvider()
911388
911582
  }
911389
911583
  });
911390
- const venus = createVenusService({ token: token.value });
911584
+ let sdkGenApiCandidate;
911585
+ const sdkGenApiLanguage = getFernSdkGenApiLanguage(generatorInvocation.name);
911586
+ if (sdkGenApiRoute != null) {
911587
+ if (replay?.enabled === true) {
911588
+ return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support replay", void 0, {
911589
+ code: CliError.Code.ConfigError
911590
+ });
911591
+ }
911592
+ if (generateFullProject === true) {
911593
+ return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support full-project generation", void 0, { code: CliError.Code.ConfigError });
911594
+ }
911595
+ const candidate = {
911596
+ generatorInvocation,
911597
+ sdkVersion: resolvedVersion,
911598
+ specsTarGzBuffer,
911599
+ whitelabel
911600
+ };
911601
+ if (!isEligibleForFernSdkGenApi(candidate)) {
911602
+ const reason = resolvedVersion == null ? "the SDK version could not be resolved" : (0, import_autoversion2.isAutoVersion)(resolvedVersion) ? "automatic SDK versioning has not yet moved from Fiddle to the shared pipeline" : whitelabel != null ? "whitelabel generation has not yet moved from Fiddle to the shared pipeline" : specsTarGzBuffer == null ? "the source archive is unavailable" : `generator language ${generatorInvocation.language ?? "unknown"} does not match ${sdkGenApiLanguage}`;
911603
+ return interactiveTaskContext.failAndThrow(`Cannot submit SDK generation to sdk-gen-api: ${reason}`, void 0, {
911604
+ code: CliError.Code.ConfigError
911605
+ });
911606
+ }
911607
+ sdkGenApiCandidate = candidate;
911608
+ if (sdkGenApiRoute.payloadKind === "sdk-config-v1") {
911609
+ return interactiveTaskContext.failAndThrow(`Cannot submit ${candidate.generatorInvocation.name} ${candidate.generatorInvocation.version} from legacy Fern configuration. Run \`fern sdk migrate --output <path>\` to create SDK Config v1 before using this generator version.`, void 0, { code: CliError.Code.ConfigError });
911610
+ }
911611
+ if (sdkGenApiTargetIdSeed == null) {
911612
+ throw new Error("sdk-gen-api target is missing its preparation ID");
911613
+ }
911614
+ await sdkGenApiPreparationBatch?.ready(sdkGenApiTargetIdSeed);
911615
+ }
911616
+ const requiresFdrRegistration = sdkGenApiRoute?.payloadKind !== "sdk-config-v1";
911391
911617
  let generateOauthClients = false;
911392
911618
  let generatePaginatedClients = false;
911393
- if (!isAirGapped) {
911619
+ if (!isAirGapped && requiresFdrRegistration) {
911620
+ const venus = createVenusService({ token: token.value });
911394
911621
  const orgResponse = await venus.organization.get({ orgId: projectConfig.organization });
911395
911622
  if (orgResponse.ok) {
911396
911623
  if (orgResponse.body.isWhitelabled) {
@@ -911404,50 +911631,52 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911404
911631
  generatePaginatedClients = orgResponse.body.paginationEnabled ?? false;
911405
911632
  }
911406
911633
  }
911407
- const sources = workspace.getSources();
911408
911634
  let fdrApiDefinitionId;
911409
- let sourceUploads;
911410
- const apiDefinition = convertIrToFdrApi({
911411
- ir: ir3,
911412
- snippetsConfig: {
911413
- typescriptSdk: void 0,
911414
- pythonSdk: void 0,
911415
- javaSdk: void 0,
911416
- rubySdk: void 0,
911417
- goSdk: void 0,
911418
- csharpSdk: void 0,
911419
- phpSdk: void 0,
911420
- swiftSdk: void 0,
911421
- rustSdk: void 0
911422
- },
911423
- context: interactiveTaskContext
911424
- });
911425
- try {
911426
- const response = await fdr.api.register.registerApiDefinition({
911427
- orgId: FdrAPI_exports.OrgId(organization),
911428
- apiId: FdrAPI_exports.ApiId(getOriginalName(ir3.apiName)),
911429
- definition: apiDefinition,
911430
- sources: sources.length > 0 ? convertToFdrApiDefinitionSources(sources) : void 0
911635
+ if (requiresFdrRegistration) {
911636
+ const sources = workspace.getSources();
911637
+ let sourceUploads;
911638
+ const apiDefinition = convertIrToFdrApi({
911639
+ ir: ir3,
911640
+ snippetsConfig: {
911641
+ typescriptSdk: void 0,
911642
+ pythonSdk: void 0,
911643
+ javaSdk: void 0,
911644
+ rubySdk: void 0,
911645
+ goSdk: void 0,
911646
+ csharpSdk: void 0,
911647
+ phpSdk: void 0,
911648
+ swiftSdk: void 0,
911649
+ rustSdk: void 0
911650
+ },
911651
+ context: interactiveTaskContext
911431
911652
  });
911432
- fdrApiDefinitionId = response.apiDefinitionId;
911433
- sourceUploads = response.sources ?? void 0;
911434
- } catch (error50) {
911435
- const sourceUploader2 = new SourceUploader(interactiveTaskContext, sources);
911436
- if (sourceUploader2.sourceTypes.has("protobuf")) {
911437
- interactiveTaskContext.failAndThrow(`Failed to register API definition: ${JSON.stringify(error50)}`);
911653
+ try {
911654
+ const response = await fdr.api.register.registerApiDefinition({
911655
+ orgId: FdrAPI_exports.OrgId(organization),
911656
+ apiId: FdrAPI_exports.ApiId(getOriginalName(ir3.apiName)),
911657
+ definition: apiDefinition,
911658
+ sources: sources.length > 0 ? convertToFdrApiDefinitionSources(sources) : void 0
911659
+ });
911660
+ fdrApiDefinitionId = response.apiDefinitionId;
911661
+ sourceUploads = response.sources ?? void 0;
911662
+ } catch (error50) {
911663
+ const sourceUploader2 = new SourceUploader(interactiveTaskContext, sources);
911664
+ if (sourceUploader2.sourceTypes.has("protobuf")) {
911665
+ interactiveTaskContext.failAndThrow(`Failed to register API definition: ${JSON.stringify(error50)}`);
911666
+ }
911667
+ }
911668
+ const sourceUploader = new SourceUploader(interactiveTaskContext, sources);
911669
+ if (sourceUploads == null && sourceUploader.sourceTypes.has("protobuf")) {
911670
+ interactiveTaskContext.failAndThrow("Did not successfully upload Protobuf source files.", void 0, {
911671
+ code: CliError.Code.NetworkError
911672
+ });
911673
+ }
911674
+ if (sourceUploads != null) {
911675
+ interactiveTaskContext.logger.debug("Uploading source files ...");
911676
+ const sourceConfig = await sourceUploader.uploadSources(sourceUploads);
911677
+ interactiveTaskContext.logger.debug("Setting IR source configuration ...");
911678
+ ir3.sourceConfig = sourceConfig;
911438
911679
  }
911439
- }
911440
- const sourceUploader = new SourceUploader(interactiveTaskContext, sources);
911441
- if (sourceUploads == null && sourceUploader.sourceTypes.has("protobuf")) {
911442
- interactiveTaskContext.failAndThrow("Did not successfully upload Protobuf source files.", void 0, {
911443
- code: CliError.Code.NetworkError
911444
- });
911445
- }
911446
- if (sourceUploads != null) {
911447
- interactiveTaskContext.logger.debug("Uploading source files ...");
911448
- const sourceConfig = await sourceUploader.uploadSources(sourceUploads);
911449
- interactiveTaskContext.logger.debug("Setting IR source configuration ...");
911450
- ir3.sourceConfig = sourceConfig;
911451
911680
  }
911452
911681
  if (dynamicIrOnly) {
911453
911682
  interactiveTaskContext.logger.info("Dynamic IR only mode: skipping SDK generation and uploading dynamic IR only");
@@ -911498,7 +911727,7 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911498
911727
  ...ir3,
911499
911728
  fdrApiDefinitionId,
911500
911729
  publishConfig: getPublishConfig({
911501
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911730
+ generatorInvocation,
911502
911731
  version: resolvedVersion,
911503
911732
  userProvidedVersion: version7,
911504
911733
  packageName,
@@ -911508,76 +911737,56 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911508
911737
  })
911509
911738
  };
911510
911739
  let result;
911511
- let usedSdkGenApi = false;
911512
- const sdkGenApiEnabled = isFernSdkGenApiEnabled();
911513
- const sdkGenApiLanguage = getFernSdkGenApiLanguage(generatorInvocationWithEnvVarSubstitutions.name);
911514
- if (sdkGenApiEnabled && sdkGenApiLanguage != null) {
911515
- if (replay?.enabled === true) {
911516
- return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support replay", void 0, {
911517
- code: CliError.Code.ConfigError
911518
- });
911519
- }
911520
- if (generateFullProject === true) {
911521
- return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support full-project generation", void 0, { code: CliError.Code.ConfigError });
911522
- }
911523
- const candidate = {
911524
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911525
- sdkVersion: resolvedVersion,
911526
- specsTarGzBuffer,
911527
- whitelabel
911528
- };
911529
- if (!isEligibleForFernSdkGenApi(candidate)) {
911530
- const reason = resolvedVersion == null ? "the SDK version could not be resolved" : (0, import_autoversion2.isAutoVersion)(resolvedVersion) ? "automatic SDK versioning has not yet moved from Fiddle to the shared pipeline" : whitelabel != null ? "whitelabel generation has not yet moved from Fiddle to the shared pipeline" : specsTarGzBuffer == null ? "the source archive is unavailable" : `generator language ${generatorInvocationWithEnvVarSubstitutions.language ?? "unknown"} does not match ${sdkGenApiLanguage}`;
911531
- return interactiveTaskContext.failAndThrow(`Cannot submit SDK generation to sdk-gen-api: ${reason}`, void 0, {
911532
- code: CliError.Code.ConfigError
911533
- });
911740
+ if (sdkGenApiRoute != null) {
911741
+ if (sdkGenApiCandidate == null) {
911742
+ throw new Error("sdk-gen-api target passed preflight without an eligible candidate");
911534
911743
  }
911535
- if (verify2 === true) {
911536
- interactiveTaskContext.logger.warn("sdk-gen-api does not yet run Fern's post-generation verification step");
911744
+ if (sdkGenApiRoute.payloadKind !== "fern-runtime-bundle") {
911745
+ throw new Error("Legacy Fern generation reached sdk-gen-api without a Fern runtime bundle route");
911537
911746
  }
911538
- const runtimeBundle = await prepareFernSdkGenApiRuntimeBundle({
911539
- apiName: getOriginalName(ir3.apiName),
911540
- organization,
911541
- generatorInvocation: candidate.generatorInvocation,
911542
- sdkVersion: candidate.sdkVersion,
911543
- intermediateRepresentation: enrichedIntermediateRepresentation,
911544
- irVersionOverride,
911545
- generateOauthClients,
911546
- generatePaginatedClients,
911547
- context: interactiveTaskContext
911548
- });
911549
911747
  const parameters2 = {
911550
911748
  apiName: getOriginalName(ir3.apiName),
911551
911749
  organization,
911552
911750
  cliVersion: workspace.cliVersion,
911553
- generatorInvocation: candidate.generatorInvocation,
911554
- sdkVersion: candidate.sdkVersion,
911751
+ generatorInvocation: sdkGenApiCandidate.generatorInvocation,
911752
+ sdkVersion: sdkGenApiCandidate.sdkVersion,
911753
+ apiVersion: ir3.specVersion,
911555
911754
  token,
911556
- specsTarGzBuffer: candidate.specsTarGzBuffer,
911557
- runtimeBundle,
911755
+ specsTarGzBuffer: sdkGenApiCandidate.specsTarGzBuffer,
911756
+ payload: {
911757
+ payloadKind: sdkGenApiRoute.payloadKind,
911758
+ body: await prepareFernSdkGenApiRuntimeBundle({
911759
+ apiName: getOriginalName(ir3.apiName),
911760
+ organization,
911761
+ generatorInvocation: sdkGenApiCandidate.generatorInvocation,
911762
+ sdkVersion: sdkGenApiCandidate.sdkVersion,
911763
+ intermediateRepresentation: enrichedIntermediateRepresentation,
911764
+ irVersionOverride,
911765
+ generateOauthClients,
911766
+ generatePaginatedClients,
911767
+ context: interactiveTaskContext
911768
+ })
911769
+ },
911558
911770
  absolutePathToPreview,
911559
911771
  context: interactiveTaskContext,
911560
911772
  targetIdSeed: sdkGenApiTargetIdSeed,
911773
+ sourceSpecIndexes: sdkGenApiSourceArchive?.specIndexes,
911561
911774
  audiences: audiences.type === "select" ? audiences.audiences : void 0,
911562
911775
  skipFernignore
911563
911776
  };
911564
911777
  result = await (sdkGenApiBatch?.run(parameters2) ?? runFernSdkGenApiBuild(parameters2));
911565
- usedSdkGenApi = true;
911566
911778
  } else {
911567
- sdkGenApiBatch?.skip();
911568
- }
911569
- if (!usedSdkGenApi) {
911570
911779
  const job = await createAndStartJob({
911571
911780
  projectConfig,
911572
911781
  workspace,
911573
911782
  organization,
911574
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911783
+ generatorInvocation,
911575
911784
  context: interactiveTaskContext,
911576
911785
  version: resolvedVersion,
911577
911786
  intermediateRepresentation: enrichedIntermediateRepresentation,
911578
911787
  shouldLogS3Url,
911579
911788
  token,
911580
- whitelabel: whitelabel != null ? substituteEnvVars(whitelabel) : void 0,
911789
+ whitelabel: resolvedWhitelabel,
911581
911790
  replay,
911582
911791
  irVersionOverride,
911583
911792
  absolutePathToPreview,
@@ -911784,10 +911993,51 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911784
911993
  effectiveOccurrenceTracker.recordOccurrences(generatorGroup.generators);
911785
911994
  }
911786
911995
  const generatorsYmlAbsolutePath = workspace.generatorsConfiguration?.absolutePathToConfiguration;
911787
- const sdkGenApiCandidateIndexes = new Set(isFernSdkGenApiEnabled() ? generatorGroup.generators.flatMap((generator, index3) => getFernSdkGenApiLanguage(generator.name) != null ? [index3] : []) : []);
911996
+ const routePreparation = prepareFernSdkGenApiRoutes({
911997
+ generators: generatorGroup.generators,
911998
+ enabled: isFernSdkGenApiEnabled(),
911999
+ requireEnvVars,
912000
+ isPreview: isPreview ?? absolutePathToPreview != null,
912001
+ verify: verify2,
912002
+ skipIfNoDiff,
912003
+ autoMerge
912004
+ });
912005
+ const sdkGenApiRoutes = routePreparation.map((result) => result.route);
912006
+ const resolvedGenerators = routePreparation.map((result) => result.generatorInvocation);
912007
+ const routeErrors = routePreparation.map((result) => result.error);
912008
+ if (automation == null) {
912009
+ throwFirstPreflightError(routeErrors, generatorGroup.generators);
912010
+ }
912011
+ const sourceRequests = resolvedGenerators.flatMap((generatorInvocation, generatorIndex) => routePreparation[generatorIndex]?.error == null ? [{ generatorIndex, generatorInvocation, sdkGenApiRoute: sdkGenApiRoutes[generatorIndex] }] : []);
912012
+ let sourceResolution = { sourceArchives: /* @__PURE__ */ new Map(), errors: /* @__PURE__ */ new Map() };
912013
+ if (sourceRequests.length > 0) {
912014
+ try {
912015
+ sourceResolution = await getSpecsTarGzBuffer?.(sourceRequests) ?? sourceResolution;
912016
+ } catch (error50) {
912017
+ sourceResolution = {
912018
+ sourceArchives: /* @__PURE__ */ new Map(),
912019
+ errors: new Map(sourceRequests.map((request7) => [request7.generatorIndex, error50]))
912020
+ };
912021
+ }
912022
+ }
912023
+ const sourcePreflight = preflightFernSdkGenApiSources({
912024
+ generators: resolvedGenerators,
912025
+ routes: sdkGenApiRoutes,
912026
+ routeErrors,
912027
+ sourceResolution
912028
+ });
912029
+ const sourceArchives = sourcePreflight.sourceArchives;
912030
+ const preflightErrors = routePreparation.map((result, index3) => result.error ?? sourcePreflight.preflightErrors[index3]);
912031
+ if (automation == null) {
912032
+ throwFirstPreflightError(preflightErrors, generatorGroup.generators);
912033
+ }
912034
+ const sdkGenApiCandidateIndexes = getFernSdkGenApiCandidateIndexes(sdkGenApiRoutes, preflightErrors);
912035
+ validateFernSdkGenApiTargetCount(sdkGenApiCandidateIndexes.size);
911788
912036
  const sdkGenApiBatch = sdkGenApiCandidateIndexes.size > 1 ? new FernSdkGenApiBatch(sdkGenApiCandidateIndexes.size) : void 0;
912037
+ const sdkGenApiPreparationBatch = sdkGenApiCandidateIndexes.size > 0 ? new FernSdkGenApiPreparationBatch([...sdkGenApiCandidateIndexes].map(String)) : void 0;
911789
912038
  const results = await Promise.all(generatorGroup.generators.map((generatorInvocation, generatorIndex) => context3.runInteractiveTask({ name: generatorInvocation.name }, (interactiveTaskContext) => generateOne({
911790
912039
  generatorInvocation,
912040
+ resolvedGeneratorInvocation: resolvedGenerators[generatorIndex] ?? generatorInvocation,
911791
912041
  interactiveTaskContext,
911792
912042
  // Closed-over state + params passed through to the per-generator worker.
911793
912043
  projectConfig,
@@ -911821,7 +912071,10 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911821
912071
  generatorsYmlAbsolutePath,
911822
912072
  occurrenceTracker: effectiveOccurrenceTracker,
911823
912073
  loginCommand,
911824
- getSpecsTarGzBuffer,
912074
+ specsTarGzArchive: sourceArchives[generatorIndex],
912075
+ sdkGenApiPreflightError: preflightErrors[generatorIndex],
912076
+ sdkGenApiRoute: sdkGenApiRoutes[generatorIndex],
912077
+ sdkGenApiPreparationBatch: sdkGenApiCandidateIndexes.has(generatorIndex) ? sdkGenApiPreparationBatch : void 0,
911825
912078
  sdkGenApiBatch: sdkGenApiCandidateIndexes.has(generatorIndex) ? sdkGenApiBatch : void 0,
911826
912079
  sdkGenApiTargetIdSeed: generatorIndex.toString(),
911827
912080
  generateFullProject,
@@ -911834,11 +912087,105 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911834
912087
  snippetsProducedBy
911835
912088
  };
911836
912089
  }
911837
- async function generateOne({ generatorInvocation, interactiveTaskContext, projectConfig, organization, workspace, context: context3, generatorGroup, version: version7, shouldLogS3Url, token, whitelabel, replay, absolutePathToPreview, isPreview, fiddlePreview, pushPreviewBranch, mode, fernignorePath, skipFernignore, dynamicIrOnly, validateWorkspace, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, automation, generatorsYmlAbsolutePath, occurrenceTracker, loginCommand, getSpecsTarGzBuffer, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject, onSnippetsProduced }) {
912090
+ function prepareFernSdkGenApiRoutes({ generators, enabled, requireEnvVars, isPreview, verify: verify2, skipIfNoDiff, autoMerge }) {
912091
+ return generators.map((generatorInvocation) => {
912092
+ let resolved = generatorInvocation;
912093
+ try {
912094
+ resolved = replaceEnvVariables(generatorInvocation, {
912095
+ onError: (error50) => {
912096
+ if (!isPreview && requireEnvVars) {
912097
+ throw error50;
912098
+ }
912099
+ }
912100
+ }, { substituteAsEmpty: isPreview });
912101
+ const route = selectFernSdkGenApiRoute(resolved);
912102
+ if (!enabled) {
912103
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912104
+ }
912105
+ const unsupportedOutput = getFernSdkGenApiUnsupportedOutput({
912106
+ generatorInvocation: resolved,
912107
+ verify: verify2,
912108
+ skipIfNoDiff,
912109
+ autoMerge
912110
+ });
912111
+ if (route != null && unsupportedOutput != null) {
912112
+ if (route.configKind === "legacy-fern") {
912113
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912114
+ }
912115
+ throw new Error(`Cannot route ${resolved.name} ${resolved.version} through sdk-gen-api: ${unsupportedOutput}. This generator version requires SDK Config v1, so Fern cannot fall back to legacy Fiddle generation.`);
912116
+ }
912117
+ return {
912118
+ generatorInvocation: resolved,
912119
+ route,
912120
+ error: void 0
912121
+ };
912122
+ } catch (error50) {
912123
+ if (!enabled && error50 instanceof GeneratorConfigCompatibilityError && error50.code === "INVALID_GENERATOR_VERSION") {
912124
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912125
+ }
912126
+ const routeError = error50 instanceof GeneratorConfigCompatibilityError ? new CliError({
912127
+ message: formatGeneratorConfigCompatibilityError(error50),
912128
+ code: CliError.Code.ConfigError
912129
+ }) : error50;
912130
+ return { generatorInvocation: resolved, route: void 0, error: routeError };
912131
+ }
912132
+ });
912133
+ }
912134
+ function getFernSdkGenApiUnsupportedOutput({ generatorInvocation, verify: verify2, skipIfNoDiff, autoMerge }) {
912135
+ const unsupported = [];
912136
+ if (generatorInvocation.outputMode.type !== "downloadFiles") {
912137
+ unsupported.push(`${generatorInvocation.outputMode.type} delivery requires Fern-managed GitHub or registry credentials that sdk-gen-api cannot resolve`);
912138
+ }
912139
+ if (verify2 === true) {
912140
+ unsupported.push("verify=true is not implemented by sdk-gen-api");
912141
+ }
912142
+ if (skipIfNoDiff === true) {
912143
+ unsupported.push("skipIfNoDiff=true is not implemented by sdk-gen-api");
912144
+ }
912145
+ if (autoMerge === true) {
912146
+ unsupported.push("autoMerge=true is not implemented by sdk-gen-api");
912147
+ }
912148
+ return unsupported.length > 0 ? unsupported.join("; ") : void 0;
912149
+ }
912150
+ function preflightFernSdkGenApiSources({ generators, routes, routeErrors, sourceResolution }) {
912151
+ return {
912152
+ sourceArchives: generators.map((_5, index3) => sourceResolution.sourceArchives.get(index3)),
912153
+ preflightErrors: generators.map((_5, index3) => {
912154
+ if (routeErrors?.[index3] != null) {
912155
+ return void 0;
912156
+ }
912157
+ const route = routes[index3];
912158
+ if (route == null) {
912159
+ return void 0;
912160
+ }
912161
+ const sourceError = sourceResolution.errors.get(index3);
912162
+ if (sourceError != null) {
912163
+ return sourceError;
912164
+ }
912165
+ const sourceArchive = sourceResolution.sourceArchives.get(index3);
912166
+ if (sourceArchive == null) {
912167
+ return new Error(`Resolved source archive is unavailable for ${route.generatorId}`);
912168
+ }
912169
+ try {
912170
+ validateFernSdkGenApiSourceCompatibility(route, sourceArchive);
912171
+ return void 0;
912172
+ } catch (error50) {
912173
+ return error50;
912174
+ }
912175
+ })
912176
+ };
912177
+ }
912178
+ function getFernSdkGenApiCandidateIndexes(routes, preflightErrors) {
912179
+ return new Set(routes.flatMap((route, index3) => route != null && preflightErrors[index3] == null ? [index3] : []));
912180
+ }
912181
+ async function generateOne({ generatorInvocation, resolvedGeneratorInvocation, interactiveTaskContext, projectConfig, organization, workspace, context: context3, generatorGroup, version: version7, shouldLogS3Url, token, whitelabel, replay, absolutePathToPreview, isPreview, fiddlePreview, pushPreviewBranch, mode, fernignorePath, skipFernignore, dynamicIrOnly, validateWorkspace, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, automation, generatorsYmlAbsolutePath, occurrenceTracker, loginCommand, specsTarGzArchive, sdkGenApiPreflightError, sdkGenApiRoute, sdkGenApiPreparationBatch, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject, onSnippetsProduced }) {
911838
912182
  const startedAt = Date.now();
911839
912183
  try {
911840
- const settings = getBaseOpenAPIWorkspaceSettingsFromGeneratorInvocation(generatorInvocation);
911841
- const fernWorkspace = await workspace.toFernWorkspace({ context: context3 }, settings, generatorInvocation.apiOverride?.specs);
912184
+ if (sdkGenApiPreflightError != null) {
912185
+ throw sdkGenApiPreflightError;
912186
+ }
912187
+ const settings = getBaseOpenAPIWorkspaceSettingsFromGeneratorInvocation(resolvedGeneratorInvocation);
912188
+ const fernWorkspace = await workspace.toFernWorkspace({ context: context3 }, settings, resolvedGeneratorInvocation.apiOverride?.specs);
911842
912189
  if (validateWorkspace) {
911843
912190
  await validateAPIWorkspaceAndLogIssues({
911844
912191
  workspace: fernWorkspace,
@@ -911848,7 +912195,7 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911848
912195
  });
911849
912196
  }
911850
912197
  const effectiveFernignorePath = skipFernignore ? void 0 : fernignorePath ?? await resolveAutoDiscoveredFernignorePath({
911851
- generatorInvocation,
912198
+ generatorInvocation: resolvedGeneratorInvocation,
911852
912199
  context: interactiveTaskContext
911853
912200
  });
911854
912201
  const remoteTaskHandlerResponse = await runRemoteGenerationForGenerator({
@@ -911857,9 +912204,9 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911857
912204
  workspace: fernWorkspace,
911858
912205
  interactiveTaskContext,
911859
912206
  generatorInvocation: {
911860
- ...generatorInvocation,
911861
- outputMode: generatorInvocation.outputMode._visit({
911862
- downloadFiles: () => generatorInvocation.outputMode,
912207
+ ...resolvedGeneratorInvocation,
912208
+ outputMode: resolvedGeneratorInvocation.outputMode._visit({
912209
+ downloadFiles: () => resolvedGeneratorInvocation.outputMode,
911863
912210
  github: (val) => {
911864
912211
  return api_exports4.OutputMode.github({
911865
912212
  ...val,
@@ -911870,11 +912217,11 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911870
912217
  if (mode === "pull-request") {
911871
912218
  return api_exports4.OutputMode.githubV2(api_exports4.GithubOutputModeV2.pullRequest(val));
911872
912219
  }
911873
- return generatorInvocation.outputMode;
912220
+ return resolvedGeneratorInvocation.outputMode;
911874
912221
  },
911875
- publish: () => generatorInvocation.outputMode,
911876
- publishV2: () => generatorInvocation.outputMode,
911877
- _other: () => generatorInvocation.outputMode
912222
+ publish: () => resolvedGeneratorInvocation.outputMode,
912223
+ publishV2: () => resolvedGeneratorInvocation.outputMode,
912224
+ _other: () => resolvedGeneratorInvocation.outputMode
911878
912225
  })
911879
912226
  },
911880
912227
  version: version7,
@@ -911883,8 +912230,8 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911883
912230
  token,
911884
912231
  whitelabel,
911885
912232
  replay,
911886
- readme: generatorInvocation.readme,
911887
- irVersionOverride: generatorInvocation.irVersionOverride,
912233
+ readme: resolvedGeneratorInvocation.readme,
912234
+ irVersionOverride: resolvedGeneratorInvocation.irVersionOverride,
911888
912235
  absolutePathToPreview,
911889
912236
  isPreview,
911890
912237
  fiddlePreview,
@@ -911901,7 +912248,10 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911901
912248
  noReplay,
911902
912249
  disableTelemetry,
911903
912250
  loginCommand,
911904
- specsTarGzBuffer: await getSpecsTarGzBuffer?.(generatorInvocation.name),
912251
+ specsTarGzBuffer: specsTarGzArchive?.buffer,
912252
+ sdkGenApiSourceArchive: specsTarGzArchive,
912253
+ sdkGenApiRoute,
912254
+ sdkGenApiPreparationBatch,
911905
912255
  sdkGenApiBatch,
911906
912256
  sdkGenApiTargetIdSeed,
911907
912257
  generateFullProject
@@ -911943,7 +912293,12 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911943
912293
  isAutomation: automation != null
911944
912294
  });
911945
912295
  } catch (error50) {
911946
- sdkGenApiBatch?.cancel(error50);
912296
+ sdkGenApiPreparationBatch?.fail(sdkGenApiTargetIdSeed, error50, automation != null);
912297
+ if (automation != null) {
912298
+ sdkGenApiBatch?.remove(sdkGenApiTargetIdSeed, error50);
912299
+ } else {
912300
+ sdkGenApiBatch?.cancel(error50);
912301
+ }
911947
912302
  if (automation == null) {
911948
912303
  throw error50;
911949
912304
  }
@@ -911978,6 +912333,17 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911978
912333
  });
911979
912334
  }
911980
912335
  }
912336
+ function throwFirstPreflightError(errors4, generators) {
912337
+ const failedIndex = errors4.findIndex((error51) => error51 != null);
912338
+ if (failedIndex < 0) {
912339
+ return;
912340
+ }
912341
+ const error50 = errors4[failedIndex];
912342
+ if (error50 instanceof CliError) {
912343
+ throw error50;
912344
+ }
912345
+ throw new Error(`Cannot prepare sdk-gen-api target ${generators[failedIndex]?.name ?? failedIndex.toString()}: ${extractErrorMessage(error50)}`, { cause: error50 });
912346
+ }
911981
912347
  async function emitGenerationAnnotations(ctx) {
911982
912348
  if (!shouldEmitGithubAnnotations()) {
911983
912349
  return;
@@ -914210,7 +914576,7 @@ var LegacyDocsPublisher = class {
914210
914576
  previewId,
914211
914577
  disableTemplates: void 0,
914212
914578
  skipUpload,
914213
- cliVersion: "5.111.0",
914579
+ cliVersion: "5.112.0",
914214
914580
  loginCommand: "fern auth login"
914215
914581
  });
914216
914582
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -968505,6 +968871,8 @@ async function copySnippetJsonIfNonEmpty({ src, dest }) {
968505
968871
  }
968506
968872
 
968507
968873
  // ../generation/local-generation/local-workspace-runner/lib/rawSpecs.js
968874
+ var import_node_util10 = require("util");
968875
+ init_lib17();
968508
968876
  init_lib4();
968509
968877
  init_lib8();
968510
968878
  init_lib35();
@@ -968547,7 +968915,14 @@ async function collectRawSpecs({ specs, hostOutputDir, containerBaseDir, context
968547
968915
  async function resolveAndWriteSpec({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3, audiences }) {
968548
968916
  switch (spec.type) {
968549
968917
  case "openapi":
968550
- return resolveOpenAPIOrAsyncAPI({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3, audiences });
968918
+ return resolveOpenAPIOrAsyncAPI({
968919
+ spec,
968920
+ hostOutputDir,
968921
+ containerBaseDir,
968922
+ context: context3,
968923
+ index: index3,
968924
+ audiences
968925
+ });
968551
968926
  case "openrpc":
968552
968927
  return resolveOpenRPC({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3 });
968553
968928
  case "protobuf":
@@ -968582,9 +968957,41 @@ async function resolveOpenAPIOrAsyncAPI({ spec, hostOutputDir, containerBaseDir,
968582
968957
  return {
968583
968958
  type: isAsync2 ? "asyncapi" : "openapi",
968584
968959
  specPath: toContainerPath(filename, containerBaseDir),
968585
- namespace: spec.namespace
968960
+ namespace: spec.namespace,
968961
+ apiImportSettings: mapApiImportSettings(getOpenAPISettings({ overrides: spec.settings }))
968586
968962
  };
968587
968963
  }
968964
+ var SDK_CONFIG_IMPORT_SETTING_MAPPERS = {
968965
+ respectNullableSchemas: (settings) => ({ respectNullableSchemas: settings.respectNullableSchemas }),
968966
+ useTitlesAsName: (settings) => ({ titleAsSchemaName: settings.useTitlesAsName }),
968967
+ coerceEnumsToLiterals: (settings) => ({ coerceEnumsToLiterals: settings.coerceEnumsToLiterals }),
968968
+ shouldUseIdiomaticRequestNames: (settings) => ({
968969
+ idiomaticRequestNames: settings.shouldUseIdiomaticRequestNames
968970
+ }),
968971
+ wrapReferencesToNullableInOptional: (settings) => ({
968972
+ wrapReferencesToNullableInOptional: settings.wrapReferencesToNullableInOptional
968973
+ }),
968974
+ coerceOptionalSchemasToNullable: (settings) => ({
968975
+ coerceOptionalSchemasToNullable: settings.coerceOptionalSchemasToNullable
968976
+ }),
968977
+ pathParameterOrder: (settings) => ({ pathParameterOrder: settings.pathParameterOrder }),
968978
+ onlyIncludeReferencedSchemas: (settings) => ({
968979
+ onlyIncludeReferencedSchemas: settings.onlyIncludeReferencedSchemas
968980
+ }),
968981
+ objectQueryParameters: (settings) => ({ objectQueryParameters: settings.objectQueryParameters }),
968982
+ typeDatesAsStrings: (settings) => ({ typeDatesAsStrings: settings.typeDatesAsStrings }),
968983
+ groupMultiApiEnvironments: (settings) => ({
968984
+ groupMultiApiEnvironments: settings.groupMultiApiEnvironments
968985
+ }),
968986
+ defaultIntegerFormat: (settings) => ({ defaultIntegerFormat: settings.defaultIntegerFormat })
968987
+ };
968988
+ function mapApiImportSettings(settings) {
968989
+ const mappedSettings = {};
968990
+ for (const mapSetting of Object.values(SDK_CONFIG_IMPORT_SETTING_MAPPERS)) {
968991
+ Object.assign(mappedSettings, mapSetting(settings));
968992
+ }
968993
+ return mappedSettings;
968994
+ }
968588
968995
  async function resolveOpenRPC({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3 }) {
968589
968996
  const filename = `openrpc${index3}.json`;
968590
968997
  const rawContent = await (0, import_promises143.readFile)(spec.absoluteFilepath, "utf-8");
@@ -968758,30 +969165,318 @@ function matchesAudiences(operation, selectedAudiences) {
968758
969165
  function hasOperations(pathItem) {
968759
969166
  return Object.keys(pathItem).some((key2) => HTTP_METHODS3.has(key2.toLowerCase()));
968760
969167
  }
968761
- async function createSpecsTarGzBuffer({ specs, context: context3, audiences }) {
969168
+ async function createGroupedSpecsTarGzArchiveSettled({ generatorSelections, context: context3, audiences }) {
969169
+ const deduplicated = deduplicateGeneratorSelections(generatorSelections);
969170
+ const errorsByGeneratorIndex = /* @__PURE__ */ new Map();
969171
+ const tmpDir = await import_tmp_promise17.default.dir({ unsafeCleanup: true });
969172
+ try {
969173
+ const materializedRoot = import_path99.default.join(tmpDir.path, "materialized");
969174
+ await (0, import_promises143.mkdir)(materializedRoot);
969175
+ const materializedSpecs = await Promise.allSettled(deduplicated.uniqueSpecs.map(async (spec, uniqueSpecIndex) => {
969176
+ const directory = import_path99.default.join(materializedRoot, uniqueSpecIndex.toString());
969177
+ await (0, import_promises143.mkdir)(directory);
969178
+ const manifest = await collectRawSpecs({
969179
+ specs: [spec],
969180
+ hostOutputDir: AbsoluteFilePath2.of(directory),
969181
+ containerBaseDir: "/fern/specs",
969182
+ context: context3,
969183
+ audiences
969184
+ });
969185
+ const manifestEntry = manifest.specs[0];
969186
+ if (manifestEntry == null) {
969187
+ throw new Error(`Materialized source ${uniqueSpecIndex} did not produce a manifest entry`);
969188
+ }
969189
+ return { directory, manifestEntry };
969190
+ }));
969191
+ materializedSpecs.forEach((result, uniqueSpecIndex) => {
969192
+ if (result.status === "fulfilled") {
969193
+ return;
969194
+ }
969195
+ for (const generatorIndex of deduplicated.generatorIndexesByUniqueSpecIndex[uniqueSpecIndex] ?? []) {
969196
+ if (!errorsByGeneratorIndex.has(generatorIndex)) {
969197
+ errorsByGeneratorIndex.set(generatorIndex, result.reason);
969198
+ }
969199
+ }
969200
+ });
969201
+ const successfulGeneratorIndexes = new Set(generatorSelections.map((selection) => selection.generatorIndex).filter((generatorIndex) => !errorsByGeneratorIndex.has(generatorIndex)));
969202
+ if (successfulGeneratorIndexes.size === 0) {
969203
+ return { archive: void 0, errorsByGeneratorIndex };
969204
+ }
969205
+ try {
969206
+ const archive3 = await createArchiveFromMaterializedSpecs({
969207
+ materializedSpecs,
969208
+ deduplicated,
969209
+ successfulGeneratorIndexes,
969210
+ root: tmpDir.path
969211
+ });
969212
+ assertGeneratorSelectionOutcomes({ generatorSelections, archive: archive3, errorsByGeneratorIndex });
969213
+ return { archive: archive3, errorsByGeneratorIndex };
969214
+ } catch (error50) {
969215
+ for (const generatorIndex of successfulGeneratorIndexes) {
969216
+ errorsByGeneratorIndex.set(generatorIndex, error50);
969217
+ }
969218
+ return { archive: void 0, errorsByGeneratorIndex };
969219
+ }
969220
+ } finally {
969221
+ await tmpDir.cleanup();
969222
+ }
969223
+ }
969224
+ function deduplicateGeneratorSelections(generatorSelections) {
969225
+ const uniqueSpecs = [];
969226
+ const indexesBySpecKey = /* @__PURE__ */ new Map();
969227
+ const uniqueSpecIndexesByGeneratorIndex = /* @__PURE__ */ new Map();
969228
+ const generatorIndexesByUniqueSpecIndex = [];
969229
+ const orderedSelections = [...generatorSelections].sort((left3, right3) => left3.generatorIndex - right3.generatorIndex);
969230
+ for (const selection of orderedSelections) {
969231
+ if (uniqueSpecIndexesByGeneratorIndex.has(selection.generatorIndex)) {
969232
+ throw new Error(`Duplicate source selection for generator index ${selection.generatorIndex}`);
969233
+ }
969234
+ const indexes = selection.specs.map((spec) => {
969235
+ const key2 = createSpecDeduplicationKey(spec);
969236
+ const existingIndex = indexesBySpecKey.get(key2);
969237
+ if (existingIndex != null) {
969238
+ return existingIndex;
969239
+ }
969240
+ const index3 = uniqueSpecs.length;
969241
+ uniqueSpecs.push(spec);
969242
+ indexesBySpecKey.set(key2, index3);
969243
+ generatorIndexesByUniqueSpecIndex[index3] = /* @__PURE__ */ new Set();
969244
+ return index3;
969245
+ });
969246
+ for (const index3 of new Set(indexes)) {
969247
+ generatorIndexesByUniqueSpecIndex[index3]?.add(selection.generatorIndex);
969248
+ }
969249
+ uniqueSpecIndexesByGeneratorIndex.set(selection.generatorIndex, [...new Set(indexes)]);
969250
+ }
969251
+ return { uniqueSpecs, uniqueSpecIndexesByGeneratorIndex, generatorIndexesByUniqueSpecIndex };
969252
+ }
969253
+ async function createArchiveFromMaterializedSpecs({ materializedSpecs, deduplicated, successfulGeneratorIndexes, root: root6 }) {
969254
+ const contentDirectory = import_path99.default.join(root6, "content");
969255
+ await (0, import_promises143.mkdir)(contentDirectory);
969256
+ const manifest = { specs: [] };
969257
+ const archiveSpecIndexByUniqueSpecIndex = /* @__PURE__ */ new Map();
969258
+ const typeCounters = /* @__PURE__ */ new Map();
969259
+ for (const [uniqueSpecIndex, generatorIndexes] of deduplicated.generatorIndexesByUniqueSpecIndex.entries()) {
969260
+ if (![...generatorIndexes].some((generatorIndex) => successfulGeneratorIndexes.has(generatorIndex))) {
969261
+ continue;
969262
+ }
969263
+ const materialized = materializedSpecs[uniqueSpecIndex];
969264
+ if (materialized?.status !== "fulfilled") {
969265
+ throw new Error(`Successful generator references source ${uniqueSpecIndex}, which was not materialized`);
969266
+ }
969267
+ const type7 = materialized.value.manifestEntry.type;
969268
+ const typeIndex = typeCounters.get(type7) ?? 0;
969269
+ typeCounters.set(type7, typeIndex + 1);
969270
+ const manifestEntry = await copyMaterializedSpec({
969271
+ materialized: materialized.value,
969272
+ contentDirectory,
969273
+ typeIndex
969274
+ });
969275
+ archiveSpecIndexByUniqueSpecIndex.set(uniqueSpecIndex, manifest.specs.length);
969276
+ manifest.specs.push(manifestEntry);
969277
+ }
969278
+ const specIndexesByGeneratorIndex = /* @__PURE__ */ new Map();
969279
+ for (const [generatorIndex, uniqueSpecIndexes] of deduplicated.uniqueSpecIndexesByGeneratorIndex) {
969280
+ if (!successfulGeneratorIndexes.has(generatorIndex)) {
969281
+ continue;
969282
+ }
969283
+ specIndexesByGeneratorIndex.set(generatorIndex, uniqueSpecIndexes.map((uniqueSpecIndex) => {
969284
+ const archiveSpecIndex = archiveSpecIndexByUniqueSpecIndex.get(uniqueSpecIndex);
969285
+ if (archiveSpecIndex == null) {
969286
+ throw new Error(`Source ${uniqueSpecIndex} is unavailable for generator index ${generatorIndex}`);
969287
+ }
969288
+ return archiveSpecIndex;
969289
+ }));
969290
+ }
969291
+ const archive3 = await createArchiveFromDirectory({
969292
+ contentDirectory,
969293
+ tarGzPath: import_path99.default.join(root6, "specs.tar.gz"),
969294
+ manifest
969295
+ });
969296
+ return { ...archive3, specIndexesByGeneratorIndex };
969297
+ }
969298
+ async function copyMaterializedSpec({ materialized, contentDirectory, typeIndex }) {
969299
+ const sourcePrefix = `${materialized.manifestEntry.type}0`;
969300
+ const targetPrefix = `${materialized.manifestEntry.type}${typeIndex}`;
969301
+ assertSupportedMaterializedManifestEntry(materialized.manifestEntry);
969302
+ for (const entry of await (0, import_promises143.readdir)(materialized.directory, { withFileTypes: true })) {
969303
+ if (!hasSourcePrefix(entry.name) || !entry.isFile() && !entry.isDirectory()) {
969304
+ throw new Error(`Unsupported materialized source entry: ${entry.name}`);
969305
+ }
969306
+ await (0, import_promises143.cp)(import_path99.default.join(materialized.directory, entry.name), import_path99.default.join(contentDirectory, replacePrefix(entry.name)), {
969307
+ recursive: entry.isDirectory()
969308
+ });
969309
+ }
969310
+ return {
969311
+ ...materialized.manifestEntry,
969312
+ specPath: replaceContainerPathPrefix(materialized.manifestEntry.specPath),
969313
+ ...materialized.manifestEntry.overridePaths == null ? {} : {
969314
+ overridePaths: materialized.manifestEntry.overridePaths.map(replaceContainerPathPrefix)
969315
+ }
969316
+ };
969317
+ function replacePrefix(value2) {
969318
+ return `${targetPrefix}${value2.slice(sourcePrefix.length)}`;
969319
+ }
969320
+ function hasSourcePrefix(value2) {
969321
+ return value2 === sourcePrefix || value2.startsWith(`${sourcePrefix}.`) || value2.startsWith(`${sourcePrefix}-`);
969322
+ }
969323
+ function replaceContainerPathPrefix(value2) {
969324
+ const basename8 = import_path99.default.posix.basename(value2);
969325
+ if (!hasSourcePrefix(basename8)) {
969326
+ throw new Error(`Unexpected materialized source path: ${value2}`);
969327
+ }
969328
+ return import_path99.default.posix.join(import_path99.default.posix.dirname(value2), replacePrefix(basename8));
969329
+ }
969330
+ }
969331
+ var SUPPORTED_MATERIALIZED_MANIFEST_ENTRY_KEYS = /* @__PURE__ */ new Set([
969332
+ "type",
969333
+ "specPath",
969334
+ "overridePaths",
969335
+ "namespace",
969336
+ "apiImportSettings"
969337
+ ]);
969338
+ function assertSupportedMaterializedManifestEntry(entry) {
969339
+ for (const key2 of Object.keys(entry)) {
969340
+ if (!SUPPORTED_MATERIALIZED_MANIFEST_ENTRY_KEYS.has(key2)) {
969341
+ throw new Error(`Unsupported materialized manifest entry field: ${key2}`);
969342
+ }
969343
+ }
969344
+ }
969345
+ function assertGeneratorSelectionOutcomes({ generatorSelections, archive: archive3, errorsByGeneratorIndex }) {
969346
+ for (const { generatorIndex } of generatorSelections) {
969347
+ const hasArchive = archive3.specIndexesByGeneratorIndex.has(generatorIndex);
969348
+ const hasError = errorsByGeneratorIndex.has(generatorIndex);
969349
+ if (hasArchive === hasError) {
969350
+ throw new Error(`Generator index ${generatorIndex} must have exactly one source archive or materialization error outcome`);
969351
+ }
969352
+ }
969353
+ }
969354
+ var SDK_CONFIG_IMPORT_SETTING_KEYS = new Set(Object.keys(SDK_CONFIG_IMPORT_SETTING_MAPPERS));
969355
+ var DEFAULT_OPENAPI_SETTINGS = getOpenAPISettings();
969356
+ function validateSdkConfigImportSettings(specs) {
969357
+ for (const spec of specs) {
969358
+ if (spec.type !== "openapi") {
969359
+ continue;
969360
+ }
969361
+ const settings = getOpenAPISettings({ overrides: spec.settings });
969362
+ for (const key2 of Object.getOwnPropertyNames(settings)) {
969363
+ const value2 = Reflect.get(settings, key2);
969364
+ if (SDK_CONFIG_IMPORT_SETTING_KEYS.has(key2) || key2 === "audiences" && Array.isArray(value2) && value2.length === 0 || (0, import_node_util10.isDeepStrictEqual)(value2, Reflect.get(DEFAULT_OPENAPI_SETTINGS, key2))) {
969365
+ continue;
969366
+ }
969367
+ throw new Error(`SDK Config v1 cannot preserve effective OpenAPI import setting ${key2}=${JSON.stringify(value2)} for ${spec.absoluteFilepath}. Remove that setting or use a pre-cutover generator version until the shared SDK Config contract supports it.`);
969368
+ }
969369
+ }
969370
+ }
969371
+ async function createSpecsTarGzArchive({ specs, context: context3, audiences }) {
968762
969372
  const tmpDir = await import_tmp_promise17.default.dir({ unsafeCleanup: true });
968763
969373
  try {
969374
+ const contentDirectory = import_path99.default.join(tmpDir.path, "content");
969375
+ await (0, import_promises143.mkdir)(contentDirectory);
968764
969376
  const manifest = await collectRawSpecs({
968765
969377
  specs,
968766
- hostOutputDir: AbsoluteFilePath2.of(tmpDir.path),
969378
+ hostOutputDir: AbsoluteFilePath2.of(contentDirectory),
968767
969379
  containerBaseDir: "/fern/specs",
968768
969380
  context: context3,
968769
969381
  audiences
968770
969382
  });
968771
- await (0, import_promises143.writeFile)(join8(AbsoluteFilePath2.of(tmpDir.path), RelativeFilePath2.of(SPECS_MANIFEST_FILENAME)), JSON.stringify(manifest, void 0, 4));
968772
- const tarGzPath = join8(AbsoluteFilePath2.of(tmpDir.path), RelativeFilePath2.of("specs.tar.gz"));
968773
- await Kn({
968774
- gzip: true,
968775
- cwd: tmpDir.path,
968776
- file: tarGzPath,
968777
- portable: true,
968778
- filter: (entryPath) => entryPath !== "./specs.tar.gz"
968779
- }, ["."]);
968780
- return await (0, import_promises143.readFile)(tarGzPath);
969383
+ return await createArchiveFromDirectory({
969384
+ contentDirectory,
969385
+ tarGzPath: import_path99.default.join(tmpDir.path, "specs.tar.gz"),
969386
+ manifest
969387
+ });
968781
969388
  } finally {
968782
969389
  await tmpDir.cleanup();
968783
969390
  }
968784
969391
  }
969392
+ async function createArchiveFromDirectory({ contentDirectory, tarGzPath, manifest }) {
969393
+ await (0, import_promises143.writeFile)(join8(AbsoluteFilePath2.of(contentDirectory), RelativeFilePath2.of(SPECS_MANIFEST_FILENAME)), JSON.stringify(manifest, void 0, 4));
969394
+ const archiveEntries = await listDeterministicArchiveEntries(contentDirectory);
969395
+ await Kn({
969396
+ gzip: true,
969397
+ cwd: contentDirectory,
969398
+ file: tarGzPath,
969399
+ portable: true,
969400
+ mtime: /* @__PURE__ */ new Date(0),
969401
+ onWriteEntry: (entry) => {
969402
+ if (entry.stat != null) {
969403
+ entry.stat.mode = 420;
969404
+ }
969405
+ }
969406
+ }, archiveEntries);
969407
+ return { buffer: await (0, import_promises143.readFile)(tarGzPath), manifest };
969408
+ }
969409
+ async function listDeterministicArchiveEntries(root6, relativeDirectory = "") {
969410
+ const absoluteDirectory = relativeDirectory === "" ? root6 : import_path99.default.join(root6, ...relativeDirectory.split(import_path99.default.posix.sep));
969411
+ const directoryEntries = await (0, import_promises143.readdir)(absoluteDirectory, { withFileTypes: true });
969412
+ const archiveEntries = [];
969413
+ for (const entry of directoryEntries.sort((left3, right3) => compareStrings(left3.name, right3.name))) {
969414
+ const relativePath = import_path99.default.posix.join(relativeDirectory, entry.name);
969415
+ if (entry.isDirectory()) {
969416
+ archiveEntries.push(...await listDeterministicArchiveEntries(root6, relativePath));
969417
+ continue;
969418
+ }
969419
+ if (!entry.isFile()) {
969420
+ throw new Error(`Unsupported generated source archive entry: ${relativePath}`);
969421
+ }
969422
+ archiveEntries.push(relativePath);
969423
+ }
969424
+ return archiveEntries;
969425
+ }
969426
+ function compareStrings(left3, right3) {
969427
+ return left3 < right3 ? -1 : left3 > right3 ? 1 : 0;
969428
+ }
969429
+ function createSpecDeduplicationKey(spec) {
969430
+ switch (spec.type) {
969431
+ case "openapi":
969432
+ return stableStringify3({
969433
+ type: spec.type,
969434
+ path: spec.absoluteFilepath,
969435
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969436
+ overlay: spec.absoluteFilepathToOverlays,
969437
+ namespace: spec.namespace,
969438
+ settings: getOpenAPISettings({ overrides: spec.settings })
969439
+ });
969440
+ case "openrpc":
969441
+ return stableStringify3({
969442
+ type: spec.type,
969443
+ path: spec.absoluteFilepath,
969444
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969445
+ namespace: spec.namespace
969446
+ });
969447
+ case "protobuf":
969448
+ return stableStringify3({
969449
+ type: spec.type,
969450
+ root: spec.absoluteFilepathToProtobufRoot,
969451
+ target: spec.absoluteFilepathToProtobufTarget,
969452
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969453
+ dependencies: spec.dependencies,
969454
+ settings: getOpenAPISettings({ overrides: spec.settings })
969455
+ });
969456
+ case "graphql":
969457
+ return stableStringify3({
969458
+ type: spec.type,
969459
+ path: spec.absoluteFilepath,
969460
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969461
+ examples: spec.absoluteFilepathToExamples,
969462
+ namespace: spec.namespace
969463
+ });
969464
+ default:
969465
+ assertNever(spec);
969466
+ }
969467
+ }
969468
+ function stableStringify3(value2) {
969469
+ return JSON.stringify(sortJsonValue(value2));
969470
+ }
969471
+ function sortJsonValue(value2) {
969472
+ if (Array.isArray(value2)) {
969473
+ return value2.map(sortJsonValue);
969474
+ }
969475
+ if (value2 == null || typeof value2 !== "object") {
969476
+ return value2;
969477
+ }
969478
+ return Object.fromEntries(Object.entries(value2).sort(([left3], [right3]) => compareStrings(left3, right3)).map(([key2, child]) => [key2, sortJsonValue(child)]));
969479
+ }
968785
969480
 
968786
969481
  // ../generation/local-generation/local-workspace-runner/lib/runGenerator.js
968787
969482
  function extractLicenseFilePath(generatorInvocation, absolutePathToFernConfig) {
@@ -979681,7 +980376,7 @@ var {
979681
980376
  } = signalExitWrap(processOk(process21) ? new SignalExit(process21) : new SignalExitFallback());
979682
980377
 
979683
980378
  // ../../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.17/node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
979684
- var import_node_util10 = require("util");
980379
+ var import_node_util11 = require("util");
979685
980380
 
979686
980381
  // ../../../node_modules/.pnpm/@inquirer+ansi@1.0.2/node_modules/@inquirer/ansi/dist/esm/index.js
979687
980382
  var ESC2 = "\x1B[";
@@ -979719,7 +980414,7 @@ var ScreenManager2 = class {
979719
980414
  }
979720
980415
  render(content5, bottomContent = "") {
979721
980416
  const promptLine = lastLine2(content5);
979722
- const rawPromptLine = (0, import_node_util10.stripVTControlCharacters)(promptLine);
980417
+ const rawPromptLine = (0, import_node_util11.stripVTControlCharacters)(promptLine);
979723
980418
  let prompt2 = rawPromptLine;
979724
980419
  if (this.rl.line.length > 0) {
979725
980420
  prompt2 = prompt2.slice(0, -this.rl.line.length);
@@ -981130,7 +981825,7 @@ function getAutomationContextFromEnv() {
981130
981825
  config_branch: process.env.FERN_CONFIG_BRANCH,
981131
981826
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
981132
981827
  trigger: process.env.GITHUB_EVENT_NAME,
981133
- cli_version: "5.111.0"
981828
+ cli_version: "5.112.0"
981134
981829
  };
981135
981830
  }
981136
981831
  function isAutomationMode() {
@@ -981962,7 +982657,7 @@ var CliContext = class _CliContext {
981962
982657
  if (false) {
981963
982658
  this.logger.error("CLI_VERSION is not defined");
981964
982659
  }
981965
- return "5.111.0";
982660
+ return "5.112.0";
981966
982661
  }
981967
982662
  getCliName() {
981968
982663
  if (false) {
@@ -983605,18 +984300,118 @@ function expandGroupFilter(groupNames, generatorsConfiguration) {
983605
984300
  // src/commands/generate/generateAPIWorkspace.ts
983606
984301
  init_lib20();
983607
984302
  init_lib8();
983608
- init_lib35();
983609
984303
  init_lib6();
983610
984304
  init_esm18();
983611
984305
 
983612
- // src/commands/generate/createSpecsTarGzCache.ts
983613
- function createSpecsTarGzCache(createArchive) {
983614
- let archivePromise;
983615
- return () => {
983616
- archivePromise ??= createArchive();
983617
- return archivePromise;
984306
+ // src/commands/generate/createFernSourceArchiveResolver.ts
984307
+ init_lib35();
984308
+ function createFernSourceArchiveResolver({
984309
+ workspace,
984310
+ context: context3,
984311
+ group
984312
+ }) {
984313
+ return async (requests3) => {
984314
+ const sourceArchives = /* @__PURE__ */ new Map();
984315
+ const errors4 = /* @__PURE__ */ new Map();
984316
+ if (!(workspace instanceof OSSWorkspace)) {
984317
+ for (const request7 of requests3) {
984318
+ if (requestRequiresSourceArchive(request7)) {
984319
+ errors4.set(
984320
+ request7.generatorIndex,
984321
+ new Error(
984322
+ `Generator index ${request7.generatorIndex} (${request7.generatorInvocation.name}) requires a source archive, but workspace type ${workspace.type} does not expose source specs`
984323
+ )
984324
+ );
984325
+ }
984326
+ }
984327
+ return { sourceArchives, errors: errors4 };
984328
+ }
984329
+ const settledSelections = await Promise.allSettled(
984330
+ requests3.map(async (request7) => {
984331
+ if (request7.sdkGenApiRoute == null) {
984332
+ return void 0;
984333
+ }
984334
+ const specs = await workspace.getAllSpecsForGenerator(request7.generatorInvocation.apiOverride?.specs);
984335
+ if (request7.sdkGenApiRoute.payloadKind === "sdk-config-v1") {
984336
+ validateSdkConfigImportSettings(specs);
984337
+ }
984338
+ return specs;
984339
+ })
984340
+ );
984341
+ const generatorSelections = settledSelections.flatMap((result, index3) => {
984342
+ const request7 = requests3[index3];
984343
+ if (request7 == null) {
984344
+ throw new Error(`Missing source archive request at settled index ${index3}`);
984345
+ }
984346
+ if (result.status === "rejected") {
984347
+ errors4.set(request7.generatorIndex, result.reason);
984348
+ return [];
984349
+ }
984350
+ return result.value == null ? [] : [{ generatorIndex: request7.generatorIndex, specs: result.value }];
984351
+ });
984352
+ if (generatorSelections.length > 0) {
984353
+ const settledArchive = await createGroupedSpecsTarGzArchiveSettled({
984354
+ generatorSelections,
984355
+ context: context3,
984356
+ audiences: group.audiences
984357
+ });
984358
+ for (const [generatorIndex, error50] of settledArchive.errorsByGeneratorIndex) {
984359
+ errors4.set(generatorIndex, error50);
984360
+ }
984361
+ if (settledArchive.archive != null) {
984362
+ const { specIndexesByGeneratorIndex, ...sourceArchive } = settledArchive.archive;
984363
+ for (const [generatorIndex, specIndexes] of specIndexesByGeneratorIndex) {
984364
+ sourceArchives.set(generatorIndex, { ...sourceArchive, specIndexes });
984365
+ }
984366
+ }
984367
+ }
984368
+ const rootRequests = requests3.filter(
984369
+ (request7) => request7.sdkGenApiRoute == null && generatorWantsSpecs(request7.generatorInvocation.name) && !errors4.has(request7.generatorIndex)
984370
+ );
984371
+ if (rootRequests.length > 0) {
984372
+ try {
984373
+ const archive3 = await createSpecsTarGzArchive({
984374
+ specs: workspace.allSpecs,
984375
+ context: context3,
984376
+ audiences: group.audiences
984377
+ });
984378
+ const specIndexes = archive3.manifest.specs.map((_5, index3) => index3);
984379
+ for (const request7 of rootRequests) {
984380
+ sourceArchives.set(request7.generatorIndex, { ...archive3, specIndexes });
984381
+ }
984382
+ } catch (error50) {
984383
+ for (const request7 of rootRequests) {
984384
+ errors4.set(request7.generatorIndex, error50);
984385
+ }
984386
+ }
984387
+ }
984388
+ for (const request7 of requests3) {
984389
+ if (!requestRequiresSourceArchive(request7)) {
984390
+ continue;
984391
+ }
984392
+ const hasArchive = sourceArchives.has(request7.generatorIndex);
984393
+ const hasError = errors4.has(request7.generatorIndex);
984394
+ if (hasArchive && hasError) {
984395
+ throw new Error(
984396
+ `Generator index ${request7.generatorIndex} produced both a source archive and a source preparation error`,
984397
+ { cause: errors4.get(request7.generatorIndex) }
984398
+ );
984399
+ }
984400
+ if (!hasArchive && !hasError) {
984401
+ errors4.set(
984402
+ request7.generatorIndex,
984403
+ new Error(
984404
+ `Generator index ${request7.generatorIndex} did not produce a source archive or source preparation error`
984405
+ )
984406
+ );
984407
+ }
984408
+ }
984409
+ return { sourceArchives, errors: errors4 };
983618
984410
  };
983619
984411
  }
984412
+ function requestRequiresSourceArchive(request7) {
984413
+ return request7.sdkGenApiRoute != null || generatorWantsSpecs(request7.generatorInvocation.name);
984414
+ }
983620
984415
 
983621
984416
  // src/commands/generate/packLocalOutput.ts
983622
984417
  init_lib20();
@@ -984273,21 +985068,11 @@ async function generateWorkspace({
984273
985068
  disableTelemetry: isTelemetryDisabled()
984274
985069
  });
984275
985070
  } else if (token != null) {
984276
- const ossWorkspace = workspace instanceof OSSWorkspace ? workspace : void 0;
984277
- const getCachedSpecsTarGz = ossWorkspace == null ? void 0 : createSpecsTarGzCache(
984278
- () => createSpecsTarGzBuffer({
984279
- specs: ossWorkspace.allSpecs,
984280
- context: groupContext,
984281
- audiences: group.audiences
984282
- })
984283
- );
984284
- const getSpecsTarGz = async (generatorName2) => {
984285
- const sdkGenApiNeedsSpecs = isFernSdkGenApiEnabled() && getFernSdkGenApiLanguage(generatorName2) != null;
984286
- if (getCachedSpecsTarGz == null || !generatorWantsSpecs(generatorName2) && !sdkGenApiNeedsSpecs) {
984287
- return void 0;
984288
- }
984289
- return getCachedSpecsTarGz();
984290
- };
985071
+ const getSpecsTarGz = createFernSourceArchiveResolver({
985072
+ workspace,
985073
+ context: groupContext,
985074
+ group
985075
+ });
984291
985076
  await runRemoteGenerationForAPIWorkspace({
984292
985077
  projectConfig,
984293
985078
  organization,
@@ -996755,7 +997540,12 @@ async function sdkPreview({
996755
997540
  absolutePathToPreview: absolutePathToOutput,
996756
997541
  isPreview: true,
996757
997542
  fiddlePreview: false,
996758
- pushPreviewBranch: false
997543
+ pushPreviewBranch: false,
997544
+ getSpecsTarGzBuffer: createFernSourceArchiveResolver({
997545
+ workspace,
997546
+ context: context3,
997547
+ group: publishGroup
997548
+ })
996759
997549
  });
996760
997550
  });
996761
997551
  if (shouldRunTwoJobs) {
@@ -996770,7 +997560,12 @@ async function sdkPreview({
996770
997560
  absolutePathToPreview: void 0,
996771
997561
  isPreview: true,
996772
997562
  fiddlePreview: true,
996773
- pushPreviewBranch: true
997563
+ pushPreviewBranch: true,
997564
+ getSpecsTarGzBuffer: createFernSourceArchiveResolver({
997565
+ workspace,
997566
+ context: context3,
997567
+ group: diffGroup
997568
+ })
996774
997569
  });
996775
997570
  });
996776
997571
  }