@fern-api/fern-api-dev 5.111.0 → 5.112.1

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 +1056 -245
  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) {
@@ -147380,7 +147380,10 @@ function buildEndpoint({ endpoint: endpoint3, declarationFile, context: context3
147380
147380
  }
147381
147381
  context3.builder.addError(errorDeclarationFile, {
147382
147382
  name: errorName,
147383
- schema: context3.isErrorUnknownSchema(parseInt(statusCode)) ? { ...errorDeclaration, type: "unknown" } : errorDeclaration
147383
+ schema: context3.isErrorUnknownSchema({
147384
+ statusCode: parseInt(statusCode),
147385
+ namespace: maybeEndpointNamespace
147386
+ }) ? { ...errorDeclaration, type: "unknown" } : errorDeclaration
147384
147387
  });
147385
147388
  if (convertedEndpoint.errors == null) {
147386
147389
  convertedEndpoint.errors = [];
@@ -149305,6 +149308,9 @@ var init_lib14 = __esm({
149305
149308
  });
149306
149309
 
149307
149310
  // ../api-importers/openapi/openapi-ir-to-fern/lib/OpenApiIrConverterContext.js
149311
+ function getErrorKey({ statusCode, namespace }) {
149312
+ return namespace != null ? `${namespace}:${statusCode}` : `${statusCode}`;
149313
+ }
149308
149314
  var OpenApiIrConverterContext;
149309
149315
  var init_OpenApiIrConverterContext = __esm({
149310
149316
  "../api-importers/openapi/openapi-ir-to-fern/lib/OpenApiIrConverterContext.js"() {
@@ -149314,6 +149320,7 @@ var init_OpenApiIrConverterContext = __esm({
149314
149320
  init_lib13();
149315
149321
  init_ConvertOpenAPIOptions();
149316
149322
  init_State();
149323
+ init_getNamespaceFromGroup();
149317
149324
  OpenApiIrConverterContext = class {
149318
149325
  logger;
149319
149326
  taskContext;
@@ -149379,17 +149386,18 @@ var init_OpenApiIrConverterContext = __esm({
149379
149386
  if (ir3.title != null) {
149380
149387
  this.builder.setDisplayName({ displayName: ir3.title });
149381
149388
  }
149382
- const schemaByStatusCode = {};
149389
+ const schemaByErrorKey = {};
149383
149390
  if (!this.enableUniqueErrorsPerEndpoint) {
149384
149391
  for (const endpoint3 of ir3.endpoints) {
149392
+ const namespace = getEndpointNamespace(endpoint3.sdkName, endpoint3.namespace);
149385
149393
  for (const [statusCodeString, error50] of Object.entries(endpoint3.errors)) {
149386
- const statusCode = parseInt(statusCodeString);
149387
- const existingSchema = schemaByStatusCode[statusCode];
149394
+ const key2 = getErrorKey({ statusCode: parseInt(statusCodeString), namespace });
149395
+ const existingSchema = schemaByErrorKey[key2];
149388
149396
  if (existingSchema == null && error50.schema != null) {
149389
- schemaByStatusCode[statusCode] = error50.schema;
149397
+ schemaByErrorKey[key2] = error50.schema;
149390
149398
  } else if (existingSchema != null && error50.schema != null && isSchemaEqual(existingSchema, error50.schema)) {
149391
149399
  } else {
149392
- this.unknownSchema.add(statusCode);
149400
+ this.unknownSchema.add(key2);
149393
149401
  }
149394
149402
  }
149395
149403
  }
@@ -149432,10 +149440,11 @@ var init_OpenApiIrConverterContext = __esm({
149432
149440
  return this.urlIdMap.get(serverUrl);
149433
149441
  }
149434
149442
  /**
149435
- * Is error an unknown schema
149443
+ * Is error an unknown schema. Errors are shared per status code within a namespace,
149444
+ * so a schema mismatch in one namespace does not affect errors in another.
149436
149445
  */
149437
- isErrorUnknownSchema(statusCode) {
149438
- return this.unknownSchema.has(statusCode);
149446
+ isErrorUnknownSchema({ statusCode, namespace }) {
149447
+ return this.unknownSchema.has(getErrorKey({ statusCode, namespace }));
149439
149448
  }
149440
149449
  /**
149441
149450
  * Returns the current endpoint method being processed
@@ -200410,6 +200419,13 @@ var init_openapi = __esm({
200410
200419
  }
200411
200420
  });
200412
200421
 
200422
+ // ../../commons/api-workspace-commons/lib/RawSpecs.js
200423
+ var init_RawSpecs = __esm({
200424
+ "../../commons/api-workspace-commons/lib/RawSpecs.js"() {
200425
+ "use strict";
200426
+ }
200427
+ });
200428
+
200413
200429
  // ../../commons/api-workspace-commons/lib/Source.js
200414
200430
  var init_Source5 = __esm({
200415
200431
  "../../commons/api-workspace-commons/lib/Source.js"() {
@@ -200568,6 +200584,7 @@ var init_lib17 = __esm({
200568
200584
  init_getFilesystemPublishTarget();
200569
200585
  init_getOriginGitCommit();
200570
200586
  init_openapi();
200587
+ init_RawSpecs();
200571
200588
  init_Source5();
200572
200589
  init_Spec();
200573
200590
  init_utils11();
@@ -374265,6 +374282,7 @@ var init_OSSWorkspace = __esm({
374265
374282
  init_lib31();
374266
374283
  init_lib21();
374267
374284
  init_lib12();
374285
+ init_lib20();
374268
374286
  init_lib4();
374269
374287
  init_lib8();
374270
374288
  init_lib9();
@@ -374666,6 +374684,13 @@ var init_OSSWorkspace = __esm({
374666
374684
  sources: this.sources
374667
374685
  });
374668
374686
  }
374687
+ async getAllSpecsForGenerator(specsOverride) {
374688
+ if (specsOverride == null) {
374689
+ return this.allSpecs;
374690
+ }
374691
+ const overrideSpecs = await this.convertSpecsOverrideToSpecs(specsOverride);
374692
+ return overrideSpecs.filter((spec) => spec.type !== "protobuf" || !spec.fromOpenAPI);
374693
+ }
374669
374694
  async createWorkspaceWithSpecsOverride({ context: context3 }, specsOverride, settings) {
374670
374695
  const overrideSpecs = await this.convertSpecsOverrideToSpecs(specsOverride);
374671
374696
  const overrideAllSpecs = overrideSpecs.filter((spec) => spec.type !== "protobuf" || !spec.fromOpenAPI);
@@ -374724,8 +374749,9 @@ var init_OSSWorkspace = __esm({
374724
374749
  absoluteFilepath,
374725
374750
  absoluteFilepathToOverrides,
374726
374751
  absoluteFilepathToOverlays,
374727
- // Use default settings from existing specs for compatibility
374728
- settings: this.specs.length > 0 ? this.specs[0]?.settings : void 0,
374752
+ settings: getOpenAPISettings({
374753
+ options: mergeSettings(this.generatorsConfiguration?.api?.settings ?? parseOpenApiDefinitionSettingsSchema(void 0), parseOpenApiDefinitionSettingsSchema(spec.settings))
374754
+ }),
374729
374755
  source: {
374730
374756
  type: "openapi",
374731
374757
  file: absoluteFilepath
@@ -494571,9 +494597,9 @@ var require_graceful_fs2 = __commonJS({
494571
494597
  }
494572
494598
  }
494573
494599
  var fs$readdir = fs35.readdir;
494574
- fs35.readdir = readdir23;
494600
+ fs35.readdir = readdir24;
494575
494601
  var noReaddirOptionVersions = /^v[0-5]\./;
494576
- function readdir23(path122, options2, cb) {
494602
+ function readdir24(path122, options2, cb) {
494577
494603
  if (typeof options2 === "function")
494578
494604
  cb = options2, options2 = null;
494579
494605
  var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path123, options3, cb2, startTime) {
@@ -503426,10 +503452,10 @@ var require_make_dir = __commonJS({
503426
503452
  module4.exports = (input3, opts) => Promise.resolve().then(() => {
503427
503453
  checkPath(input3);
503428
503454
  opts = Object.assign({}, defaults3, opts);
503429
- const mkdir49 = pify(opts.fs.mkdir);
503455
+ const mkdir50 = pify(opts.fs.mkdir);
503430
503456
  const stat8 = pify(opts.fs.stat);
503431
503457
  const make = (pth) => {
503432
- return mkdir49(pth, opts.mode).then(() => pth).catch((err) => {
503458
+ return mkdir50(pth, opts.mode).then(() => pth).catch((err) => {
503433
503459
  if (err.code === "ENOENT") {
503434
503460
  if (err.message.includes("null bytes") || path122.dirname(pth) === pth) {
503435
503461
  throw err;
@@ -637453,14 +637479,14 @@ var require_empty2 = __commonJS({
637453
637479
  var u5 = require_universalify().fromPromise;
637454
637480
  var fs34 = require_fs();
637455
637481
  var path122 = require("path");
637456
- var mkdir49 = require_mkdirs();
637482
+ var mkdir50 = require_mkdirs();
637457
637483
  var remove3 = require_remove3();
637458
637484
  var emptyDir = u5(async function emptyDir2(dir) {
637459
637485
  let items;
637460
637486
  try {
637461
637487
  items = await fs34.readdir(dir);
637462
637488
  } catch {
637463
- return mkdir49.mkdirs(dir);
637489
+ return mkdir50.mkdirs(dir);
637464
637490
  }
637465
637491
  return Promise.all(items.map((item) => remove3.remove(path122.join(dir, item))));
637466
637492
  });
@@ -637469,7 +637495,7 @@ var require_empty2 = __commonJS({
637469
637495
  try {
637470
637496
  items = fs34.readdirSync(dir);
637471
637497
  } catch {
637472
- return mkdir49.mkdirsSync(dir);
637498
+ return mkdir50.mkdirsSync(dir);
637473
637499
  }
637474
637500
  items.forEach((item) => {
637475
637501
  item = path122.join(dir, item);
@@ -637492,7 +637518,7 @@ var require_file2 = __commonJS({
637492
637518
  var u5 = require_universalify().fromPromise;
637493
637519
  var path122 = require("path");
637494
637520
  var fs34 = require_fs();
637495
- var mkdir49 = require_mkdirs();
637521
+ var mkdir50 = require_mkdirs();
637496
637522
  async function createFile(file4) {
637497
637523
  let stats;
637498
637524
  try {
@@ -637506,7 +637532,7 @@ var require_file2 = __commonJS({
637506
637532
  dirStats = await fs34.stat(dir);
637507
637533
  } catch (err) {
637508
637534
  if (err.code === "ENOENT") {
637509
- await mkdir49.mkdirs(dir);
637535
+ await mkdir50.mkdirs(dir);
637510
637536
  await fs34.writeFile(file4, "");
637511
637537
  return;
637512
637538
  } else {
@@ -637532,7 +637558,7 @@ var require_file2 = __commonJS({
637532
637558
  fs34.readdirSync(dir);
637533
637559
  }
637534
637560
  } catch (err) {
637535
- if (err && err.code === "ENOENT") mkdir49.mkdirsSync(dir);
637561
+ if (err && err.code === "ENOENT") mkdir50.mkdirsSync(dir);
637536
637562
  else throw err;
637537
637563
  }
637538
637564
  fs34.writeFileSync(file4, "");
@@ -637551,7 +637577,7 @@ var require_link = __commonJS({
637551
637577
  var u5 = require_universalify().fromPromise;
637552
637578
  var path122 = require("path");
637553
637579
  var fs34 = require_fs();
637554
- var mkdir49 = require_mkdirs();
637580
+ var mkdir50 = require_mkdirs();
637555
637581
  var { pathExists: pathExists2 } = require_path_exists();
637556
637582
  var { areIdentical } = require_stat();
637557
637583
  async function createLink(srcpath, dstpath) {
@@ -637571,7 +637597,7 @@ var require_link = __commonJS({
637571
637597
  const dir = path122.dirname(dstpath);
637572
637598
  const dirExists = await pathExists2(dir);
637573
637599
  if (!dirExists) {
637574
- await mkdir49.mkdirs(dir);
637600
+ await mkdir50.mkdirs(dir);
637575
637601
  }
637576
637602
  await fs34.link(srcpath, dstpath);
637577
637603
  }
@@ -637591,7 +637617,7 @@ var require_link = __commonJS({
637591
637617
  const dir = path122.dirname(dstpath);
637592
637618
  const dirExists = fs34.existsSync(dir);
637593
637619
  if (dirExists) return fs34.linkSync(srcpath, dstpath);
637594
- mkdir49.mkdirsSync(dir);
637620
+ mkdir50.mkdirsSync(dir);
637595
637621
  return fs34.linkSync(srcpath, dstpath);
637596
637622
  }
637597
637623
  module4.exports = {
@@ -637927,19 +637953,19 @@ var require_output_file = __commonJS({
637927
637953
  var u5 = require_universalify().fromPromise;
637928
637954
  var fs34 = require_fs();
637929
637955
  var path122 = require("path");
637930
- var mkdir49 = require_mkdirs();
637956
+ var mkdir50 = require_mkdirs();
637931
637957
  var pathExists2 = require_path_exists().pathExists;
637932
637958
  async function outputFile(file4, data2, encoding = "utf-8") {
637933
637959
  const dir = path122.dirname(file4);
637934
637960
  if (!await pathExists2(dir)) {
637935
- await mkdir49.mkdirs(dir);
637961
+ await mkdir50.mkdirs(dir);
637936
637962
  }
637937
637963
  return fs34.writeFile(file4, data2, encoding);
637938
637964
  }
637939
637965
  function outputFileSync(file4, ...args) {
637940
637966
  const dir = path122.dirname(file4);
637941
637967
  if (!fs34.existsSync(dir)) {
637942
- mkdir49.mkdirsSync(dir);
637968
+ mkdir50.mkdirsSync(dir);
637943
637969
  }
637944
637970
  fs34.writeFileSync(file4, ...args);
637945
637971
  }
@@ -705504,7 +705530,7 @@ var AccessTokenPosthogManager = class {
705504
705530
  properties: {
705505
705531
  ...event,
705506
705532
  ...event.properties,
705507
- version: "5.111.0",
705533
+ version: "5.112.1",
705508
705534
  usingAccessToken: true,
705509
705535
  ...getRunIdProperties()
705510
705536
  }
@@ -705570,7 +705596,7 @@ var UserPosthogManager = class {
705570
705596
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
705571
705597
  event: "CLI",
705572
705598
  properties: {
705573
- version: "5.111.0",
705599
+ version: "5.112.1",
705574
705600
  ...event,
705575
705601
  ...event.properties,
705576
705602
  usingAccessToken: false,
@@ -887246,7 +887272,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
887246
887272
  var LOGS_FOLDER_NAME = "logs";
887247
887273
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
887248
887274
  function getCliSource() {
887249
- const version7 = "5.111.0";
887275
+ const version7 = "5.112.1";
887250
887276
  return `cli@${version7}`;
887251
887277
  }
887252
887278
  var DebugLogger = class {
@@ -908903,6 +908929,28 @@ function getGeneratorLanguage(generatorId) {
908903
908929
  return getGeneratorPolicy(generatorId)?.language;
908904
908930
  }
908905
908931
  function validateGeneratorConfigCompatibility(input3) {
908932
+ const route = selectGeneratorConfigRoute(input3);
908933
+ const receivedConfigKind = input3.configKind;
908934
+ if (!isGenerationConfigKind(receivedConfigKind)) {
908935
+ throw compatibilityError(input3, {
908936
+ code: "INVALID_CONFIG_KIND",
908937
+ message: "Configuration kind must be legacy-fern or sdk-config-v1",
908938
+ cutoverVersion: route.cutoverVersion,
908939
+ expectedLanguage: route.language,
908940
+ expectedConfigKind: route.configKind,
908941
+ recommendedAction: "USE_SUPPORTED_CONFIG_KIND"
908942
+ }, receivedConfigKind);
908943
+ }
908944
+ if (receivedConfigKind !== route.configKind) {
908945
+ const policy = getGeneratorPolicy(input3.generatorId);
908946
+ if (policy === void 0) {
908947
+ throw new Error(`Missing validated generator policy for ${input3.generatorId}`);
908948
+ }
908949
+ throw configKindError(input3, policy, route.configKind, receivedConfigKind);
908950
+ }
908951
+ return route;
908952
+ }
908953
+ function selectGeneratorConfigRoute(input3) {
908906
908954
  const policy = getGeneratorPolicy(input3.generatorId);
908907
908955
  if (policy === void 0) {
908908
908956
  throw compatibilityError(input3, {
@@ -908937,27 +908985,13 @@ function validateGeneratorConfigCompatibility(input3) {
908937
908985
  }
908938
908986
  const isBeforeCutover = compareSemver(requestedVersion, policy.parsedCutoverVersion) < 0;
908939
908987
  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
908988
  return {
908955
908989
  generatorId: input3.generatorId,
908956
908990
  language: policy.language,
908957
908991
  requestedVersion: input3.requestedVersion,
908958
908992
  cutoverVersion: policy.cutoverVersion,
908959
- configKind: receivedConfigKind,
908960
- payloadKind: isBeforeCutover ? "fern-runtime-bundle" : "sdk-config-ir-v1"
908993
+ configKind: expectedConfigKind,
908994
+ payloadKind: isBeforeCutover ? "fern-runtime-bundle" : "sdk-config-v1"
908961
908995
  };
908962
908996
  }
908963
908997
  function compatibilityError(input3, details, receivedConfigKind = input3.configKind) {
@@ -908988,13 +909022,15 @@ function isGenerationConfigKind(value2) {
908988
909022
  var POLL_INTERVAL_MS2 = 2e3;
908989
909023
  var POLL_TIMEOUT_MS2 = 15 * 60 * 1e3;
908990
909024
  var REQUEST_TIMEOUT_MS = 6e4;
908991
- var MAX_BUNDLES = 64;
909025
+ var MAX_PAYLOADS = 64;
908992
909026
  var MAX_SOURCE_COMPRESSED_BYTES = 25 * 1024 * 1024;
908993
909027
  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;
909028
+ var MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES = 5 * 1024 * 1024;
909029
+ var MAX_PAYLOAD_BYTES = 25 * 1024 * 1024;
909030
+ var MAX_TOTAL_RUNTIME_BUNDLE_COMPRESSED_BYTES = 25 * 1024 * 1024;
909031
+ var MAX_TOTAL_PAYLOAD_BYTES = 100 * 1024 * 1024;
909032
+ var MAX_TOTAL_UPLOAD_FILE_BYTES = 50 * 1024 * 1024;
909033
+ var MAX_REQUEST_FIELD_BYTES = 1024 * 1024;
908998
909034
  var MAX_MULTIPART_BODY_BYTES = 60 * 1024 * 1024;
908999
909035
  var LOOPBACK_HOSTNAMES2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
909000
909036
  var TARGET_ID_SEED_COLLATOR = new Intl.Collator("en", { numeric: true });
@@ -909025,6 +909061,18 @@ function getFernSdkGenApiOrigin() {
909025
909061
  function getFernSdkGenApiLanguage(generatorName) {
909026
909062
  return getGeneratorLanguage(generatorName);
909027
909063
  }
909064
+ function selectFernSdkGenApiRoute(generatorInvocation) {
909065
+ const language = getFernSdkGenApiLanguage(generatorInvocation.name);
909066
+ if (language == null) {
909067
+ return void 0;
909068
+ }
909069
+ return validateGeneratorConfigCompatibility({
909070
+ generatorId: generatorInvocation.name,
909071
+ language: generatorInvocation.language ?? language,
909072
+ requestedVersion: generatorInvocation.version,
909073
+ configKind: "legacy-fern"
909074
+ });
909075
+ }
909028
909076
  function mapFernSdkGenApiOutput(generatorInvocation) {
909029
909077
  const outputMode = generatorInvocation.outputMode;
909030
909078
  switch (outputMode.type) {
@@ -909226,6 +909274,7 @@ function isEligibleForFernSdkGenApi(candidate) {
909226
909274
  var FernSdkGenApiBatch = class {
909227
909275
  expectedTargets;
909228
909276
  participants = [];
909277
+ removedTargetIds = /* @__PURE__ */ new Set();
909229
909278
  terminalError;
909230
909279
  dispatched = false;
909231
909280
  constructor(expectedTargets) {
@@ -909238,6 +909287,9 @@ var FernSdkGenApiBatch = class {
909238
909287
  if (this.terminalError != null) {
909239
909288
  return Promise.reject(this.terminalError);
909240
909289
  }
909290
+ if (parameters2.targetIdSeed != null && this.removedTargetIds.has(parameters2.targetIdSeed)) {
909291
+ return Promise.reject(new Error(`Fern sdk-gen-api target ${parameters2.targetIdSeed} was removed`));
909292
+ }
909241
909293
  if (this.dispatched) {
909242
909294
  return Promise.reject(new Error("The Fern sdk-gen-api batch was already dispatched"));
909243
909295
  }
@@ -909254,6 +909306,22 @@ var FernSdkGenApiBatch = class {
909254
909306
  this.expectedTargets -= 1;
909255
909307
  this.dispatchIfReady();
909256
909308
  }
909309
+ /** Removes one failed automation target while preserving undispatched siblings. */
909310
+ remove(targetIdSeed, error50) {
909311
+ if (this.dispatched || this.terminalError != null) {
909312
+ return false;
909313
+ }
909314
+ if (this.removedTargetIds.has(targetIdSeed)) {
909315
+ return false;
909316
+ }
909317
+ this.removedTargetIds.add(targetIdSeed);
909318
+ const participantIndex = this.participants.findIndex((participant2) => participant2.targetIdSeed === targetIdSeed);
909319
+ const [participant] = participantIndex >= 0 ? this.participants.splice(participantIndex, 1) : [];
909320
+ participant?.reject(error50);
909321
+ this.expectedTargets -= 1;
909322
+ this.dispatchIfReady();
909323
+ return true;
909324
+ }
909257
909325
  /** Prevents siblings waiting at the batch barrier from hanging if preparation of one fails. */
909258
909326
  cancel(error50) {
909259
909327
  if (this.dispatched || this.terminalError != null) {
@@ -909265,7 +909333,7 @@ var FernSdkGenApiBatch = class {
909265
909333
  }
909266
909334
  }
909267
909335
  dispatchIfReady() {
909268
- if (this.dispatched || this.terminalError != null || this.participants.length !== this.expectedTargets) {
909336
+ if (this.dispatched || this.terminalError != null || this.expectedTargets === 0 || this.participants.length !== this.expectedTargets) {
909269
909337
  return;
909270
909338
  }
909271
909339
  this.dispatched = true;
@@ -909291,6 +909359,72 @@ var FernSdkGenApiBatch = class {
909291
909359
  }
909292
909360
  }
909293
909361
  };
909362
+ var FernSdkGenApiPreparationBatch = class {
909363
+ expectedTargetIds;
909364
+ settledTargetIds = /* @__PURE__ */ new Set();
909365
+ waiters = [];
909366
+ preflightParticipants = [];
909367
+ terminalError;
909368
+ didRunPreflight = false;
909369
+ constructor(targetIds) {
909370
+ this.expectedTargetIds = new Set(targetIds);
909371
+ if (this.expectedTargetIds.size !== targetIds.length) {
909372
+ throw new Error("Fern sdk-gen-api preparation target IDs must be unique");
909373
+ }
909374
+ }
909375
+ ready(targetId, preflightParameters) {
909376
+ this.assertExpected(targetId);
909377
+ if (this.settledTargetIds.has(targetId)) {
909378
+ throw new Error(`Fern sdk-gen-api target ${targetId} prepared more than once`);
909379
+ }
909380
+ this.settledTargetIds.add(targetId);
909381
+ if (preflightParameters != null) {
909382
+ this.preflightParticipants.push(preflightParameters);
909383
+ }
909384
+ return new Promise((resolve15, reject) => {
909385
+ this.waiters.push({ resolve: resolve15, reject });
909386
+ this.finishIfSettled();
909387
+ });
909388
+ }
909389
+ /** Returns true only when this call newly settles a target that failed before preparation. */
909390
+ fail(targetId, error50, isolateFailure) {
909391
+ this.assertExpected(targetId);
909392
+ if (this.settledTargetIds.has(targetId)) {
909393
+ return false;
909394
+ }
909395
+ this.settledTargetIds.add(targetId);
909396
+ if (!isolateFailure) {
909397
+ this.terminalError = error50;
909398
+ }
909399
+ this.finishIfSettled();
909400
+ return true;
909401
+ }
909402
+ assertExpected(targetId) {
909403
+ if (!this.expectedTargetIds.has(targetId)) {
909404
+ throw new Error(`Unexpected Fern sdk-gen-api preparation target ${targetId}`);
909405
+ }
909406
+ }
909407
+ finishIfSettled() {
909408
+ if (this.settledTargetIds.size !== this.expectedTargetIds.size) {
909409
+ return;
909410
+ }
909411
+ if (!this.didRunPreflight && this.terminalError == null && this.preflightParticipants.length > 0) {
909412
+ this.didRunPreflight = true;
909413
+ try {
909414
+ prepareFernSdkGenApiSubmission(this.preflightParticipants);
909415
+ } catch (error50) {
909416
+ this.terminalError = error50;
909417
+ }
909418
+ }
909419
+ for (const waiter of this.waiters) {
909420
+ if (this.terminalError != null) {
909421
+ waiter.reject(this.terminalError);
909422
+ } else {
909423
+ waiter.resolve();
909424
+ }
909425
+ }
909426
+ }
909427
+ };
909294
909428
  async function runFernSdkGenApiBuild(parameters2) {
909295
909429
  const [result] = await executeFernSdkGenApiBuild([parameters2]);
909296
909430
  if (result?.status === "fulfilled") {
@@ -909298,7 +909432,12 @@ async function runFernSdkGenApiBuild(parameters2) {
909298
909432
  }
909299
909433
  throw result?.reason ?? new Error("sdk-gen-api did not return the requested target");
909300
909434
  }
909301
- async function executeFernSdkGenApiBuild(participants) {
909435
+ function validateFernSdkGenApiTargetCount(targetCount) {
909436
+ if (targetCount > MAX_PAYLOADS) {
909437
+ throw new Error(`sdk-gen-api supports at most ${MAX_PAYLOADS} target payloads per build; received ${targetCount}`);
909438
+ }
909439
+ }
909440
+ function prepareFernSdkGenApiSubmission(participants) {
909302
909441
  const first3 = participants[0];
909303
909442
  if (first3 == null) {
909304
909443
  throw new Error("Cannot submit an empty Fern sdk-gen-api build");
@@ -909325,13 +909464,20 @@ async function executeFernSdkGenApiBuild(participants) {
909325
909464
  targets: participants.map((participant) => ({
909326
909465
  generatorInvocation: participant.generatorInvocation,
909327
909466
  sdkVersion: participant.sdkVersion,
909467
+ apiVersion: participant.apiVersion,
909328
909468
  targetIdSeed: participant.targetIdSeed,
909469
+ sourceSpecIndexes: participant.sourceSpecIndexes,
909329
909470
  audiences: participant.audiences,
909330
- runtimeBundle: participant.runtimeBundle
909471
+ payload: participant.payload
909331
909472
  }))
909332
909473
  });
909474
+ const serializedRequest = JSON.stringify(request7);
909475
+ const serializedRequestBytes = Buffer.byteLength(serializedRequest, "utf8");
909476
+ if (serializedRequestBytes > MAX_REQUEST_FIELD_BYTES) {
909477
+ 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 });
909478
+ }
909333
909479
  const form = new import_form_data4.default();
909334
- form.append("request", JSON.stringify(request7));
909480
+ form.append("request", serializedRequest);
909335
909481
  form.append("sources", first3.specsTarGzBuffer, {
909336
909482
  filename: "specs.tar.gz",
909337
909483
  contentType: "application/gzip"
@@ -909339,17 +909485,22 @@ async function executeFernSdkGenApiBuild(participants) {
909339
909485
  participants.forEach((participant, index3) => {
909340
909486
  const target = request7.targets[index3];
909341
909487
  if (target == null) {
909342
- throw new Error(`Cannot pair sdk-gen-api runtime bundle at index ${index3} with a target`);
909488
+ throw new Error(`Cannot pair sdk-gen-api payload at index ${index3} with a target`);
909343
909489
  }
909344
- form.append("bundles", participant.runtimeBundle, {
909345
- filename: `${target.targetId}.json.gz`,
909346
- contentType: "application/gzip"
909490
+ const isRuntimeBundle = participant.payload.payloadKind === "fern-runtime-bundle";
909491
+ form.append("payloads", participant.payload.body, {
909492
+ filename: `${target.targetId}.json${isRuntimeBundle ? ".gz" : ""}`,
909493
+ contentType: isRuntimeBundle ? "application/gzip" : "application/json"
909347
909494
  });
909348
909495
  });
909349
909496
  const multipartBodyLength = form.getLengthSync();
909350
909497
  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 });
909498
+ 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
909499
  }
909500
+ return { first: first3, origin: origin2, request: request7, form };
909501
+ }
909502
+ async function executeFernSdkGenApiBuild(participants) {
909503
+ const { first: first3, origin: origin2, request: request7, form } = prepareFernSdkGenApiSubmission(participants);
909353
909504
  let buildId;
909354
909505
  try {
909355
909506
  const response = await axios_default.post(`${origin2}/v1/fern/build`, form, {
@@ -909427,7 +909578,7 @@ function assertGeneratorConfigCompatibility(participants) {
909427
909578
  generatorId: generatorInvocation.name,
909428
909579
  language,
909429
909580
  requestedVersion: generatorInvocation.version,
909430
- configKind: "legacy-fern"
909581
+ configKind: participant.payload.payloadKind === "fern-runtime-bundle" ? "legacy-fern" : "sdk-config-v1"
909431
909582
  });
909432
909583
  } catch (error50) {
909433
909584
  if (!(error50 instanceof GeneratorConfigCompatibilityError)) {
@@ -909452,8 +909603,8 @@ function formatGeneratorConfigCompatibilityError(error50) {
909452
909603
  `retryable=${error50.retryable}`,
909453
909604
  `recommendedAction=${error50.recommendedAction}`
909454
909605
  ].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}`;
909606
+ const migrationHint = error50.recommendedAction === "USE_SDK_CONFIG_V1" ? " Run `fern sdk migrate --output <path>` to migrate this SDK configuration before using this generator version." : "";
909607
+ return `Cannot submit SDK generation to sdk-gen-api: ${error50.message} [${diagnostic}].${migrationHint}`;
909457
909608
  }
909458
909609
  function compareFernSdkGenApiParticipants(left3, right3) {
909459
909610
  const seedComparison = TARGET_ID_SEED_COLLATOR.compare(left3.targetIdSeed ?? "", right3.targetIdSeed ?? "");
@@ -909471,20 +909622,25 @@ function compareFernSdkGenApiParticipants(left3, right3) {
909471
909622
  return left3.sdkVersion.localeCompare(right3.sdkVersion);
909472
909623
  }
909473
909624
  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 });
909625
+ if (participants.length > MAX_PAYLOADS) {
909626
+ 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
909627
  }
909477
909628
  if (first3.specsTarGzBuffer.length > MAX_SOURCE_COMPRESSED_BYTES) {
909478
909629
  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
909630
  }
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 });
909631
+ const oversizedPayloadIndex = participants.findIndex((participant) => participant.payload.body.length > (participant.payload.payloadKind === "fern-runtime-bundle" ? MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES : MAX_PAYLOAD_BYTES));
909632
+ if (oversizedPayloadIndex >= 0) {
909633
+ const participant = participants[oversizedPayloadIndex];
909634
+ const maxBytes = participant?.payload.payloadKind === "fern-runtime-bundle" ? MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES : MAX_PAYLOAD_BYTES;
909635
+ 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
909636
  }
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 });
909637
+ const totalUploadFileBytes = participants.reduce((total, participant) => total + participant.payload.body.length, first3.specsTarGzBuffer.length);
909638
+ if (totalUploadFileBytes > MAX_TOTAL_UPLOAD_FILE_BYTES) {
909639
+ 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 });
909640
+ }
909641
+ const totalRuntimeBundleBytes = participants.reduce((total, participant) => participant.payload.payloadKind === "fern-runtime-bundle" ? total + participant.payload.body.length : total, 0);
909642
+ if (totalRuntimeBundleBytes > MAX_TOTAL_RUNTIME_BUNDLE_COMPRESSED_BYTES) {
909643
+ 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
909644
  }
909489
909645
  getBoundedGzipSize({
909490
909646
  buffer: first3.specsTarGzBuffer,
@@ -909492,19 +909648,23 @@ function validateProtocolInputs(participants, first3) {
909492
909648
  label: "source archive",
909493
909649
  context: first3.context
909494
909650
  });
909495
- let totalDecompressedBundleBytes = 0;
909651
+ let totalPayloadBytes = 0;
909496
909652
  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()}`,
909653
+ totalPayloadBytes += participant.payload.payloadKind === "fern-runtime-bundle" ? getBoundedGzipSize({
909654
+ buffer: participant.payload.body,
909655
+ maxBytes: MAX_PAYLOAD_BYTES,
909656
+ label: payloadLabel(participant, index3),
909501
909657
  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 });
909658
+ }) : participant.payload.body.length;
909659
+ if (totalPayloadBytes > MAX_TOTAL_PAYLOAD_BYTES) {
909660
+ 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
909661
  }
909506
909662
  }
909507
909663
  }
909664
+ function payloadLabel(participant, index3) {
909665
+ const kind = participant?.payload.payloadKind ?? "target payload";
909666
+ return `${kind} ${participant?.targetIdSeed ?? index3.toString()}`;
909667
+ }
909508
909668
  function getBoundedGzipSize({ buffer, maxBytes, label, context: context3 }) {
909509
909669
  let decompressed;
909510
909670
  try {
@@ -909587,23 +909747,41 @@ function createFernSdkGenApiBatchRequest({ apiName, organization, cliVersion, sp
909587
909747
  if (targets2.length === 0) {
909588
909748
  throw new Error("Cannot create an empty Fern sdk-gen-api request");
909589
909749
  }
909590
- const requestTargets = targets2.map(({ generatorInvocation, sdkVersion, targetIdSeed, audiences }, index3) => {
909750
+ const apiInputs = [];
909751
+ const apiInputIds = targets2.map(({ targetIdSeed, sourceSpecIndexes }, index3) => {
909752
+ if (sourceSpecIndexes == null) {
909753
+ if (!apiInputs.some((input3) => input3.id === "default")) {
909754
+ apiInputs.push({ id: "default", specIndexes: "all" });
909755
+ }
909756
+ return "default";
909757
+ }
909758
+ const id = `target-${targetIdSeed ?? index3.toString()}`;
909759
+ apiInputs.push({ id, specIndexes: sourceSpecIndexes });
909760
+ return id;
909761
+ });
909762
+ const requestTargets = targets2.map(({ generatorInvocation, sdkVersion, apiVersion, targetIdSeed, audiences, payload }, index3) => {
909591
909763
  const language = getFernSdkGenApiLanguage(generatorInvocation.name);
909592
909764
  if (language == null) {
909593
909765
  throw new Error(`Unsupported Fern SDK generator: ${generatorInvocation.name}`);
909594
909766
  }
909595
909767
  const output2 = mapFernSdkGenApiOutput(generatorInvocation);
909768
+ const packageConfig = payload.package ?? output2.package;
909596
909769
  const targetId = (0, import_crypto10.createHash)("sha256").update(`${apiName}:${generatorInvocation.name}:${generatorInvocation.version}:${targetIdSeed ?? index3.toString()}`).digest("hex").slice(0, 20);
909597
909770
  return {
909598
909771
  targetId,
909599
- apiInputId: "default",
909772
+ apiInputId: apiInputIds[index3] ?? "default",
909600
909773
  language,
909601
- sdk: { name: apiName, version: sdkVersion },
909774
+ sdk: {
909775
+ name: apiName,
909776
+ version: sdkVersion,
909777
+ ...apiVersion != null ? { apiVersion } : {}
909778
+ },
909602
909779
  fernGenerator: {
909603
909780
  id: generatorInvocation.name,
909604
909781
  version: generatorInvocation.version
909605
909782
  },
909606
- ...output2.package != null ? { package: output2.package } : {},
909783
+ payloadKind: payload.payloadKind,
909784
+ ...packageConfig != null ? { package: packageConfig } : {},
909607
909785
  invocation: {
909608
909786
  customConfig: stripCliConfigKeys(generatorInvocation.config) ?? {},
909609
909787
  keywords: generatorInvocation.keywords ?? [],
@@ -909622,15 +909800,14 @@ function createFernSdkGenApiBatchRequest({ apiName, organization, cliVersion, sp
909622
909800
  requestedOutput: output2.requestedOutput
909623
909801
  };
909624
909802
  });
909625
- const apiInputs = [{ id: "default", specIndexes: "all" }];
909626
- const runtimeBundleHashes = targets2.map((target) => (0, import_crypto10.createHash)("sha256").update(target.runtimeBundle).digest("hex"));
909803
+ const payloadHashes = targets2.map((target) => (0, import_crypto10.createHash)("sha256").update(target.payload.body).digest("hex"));
909627
909804
  const idempotencyKey = (0, import_crypto10.createHash)("sha256").update(specsTarGzBuffer).update(JSON.stringify({
909628
909805
  protocolVersion: 2,
909629
909806
  organization,
909630
909807
  apiName,
909631
909808
  apiInputs,
909632
909809
  targets: requestTargets,
909633
- runtimeBundleHashes
909810
+ payloadHashes
909634
909811
  })).digest("hex");
909635
909812
  return {
909636
909813
  protocolVersion: 2,
@@ -910758,6 +910935,33 @@ async function downloadFileForTask({ s3PreSignedReadUrl, absolutePathToLocalOutp
910758
910935
  await (0, import_promises122.pipeline)(request7.data, (0, import_fs37.createWriteStream)(absolutePathToLocalOutput));
910759
910936
  }
910760
910937
 
910938
+ // ../generation/remote-generation/remote-workspace-runner/lib/fernSdkGenApiSourceArchive.js
910939
+ function validateFernSdkGenApiSourceCompatibility(route, sourceArchive) {
910940
+ if (route.payloadKind !== "sdk-config-v1" || route.configKind !== "sdk-config-v1") {
910941
+ return;
910942
+ }
910943
+ if (sourceArchive.specIndexes.length === 0) {
910944
+ throw new Error("SDK Config v1 requires at least one effective Fern source spec");
910945
+ }
910946
+ const seenIndexes = /* @__PURE__ */ new Set();
910947
+ for (const manifestIndex of sourceArchive.specIndexes) {
910948
+ if (seenIndexes.has(manifestIndex)) {
910949
+ throw new Error(`Fern target source selection contains duplicate manifest index ${manifestIndex}`);
910950
+ }
910951
+ seenIndexes.add(manifestIndex);
910952
+ const source2 = sourceArchive.manifest.specs[manifestIndex];
910953
+ if (source2 == null) {
910954
+ throw new Error(`Fern source manifest does not contain selected index ${manifestIndex}`);
910955
+ }
910956
+ if (!isSupportedSourceType(source2.type)) {
910957
+ 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.`);
910958
+ }
910959
+ }
910960
+ }
910961
+ function isSupportedSourceType(type7) {
910962
+ return type7 === "openapi" || type7 === "asyncapi" || type7 === "graphql";
910963
+ }
910964
+
910761
910965
  // ../generation/remote-generation/remote-workspace-runner/lib/resolveAutoDiscoveredFernignorePath.js
910762
910966
  init_lib12();
910763
910967
  init_lib8();
@@ -911317,26 +911521,25 @@ var SourceUploader = class {
911317
911521
  };
911318
911522
 
911319
911523
  // ../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 }) {
911524
+ 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
911525
  const fdr = createFdrService({ token: token.value });
911322
911526
  const fdrOrigin = "https://registry-dev2.buildwithfern.com";
911323
911527
  const isAirGapped = await detectAirGappedMode(`${fdrOrigin}/health`, interactiveTaskContext.logger);
911324
911528
  const packageName = generators_yml_exports.getPackageName({ generatorInvocation }) ?? (generatorInvocation.outputMode.type === "downloadFiles" ? getPackageNameFromGeneratorConfig(generatorInvocation) : void 0);
911325
911529
  const isPreview = isPreviewOverride ?? absolutePathToPreview != null;
911326
- const substituteEnvVars = (stringOrObject) => replaceEnvVariables(stringOrObject, {
911327
- onError: (e2) => {
911530
+ const resolvedWhitelabel = whitelabel == null ? void 0 : replaceEnvVariables(whitelabel, {
911531
+ onError: (error50) => {
911328
911532
  if (!isPreview && requireEnvVars) {
911329
- interactiveTaskContext.failAndThrow(void 0, e2, {
911533
+ interactiveTaskContext.failAndThrow(void 0, error50, {
911330
911534
  code: CliError.Code.EnvironmentError
911331
911535
  });
911332
911536
  }
911333
911537
  }
911334
911538
  }, { substituteAsEmpty: isPreview });
911335
- const generatorInvocationWithEnvVarSubstitutions = substituteEnvVars(generatorInvocation);
911336
911539
  const dynamicGeneratorConfig = getDynamicGeneratorConfig({
911337
911540
  apiName: workspace.definition.rootApiFile.contents.name,
911338
911541
  organization,
911339
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions
911542
+ generatorInvocation
911340
911543
  });
911341
911544
  const resolvedVersion = version7 ?? await computeSemanticVersion({ packageName, generatorInvocation });
911342
911545
  if (version7 != null) {
@@ -911387,10 +911590,43 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911387
911590
  ciProvider: detectCiProvider()
911388
911591
  }
911389
911592
  });
911390
- const venus = createVenusService({ token: token.value });
911593
+ let sdkGenApiCandidate;
911594
+ const sdkGenApiLanguage = getFernSdkGenApiLanguage(generatorInvocation.name);
911595
+ if (sdkGenApiRoute != null) {
911596
+ if (replay?.enabled === true) {
911597
+ return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support replay", void 0, {
911598
+ code: CliError.Code.ConfigError
911599
+ });
911600
+ }
911601
+ if (generateFullProject === true) {
911602
+ return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support full-project generation", void 0, { code: CliError.Code.ConfigError });
911603
+ }
911604
+ const candidate = {
911605
+ generatorInvocation,
911606
+ sdkVersion: resolvedVersion,
911607
+ specsTarGzBuffer,
911608
+ whitelabel
911609
+ };
911610
+ if (!isEligibleForFernSdkGenApi(candidate)) {
911611
+ 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}`;
911612
+ return interactiveTaskContext.failAndThrow(`Cannot submit SDK generation to sdk-gen-api: ${reason}`, void 0, {
911613
+ code: CliError.Code.ConfigError
911614
+ });
911615
+ }
911616
+ sdkGenApiCandidate = candidate;
911617
+ if (sdkGenApiRoute.payloadKind === "sdk-config-v1") {
911618
+ 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 });
911619
+ }
911620
+ if (sdkGenApiTargetIdSeed == null) {
911621
+ throw new Error("sdk-gen-api target is missing its preparation ID");
911622
+ }
911623
+ await sdkGenApiPreparationBatch?.ready(sdkGenApiTargetIdSeed);
911624
+ }
911625
+ const requiresFdrRegistration = sdkGenApiRoute?.payloadKind !== "sdk-config-v1";
911391
911626
  let generateOauthClients = false;
911392
911627
  let generatePaginatedClients = false;
911393
- if (!isAirGapped) {
911628
+ if (!isAirGapped && requiresFdrRegistration) {
911629
+ const venus = createVenusService({ token: token.value });
911394
911630
  const orgResponse = await venus.organization.get({ orgId: projectConfig.organization });
911395
911631
  if (orgResponse.ok) {
911396
911632
  if (orgResponse.body.isWhitelabled) {
@@ -911404,50 +911640,52 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911404
911640
  generatePaginatedClients = orgResponse.body.paginationEnabled ?? false;
911405
911641
  }
911406
911642
  }
911407
- const sources = workspace.getSources();
911408
911643
  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
911644
+ if (requiresFdrRegistration) {
911645
+ const sources = workspace.getSources();
911646
+ let sourceUploads;
911647
+ const apiDefinition = convertIrToFdrApi({
911648
+ ir: ir3,
911649
+ snippetsConfig: {
911650
+ typescriptSdk: void 0,
911651
+ pythonSdk: void 0,
911652
+ javaSdk: void 0,
911653
+ rubySdk: void 0,
911654
+ goSdk: void 0,
911655
+ csharpSdk: void 0,
911656
+ phpSdk: void 0,
911657
+ swiftSdk: void 0,
911658
+ rustSdk: void 0
911659
+ },
911660
+ context: interactiveTaskContext
911431
911661
  });
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)}`);
911662
+ try {
911663
+ const response = await fdr.api.register.registerApiDefinition({
911664
+ orgId: FdrAPI_exports.OrgId(organization),
911665
+ apiId: FdrAPI_exports.ApiId(getOriginalName(ir3.apiName)),
911666
+ definition: apiDefinition,
911667
+ sources: sources.length > 0 ? convertToFdrApiDefinitionSources(sources) : void 0
911668
+ });
911669
+ fdrApiDefinitionId = response.apiDefinitionId;
911670
+ sourceUploads = response.sources ?? void 0;
911671
+ } catch (error50) {
911672
+ const sourceUploader2 = new SourceUploader(interactiveTaskContext, sources);
911673
+ if (sourceUploader2.sourceTypes.has("protobuf")) {
911674
+ interactiveTaskContext.failAndThrow(`Failed to register API definition: ${JSON.stringify(error50)}`);
911675
+ }
911676
+ }
911677
+ const sourceUploader = new SourceUploader(interactiveTaskContext, sources);
911678
+ if (sourceUploads == null && sourceUploader.sourceTypes.has("protobuf")) {
911679
+ interactiveTaskContext.failAndThrow("Did not successfully upload Protobuf source files.", void 0, {
911680
+ code: CliError.Code.NetworkError
911681
+ });
911682
+ }
911683
+ if (sourceUploads != null) {
911684
+ interactiveTaskContext.logger.debug("Uploading source files ...");
911685
+ const sourceConfig = await sourceUploader.uploadSources(sourceUploads);
911686
+ interactiveTaskContext.logger.debug("Setting IR source configuration ...");
911687
+ ir3.sourceConfig = sourceConfig;
911438
911688
  }
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
911689
  }
911452
911690
  if (dynamicIrOnly) {
911453
911691
  interactiveTaskContext.logger.info("Dynamic IR only mode: skipping SDK generation and uploading dynamic IR only");
@@ -911498,7 +911736,7 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911498
911736
  ...ir3,
911499
911737
  fdrApiDefinitionId,
911500
911738
  publishConfig: getPublishConfig({
911501
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911739
+ generatorInvocation,
911502
911740
  version: resolvedVersion,
911503
911741
  userProvidedVersion: version7,
911504
911742
  packageName,
@@ -911508,76 +911746,56 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911508
911746
  })
911509
911747
  };
911510
911748
  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
- });
911749
+ if (sdkGenApiRoute != null) {
911750
+ if (sdkGenApiCandidate == null) {
911751
+ throw new Error("sdk-gen-api target passed preflight without an eligible candidate");
911519
911752
  }
911520
- if (generateFullProject === true) {
911521
- return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support full-project generation", void 0, { code: CliError.Code.ConfigError });
911753
+ if (sdkGenApiRoute.payloadKind !== "fern-runtime-bundle") {
911754
+ throw new Error("Legacy Fern generation reached sdk-gen-api without a Fern runtime bundle route");
911522
911755
  }
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
- });
911534
- }
911535
- if (verify2 === true) {
911536
- interactiveTaskContext.logger.warn("sdk-gen-api does not yet run Fern's post-generation verification step");
911537
- }
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
911756
  const parameters2 = {
911550
911757
  apiName: getOriginalName(ir3.apiName),
911551
911758
  organization,
911552
911759
  cliVersion: workspace.cliVersion,
911553
- generatorInvocation: candidate.generatorInvocation,
911554
- sdkVersion: candidate.sdkVersion,
911760
+ generatorInvocation: sdkGenApiCandidate.generatorInvocation,
911761
+ sdkVersion: sdkGenApiCandidate.sdkVersion,
911762
+ apiVersion: ir3.specVersion,
911555
911763
  token,
911556
- specsTarGzBuffer: candidate.specsTarGzBuffer,
911557
- runtimeBundle,
911764
+ specsTarGzBuffer: sdkGenApiCandidate.specsTarGzBuffer,
911765
+ payload: {
911766
+ payloadKind: sdkGenApiRoute.payloadKind,
911767
+ body: await prepareFernSdkGenApiRuntimeBundle({
911768
+ apiName: getOriginalName(ir3.apiName),
911769
+ organization,
911770
+ generatorInvocation: sdkGenApiCandidate.generatorInvocation,
911771
+ sdkVersion: sdkGenApiCandidate.sdkVersion,
911772
+ intermediateRepresentation: enrichedIntermediateRepresentation,
911773
+ irVersionOverride,
911774
+ generateOauthClients,
911775
+ generatePaginatedClients,
911776
+ context: interactiveTaskContext
911777
+ })
911778
+ },
911558
911779
  absolutePathToPreview,
911559
911780
  context: interactiveTaskContext,
911560
911781
  targetIdSeed: sdkGenApiTargetIdSeed,
911782
+ sourceSpecIndexes: sdkGenApiSourceArchive?.specIndexes,
911561
911783
  audiences: audiences.type === "select" ? audiences.audiences : void 0,
911562
911784
  skipFernignore
911563
911785
  };
911564
911786
  result = await (sdkGenApiBatch?.run(parameters2) ?? runFernSdkGenApiBuild(parameters2));
911565
- usedSdkGenApi = true;
911566
911787
  } else {
911567
- sdkGenApiBatch?.skip();
911568
- }
911569
- if (!usedSdkGenApi) {
911570
911788
  const job = await createAndStartJob({
911571
911789
  projectConfig,
911572
911790
  workspace,
911573
911791
  organization,
911574
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911792
+ generatorInvocation,
911575
911793
  context: interactiveTaskContext,
911576
911794
  version: resolvedVersion,
911577
911795
  intermediateRepresentation: enrichedIntermediateRepresentation,
911578
911796
  shouldLogS3Url,
911579
911797
  token,
911580
- whitelabel: whitelabel != null ? substituteEnvVars(whitelabel) : void 0,
911798
+ whitelabel: resolvedWhitelabel,
911581
911799
  replay,
911582
911800
  irVersionOverride,
911583
911801
  absolutePathToPreview,
@@ -911784,10 +912002,51 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911784
912002
  effectiveOccurrenceTracker.recordOccurrences(generatorGroup.generators);
911785
912003
  }
911786
912004
  const generatorsYmlAbsolutePath = workspace.generatorsConfiguration?.absolutePathToConfiguration;
911787
- const sdkGenApiCandidateIndexes = new Set(isFernSdkGenApiEnabled() ? generatorGroup.generators.flatMap((generator, index3) => getFernSdkGenApiLanguage(generator.name) != null ? [index3] : []) : []);
912005
+ const routePreparation = prepareFernSdkGenApiRoutes({
912006
+ generators: generatorGroup.generators,
912007
+ enabled: isFernSdkGenApiEnabled(),
912008
+ requireEnvVars,
912009
+ isPreview: isPreview ?? absolutePathToPreview != null,
912010
+ verify: verify2,
912011
+ skipIfNoDiff,
912012
+ autoMerge
912013
+ });
912014
+ const sdkGenApiRoutes = routePreparation.map((result) => result.route);
912015
+ const resolvedGenerators = routePreparation.map((result) => result.generatorInvocation);
912016
+ const routeErrors = routePreparation.map((result) => result.error);
912017
+ if (automation == null) {
912018
+ throwFirstPreflightError(routeErrors, generatorGroup.generators);
912019
+ }
912020
+ const sourceRequests = resolvedGenerators.flatMap((generatorInvocation, generatorIndex) => routePreparation[generatorIndex]?.error == null ? [{ generatorIndex, generatorInvocation, sdkGenApiRoute: sdkGenApiRoutes[generatorIndex] }] : []);
912021
+ let sourceResolution = { sourceArchives: /* @__PURE__ */ new Map(), errors: /* @__PURE__ */ new Map() };
912022
+ if (sourceRequests.length > 0) {
912023
+ try {
912024
+ sourceResolution = await getSpecsTarGzBuffer?.(sourceRequests) ?? sourceResolution;
912025
+ } catch (error50) {
912026
+ sourceResolution = {
912027
+ sourceArchives: /* @__PURE__ */ new Map(),
912028
+ errors: new Map(sourceRequests.map((request7) => [request7.generatorIndex, error50]))
912029
+ };
912030
+ }
912031
+ }
912032
+ const sourcePreflight = preflightFernSdkGenApiSources({
912033
+ generators: resolvedGenerators,
912034
+ routes: sdkGenApiRoutes,
912035
+ routeErrors,
912036
+ sourceResolution
912037
+ });
912038
+ const sourceArchives = sourcePreflight.sourceArchives;
912039
+ const preflightErrors = routePreparation.map((result, index3) => result.error ?? sourcePreflight.preflightErrors[index3]);
912040
+ if (automation == null) {
912041
+ throwFirstPreflightError(preflightErrors, generatorGroup.generators);
912042
+ }
912043
+ const sdkGenApiCandidateIndexes = getFernSdkGenApiCandidateIndexes(sdkGenApiRoutes, preflightErrors);
912044
+ validateFernSdkGenApiTargetCount(sdkGenApiCandidateIndexes.size);
911788
912045
  const sdkGenApiBatch = sdkGenApiCandidateIndexes.size > 1 ? new FernSdkGenApiBatch(sdkGenApiCandidateIndexes.size) : void 0;
912046
+ const sdkGenApiPreparationBatch = sdkGenApiCandidateIndexes.size > 0 ? new FernSdkGenApiPreparationBatch([...sdkGenApiCandidateIndexes].map(String)) : void 0;
911789
912047
  const results = await Promise.all(generatorGroup.generators.map((generatorInvocation, generatorIndex) => context3.runInteractiveTask({ name: generatorInvocation.name }, (interactiveTaskContext) => generateOne({
911790
912048
  generatorInvocation,
912049
+ resolvedGeneratorInvocation: resolvedGenerators[generatorIndex] ?? generatorInvocation,
911791
912050
  interactiveTaskContext,
911792
912051
  // Closed-over state + params passed through to the per-generator worker.
911793
912052
  projectConfig,
@@ -911821,7 +912080,10 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911821
912080
  generatorsYmlAbsolutePath,
911822
912081
  occurrenceTracker: effectiveOccurrenceTracker,
911823
912082
  loginCommand,
911824
- getSpecsTarGzBuffer,
912083
+ specsTarGzArchive: sourceArchives[generatorIndex],
912084
+ sdkGenApiPreflightError: preflightErrors[generatorIndex],
912085
+ sdkGenApiRoute: sdkGenApiRoutes[generatorIndex],
912086
+ sdkGenApiPreparationBatch: sdkGenApiCandidateIndexes.has(generatorIndex) ? sdkGenApiPreparationBatch : void 0,
911825
912087
  sdkGenApiBatch: sdkGenApiCandidateIndexes.has(generatorIndex) ? sdkGenApiBatch : void 0,
911826
912088
  sdkGenApiTargetIdSeed: generatorIndex.toString(),
911827
912089
  generateFullProject,
@@ -911834,11 +912096,105 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911834
912096
  snippetsProducedBy
911835
912097
  };
911836
912098
  }
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 }) {
912099
+ function prepareFernSdkGenApiRoutes({ generators, enabled, requireEnvVars, isPreview, verify: verify2, skipIfNoDiff, autoMerge }) {
912100
+ return generators.map((generatorInvocation) => {
912101
+ let resolved = generatorInvocation;
912102
+ try {
912103
+ resolved = replaceEnvVariables(generatorInvocation, {
912104
+ onError: (error50) => {
912105
+ if (!isPreview && requireEnvVars) {
912106
+ throw error50;
912107
+ }
912108
+ }
912109
+ }, { substituteAsEmpty: isPreview });
912110
+ const route = selectFernSdkGenApiRoute(resolved);
912111
+ if (!enabled) {
912112
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912113
+ }
912114
+ const unsupportedOutput = getFernSdkGenApiUnsupportedOutput({
912115
+ generatorInvocation: resolved,
912116
+ verify: verify2,
912117
+ skipIfNoDiff,
912118
+ autoMerge
912119
+ });
912120
+ if (route != null && unsupportedOutput != null) {
912121
+ if (route.configKind === "legacy-fern") {
912122
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912123
+ }
912124
+ 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.`);
912125
+ }
912126
+ return {
912127
+ generatorInvocation: resolved,
912128
+ route,
912129
+ error: void 0
912130
+ };
912131
+ } catch (error50) {
912132
+ if (!enabled && error50 instanceof GeneratorConfigCompatibilityError && error50.code === "INVALID_GENERATOR_VERSION") {
912133
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912134
+ }
912135
+ const routeError = error50 instanceof GeneratorConfigCompatibilityError ? new CliError({
912136
+ message: formatGeneratorConfigCompatibilityError(error50),
912137
+ code: CliError.Code.ConfigError
912138
+ }) : error50;
912139
+ return { generatorInvocation: resolved, route: void 0, error: routeError };
912140
+ }
912141
+ });
912142
+ }
912143
+ function getFernSdkGenApiUnsupportedOutput({ generatorInvocation, verify: verify2, skipIfNoDiff, autoMerge }) {
912144
+ const unsupported = [];
912145
+ if (generatorInvocation.outputMode.type !== "downloadFiles") {
912146
+ unsupported.push(`${generatorInvocation.outputMode.type} delivery requires Fern-managed GitHub or registry credentials that sdk-gen-api cannot resolve`);
912147
+ }
912148
+ if (verify2 === true) {
912149
+ unsupported.push("verify=true is not implemented by sdk-gen-api");
912150
+ }
912151
+ if (skipIfNoDiff === true) {
912152
+ unsupported.push("skipIfNoDiff=true is not implemented by sdk-gen-api");
912153
+ }
912154
+ if (autoMerge === true) {
912155
+ unsupported.push("autoMerge=true is not implemented by sdk-gen-api");
912156
+ }
912157
+ return unsupported.length > 0 ? unsupported.join("; ") : void 0;
912158
+ }
912159
+ function preflightFernSdkGenApiSources({ generators, routes, routeErrors, sourceResolution }) {
912160
+ return {
912161
+ sourceArchives: generators.map((_5, index3) => sourceResolution.sourceArchives.get(index3)),
912162
+ preflightErrors: generators.map((_5, index3) => {
912163
+ if (routeErrors?.[index3] != null) {
912164
+ return void 0;
912165
+ }
912166
+ const route = routes[index3];
912167
+ if (route == null) {
912168
+ return void 0;
912169
+ }
912170
+ const sourceError = sourceResolution.errors.get(index3);
912171
+ if (sourceError != null) {
912172
+ return sourceError;
912173
+ }
912174
+ const sourceArchive = sourceResolution.sourceArchives.get(index3);
912175
+ if (sourceArchive == null) {
912176
+ return new Error(`Resolved source archive is unavailable for ${route.generatorId}`);
912177
+ }
912178
+ try {
912179
+ validateFernSdkGenApiSourceCompatibility(route, sourceArchive);
912180
+ return void 0;
912181
+ } catch (error50) {
912182
+ return error50;
912183
+ }
912184
+ })
912185
+ };
912186
+ }
912187
+ function getFernSdkGenApiCandidateIndexes(routes, preflightErrors) {
912188
+ return new Set(routes.flatMap((route, index3) => route != null && preflightErrors[index3] == null ? [index3] : []));
912189
+ }
912190
+ 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
912191
  const startedAt = Date.now();
911839
912192
  try {
911840
- const settings = getBaseOpenAPIWorkspaceSettingsFromGeneratorInvocation(generatorInvocation);
911841
- const fernWorkspace = await workspace.toFernWorkspace({ context: context3 }, settings, generatorInvocation.apiOverride?.specs);
912193
+ if (sdkGenApiPreflightError != null) {
912194
+ throw sdkGenApiPreflightError;
912195
+ }
912196
+ const settings = getBaseOpenAPIWorkspaceSettingsFromGeneratorInvocation(resolvedGeneratorInvocation);
912197
+ const fernWorkspace = await workspace.toFernWorkspace({ context: context3 }, settings, resolvedGeneratorInvocation.apiOverride?.specs);
911842
912198
  if (validateWorkspace) {
911843
912199
  await validateAPIWorkspaceAndLogIssues({
911844
912200
  workspace: fernWorkspace,
@@ -911848,7 +912204,7 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911848
912204
  });
911849
912205
  }
911850
912206
  const effectiveFernignorePath = skipFernignore ? void 0 : fernignorePath ?? await resolveAutoDiscoveredFernignorePath({
911851
- generatorInvocation,
912207
+ generatorInvocation: resolvedGeneratorInvocation,
911852
912208
  context: interactiveTaskContext
911853
912209
  });
911854
912210
  const remoteTaskHandlerResponse = await runRemoteGenerationForGenerator({
@@ -911857,9 +912213,9 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911857
912213
  workspace: fernWorkspace,
911858
912214
  interactiveTaskContext,
911859
912215
  generatorInvocation: {
911860
- ...generatorInvocation,
911861
- outputMode: generatorInvocation.outputMode._visit({
911862
- downloadFiles: () => generatorInvocation.outputMode,
912216
+ ...resolvedGeneratorInvocation,
912217
+ outputMode: resolvedGeneratorInvocation.outputMode._visit({
912218
+ downloadFiles: () => resolvedGeneratorInvocation.outputMode,
911863
912219
  github: (val) => {
911864
912220
  return api_exports4.OutputMode.github({
911865
912221
  ...val,
@@ -911870,11 +912226,11 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911870
912226
  if (mode === "pull-request") {
911871
912227
  return api_exports4.OutputMode.githubV2(api_exports4.GithubOutputModeV2.pullRequest(val));
911872
912228
  }
911873
- return generatorInvocation.outputMode;
912229
+ return resolvedGeneratorInvocation.outputMode;
911874
912230
  },
911875
- publish: () => generatorInvocation.outputMode,
911876
- publishV2: () => generatorInvocation.outputMode,
911877
- _other: () => generatorInvocation.outputMode
912231
+ publish: () => resolvedGeneratorInvocation.outputMode,
912232
+ publishV2: () => resolvedGeneratorInvocation.outputMode,
912233
+ _other: () => resolvedGeneratorInvocation.outputMode
911878
912234
  })
911879
912235
  },
911880
912236
  version: version7,
@@ -911883,8 +912239,8 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911883
912239
  token,
911884
912240
  whitelabel,
911885
912241
  replay,
911886
- readme: generatorInvocation.readme,
911887
- irVersionOverride: generatorInvocation.irVersionOverride,
912242
+ readme: resolvedGeneratorInvocation.readme,
912243
+ irVersionOverride: resolvedGeneratorInvocation.irVersionOverride,
911888
912244
  absolutePathToPreview,
911889
912245
  isPreview,
911890
912246
  fiddlePreview,
@@ -911901,7 +912257,10 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911901
912257
  noReplay,
911902
912258
  disableTelemetry,
911903
912259
  loginCommand,
911904
- specsTarGzBuffer: await getSpecsTarGzBuffer?.(generatorInvocation.name),
912260
+ specsTarGzBuffer: specsTarGzArchive?.buffer,
912261
+ sdkGenApiSourceArchive: specsTarGzArchive,
912262
+ sdkGenApiRoute,
912263
+ sdkGenApiPreparationBatch,
911905
912264
  sdkGenApiBatch,
911906
912265
  sdkGenApiTargetIdSeed,
911907
912266
  generateFullProject
@@ -911943,7 +912302,12 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911943
912302
  isAutomation: automation != null
911944
912303
  });
911945
912304
  } catch (error50) {
911946
- sdkGenApiBatch?.cancel(error50);
912305
+ sdkGenApiPreparationBatch?.fail(sdkGenApiTargetIdSeed, error50, automation != null);
912306
+ if (automation != null) {
912307
+ sdkGenApiBatch?.remove(sdkGenApiTargetIdSeed, error50);
912308
+ } else {
912309
+ sdkGenApiBatch?.cancel(error50);
912310
+ }
911947
912311
  if (automation == null) {
911948
912312
  throw error50;
911949
912313
  }
@@ -911978,6 +912342,17 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911978
912342
  });
911979
912343
  }
911980
912344
  }
912345
+ function throwFirstPreflightError(errors4, generators) {
912346
+ const failedIndex = errors4.findIndex((error51) => error51 != null);
912347
+ if (failedIndex < 0) {
912348
+ return;
912349
+ }
912350
+ const error50 = errors4[failedIndex];
912351
+ if (error50 instanceof CliError) {
912352
+ throw error50;
912353
+ }
912354
+ throw new Error(`Cannot prepare sdk-gen-api target ${generators[failedIndex]?.name ?? failedIndex.toString()}: ${extractErrorMessage(error50)}`, { cause: error50 });
912355
+ }
911981
912356
  async function emitGenerationAnnotations(ctx) {
911982
912357
  if (!shouldEmitGithubAnnotations()) {
911983
912358
  return;
@@ -914210,7 +914585,7 @@ var LegacyDocsPublisher = class {
914210
914585
  previewId,
914211
914586
  disableTemplates: void 0,
914212
914587
  skipUpload,
914213
- cliVersion: "5.111.0",
914588
+ cliVersion: "5.112.1",
914214
914589
  loginCommand: "fern auth login"
914215
914590
  });
914216
914591
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -965096,6 +965471,7 @@ var TypescriptCustomConfigSchema = external_exports2.strictObject({
965096
965471
  noOptionalProperties: external_exports2.optional(external_exports2.boolean()),
965097
965472
  tolerateRepublish: external_exports2.optional(external_exports2.boolean()),
965098
965473
  packageJson: external_exports2.optional(external_exports2.record(external_exports2.any())),
965474
+ packageJsonMergeStrategy: external_exports2.optional(external_exports2.enum(["shallow", "deep"])),
965099
965475
  publishToJsr: external_exports2.optional(external_exports2.boolean()),
965100
965476
  omitUndefined: external_exports2.optional(external_exports2.boolean()),
965101
965477
  useLegacyExports: external_exports2.optional(external_exports2.boolean()),
@@ -965155,6 +965531,12 @@ var TypescriptCustomConfigSchema = external_exports2.strictObject({
965155
965531
  // get auth headers when credentials are supplied, and no endpoint gets them
965156
965532
  // when credentials are absent.
965157
965533
  "optional-auth": external_exports2.optional(external_exports2.boolean()),
965534
+ // When true, the generated auth providers read environment variables through a
965535
+ // `typeof process !== "undefined"` guard, so they fall back to the normal
965536
+ // missing-credential error instead of throwing `ReferenceError: process is not
965537
+ // defined` in runtimes without a Node `process` global (browsers, Cloudflare
965538
+ // Workers, Deno). Node behavior is unchanged.
965539
+ guardProcessEnvAccess: external_exports2.optional(external_exports2.boolean()),
965158
965540
  generateReactQueryHooks: external_exports2.optional(external_exports2.boolean()),
965159
965541
  // beta (not in docs)
965160
965542
  includeContentHeadersOnFileDownloadResponse: external_exports2.optional(external_exports2.boolean()),
@@ -968505,6 +968887,8 @@ async function copySnippetJsonIfNonEmpty({ src, dest }) {
968505
968887
  }
968506
968888
 
968507
968889
  // ../generation/local-generation/local-workspace-runner/lib/rawSpecs.js
968890
+ var import_node_util10 = require("util");
968891
+ init_lib17();
968508
968892
  init_lib4();
968509
968893
  init_lib8();
968510
968894
  init_lib35();
@@ -968547,7 +968931,14 @@ async function collectRawSpecs({ specs, hostOutputDir, containerBaseDir, context
968547
968931
  async function resolveAndWriteSpec({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3, audiences }) {
968548
968932
  switch (spec.type) {
968549
968933
  case "openapi":
968550
- return resolveOpenAPIOrAsyncAPI({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3, audiences });
968934
+ return resolveOpenAPIOrAsyncAPI({
968935
+ spec,
968936
+ hostOutputDir,
968937
+ containerBaseDir,
968938
+ context: context3,
968939
+ index: index3,
968940
+ audiences
968941
+ });
968551
968942
  case "openrpc":
968552
968943
  return resolveOpenRPC({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3 });
968553
968944
  case "protobuf":
@@ -968582,9 +968973,41 @@ async function resolveOpenAPIOrAsyncAPI({ spec, hostOutputDir, containerBaseDir,
968582
968973
  return {
968583
968974
  type: isAsync2 ? "asyncapi" : "openapi",
968584
968975
  specPath: toContainerPath(filename, containerBaseDir),
968585
- namespace: spec.namespace
968976
+ namespace: spec.namespace,
968977
+ apiImportSettings: mapApiImportSettings(getOpenAPISettings({ overrides: spec.settings }))
968586
968978
  };
968587
968979
  }
968980
+ var SDK_CONFIG_IMPORT_SETTING_MAPPERS = {
968981
+ respectNullableSchemas: (settings) => ({ respectNullableSchemas: settings.respectNullableSchemas }),
968982
+ useTitlesAsName: (settings) => ({ titleAsSchemaName: settings.useTitlesAsName }),
968983
+ coerceEnumsToLiterals: (settings) => ({ coerceEnumsToLiterals: settings.coerceEnumsToLiterals }),
968984
+ shouldUseIdiomaticRequestNames: (settings) => ({
968985
+ idiomaticRequestNames: settings.shouldUseIdiomaticRequestNames
968986
+ }),
968987
+ wrapReferencesToNullableInOptional: (settings) => ({
968988
+ wrapReferencesToNullableInOptional: settings.wrapReferencesToNullableInOptional
968989
+ }),
968990
+ coerceOptionalSchemasToNullable: (settings) => ({
968991
+ coerceOptionalSchemasToNullable: settings.coerceOptionalSchemasToNullable
968992
+ }),
968993
+ pathParameterOrder: (settings) => ({ pathParameterOrder: settings.pathParameterOrder }),
968994
+ onlyIncludeReferencedSchemas: (settings) => ({
968995
+ onlyIncludeReferencedSchemas: settings.onlyIncludeReferencedSchemas
968996
+ }),
968997
+ objectQueryParameters: (settings) => ({ objectQueryParameters: settings.objectQueryParameters }),
968998
+ typeDatesAsStrings: (settings) => ({ typeDatesAsStrings: settings.typeDatesAsStrings }),
968999
+ groupMultiApiEnvironments: (settings) => ({
969000
+ groupMultiApiEnvironments: settings.groupMultiApiEnvironments
969001
+ }),
969002
+ defaultIntegerFormat: (settings) => ({ defaultIntegerFormat: settings.defaultIntegerFormat })
969003
+ };
969004
+ function mapApiImportSettings(settings) {
969005
+ const mappedSettings = {};
969006
+ for (const mapSetting of Object.values(SDK_CONFIG_IMPORT_SETTING_MAPPERS)) {
969007
+ Object.assign(mappedSettings, mapSetting(settings));
969008
+ }
969009
+ return mappedSettings;
969010
+ }
968588
969011
  async function resolveOpenRPC({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3 }) {
968589
969012
  const filename = `openrpc${index3}.json`;
968590
969013
  const rawContent = await (0, import_promises143.readFile)(spec.absoluteFilepath, "utf-8");
@@ -968758,30 +969181,318 @@ function matchesAudiences(operation, selectedAudiences) {
968758
969181
  function hasOperations(pathItem) {
968759
969182
  return Object.keys(pathItem).some((key2) => HTTP_METHODS3.has(key2.toLowerCase()));
968760
969183
  }
968761
- async function createSpecsTarGzBuffer({ specs, context: context3, audiences }) {
969184
+ async function createGroupedSpecsTarGzArchiveSettled({ generatorSelections, context: context3, audiences }) {
969185
+ const deduplicated = deduplicateGeneratorSelections(generatorSelections);
969186
+ const errorsByGeneratorIndex = /* @__PURE__ */ new Map();
968762
969187
  const tmpDir = await import_tmp_promise17.default.dir({ unsafeCleanup: true });
968763
969188
  try {
969189
+ const materializedRoot = import_path99.default.join(tmpDir.path, "materialized");
969190
+ await (0, import_promises143.mkdir)(materializedRoot);
969191
+ const materializedSpecs = await Promise.allSettled(deduplicated.uniqueSpecs.map(async (spec, uniqueSpecIndex) => {
969192
+ const directory = import_path99.default.join(materializedRoot, uniqueSpecIndex.toString());
969193
+ await (0, import_promises143.mkdir)(directory);
969194
+ const manifest = await collectRawSpecs({
969195
+ specs: [spec],
969196
+ hostOutputDir: AbsoluteFilePath2.of(directory),
969197
+ containerBaseDir: "/fern/specs",
969198
+ context: context3,
969199
+ audiences
969200
+ });
969201
+ const manifestEntry = manifest.specs[0];
969202
+ if (manifestEntry == null) {
969203
+ throw new Error(`Materialized source ${uniqueSpecIndex} did not produce a manifest entry`);
969204
+ }
969205
+ return { directory, manifestEntry };
969206
+ }));
969207
+ materializedSpecs.forEach((result, uniqueSpecIndex) => {
969208
+ if (result.status === "fulfilled") {
969209
+ return;
969210
+ }
969211
+ for (const generatorIndex of deduplicated.generatorIndexesByUniqueSpecIndex[uniqueSpecIndex] ?? []) {
969212
+ if (!errorsByGeneratorIndex.has(generatorIndex)) {
969213
+ errorsByGeneratorIndex.set(generatorIndex, result.reason);
969214
+ }
969215
+ }
969216
+ });
969217
+ const successfulGeneratorIndexes = new Set(generatorSelections.map((selection) => selection.generatorIndex).filter((generatorIndex) => !errorsByGeneratorIndex.has(generatorIndex)));
969218
+ if (successfulGeneratorIndexes.size === 0) {
969219
+ return { archive: void 0, errorsByGeneratorIndex };
969220
+ }
969221
+ try {
969222
+ const archive3 = await createArchiveFromMaterializedSpecs({
969223
+ materializedSpecs,
969224
+ deduplicated,
969225
+ successfulGeneratorIndexes,
969226
+ root: tmpDir.path
969227
+ });
969228
+ assertGeneratorSelectionOutcomes({ generatorSelections, archive: archive3, errorsByGeneratorIndex });
969229
+ return { archive: archive3, errorsByGeneratorIndex };
969230
+ } catch (error50) {
969231
+ for (const generatorIndex of successfulGeneratorIndexes) {
969232
+ errorsByGeneratorIndex.set(generatorIndex, error50);
969233
+ }
969234
+ return { archive: void 0, errorsByGeneratorIndex };
969235
+ }
969236
+ } finally {
969237
+ await tmpDir.cleanup();
969238
+ }
969239
+ }
969240
+ function deduplicateGeneratorSelections(generatorSelections) {
969241
+ const uniqueSpecs = [];
969242
+ const indexesBySpecKey = /* @__PURE__ */ new Map();
969243
+ const uniqueSpecIndexesByGeneratorIndex = /* @__PURE__ */ new Map();
969244
+ const generatorIndexesByUniqueSpecIndex = [];
969245
+ const orderedSelections = [...generatorSelections].sort((left3, right3) => left3.generatorIndex - right3.generatorIndex);
969246
+ for (const selection of orderedSelections) {
969247
+ if (uniqueSpecIndexesByGeneratorIndex.has(selection.generatorIndex)) {
969248
+ throw new Error(`Duplicate source selection for generator index ${selection.generatorIndex}`);
969249
+ }
969250
+ const indexes = selection.specs.map((spec) => {
969251
+ const key2 = createSpecDeduplicationKey(spec);
969252
+ const existingIndex = indexesBySpecKey.get(key2);
969253
+ if (existingIndex != null) {
969254
+ return existingIndex;
969255
+ }
969256
+ const index3 = uniqueSpecs.length;
969257
+ uniqueSpecs.push(spec);
969258
+ indexesBySpecKey.set(key2, index3);
969259
+ generatorIndexesByUniqueSpecIndex[index3] = /* @__PURE__ */ new Set();
969260
+ return index3;
969261
+ });
969262
+ for (const index3 of new Set(indexes)) {
969263
+ generatorIndexesByUniqueSpecIndex[index3]?.add(selection.generatorIndex);
969264
+ }
969265
+ uniqueSpecIndexesByGeneratorIndex.set(selection.generatorIndex, [...new Set(indexes)]);
969266
+ }
969267
+ return { uniqueSpecs, uniqueSpecIndexesByGeneratorIndex, generatorIndexesByUniqueSpecIndex };
969268
+ }
969269
+ async function createArchiveFromMaterializedSpecs({ materializedSpecs, deduplicated, successfulGeneratorIndexes, root: root6 }) {
969270
+ const contentDirectory = import_path99.default.join(root6, "content");
969271
+ await (0, import_promises143.mkdir)(contentDirectory);
969272
+ const manifest = { specs: [] };
969273
+ const archiveSpecIndexByUniqueSpecIndex = /* @__PURE__ */ new Map();
969274
+ const typeCounters = /* @__PURE__ */ new Map();
969275
+ for (const [uniqueSpecIndex, generatorIndexes] of deduplicated.generatorIndexesByUniqueSpecIndex.entries()) {
969276
+ if (![...generatorIndexes].some((generatorIndex) => successfulGeneratorIndexes.has(generatorIndex))) {
969277
+ continue;
969278
+ }
969279
+ const materialized = materializedSpecs[uniqueSpecIndex];
969280
+ if (materialized?.status !== "fulfilled") {
969281
+ throw new Error(`Successful generator references source ${uniqueSpecIndex}, which was not materialized`);
969282
+ }
969283
+ const type7 = materialized.value.manifestEntry.type;
969284
+ const typeIndex = typeCounters.get(type7) ?? 0;
969285
+ typeCounters.set(type7, typeIndex + 1);
969286
+ const manifestEntry = await copyMaterializedSpec({
969287
+ materialized: materialized.value,
969288
+ contentDirectory,
969289
+ typeIndex
969290
+ });
969291
+ archiveSpecIndexByUniqueSpecIndex.set(uniqueSpecIndex, manifest.specs.length);
969292
+ manifest.specs.push(manifestEntry);
969293
+ }
969294
+ const specIndexesByGeneratorIndex = /* @__PURE__ */ new Map();
969295
+ for (const [generatorIndex, uniqueSpecIndexes] of deduplicated.uniqueSpecIndexesByGeneratorIndex) {
969296
+ if (!successfulGeneratorIndexes.has(generatorIndex)) {
969297
+ continue;
969298
+ }
969299
+ specIndexesByGeneratorIndex.set(generatorIndex, uniqueSpecIndexes.map((uniqueSpecIndex) => {
969300
+ const archiveSpecIndex = archiveSpecIndexByUniqueSpecIndex.get(uniqueSpecIndex);
969301
+ if (archiveSpecIndex == null) {
969302
+ throw new Error(`Source ${uniqueSpecIndex} is unavailable for generator index ${generatorIndex}`);
969303
+ }
969304
+ return archiveSpecIndex;
969305
+ }));
969306
+ }
969307
+ const archive3 = await createArchiveFromDirectory({
969308
+ contentDirectory,
969309
+ tarGzPath: import_path99.default.join(root6, "specs.tar.gz"),
969310
+ manifest
969311
+ });
969312
+ return { ...archive3, specIndexesByGeneratorIndex };
969313
+ }
969314
+ async function copyMaterializedSpec({ materialized, contentDirectory, typeIndex }) {
969315
+ const sourcePrefix = `${materialized.manifestEntry.type}0`;
969316
+ const targetPrefix = `${materialized.manifestEntry.type}${typeIndex}`;
969317
+ assertSupportedMaterializedManifestEntry(materialized.manifestEntry);
969318
+ for (const entry of await (0, import_promises143.readdir)(materialized.directory, { withFileTypes: true })) {
969319
+ if (!hasSourcePrefix(entry.name) || !entry.isFile() && !entry.isDirectory()) {
969320
+ throw new Error(`Unsupported materialized source entry: ${entry.name}`);
969321
+ }
969322
+ await (0, import_promises143.cp)(import_path99.default.join(materialized.directory, entry.name), import_path99.default.join(contentDirectory, replacePrefix(entry.name)), {
969323
+ recursive: entry.isDirectory()
969324
+ });
969325
+ }
969326
+ return {
969327
+ ...materialized.manifestEntry,
969328
+ specPath: replaceContainerPathPrefix(materialized.manifestEntry.specPath),
969329
+ ...materialized.manifestEntry.overridePaths == null ? {} : {
969330
+ overridePaths: materialized.manifestEntry.overridePaths.map(replaceContainerPathPrefix)
969331
+ }
969332
+ };
969333
+ function replacePrefix(value2) {
969334
+ return `${targetPrefix}${value2.slice(sourcePrefix.length)}`;
969335
+ }
969336
+ function hasSourcePrefix(value2) {
969337
+ return value2 === sourcePrefix || value2.startsWith(`${sourcePrefix}.`) || value2.startsWith(`${sourcePrefix}-`);
969338
+ }
969339
+ function replaceContainerPathPrefix(value2) {
969340
+ const basename8 = import_path99.default.posix.basename(value2);
969341
+ if (!hasSourcePrefix(basename8)) {
969342
+ throw new Error(`Unexpected materialized source path: ${value2}`);
969343
+ }
969344
+ return import_path99.default.posix.join(import_path99.default.posix.dirname(value2), replacePrefix(basename8));
969345
+ }
969346
+ }
969347
+ var SUPPORTED_MATERIALIZED_MANIFEST_ENTRY_KEYS = /* @__PURE__ */ new Set([
969348
+ "type",
969349
+ "specPath",
969350
+ "overridePaths",
969351
+ "namespace",
969352
+ "apiImportSettings"
969353
+ ]);
969354
+ function assertSupportedMaterializedManifestEntry(entry) {
969355
+ for (const key2 of Object.keys(entry)) {
969356
+ if (!SUPPORTED_MATERIALIZED_MANIFEST_ENTRY_KEYS.has(key2)) {
969357
+ throw new Error(`Unsupported materialized manifest entry field: ${key2}`);
969358
+ }
969359
+ }
969360
+ }
969361
+ function assertGeneratorSelectionOutcomes({ generatorSelections, archive: archive3, errorsByGeneratorIndex }) {
969362
+ for (const { generatorIndex } of generatorSelections) {
969363
+ const hasArchive = archive3.specIndexesByGeneratorIndex.has(generatorIndex);
969364
+ const hasError = errorsByGeneratorIndex.has(generatorIndex);
969365
+ if (hasArchive === hasError) {
969366
+ throw new Error(`Generator index ${generatorIndex} must have exactly one source archive or materialization error outcome`);
969367
+ }
969368
+ }
969369
+ }
969370
+ var SDK_CONFIG_IMPORT_SETTING_KEYS = new Set(Object.keys(SDK_CONFIG_IMPORT_SETTING_MAPPERS));
969371
+ var DEFAULT_OPENAPI_SETTINGS = getOpenAPISettings();
969372
+ function validateSdkConfigImportSettings(specs) {
969373
+ for (const spec of specs) {
969374
+ if (spec.type !== "openapi") {
969375
+ continue;
969376
+ }
969377
+ const settings = getOpenAPISettings({ overrides: spec.settings });
969378
+ for (const key2 of Object.getOwnPropertyNames(settings)) {
969379
+ const value2 = Reflect.get(settings, key2);
969380
+ 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))) {
969381
+ continue;
969382
+ }
969383
+ 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.`);
969384
+ }
969385
+ }
969386
+ }
969387
+ async function createSpecsTarGzArchive({ specs, context: context3, audiences }) {
969388
+ const tmpDir = await import_tmp_promise17.default.dir({ unsafeCleanup: true });
969389
+ try {
969390
+ const contentDirectory = import_path99.default.join(tmpDir.path, "content");
969391
+ await (0, import_promises143.mkdir)(contentDirectory);
968764
969392
  const manifest = await collectRawSpecs({
968765
969393
  specs,
968766
- hostOutputDir: AbsoluteFilePath2.of(tmpDir.path),
969394
+ hostOutputDir: AbsoluteFilePath2.of(contentDirectory),
968767
969395
  containerBaseDir: "/fern/specs",
968768
969396
  context: context3,
968769
969397
  audiences
968770
969398
  });
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);
969399
+ return await createArchiveFromDirectory({
969400
+ contentDirectory,
969401
+ tarGzPath: import_path99.default.join(tmpDir.path, "specs.tar.gz"),
969402
+ manifest
969403
+ });
968781
969404
  } finally {
968782
969405
  await tmpDir.cleanup();
968783
969406
  }
968784
969407
  }
969408
+ async function createArchiveFromDirectory({ contentDirectory, tarGzPath, manifest }) {
969409
+ await (0, import_promises143.writeFile)(join8(AbsoluteFilePath2.of(contentDirectory), RelativeFilePath2.of(SPECS_MANIFEST_FILENAME)), JSON.stringify(manifest, void 0, 4));
969410
+ const archiveEntries = await listDeterministicArchiveEntries(contentDirectory);
969411
+ await Kn({
969412
+ gzip: true,
969413
+ cwd: contentDirectory,
969414
+ file: tarGzPath,
969415
+ portable: true,
969416
+ mtime: /* @__PURE__ */ new Date(0),
969417
+ onWriteEntry: (entry) => {
969418
+ if (entry.stat != null) {
969419
+ entry.stat.mode = 420;
969420
+ }
969421
+ }
969422
+ }, archiveEntries);
969423
+ return { buffer: await (0, import_promises143.readFile)(tarGzPath), manifest };
969424
+ }
969425
+ async function listDeterministicArchiveEntries(root6, relativeDirectory = "") {
969426
+ const absoluteDirectory = relativeDirectory === "" ? root6 : import_path99.default.join(root6, ...relativeDirectory.split(import_path99.default.posix.sep));
969427
+ const directoryEntries = await (0, import_promises143.readdir)(absoluteDirectory, { withFileTypes: true });
969428
+ const archiveEntries = [];
969429
+ for (const entry of directoryEntries.sort((left3, right3) => compareStrings(left3.name, right3.name))) {
969430
+ const relativePath = import_path99.default.posix.join(relativeDirectory, entry.name);
969431
+ if (entry.isDirectory()) {
969432
+ archiveEntries.push(...await listDeterministicArchiveEntries(root6, relativePath));
969433
+ continue;
969434
+ }
969435
+ if (!entry.isFile()) {
969436
+ throw new Error(`Unsupported generated source archive entry: ${relativePath}`);
969437
+ }
969438
+ archiveEntries.push(relativePath);
969439
+ }
969440
+ return archiveEntries;
969441
+ }
969442
+ function compareStrings(left3, right3) {
969443
+ return left3 < right3 ? -1 : left3 > right3 ? 1 : 0;
969444
+ }
969445
+ function createSpecDeduplicationKey(spec) {
969446
+ switch (spec.type) {
969447
+ case "openapi":
969448
+ return stableStringify3({
969449
+ type: spec.type,
969450
+ path: spec.absoluteFilepath,
969451
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969452
+ overlay: spec.absoluteFilepathToOverlays,
969453
+ namespace: spec.namespace,
969454
+ settings: getOpenAPISettings({ overrides: spec.settings })
969455
+ });
969456
+ case "openrpc":
969457
+ return stableStringify3({
969458
+ type: spec.type,
969459
+ path: spec.absoluteFilepath,
969460
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969461
+ namespace: spec.namespace
969462
+ });
969463
+ case "protobuf":
969464
+ return stableStringify3({
969465
+ type: spec.type,
969466
+ root: spec.absoluteFilepathToProtobufRoot,
969467
+ target: spec.absoluteFilepathToProtobufTarget,
969468
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969469
+ dependencies: spec.dependencies,
969470
+ settings: getOpenAPISettings({ overrides: spec.settings })
969471
+ });
969472
+ case "graphql":
969473
+ return stableStringify3({
969474
+ type: spec.type,
969475
+ path: spec.absoluteFilepath,
969476
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969477
+ examples: spec.absoluteFilepathToExamples,
969478
+ namespace: spec.namespace
969479
+ });
969480
+ default:
969481
+ assertNever(spec);
969482
+ }
969483
+ }
969484
+ function stableStringify3(value2) {
969485
+ return JSON.stringify(sortJsonValue(value2));
969486
+ }
969487
+ function sortJsonValue(value2) {
969488
+ if (Array.isArray(value2)) {
969489
+ return value2.map(sortJsonValue);
969490
+ }
969491
+ if (value2 == null || typeof value2 !== "object") {
969492
+ return value2;
969493
+ }
969494
+ return Object.fromEntries(Object.entries(value2).sort(([left3], [right3]) => compareStrings(left3, right3)).map(([key2, child]) => [key2, sortJsonValue(child)]));
969495
+ }
968785
969496
 
968786
969497
  // ../generation/local-generation/local-workspace-runner/lib/runGenerator.js
968787
969498
  function extractLicenseFilePath(generatorInvocation, absolutePathToFernConfig) {
@@ -979681,7 +980392,7 @@ var {
979681
980392
  } = signalExitWrap(processOk(process21) ? new SignalExit(process21) : new SignalExitFallback());
979682
980393
 
979683
980394
  // ../../../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");
980395
+ var import_node_util11 = require("util");
979685
980396
 
979686
980397
  // ../../../node_modules/.pnpm/@inquirer+ansi@1.0.2/node_modules/@inquirer/ansi/dist/esm/index.js
979687
980398
  var ESC2 = "\x1B[";
@@ -979719,7 +980430,7 @@ var ScreenManager2 = class {
979719
980430
  }
979720
980431
  render(content5, bottomContent = "") {
979721
980432
  const promptLine = lastLine2(content5);
979722
- const rawPromptLine = (0, import_node_util10.stripVTControlCharacters)(promptLine);
980433
+ const rawPromptLine = (0, import_node_util11.stripVTControlCharacters)(promptLine);
979723
980434
  let prompt2 = rawPromptLine;
979724
980435
  if (this.rl.line.length > 0) {
979725
980436
  prompt2 = prompt2.slice(0, -this.rl.line.length);
@@ -981130,7 +981841,7 @@ function getAutomationContextFromEnv() {
981130
981841
  config_branch: process.env.FERN_CONFIG_BRANCH,
981131
981842
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
981132
981843
  trigger: process.env.GITHUB_EVENT_NAME,
981133
- cli_version: "5.111.0"
981844
+ cli_version: "5.112.1"
981134
981845
  };
981135
981846
  }
981136
981847
  function isAutomationMode() {
@@ -981962,7 +982673,7 @@ var CliContext = class _CliContext {
981962
982673
  if (false) {
981963
982674
  this.logger.error("CLI_VERSION is not defined");
981964
982675
  }
981965
- return "5.111.0";
982676
+ return "5.112.1";
981966
982677
  }
981967
982678
  getCliName() {
981968
982679
  if (false) {
@@ -983605,18 +984316,118 @@ function expandGroupFilter(groupNames, generatorsConfiguration) {
983605
984316
  // src/commands/generate/generateAPIWorkspace.ts
983606
984317
  init_lib20();
983607
984318
  init_lib8();
983608
- init_lib35();
983609
984319
  init_lib6();
983610
984320
  init_esm18();
983611
984321
 
983612
- // src/commands/generate/createSpecsTarGzCache.ts
983613
- function createSpecsTarGzCache(createArchive) {
983614
- let archivePromise;
983615
- return () => {
983616
- archivePromise ??= createArchive();
983617
- return archivePromise;
984322
+ // src/commands/generate/createFernSourceArchiveResolver.ts
984323
+ init_lib35();
984324
+ function createFernSourceArchiveResolver({
984325
+ workspace,
984326
+ context: context3,
984327
+ group
984328
+ }) {
984329
+ return async (requests3) => {
984330
+ const sourceArchives = /* @__PURE__ */ new Map();
984331
+ const errors4 = /* @__PURE__ */ new Map();
984332
+ if (!(workspace instanceof OSSWorkspace)) {
984333
+ for (const request7 of requests3) {
984334
+ if (requestRequiresSourceArchive(request7)) {
984335
+ errors4.set(
984336
+ request7.generatorIndex,
984337
+ new Error(
984338
+ `Generator index ${request7.generatorIndex} (${request7.generatorInvocation.name}) requires a source archive, but workspace type ${workspace.type} does not expose source specs`
984339
+ )
984340
+ );
984341
+ }
984342
+ }
984343
+ return { sourceArchives, errors: errors4 };
984344
+ }
984345
+ const settledSelections = await Promise.allSettled(
984346
+ requests3.map(async (request7) => {
984347
+ if (request7.sdkGenApiRoute == null) {
984348
+ return void 0;
984349
+ }
984350
+ const specs = await workspace.getAllSpecsForGenerator(request7.generatorInvocation.apiOverride?.specs);
984351
+ if (request7.sdkGenApiRoute.payloadKind === "sdk-config-v1") {
984352
+ validateSdkConfigImportSettings(specs);
984353
+ }
984354
+ return specs;
984355
+ })
984356
+ );
984357
+ const generatorSelections = settledSelections.flatMap((result, index3) => {
984358
+ const request7 = requests3[index3];
984359
+ if (request7 == null) {
984360
+ throw new Error(`Missing source archive request at settled index ${index3}`);
984361
+ }
984362
+ if (result.status === "rejected") {
984363
+ errors4.set(request7.generatorIndex, result.reason);
984364
+ return [];
984365
+ }
984366
+ return result.value == null ? [] : [{ generatorIndex: request7.generatorIndex, specs: result.value }];
984367
+ });
984368
+ if (generatorSelections.length > 0) {
984369
+ const settledArchive = await createGroupedSpecsTarGzArchiveSettled({
984370
+ generatorSelections,
984371
+ context: context3,
984372
+ audiences: group.audiences
984373
+ });
984374
+ for (const [generatorIndex, error50] of settledArchive.errorsByGeneratorIndex) {
984375
+ errors4.set(generatorIndex, error50);
984376
+ }
984377
+ if (settledArchive.archive != null) {
984378
+ const { specIndexesByGeneratorIndex, ...sourceArchive } = settledArchive.archive;
984379
+ for (const [generatorIndex, specIndexes] of specIndexesByGeneratorIndex) {
984380
+ sourceArchives.set(generatorIndex, { ...sourceArchive, specIndexes });
984381
+ }
984382
+ }
984383
+ }
984384
+ const rootRequests = requests3.filter(
984385
+ (request7) => request7.sdkGenApiRoute == null && generatorWantsSpecs(request7.generatorInvocation.name) && !errors4.has(request7.generatorIndex)
984386
+ );
984387
+ if (rootRequests.length > 0) {
984388
+ try {
984389
+ const archive3 = await createSpecsTarGzArchive({
984390
+ specs: workspace.allSpecs,
984391
+ context: context3,
984392
+ audiences: group.audiences
984393
+ });
984394
+ const specIndexes = archive3.manifest.specs.map((_5, index3) => index3);
984395
+ for (const request7 of rootRequests) {
984396
+ sourceArchives.set(request7.generatorIndex, { ...archive3, specIndexes });
984397
+ }
984398
+ } catch (error50) {
984399
+ for (const request7 of rootRequests) {
984400
+ errors4.set(request7.generatorIndex, error50);
984401
+ }
984402
+ }
984403
+ }
984404
+ for (const request7 of requests3) {
984405
+ if (!requestRequiresSourceArchive(request7)) {
984406
+ continue;
984407
+ }
984408
+ const hasArchive = sourceArchives.has(request7.generatorIndex);
984409
+ const hasError = errors4.has(request7.generatorIndex);
984410
+ if (hasArchive && hasError) {
984411
+ throw new Error(
984412
+ `Generator index ${request7.generatorIndex} produced both a source archive and a source preparation error`,
984413
+ { cause: errors4.get(request7.generatorIndex) }
984414
+ );
984415
+ }
984416
+ if (!hasArchive && !hasError) {
984417
+ errors4.set(
984418
+ request7.generatorIndex,
984419
+ new Error(
984420
+ `Generator index ${request7.generatorIndex} did not produce a source archive or source preparation error`
984421
+ )
984422
+ );
984423
+ }
984424
+ }
984425
+ return { sourceArchives, errors: errors4 };
983618
984426
  };
983619
984427
  }
984428
+ function requestRequiresSourceArchive(request7) {
984429
+ return request7.sdkGenApiRoute != null || generatorWantsSpecs(request7.generatorInvocation.name);
984430
+ }
983620
984431
 
983621
984432
  // src/commands/generate/packLocalOutput.ts
983622
984433
  init_lib20();
@@ -984273,21 +985084,11 @@ async function generateWorkspace({
984273
985084
  disableTelemetry: isTelemetryDisabled()
984274
985085
  });
984275
985086
  } 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
- };
985087
+ const getSpecsTarGz = createFernSourceArchiveResolver({
985088
+ workspace,
985089
+ context: groupContext,
985090
+ group
985091
+ });
984291
985092
  await runRemoteGenerationForAPIWorkspace({
984292
985093
  projectConfig,
984293
985094
  organization,
@@ -996755,7 +997556,12 @@ async function sdkPreview({
996755
997556
  absolutePathToPreview: absolutePathToOutput,
996756
997557
  isPreview: true,
996757
997558
  fiddlePreview: false,
996758
- pushPreviewBranch: false
997559
+ pushPreviewBranch: false,
997560
+ getSpecsTarGzBuffer: createFernSourceArchiveResolver({
997561
+ workspace,
997562
+ context: context3,
997563
+ group: publishGroup
997564
+ })
996759
997565
  });
996760
997566
  });
996761
997567
  if (shouldRunTwoJobs) {
@@ -996770,7 +997576,12 @@ async function sdkPreview({
996770
997576
  absolutePathToPreview: void 0,
996771
997577
  isPreview: true,
996772
997578
  fiddlePreview: true,
996773
- pushPreviewBranch: true
997579
+ pushPreviewBranch: true,
997580
+ getSpecsTarGzBuffer: createFernSourceArchiveResolver({
997581
+ workspace,
997582
+ context: context3,
997583
+ group: diffGroup
997584
+ })
996774
997585
  });
996775
997586
  });
996776
997587
  }