@fern-api/fern-api-dev 5.23.3-2060-gef10ff1af19 → 5.23.3-2069-g46cdcdac844

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 +1254 -254
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -25708,6 +25708,116 @@ var init_addPrefixToString = __esm({
25708
25708
  }
25709
25709
  });
25710
25710
 
25711
+ // ../../commons/core-utils/lib/anyOfPresenceConstraint.js
25712
+ function isRecord(value2) {
25713
+ return typeof value2 === "object" && value2 != null && !Array.isArray(value2);
25714
+ }
25715
+ function isObjectTypeOrAbsent(type7) {
25716
+ if (type7 == null) {
25717
+ return true;
25718
+ }
25719
+ if (typeof type7 === "string") {
25720
+ return type7 === "object";
25721
+ }
25722
+ if (Array.isArray(type7)) {
25723
+ const nonNull = type7.filter((entry) => entry !== "null");
25724
+ return nonNull.length === 1 && nonNull[0] === "object";
25725
+ }
25726
+ return false;
25727
+ }
25728
+ function restatesSiblingSubschema(branchSubschema, siblingSubschema) {
25729
+ if (branchSubschema === true) {
25730
+ return true;
25731
+ }
25732
+ if (!isRecord(branchSubschema)) {
25733
+ return false;
25734
+ }
25735
+ const sibling2 = isRecord(siblingSubschema) ? siblingSubschema : void 0;
25736
+ for (const [keyword, value2] of Object.entries(branchSubschema)) {
25737
+ if (ANNOTATION_KEYWORDS.has(keyword)) {
25738
+ continue;
25739
+ }
25740
+ if (sibling2 == null || !(keyword in sibling2) || !deepEquals(value2, sibling2[keyword])) {
25741
+ return false;
25742
+ }
25743
+ }
25744
+ return true;
25745
+ }
25746
+ function deepEquals(a3, b5) {
25747
+ if (a3 === b5) {
25748
+ return true;
25749
+ }
25750
+ if (Array.isArray(a3) && Array.isArray(b5)) {
25751
+ return a3.length === b5.length && a3.every((entry, index3) => deepEquals(entry, b5[index3]));
25752
+ }
25753
+ if (isRecord(a3) && isRecord(b5)) {
25754
+ const aKeys = Object.keys(a3).sort();
25755
+ const bKeys = Object.keys(b5).sort();
25756
+ return aKeys.length === bKeys.length && aKeys.every((key2, index3) => key2 === bKeys[index3]) && aKeys.every((key2) => deepEquals(a3[key2], b5[key2]));
25757
+ }
25758
+ return false;
25759
+ }
25760
+ function isPresenceConstraintBranch(branch, siblingProperties) {
25761
+ if (!isRecord(branch) || "$ref" in branch) {
25762
+ return false;
25763
+ }
25764
+ if (branch.allOf != null || branch.oneOf != null || branch.anyOf != null || branch.additionalProperties != null || !isObjectTypeOrAbsent(branch.type)) {
25765
+ return false;
25766
+ }
25767
+ const branchProperties = isRecord(branch.properties) ? branch.properties : {};
25768
+ const branchRequired = Array.isArray(branch.required) ? branch.required : [];
25769
+ if (Object.keys(branchProperties).length === 0 && branchRequired.length === 0) {
25770
+ return false;
25771
+ }
25772
+ for (const name2 of branchRequired) {
25773
+ if (typeof name2 !== "string" || !(name2 in siblingProperties)) {
25774
+ return false;
25775
+ }
25776
+ }
25777
+ for (const [name2, subschema] of Object.entries(branchProperties)) {
25778
+ if (!(name2 in siblingProperties)) {
25779
+ return false;
25780
+ }
25781
+ if (!restatesSiblingSubschema(subschema, siblingProperties[name2])) {
25782
+ return false;
25783
+ }
25784
+ }
25785
+ return true;
25786
+ }
25787
+ function anyOfIsPresenceConstraint(schema) {
25788
+ const anyOf = schema.anyOf;
25789
+ if (!Array.isArray(anyOf) || anyOf.length === 0) {
25790
+ return false;
25791
+ }
25792
+ if (schema.oneOf != null || schema.allOf != null) {
25793
+ return false;
25794
+ }
25795
+ if (!isRecord(schema.properties) || Object.keys(schema.properties).length === 0) {
25796
+ return false;
25797
+ }
25798
+ const siblingProperties = schema.properties;
25799
+ return anyOf.every((branch) => isPresenceConstraintBranch(branch, siblingProperties));
25800
+ }
25801
+ var ANNOTATION_KEYWORDS;
25802
+ var init_anyOfPresenceConstraint = __esm({
25803
+ "../../commons/core-utils/lib/anyOfPresenceConstraint.js"() {
25804
+ "use strict";
25805
+ ANNOTATION_KEYWORDS = /* @__PURE__ */ new Set([
25806
+ "title",
25807
+ "description",
25808
+ "default",
25809
+ "deprecated",
25810
+ "example",
25811
+ "examples",
25812
+ "readOnly",
25813
+ "writeOnly",
25814
+ "externalDocs",
25815
+ "xml",
25816
+ "$comment"
25817
+ ]);
25818
+ }
25819
+ });
25820
+
25711
25821
  // ../../../node_modules/.pnpm/jsonpath-plus@10.4.0/node_modules/jsonpath-plus/dist/index-node-esm.js
25712
25822
  function push(arr, item) {
25713
25823
  arr = arr.slice();
@@ -44690,6 +44800,7 @@ __export(lib_exports, {
44690
44800
  SKIP_MARKER: () => SKIP_MARKER,
44691
44801
  SymbolRegistry: () => SymbolRegistry,
44692
44802
  addPrefixToString: () => addPrefixToString,
44803
+ anyOfIsPresenceConstraint: () => anyOfIsPresenceConstraint,
44693
44804
  applyOpenAPIOverlay: () => applyOpenAPIOverlay,
44694
44805
  assert: () => assert2,
44695
44806
  assertDefined: () => assertDefined,
@@ -44710,6 +44821,7 @@ __export(lib_exports, {
44710
44821
  isGitAvailable: () => isGitAvailable,
44711
44822
  isNonNullish: () => isNonNullish,
44712
44823
  isPlainObject: () => isPlainObject4,
44824
+ isPresenceConstraintBranch: () => isPresenceConstraintBranch,
44713
44825
  keys: () => keys2,
44714
44826
  mapValues: () => mapValues2,
44715
44827
  mergeWithOverrides: () => mergeWithOverrides,
@@ -44737,6 +44849,7 @@ var init_lib4 = __esm({
44737
44849
  "../../commons/core-utils/lib/index.js"() {
44738
44850
  "use strict";
44739
44851
  init_addPrefixToString();
44852
+ init_anyOfPresenceConstraint();
44740
44853
  init_applyOpenAPIOverlay();
44741
44854
  init_assert();
44742
44855
  init_delay();
@@ -101228,9 +101341,9 @@ var require_graceful_fs = __commonJS({
101228
101341
  }
101229
101342
  }
101230
101343
  var fs$readdir = fs35.readdir;
101231
- fs35.readdir = readdir23;
101344
+ fs35.readdir = readdir24;
101232
101345
  var noReaddirOptionVersions = /^v[0-5]\./;
101233
- function readdir23(path122, options2, cb) {
101346
+ function readdir24(path122, options2, cb) {
101234
101347
  if (typeof options2 === "function")
101235
101348
  cb = options2, options2 = null;
101236
101349
  var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path123, options3, cb2, startTime) {
@@ -131124,6 +131237,7 @@ var init_OpenApiSettingsSchema2 = __esm({
131124
131237
  "type-dates-as-strings": schemas_exports8.boolean().optional(),
131125
131238
  "preserve-single-schema-oneof": schemas_exports8.boolean().optional(),
131126
131239
  "preserve-one-of-in-all-of": schemas_exports8.boolean().optional(),
131240
+ "any-of-sibling-properties-as-object": schemas_exports8.boolean().optional(),
131127
131241
  "inline-all-of-schemas": schemas_exports8.boolean().optional(),
131128
131242
  "resolve-aliases": ResolveAliases.optional(),
131129
131243
  "group-multi-api-environments": schemas_exports8.boolean().optional(),
@@ -152982,6 +153096,7 @@ var init_options2 = __esm({
152982
153096
  typeDatesAsStrings: false,
152983
153097
  preserveSingleSchemaOneOf: false,
152984
153098
  preserveOneOfInAllOf: false,
153099
+ anyOfSiblingPropertiesAsObject: false,
152985
153100
  inlineAllOfSchemas: false,
152986
153101
  resolveAliases: false,
152987
153102
  groupMultiApiEnvironments: false,
@@ -156641,6 +156756,12 @@ function convertSchemaObject(schema, wrapAsOptional, wrapAsNullable, context3, b
156641
156756
  }
156642
156757
  }
156643
156758
  if (schema.anyOf != null && schema.anyOf.length > 0) {
156759
+ if (context3.options.anyOfSiblingPropertiesAsObject && anyOfIsPresenceConstraint(schema)) {
156760
+ context3.logger.debug(`Treating the anyOf at ${breadcrumbs.join(".")} as an "at least one of" constraint over its sibling properties rather than a union, and converting the schema as an object.`);
156761
+ const { anyOf: _constraint, ...schemaWithoutAnyOf } = schema;
156762
+ const convertedSchema = convertSchema2(schemaWithoutAnyOf, wrapAsOptional, wrapAsNullable, context3, breadcrumbs, source2, namespace, referencedAsRequest);
156763
+ return maybeInjectDescriptionOrGroupName(convertedSchema, description, namespace, groupName);
156764
+ }
156644
156765
  if (schema.anyOf.length === 1 && schema.anyOf[0] != null) {
156645
156766
  const convertedSchema = convertSchema2(schema.anyOf[0], wrapAsOptional, wrapAsNullable, context3, breadcrumbs, source2, namespace, referencedAsRequest);
156646
156767
  return maybeInjectDescriptionOrGroupName(convertedSchema, description, namespace, groupName);
@@ -157251,6 +157372,7 @@ var SCHEMA_REFERENCE_PREFIX, globalTitleCollisionTracker;
157251
157372
  var init_convertSchemas = __esm({
157252
157373
  "../api-importers/openapi/openapi-ir-parser/lib/schema/convertSchemas.js"() {
157253
157374
  "use strict";
157375
+ init_lib4();
157254
157376
  init_lib13();
157255
157377
  init_lib6();
157256
157378
  init_lodash();
@@ -200202,6 +200324,7 @@ var init_getAPIDefinitionSettings = __esm({
200202
200324
  typeDatesAsStrings: "typeDatesAsStrings",
200203
200325
  preserveSingleSchemaOneOf: "preserveSingleSchemaOneOf",
200204
200326
  preserveOneOfInAllOf: "preserveOneOfInAllOf",
200327
+ anyOfSiblingPropertiesAsObject: "anyOfSiblingPropertiesAsObject",
200205
200328
  inlineAllOfSchemas: "inlineAllOfSchemas",
200206
200329
  resolveAliases: "resolveAliases",
200207
200330
  groupMultiApiEnvironments: "groupMultiApiEnvironments",
@@ -200287,6 +200410,13 @@ var init_openapi = __esm({
200287
200410
  }
200288
200411
  });
200289
200412
 
200413
+ // ../../commons/api-workspace-commons/lib/RawSpecs.js
200414
+ var init_RawSpecs = __esm({
200415
+ "../../commons/api-workspace-commons/lib/RawSpecs.js"() {
200416
+ "use strict";
200417
+ }
200418
+ });
200419
+
200290
200420
  // ../../commons/api-workspace-commons/lib/Source.js
200291
200421
  var init_Source5 = __esm({
200292
200422
  "../../commons/api-workspace-commons/lib/Source.js"() {
@@ -200445,6 +200575,7 @@ var init_lib17 = __esm({
200445
200575
  init_getFilesystemPublishTarget();
200446
200576
  init_getOriginGitCommit();
200447
200577
  init_openapi();
200578
+ init_RawSpecs();
200448
200579
  init_Source5();
200449
200580
  init_Spec();
200450
200581
  init_utils11();
@@ -264823,6 +264954,7 @@ function parseOpenApiDefinitionSettingsSchema(settings) {
264823
264954
  typeDatesAsStrings: settings?.["type-dates-as-strings"],
264824
264955
  preserveSingleSchemaOneOf: settings?.["preserve-single-schema-oneof"],
264825
264956
  preserveOneOfInAllOf: settings?.["preserve-one-of-in-all-of"],
264957
+ anyOfSiblingPropertiesAsObject: settings?.["any-of-sibling-properties-as-object"],
264826
264958
  inlineAllOfSchemas: settings?.["inline-all-of-schemas"],
264827
264959
  resolveAliases: settings?.["resolve-aliases"],
264828
264960
  groupMultiApiEnvironments: settings?.["group-multi-api-environments"],
@@ -265685,6 +265817,7 @@ var init_convertGeneratorsConfiguration = __esm({
265685
265817
  typeDatesAsStrings: void 0,
265686
265818
  preserveSingleSchemaOneOf: void 0,
265687
265819
  preserveOneOfInAllOf: void 0,
265820
+ anyOfSiblingPropertiesAsObject: void 0,
265688
265821
  inlineAllOfSchemas: void 0,
265689
265822
  resolveAliases: void 0,
265690
265823
  groupMultiApiEnvironments: void 0,
@@ -343851,7 +343984,7 @@ var require_oas_kit_common = __commonJS({
343851
343984
  function allSame(array3) {
343852
343985
  return new Set(array3).size <= 1;
343853
343986
  }
343854
- function deepEquals(obj1, obj2) {
343987
+ function deepEquals2(obj1, obj2) {
343855
343988
  function _equals(obj12, obj22) {
343856
343989
  return sjs.stringify(obj12) === sjs.stringify(Object.assign({}, obj12, obj22));
343857
343990
  }
@@ -343861,7 +343994,7 @@ var require_oas_kit_common = __commonJS({
343861
343994
  let result = [];
343862
343995
  for (let candidate of arr) {
343863
343996
  let dupe = result.find(function(e2, i5, a3) {
343864
- return deepEquals(e2, candidate);
343997
+ return deepEquals2(e2, candidate);
343865
343998
  });
343866
343999
  if (!dupe) result.push(candidate);
343867
344000
  }
@@ -346319,7 +346452,7 @@ async function parseOverlayFile(absoluteFilePathToOverlay, context3) {
346319
346452
  }
346320
346453
  }
346321
346454
  function validateOverlay(overlay, context3) {
346322
- if (!isRecord(overlay)) {
346455
+ if (!isRecord2(overlay)) {
346323
346456
  context3.logger.error("Overlay file must be a YAML or JSON object");
346324
346457
  return false;
346325
346458
  }
@@ -346328,7 +346461,7 @@ function validateOverlay(overlay, context3) {
346328
346461
  return false;
346329
346462
  }
346330
346463
  const info = overlay.info;
346331
- if (!isRecord(info) || typeof info.title !== "string" || info.title.length === 0 || typeof info.version !== "string" || info.version.length === 0) {
346464
+ if (!isRecord2(info) || typeof info.title !== "string" || info.title.length === 0 || typeof info.version !== "string" || info.version.length === 0) {
346332
346465
  context3.logger.error("Overlay file missing required 'info.title' or 'info.version' field");
346333
346466
  return false;
346334
346467
  }
@@ -346339,7 +346472,7 @@ function validateOverlay(overlay, context3) {
346339
346472
  }
346340
346473
  for (let i5 = 0; i5 < actions.length; i5++) {
346341
346474
  const action = actions[i5];
346342
- if (!isRecord(action) || !action.target) {
346475
+ if (!isRecord2(action) || !action.target) {
346343
346476
  context3.logger.error(`Overlay action at index ${i5} missing required 'target' field`);
346344
346477
  return false;
346345
346478
  }
@@ -346350,7 +346483,7 @@ function validateOverlay(overlay, context3) {
346350
346483
  }
346351
346484
  return true;
346352
346485
  }
346353
- function isRecord(value2) {
346486
+ function isRecord2(value2) {
346354
346487
  return typeof value2 === "object" && value2 != null && !Array.isArray(value2);
346355
346488
  }
346356
346489
  var import_promises28, import_path36, import_tmp_promise6, tempDir;
@@ -351696,6 +351829,7 @@ var TYPE_INVARIANT_KEYS, SchemaConverter;
351696
351829
  var init_SchemaConverter = __esm({
351697
351830
  "../api-importers/v3-importer-commons/lib/converters/schema/SchemaConverter.js"() {
351698
351831
  "use strict";
351832
+ init_lib4();
351699
351833
  init_lib9();
351700
351834
  init_lib30();
351701
351835
  init_CreateTypeReferenceFromFernType();
@@ -351769,6 +351903,10 @@ var init_SchemaConverter = __esm({
351769
351903
  if (maybeConvertedTypeArraySchema != null) {
351770
351904
  return maybeConvertedTypeArraySchema;
351771
351905
  }
351906
+ const maybeConvertedSiblingAnyOfConstraint = this.tryConvertSiblingAnyOfConstraint();
351907
+ if (maybeConvertedSiblingAnyOfConstraint != null) {
351908
+ return maybeConvertedSiblingAnyOfConstraint;
351909
+ }
351772
351910
  const maybeConvertedOneOfAnyOfSchema = this.tryConvertOneOfAnyOfSchema();
351773
351911
  if (maybeConvertedOneOfAnyOfSchema != null) {
351774
351912
  return maybeConvertedOneOfAnyOfSchema;
@@ -352109,6 +352247,50 @@ var init_SchemaConverter = __esm({
352109
352247
  }
352110
352248
  return void 0;
352111
352249
  }
352250
+ /**
352251
+ * A schema may declare `properties` alongside an `anyOf` whose branches only
352252
+ * re-declare some of those same properties as required, for example:
352253
+ *
352254
+ * type: object
352255
+ * properties: { a: {...}, b: {...} }
352256
+ * anyOf:
352257
+ * - { properties: { a: {...} }, required: [a] }
352258
+ * - { properties: { b: {...} }, required: [b] }
352259
+ *
352260
+ * Per JSON Schema an instance must satisfy both keywords, so the `anyOf` here
352261
+ * is a validation constraint -- "at least one of a, b" -- and not a set of
352262
+ * variants. Converting it as a union discards the sibling `properties`
352263
+ * entirely and makes the variants mutually exclusive, so a body carrying both
352264
+ * `a` and `b` silently loses one on the wire.
352265
+ *
352266
+ * Drop the `anyOf` and convert the schema as the object it declares. The "at
352267
+ * least one" constraint is not expressible in the IR and is not enforced.
352268
+ *
352269
+ * This only applies when every branch is an inline object whose properties are
352270
+ * a subset of the sibling `properties`. A branch that introduces a property,
352271
+ * or is a reference, is a genuine variant and is left to the union converter.
352272
+ *
352273
+ * Gated behind the `any-of-sibling-properties-as-object` setting.
352274
+ */
352275
+ tryConvertSiblingAnyOfConstraint() {
352276
+ if (!this.context.settings.anyOfSiblingPropertiesAsObject) {
352277
+ return void 0;
352278
+ }
352279
+ if (!anyOfIsPresenceConstraint(this.schema)) {
352280
+ return void 0;
352281
+ }
352282
+ this.context.logger.debug(`Treating the anyOf at ${this.breadcrumbs.join(".")} as an "at least one of" constraint over its sibling properties rather than a union, and converting the schema as an object.`);
352283
+ const { anyOf: _constraint, ...schemaWithoutAnyOf } = this.schema;
352284
+ return new _SchemaConverter({
352285
+ id: this.id,
352286
+ context: this.context,
352287
+ breadcrumbs: this.breadcrumbs,
352288
+ schema: schemaWithoutAnyOf,
352289
+ inlined: this.inlined,
352290
+ nameOverride: this.nameOverride,
352291
+ visitedRefs: this.visitedRefs
352292
+ }).convert();
352293
+ }
352112
352294
  tryConvertOneOfAnyOfSchema() {
352113
352295
  if (this.schema.oneOf != null || this.schema.anyOf != null) {
352114
352296
  const oneOfConverter = new OneOfSchemaConverter({
@@ -374091,6 +374273,7 @@ var init_OSSWorkspace = __esm({
374091
374273
  init_lib31();
374092
374274
  init_lib21();
374093
374275
  init_lib12();
374276
+ init_lib20();
374094
374277
  init_lib4();
374095
374278
  init_lib8();
374096
374279
  init_lib9();
@@ -374121,6 +374304,8 @@ var init_OSSWorkspace = __esm({
374121
374304
  // This avoids running buf generate twice when both toFernWorkspace() and
374122
374305
  // validateOSSWorkspace() need the same OpenAPI specs.
374123
374306
  openApiSpecsCache = /* @__PURE__ */ new Map();
374307
+ /** Guards the orphaned-`auth-schemes` warning so one command warns once. */
374308
+ hasWarnedOrphanedAuthSchemes = false;
374124
374309
  constructor({ allSpecs, specs, ...superArgs }) {
374125
374310
  const openapiSpecs = specs.filter((spec) => spec.type === "openapi" && spec.source.type === "openapi");
374126
374311
  super({
@@ -374260,10 +374445,7 @@ var init_OSSWorkspace = __esm({
374260
374445
  const specs = await this.getOpenAPISpecsCached({ context: context3 });
374261
374446
  const documents = await this.loader.loadDocuments({ context: context3, specs });
374262
374447
  let authOverrides = this.generatorsConfiguration?.api?.auth != null ? { ...this.generatorsConfiguration?.api } : void 0;
374263
- const orphanedAuthSchemeWarning = getOrphanedAuthSchemeWarning(this.generatorsConfiguration?.api);
374264
- if (orphanedAuthSchemeWarning != null) {
374265
- context3.logger.warn(orphanedAuthSchemeWarning);
374266
- }
374448
+ this.warnOnOrphanedAuthSchemes(context3);
374267
374449
  if (authOverrides == null) {
374268
374450
  authOverrides = await getAuthFromOverrideFiles(specs);
374269
374451
  }
@@ -374442,7 +374624,29 @@ var init_OSSWorkspace = __esm({
374442
374624
  }
374443
374625
  return results;
374444
374626
  }
374627
+ /**
374628
+ * Emit the orphaned-`auth-schemes` warning, at most once per workspace.
374629
+ *
374630
+ * Called from BOTH `toFernWorkspace` and `getIntermediateRepresentation`,
374631
+ * because they are different entry points: `fern generate` and plain
374632
+ * `fern check` go through the former, and only `fern check --from-openapi`
374633
+ * reaches the latter (see `validateWorkspaces.ts`, where that branch is
374634
+ * gated on `directFromOpenapi`). Warning from only one of them meant the
374635
+ * customer who hits this bug — silently, on `fern generate` — saw nothing,
374636
+ * which is the entire failure mode.
374637
+ */
374638
+ warnOnOrphanedAuthSchemes(context3) {
374639
+ if (this.hasWarnedOrphanedAuthSchemes) {
374640
+ return;
374641
+ }
374642
+ const warning = getOrphanedAuthSchemeWarning(this.generatorsConfiguration?.api);
374643
+ if (warning != null) {
374644
+ this.hasWarnedOrphanedAuthSchemes = true;
374645
+ context3.logger.warn(warning);
374646
+ }
374647
+ }
374445
374648
  async toFernWorkspace({ context: context3 }, settings, specsOverride) {
374649
+ this.warnOnOrphanedAuthSchemes(context3);
374446
374650
  if (specsOverride != null) {
374447
374651
  return this.createWorkspaceWithSpecsOverride({ context: context3 }, specsOverride, settings);
374448
374652
  }
@@ -374471,6 +374675,13 @@ var init_OSSWorkspace = __esm({
374471
374675
  sources: this.sources
374472
374676
  });
374473
374677
  }
374678
+ async getAllSpecsForGenerator(specsOverride) {
374679
+ if (specsOverride == null) {
374680
+ return this.allSpecs;
374681
+ }
374682
+ const overrideSpecs = await this.convertSpecsOverrideToSpecs(specsOverride);
374683
+ return overrideSpecs.filter((spec) => spec.type !== "protobuf" || !spec.fromOpenAPI);
374684
+ }
374474
374685
  async createWorkspaceWithSpecsOverride({ context: context3 }, specsOverride, settings) {
374475
374686
  const overrideSpecs = await this.convertSpecsOverrideToSpecs(specsOverride);
374476
374687
  const overrideAllSpecs = overrideSpecs.filter((spec) => spec.type !== "protobuf" || !spec.fromOpenAPI);
@@ -374529,8 +374740,9 @@ var init_OSSWorkspace = __esm({
374529
374740
  absoluteFilepath,
374530
374741
  absoluteFilepathToOverrides,
374531
374742
  absoluteFilepathToOverlays,
374532
- // Use default settings from existing specs for compatibility
374533
- settings: this.specs.length > 0 ? this.specs[0]?.settings : void 0,
374743
+ settings: getOpenAPISettings({
374744
+ options: mergeSettings(this.generatorsConfiguration?.api?.settings ?? parseOpenApiDefinitionSettingsSchema(void 0), parseOpenApiDefinitionSettingsSchema(spec.settings))
374745
+ }),
374534
374746
  source: {
374535
374747
  type: "openapi",
374536
374748
  file: absoluteFilepath
@@ -494376,9 +494588,9 @@ var require_graceful_fs2 = __commonJS({
494376
494588
  }
494377
494589
  }
494378
494590
  var fs$readdir = fs35.readdir;
494379
- fs35.readdir = readdir23;
494591
+ fs35.readdir = readdir24;
494380
494592
  var noReaddirOptionVersions = /^v[0-5]\./;
494381
- function readdir23(path122, options2, cb) {
494593
+ function readdir24(path122, options2, cb) {
494382
494594
  if (typeof options2 === "function")
494383
494595
  cb = options2, options2 = null;
494384
494596
  var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path123, options3, cb2, startTime) {
@@ -503231,10 +503443,10 @@ var require_make_dir = __commonJS({
503231
503443
  module4.exports = (input3, opts) => Promise.resolve().then(() => {
503232
503444
  checkPath(input3);
503233
503445
  opts = Object.assign({}, defaults3, opts);
503234
- const mkdir49 = pify(opts.fs.mkdir);
503446
+ const mkdir50 = pify(opts.fs.mkdir);
503235
503447
  const stat8 = pify(opts.fs.stat);
503236
503448
  const make = (pth) => {
503237
- return mkdir49(pth, opts.mode).then(() => pth).catch((err) => {
503449
+ return mkdir50(pth, opts.mode).then(() => pth).catch((err) => {
503238
503450
  if (err.code === "ENOENT") {
503239
503451
  if (err.message.includes("null bytes") || path122.dirname(pth) === pth) {
503240
503452
  throw err;
@@ -637258,14 +637470,14 @@ var require_empty2 = __commonJS({
637258
637470
  var u5 = require_universalify().fromPromise;
637259
637471
  var fs34 = require_fs();
637260
637472
  var path122 = require("path");
637261
- var mkdir49 = require_mkdirs();
637473
+ var mkdir50 = require_mkdirs();
637262
637474
  var remove3 = require_remove3();
637263
637475
  var emptyDir = u5(async function emptyDir2(dir) {
637264
637476
  let items;
637265
637477
  try {
637266
637478
  items = await fs34.readdir(dir);
637267
637479
  } catch {
637268
- return mkdir49.mkdirs(dir);
637480
+ return mkdir50.mkdirs(dir);
637269
637481
  }
637270
637482
  return Promise.all(items.map((item) => remove3.remove(path122.join(dir, item))));
637271
637483
  });
@@ -637274,7 +637486,7 @@ var require_empty2 = __commonJS({
637274
637486
  try {
637275
637487
  items = fs34.readdirSync(dir);
637276
637488
  } catch {
637277
- return mkdir49.mkdirsSync(dir);
637489
+ return mkdir50.mkdirsSync(dir);
637278
637490
  }
637279
637491
  items.forEach((item) => {
637280
637492
  item = path122.join(dir, item);
@@ -637297,7 +637509,7 @@ var require_file2 = __commonJS({
637297
637509
  var u5 = require_universalify().fromPromise;
637298
637510
  var path122 = require("path");
637299
637511
  var fs34 = require_fs();
637300
- var mkdir49 = require_mkdirs();
637512
+ var mkdir50 = require_mkdirs();
637301
637513
  async function createFile(file4) {
637302
637514
  let stats;
637303
637515
  try {
@@ -637311,7 +637523,7 @@ var require_file2 = __commonJS({
637311
637523
  dirStats = await fs34.stat(dir);
637312
637524
  } catch (err) {
637313
637525
  if (err.code === "ENOENT") {
637314
- await mkdir49.mkdirs(dir);
637526
+ await mkdir50.mkdirs(dir);
637315
637527
  await fs34.writeFile(file4, "");
637316
637528
  return;
637317
637529
  } else {
@@ -637337,7 +637549,7 @@ var require_file2 = __commonJS({
637337
637549
  fs34.readdirSync(dir);
637338
637550
  }
637339
637551
  } catch (err) {
637340
- if (err && err.code === "ENOENT") mkdir49.mkdirsSync(dir);
637552
+ if (err && err.code === "ENOENT") mkdir50.mkdirsSync(dir);
637341
637553
  else throw err;
637342
637554
  }
637343
637555
  fs34.writeFileSync(file4, "");
@@ -637356,7 +637568,7 @@ var require_link = __commonJS({
637356
637568
  var u5 = require_universalify().fromPromise;
637357
637569
  var path122 = require("path");
637358
637570
  var fs34 = require_fs();
637359
- var mkdir49 = require_mkdirs();
637571
+ var mkdir50 = require_mkdirs();
637360
637572
  var { pathExists: pathExists2 } = require_path_exists();
637361
637573
  var { areIdentical } = require_stat();
637362
637574
  async function createLink(srcpath, dstpath) {
@@ -637376,7 +637588,7 @@ var require_link = __commonJS({
637376
637588
  const dir = path122.dirname(dstpath);
637377
637589
  const dirExists = await pathExists2(dir);
637378
637590
  if (!dirExists) {
637379
- await mkdir49.mkdirs(dir);
637591
+ await mkdir50.mkdirs(dir);
637380
637592
  }
637381
637593
  await fs34.link(srcpath, dstpath);
637382
637594
  }
@@ -637396,7 +637608,7 @@ var require_link = __commonJS({
637396
637608
  const dir = path122.dirname(dstpath);
637397
637609
  const dirExists = fs34.existsSync(dir);
637398
637610
  if (dirExists) return fs34.linkSync(srcpath, dstpath);
637399
- mkdir49.mkdirsSync(dir);
637611
+ mkdir50.mkdirsSync(dir);
637400
637612
  return fs34.linkSync(srcpath, dstpath);
637401
637613
  }
637402
637614
  module4.exports = {
@@ -637732,19 +637944,19 @@ var require_output_file = __commonJS({
637732
637944
  var u5 = require_universalify().fromPromise;
637733
637945
  var fs34 = require_fs();
637734
637946
  var path122 = require("path");
637735
- var mkdir49 = require_mkdirs();
637947
+ var mkdir50 = require_mkdirs();
637736
637948
  var pathExists2 = require_path_exists().pathExists;
637737
637949
  async function outputFile(file4, data2, encoding = "utf-8") {
637738
637950
  const dir = path122.dirname(file4);
637739
637951
  if (!await pathExists2(dir)) {
637740
- await mkdir49.mkdirs(dir);
637952
+ await mkdir50.mkdirs(dir);
637741
637953
  }
637742
637954
  return fs34.writeFile(file4, data2, encoding);
637743
637955
  }
637744
637956
  function outputFileSync(file4, ...args) {
637745
637957
  const dir = path122.dirname(file4);
637746
637958
  if (!fs34.existsSync(dir)) {
637747
- mkdir49.mkdirsSync(dir);
637959
+ mkdir50.mkdirsSync(dir);
637748
637960
  }
637749
637961
  fs34.writeFileSync(file4, ...args);
637750
637962
  }
@@ -696657,6 +696869,14 @@ var OpenApiSettingsSchema2 = BaseApiSettingsSchema2.extend({
696657
696869
  * Defaults to false.
696658
696870
  */
696659
696871
  preserveOneOfInAllOf: external_exports.boolean().optional(),
696872
+ /**
696873
+ * When a schema declares `properties` alongside an `anyOf` that only marks
696874
+ * some of those same properties required, the `anyOf` is a constraint rather
696875
+ * than a set of variants. Set to true to convert such a schema as an object.
696876
+ * Defaults to false, converting it to a union, which drops the sibling
696877
+ * `properties`.
696878
+ */
696879
+ anyOfSiblingPropertiesAsObject: external_exports.boolean().optional(),
696660
696880
  /**
696661
696881
  * Whether to inline allOf schemas. If false, allOf schemas will be
696662
696882
  * extended in the code generation.
@@ -705301,7 +705521,7 @@ var AccessTokenPosthogManager = class {
705301
705521
  properties: {
705302
705522
  ...event,
705303
705523
  ...event.properties,
705304
- version: "5.23.3-2060-gef10ff1af19",
705524
+ version: "5.23.3-2069-g46cdcdac844",
705305
705525
  usingAccessToken: true,
705306
705526
  ...getRunIdProperties()
705307
705527
  }
@@ -705367,7 +705587,7 @@ var UserPosthogManager = class {
705367
705587
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
705368
705588
  event: "CLI",
705369
705589
  properties: {
705370
- version: "5.23.3-2060-gef10ff1af19",
705590
+ version: "5.23.3-2069-g46cdcdac844",
705371
705591
  ...event,
705372
705592
  ...event.properties,
705373
705593
  usingAccessToken: false,
@@ -712176,6 +712396,7 @@ var LegacyApiSpecAdapter = class {
712176
712396
  typeDatesAsStrings: settings.typeDatesAsStrings,
712177
712397
  preserveSingleSchemaOneOf: settings.preserveSingleSchemaOneof,
712178
712398
  preserveOneOfInAllOf: settings.preserveOneOfInAllOf,
712399
+ anyOfSiblingPropertiesAsObject: settings.anyOfSiblingPropertiesAsObject,
712179
712400
  inlineAllOfSchemas: settings.inlineAllOfSchemas,
712180
712401
  resolveAliases: settings.resolveAliases,
712181
712402
  groupMultiApiEnvironments: settings.groupMultiApiEnvironments,
@@ -885132,6 +885353,7 @@ var SETTINGS_KEY_MAP = {
885132
885353
  "type-dates-as-strings": "typeDatesAsStrings",
885133
885354
  "preserve-single-schema-oneof": "preserveSingleSchemaOneof",
885134
885355
  "preserve-one-of-in-all-of": "preserveOneOfInAllOf",
885356
+ "any-of-sibling-properties-as-object": "anyOfSiblingPropertiesAsObject",
885135
885357
  "inline-all-of-schemas": "inlineAllOfSchemas",
885136
885358
  "resolve-aliases": "resolveAliases",
885137
885359
  "group-multi-api-environments": "groupMultiApiEnvironments",
@@ -887041,7 +887263,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
887041
887263
  var LOGS_FOLDER_NAME = "logs";
887042
887264
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
887043
887265
  function getCliSource() {
887044
- const version7 = "5.23.3-2060-gef10ff1af19";
887266
+ const version7 = "5.23.3-2069-g46cdcdac844";
887045
887267
  return `cli@${version7}`;
887046
887268
  }
887047
887269
  var DebugLogger = class {
@@ -908698,6 +908920,28 @@ function getGeneratorLanguage(generatorId) {
908698
908920
  return getGeneratorPolicy(generatorId)?.language;
908699
908921
  }
908700
908922
  function validateGeneratorConfigCompatibility(input3) {
908923
+ const route = selectGeneratorConfigRoute(input3);
908924
+ const receivedConfigKind = input3.configKind;
908925
+ if (!isGenerationConfigKind(receivedConfigKind)) {
908926
+ throw compatibilityError(input3, {
908927
+ code: "INVALID_CONFIG_KIND",
908928
+ message: "Configuration kind must be legacy-fern or sdk-config-v1",
908929
+ cutoverVersion: route.cutoverVersion,
908930
+ expectedLanguage: route.language,
908931
+ expectedConfigKind: route.configKind,
908932
+ recommendedAction: "USE_SUPPORTED_CONFIG_KIND"
908933
+ }, receivedConfigKind);
908934
+ }
908935
+ if (receivedConfigKind !== route.configKind) {
908936
+ const policy = getGeneratorPolicy(input3.generatorId);
908937
+ if (policy === void 0) {
908938
+ throw new Error(`Missing validated generator policy for ${input3.generatorId}`);
908939
+ }
908940
+ throw configKindError(input3, policy, route.configKind, receivedConfigKind);
908941
+ }
908942
+ return route;
908943
+ }
908944
+ function selectGeneratorConfigRoute(input3) {
908701
908945
  const policy = getGeneratorPolicy(input3.generatorId);
908702
908946
  if (policy === void 0) {
908703
908947
  throw compatibilityError(input3, {
@@ -908732,27 +908976,13 @@ function validateGeneratorConfigCompatibility(input3) {
908732
908976
  }
908733
908977
  const isBeforeCutover = compareSemver(requestedVersion, policy.parsedCutoverVersion) < 0;
908734
908978
  const expectedConfigKind = isBeforeCutover ? "legacy-fern" : "sdk-config-v1";
908735
- const receivedConfigKind = input3.configKind;
908736
- if (!isGenerationConfigKind(receivedConfigKind)) {
908737
- throw compatibilityError(input3, {
908738
- code: "INVALID_CONFIG_KIND",
908739
- message: "Configuration kind must be legacy-fern or sdk-config-v1",
908740
- cutoverVersion: policy.cutoverVersion,
908741
- expectedLanguage: policy.language,
908742
- expectedConfigKind,
908743
- recommendedAction: "USE_SUPPORTED_CONFIG_KIND"
908744
- }, receivedConfigKind);
908745
- }
908746
- if (receivedConfigKind !== expectedConfigKind) {
908747
- throw configKindError(input3, policy, expectedConfigKind, receivedConfigKind);
908748
- }
908749
908979
  return {
908750
908980
  generatorId: input3.generatorId,
908751
908981
  language: policy.language,
908752
908982
  requestedVersion: input3.requestedVersion,
908753
908983
  cutoverVersion: policy.cutoverVersion,
908754
- configKind: receivedConfigKind,
908755
- payloadKind: isBeforeCutover ? "fern-runtime-bundle" : "sdk-config-ir-v1"
908984
+ configKind: expectedConfigKind,
908985
+ payloadKind: isBeforeCutover ? "fern-runtime-bundle" : "sdk-config-v1"
908756
908986
  };
908757
908987
  }
908758
908988
  function compatibilityError(input3, details, receivedConfigKind = input3.configKind) {
@@ -908783,13 +909013,15 @@ function isGenerationConfigKind(value2) {
908783
909013
  var POLL_INTERVAL_MS2 = 2e3;
908784
909014
  var POLL_TIMEOUT_MS2 = 15 * 60 * 1e3;
908785
909015
  var REQUEST_TIMEOUT_MS = 6e4;
908786
- var MAX_BUNDLES = 64;
909016
+ var MAX_PAYLOADS = 64;
908787
909017
  var MAX_SOURCE_COMPRESSED_BYTES = 25 * 1024 * 1024;
908788
909018
  var MAX_SOURCE_DECOMPRESSED_BYTES = 25 * 1024 * 1024;
908789
- var MAX_BUNDLE_COMPRESSED_BYTES = 5 * 1024 * 1024;
908790
- var MAX_BUNDLE_DECOMPRESSED_BYTES = 25 * 1024 * 1024;
908791
- var MAX_TOTAL_BUNDLE_COMPRESSED_BYTES = 25 * 1024 * 1024;
908792
- var MAX_TOTAL_BUNDLE_DECOMPRESSED_BYTES = 100 * 1024 * 1024;
909019
+ var MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES = 5 * 1024 * 1024;
909020
+ var MAX_PAYLOAD_BYTES = 25 * 1024 * 1024;
909021
+ var MAX_TOTAL_RUNTIME_BUNDLE_COMPRESSED_BYTES = 25 * 1024 * 1024;
909022
+ var MAX_TOTAL_PAYLOAD_BYTES = 100 * 1024 * 1024;
909023
+ var MAX_TOTAL_UPLOAD_FILE_BYTES = 50 * 1024 * 1024;
909024
+ var MAX_REQUEST_FIELD_BYTES = 1024 * 1024;
908793
909025
  var MAX_MULTIPART_BODY_BYTES = 60 * 1024 * 1024;
908794
909026
  var LOOPBACK_HOSTNAMES2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
908795
909027
  var TARGET_ID_SEED_COLLATOR = new Intl.Collator("en", { numeric: true });
@@ -908820,6 +909052,18 @@ function getFernSdkGenApiOrigin() {
908820
909052
  function getFernSdkGenApiLanguage(generatorName) {
908821
909053
  return getGeneratorLanguage(generatorName);
908822
909054
  }
909055
+ function selectFernSdkGenApiRoute(generatorInvocation) {
909056
+ const language = getFernSdkGenApiLanguage(generatorInvocation.name);
909057
+ if (language == null) {
909058
+ return void 0;
909059
+ }
909060
+ return validateGeneratorConfigCompatibility({
909061
+ generatorId: generatorInvocation.name,
909062
+ language: generatorInvocation.language ?? language,
909063
+ requestedVersion: generatorInvocation.version,
909064
+ configKind: "legacy-fern"
909065
+ });
909066
+ }
908823
909067
  function mapFernSdkGenApiOutput(generatorInvocation) {
908824
909068
  const outputMode = generatorInvocation.outputMode;
908825
909069
  switch (outputMode.type) {
@@ -909021,6 +909265,7 @@ function isEligibleForFernSdkGenApi(candidate) {
909021
909265
  var FernSdkGenApiBatch = class {
909022
909266
  expectedTargets;
909023
909267
  participants = [];
909268
+ removedTargetIds = /* @__PURE__ */ new Set();
909024
909269
  terminalError;
909025
909270
  dispatched = false;
909026
909271
  constructor(expectedTargets) {
@@ -909033,6 +909278,9 @@ var FernSdkGenApiBatch = class {
909033
909278
  if (this.terminalError != null) {
909034
909279
  return Promise.reject(this.terminalError);
909035
909280
  }
909281
+ if (parameters2.targetIdSeed != null && this.removedTargetIds.has(parameters2.targetIdSeed)) {
909282
+ return Promise.reject(new Error(`Fern sdk-gen-api target ${parameters2.targetIdSeed} was removed`));
909283
+ }
909036
909284
  if (this.dispatched) {
909037
909285
  return Promise.reject(new Error("The Fern sdk-gen-api batch was already dispatched"));
909038
909286
  }
@@ -909049,6 +909297,22 @@ var FernSdkGenApiBatch = class {
909049
909297
  this.expectedTargets -= 1;
909050
909298
  this.dispatchIfReady();
909051
909299
  }
909300
+ /** Removes one failed automation target while preserving undispatched siblings. */
909301
+ remove(targetIdSeed, error50) {
909302
+ if (this.dispatched || this.terminalError != null) {
909303
+ return false;
909304
+ }
909305
+ if (this.removedTargetIds.has(targetIdSeed)) {
909306
+ return false;
909307
+ }
909308
+ this.removedTargetIds.add(targetIdSeed);
909309
+ const participantIndex = this.participants.findIndex((participant2) => participant2.targetIdSeed === targetIdSeed);
909310
+ const [participant] = participantIndex >= 0 ? this.participants.splice(participantIndex, 1) : [];
909311
+ participant?.reject(error50);
909312
+ this.expectedTargets -= 1;
909313
+ this.dispatchIfReady();
909314
+ return true;
909315
+ }
909052
909316
  /** Prevents siblings waiting at the batch barrier from hanging if preparation of one fails. */
909053
909317
  cancel(error50) {
909054
909318
  if (this.dispatched || this.terminalError != null) {
@@ -909060,7 +909324,7 @@ var FernSdkGenApiBatch = class {
909060
909324
  }
909061
909325
  }
909062
909326
  dispatchIfReady() {
909063
- if (this.dispatched || this.terminalError != null || this.participants.length !== this.expectedTargets) {
909327
+ if (this.dispatched || this.terminalError != null || this.expectedTargets === 0 || this.participants.length !== this.expectedTargets) {
909064
909328
  return;
909065
909329
  }
909066
909330
  this.dispatched = true;
@@ -909086,6 +909350,72 @@ var FernSdkGenApiBatch = class {
909086
909350
  }
909087
909351
  }
909088
909352
  };
909353
+ var FernSdkGenApiPreparationBatch = class {
909354
+ expectedTargetIds;
909355
+ settledTargetIds = /* @__PURE__ */ new Set();
909356
+ waiters = [];
909357
+ preflightParticipants = [];
909358
+ terminalError;
909359
+ didRunPreflight = false;
909360
+ constructor(targetIds) {
909361
+ this.expectedTargetIds = new Set(targetIds);
909362
+ if (this.expectedTargetIds.size !== targetIds.length) {
909363
+ throw new Error("Fern sdk-gen-api preparation target IDs must be unique");
909364
+ }
909365
+ }
909366
+ ready(targetId, preflightParameters) {
909367
+ this.assertExpected(targetId);
909368
+ if (this.settledTargetIds.has(targetId)) {
909369
+ throw new Error(`Fern sdk-gen-api target ${targetId} prepared more than once`);
909370
+ }
909371
+ this.settledTargetIds.add(targetId);
909372
+ if (preflightParameters != null) {
909373
+ this.preflightParticipants.push(preflightParameters);
909374
+ }
909375
+ return new Promise((resolve15, reject) => {
909376
+ this.waiters.push({ resolve: resolve15, reject });
909377
+ this.finishIfSettled();
909378
+ });
909379
+ }
909380
+ /** Returns true only when this call newly settles a target that failed before preparation. */
909381
+ fail(targetId, error50, isolateFailure) {
909382
+ this.assertExpected(targetId);
909383
+ if (this.settledTargetIds.has(targetId)) {
909384
+ return false;
909385
+ }
909386
+ this.settledTargetIds.add(targetId);
909387
+ if (!isolateFailure) {
909388
+ this.terminalError = error50;
909389
+ }
909390
+ this.finishIfSettled();
909391
+ return true;
909392
+ }
909393
+ assertExpected(targetId) {
909394
+ if (!this.expectedTargetIds.has(targetId)) {
909395
+ throw new Error(`Unexpected Fern sdk-gen-api preparation target ${targetId}`);
909396
+ }
909397
+ }
909398
+ finishIfSettled() {
909399
+ if (this.settledTargetIds.size !== this.expectedTargetIds.size) {
909400
+ return;
909401
+ }
909402
+ if (!this.didRunPreflight && this.terminalError == null && this.preflightParticipants.length > 0) {
909403
+ this.didRunPreflight = true;
909404
+ try {
909405
+ prepareFernSdkGenApiSubmission(this.preflightParticipants);
909406
+ } catch (error50) {
909407
+ this.terminalError = error50;
909408
+ }
909409
+ }
909410
+ for (const waiter of this.waiters) {
909411
+ if (this.terminalError != null) {
909412
+ waiter.reject(this.terminalError);
909413
+ } else {
909414
+ waiter.resolve();
909415
+ }
909416
+ }
909417
+ }
909418
+ };
909089
909419
  async function runFernSdkGenApiBuild(parameters2) {
909090
909420
  const [result] = await executeFernSdkGenApiBuild([parameters2]);
909091
909421
  if (result?.status === "fulfilled") {
@@ -909093,7 +909423,12 @@ async function runFernSdkGenApiBuild(parameters2) {
909093
909423
  }
909094
909424
  throw result?.reason ?? new Error("sdk-gen-api did not return the requested target");
909095
909425
  }
909096
- async function executeFernSdkGenApiBuild(participants) {
909426
+ function validateFernSdkGenApiTargetCount(targetCount) {
909427
+ if (targetCount > MAX_PAYLOADS) {
909428
+ throw new Error(`sdk-gen-api supports at most ${MAX_PAYLOADS} target payloads per build; received ${targetCount}`);
909429
+ }
909430
+ }
909431
+ function prepareFernSdkGenApiSubmission(participants) {
909097
909432
  const first3 = participants[0];
909098
909433
  if (first3 == null) {
909099
909434
  throw new Error("Cannot submit an empty Fern sdk-gen-api build");
@@ -909120,13 +909455,20 @@ async function executeFernSdkGenApiBuild(participants) {
909120
909455
  targets: participants.map((participant) => ({
909121
909456
  generatorInvocation: participant.generatorInvocation,
909122
909457
  sdkVersion: participant.sdkVersion,
909458
+ apiVersion: participant.apiVersion,
909123
909459
  targetIdSeed: participant.targetIdSeed,
909460
+ sourceSpecIndexes: participant.sourceSpecIndexes,
909124
909461
  audiences: participant.audiences,
909125
- runtimeBundle: participant.runtimeBundle
909462
+ payload: participant.payload
909126
909463
  }))
909127
909464
  });
909465
+ const serializedRequest = JSON.stringify(request7);
909466
+ const serializedRequestBytes = Buffer.byteLength(serializedRequest, "utf8");
909467
+ if (serializedRequestBytes > MAX_REQUEST_FIELD_BYTES) {
909468
+ return first3.context.failAndThrow(`sdk-gen-api serialized request field is ${formatMiB(serializedRequestBytes)}, exceeding the 1 MiB UTF-8 field limit; reduce generator customConfig, readme, settings, or API override metadata`, void 0, { code: CliError.Code.ConfigError });
909469
+ }
909128
909470
  const form = new import_form_data4.default();
909129
- form.append("request", JSON.stringify(request7));
909471
+ form.append("request", serializedRequest);
909130
909472
  form.append("sources", first3.specsTarGzBuffer, {
909131
909473
  filename: "specs.tar.gz",
909132
909474
  contentType: "application/gzip"
@@ -909134,17 +909476,22 @@ async function executeFernSdkGenApiBuild(participants) {
909134
909476
  participants.forEach((participant, index3) => {
909135
909477
  const target = request7.targets[index3];
909136
909478
  if (target == null) {
909137
- throw new Error(`Cannot pair sdk-gen-api runtime bundle at index ${index3} with a target`);
909479
+ throw new Error(`Cannot pair sdk-gen-api payload at index ${index3} with a target`);
909138
909480
  }
909139
- form.append("bundles", participant.runtimeBundle, {
909140
- filename: `${target.targetId}.json.gz`,
909141
- contentType: "application/gzip"
909481
+ const isRuntimeBundle = participant.payload.payloadKind === "fern-runtime-bundle";
909482
+ form.append("payloads", participant.payload.body, {
909483
+ filename: `${target.targetId}.json${isRuntimeBundle ? ".gz" : ""}`,
909484
+ contentType: isRuntimeBundle ? "application/gzip" : "application/json"
909142
909485
  });
909143
909486
  });
909144
909487
  const multipartBodyLength = form.getLengthSync();
909145
909488
  if (multipartBodyLength > MAX_MULTIPART_BODY_BYTES) {
909146
- return first3.context.failAndThrow(`sdk-gen-api multipart request is ${formatMiB(multipartBodyLength)}, exceeding the 60 MiB limit; reduce source or target bundle size`, void 0, { code: CliError.Code.ConfigError });
909489
+ return first3.context.failAndThrow(`sdk-gen-api multipart request is ${formatMiB(multipartBodyLength)}, exceeding the 60 MiB limit; reduce source or target payload size`, void 0, { code: CliError.Code.ConfigError });
909147
909490
  }
909491
+ return { first: first3, origin: origin2, request: request7, form };
909492
+ }
909493
+ async function executeFernSdkGenApiBuild(participants) {
909494
+ const { first: first3, origin: origin2, request: request7, form } = prepareFernSdkGenApiSubmission(participants);
909148
909495
  let buildId;
909149
909496
  try {
909150
909497
  const response = await axios_default.post(`${origin2}/v1/fern/build`, form, {
@@ -909222,7 +909569,7 @@ function assertGeneratorConfigCompatibility(participants) {
909222
909569
  generatorId: generatorInvocation.name,
909223
909570
  language,
909224
909571
  requestedVersion: generatorInvocation.version,
909225
- configKind: "legacy-fern"
909572
+ configKind: participant.payload.payloadKind === "fern-runtime-bundle" ? "legacy-fern" : "sdk-config-v1"
909226
909573
  });
909227
909574
  } catch (error50) {
909228
909575
  if (!(error50 instanceof GeneratorConfigCompatibilityError)) {
@@ -909247,8 +909594,8 @@ function formatGeneratorConfigCompatibilityError(error50) {
909247
909594
  `retryable=${error50.retryable}`,
909248
909595
  `recommendedAction=${error50.recommendedAction}`
909249
909596
  ].join("; ");
909250
- const remediation = error50.code === "SDK_CONFIG_V1_REQUIRED" ? " Run `fern sdk-config migrate` to create SDK Config v1 for this target." : "";
909251
- return `Cannot submit SDK generation to sdk-gen-api: ${error50.message} [${diagnostic}].${remediation}`;
909597
+ const migrationHint = error50.recommendedAction === "USE_SDK_CONFIG_V1" ? " Run `fern sdk migrate --output <path>` to migrate this SDK configuration before using this generator version." : "";
909598
+ return `Cannot submit SDK generation to sdk-gen-api: ${error50.message} [${diagnostic}].${migrationHint}`;
909252
909599
  }
909253
909600
  function compareFernSdkGenApiParticipants(left3, right3) {
909254
909601
  const seedComparison = TARGET_ID_SEED_COLLATOR.compare(left3.targetIdSeed ?? "", right3.targetIdSeed ?? "");
@@ -909266,20 +909613,25 @@ function compareFernSdkGenApiParticipants(left3, right3) {
909266
909613
  return left3.sdkVersion.localeCompare(right3.sdkVersion);
909267
909614
  }
909268
909615
  function validateProtocolInputs(participants, first3) {
909269
- if (participants.length > MAX_BUNDLES) {
909270
- first3.context.failAndThrow(`sdk-gen-api supports at most ${MAX_BUNDLES} runtime bundles per build; received ${participants.length}`, void 0, { code: CliError.Code.ConfigError });
909616
+ if (participants.length > MAX_PAYLOADS) {
909617
+ first3.context.failAndThrow(`sdk-gen-api supports at most ${MAX_PAYLOADS} target payloads per build; received ${participants.length}`, void 0, { code: CliError.Code.ConfigError });
909271
909618
  }
909272
909619
  if (first3.specsTarGzBuffer.length > MAX_SOURCE_COMPRESSED_BYTES) {
909273
909620
  first3.context.failAndThrow(`sdk-gen-api source archive is ${formatMiB(first3.specsTarGzBuffer.length)}, exceeding the 25 MiB compressed limit`, void 0, { code: CliError.Code.ConfigError });
909274
909621
  }
909275
- const oversizedBundleIndex = participants.findIndex((participant) => participant.runtimeBundle.length > MAX_BUNDLE_COMPRESSED_BYTES);
909276
- if (oversizedBundleIndex >= 0) {
909277
- const participant = participants[oversizedBundleIndex];
909278
- first3.context.failAndThrow(`sdk-gen-api runtime bundle ${participant?.targetIdSeed ?? oversizedBundleIndex.toString()} is ${formatMiB(participant?.runtimeBundle.length ?? 0)}, exceeding the 5 MiB compressed limit`, void 0, { code: CliError.Code.ConfigError });
909622
+ const oversizedPayloadIndex = participants.findIndex((participant) => participant.payload.body.length > (participant.payload.payloadKind === "fern-runtime-bundle" ? MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES : MAX_PAYLOAD_BYTES));
909623
+ if (oversizedPayloadIndex >= 0) {
909624
+ const participant = participants[oversizedPayloadIndex];
909625
+ const maxBytes = participant?.payload.payloadKind === "fern-runtime-bundle" ? MAX_RUNTIME_BUNDLE_COMPRESSED_BYTES : MAX_PAYLOAD_BYTES;
909626
+ first3.context.failAndThrow(`sdk-gen-api ${payloadLabel(participant, oversizedPayloadIndex)} is ${formatMiB(participant?.payload.body.length ?? 0)}, exceeding the ${formatMiB(maxBytes)} upload limit`, void 0, { code: CliError.Code.ConfigError });
909627
+ }
909628
+ const totalUploadFileBytes = participants.reduce((total, participant) => total + participant.payload.body.length, first3.specsTarGzBuffer.length);
909629
+ if (totalUploadFileBytes > MAX_TOTAL_UPLOAD_FILE_BYTES) {
909630
+ first3.context.failAndThrow(`sdk-gen-api source archive and target payloads total ${formatMiB(totalUploadFileBytes)}, exceeding the 50 MiB in-memory upload limit; reduce the source archive size, target payload size, or number of targets`, void 0, { code: CliError.Code.ConfigError });
909279
909631
  }
909280
- const totalBundleBytes = participants.reduce((total, participant) => total + participant.runtimeBundle.length, 0);
909281
- if (totalBundleBytes > MAX_TOTAL_BUNDLE_COMPRESSED_BYTES) {
909282
- 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 });
909632
+ const totalRuntimeBundleBytes = participants.reduce((total, participant) => participant.payload.payloadKind === "fern-runtime-bundle" ? total + participant.payload.body.length : total, 0);
909633
+ if (totalRuntimeBundleBytes > MAX_TOTAL_RUNTIME_BUNDLE_COMPRESSED_BYTES) {
909634
+ first3.context.failAndThrow(`sdk-gen-api runtime bundles total ${formatMiB(totalRuntimeBundleBytes)}, exceeding the 25 MiB compressed limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909283
909635
  }
909284
909636
  getBoundedGzipSize({
909285
909637
  buffer: first3.specsTarGzBuffer,
@@ -909287,19 +909639,23 @@ function validateProtocolInputs(participants, first3) {
909287
909639
  label: "source archive",
909288
909640
  context: first3.context
909289
909641
  });
909290
- let totalDecompressedBundleBytes = 0;
909642
+ let totalPayloadBytes = 0;
909291
909643
  for (const [index3, participant] of participants.entries()) {
909292
- totalDecompressedBundleBytes += getBoundedGzipSize({
909293
- buffer: participant.runtimeBundle,
909294
- maxBytes: MAX_BUNDLE_DECOMPRESSED_BYTES,
909295
- label: `runtime bundle ${participant.targetIdSeed ?? index3.toString()}`,
909644
+ totalPayloadBytes += participant.payload.payloadKind === "fern-runtime-bundle" ? getBoundedGzipSize({
909645
+ buffer: participant.payload.body,
909646
+ maxBytes: MAX_PAYLOAD_BYTES,
909647
+ label: payloadLabel(participant, index3),
909296
909648
  context: first3.context
909297
- });
909298
- if (totalDecompressedBundleBytes > MAX_TOTAL_BUNDLE_DECOMPRESSED_BYTES) {
909299
- first3.context.failAndThrow(`sdk-gen-api runtime bundles total ${formatMiB(totalDecompressedBundleBytes)} decompressed, exceeding the 100 MiB decompressed limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909649
+ }) : participant.payload.body.length;
909650
+ if (totalPayloadBytes > MAX_TOTAL_PAYLOAD_BYTES) {
909651
+ first3.context.failAndThrow(`sdk-gen-api target payloads total ${formatMiB(totalPayloadBytes)}, exceeding the 100 MiB decoded limit; reduce the number or size of targets`, void 0, { code: CliError.Code.ConfigError });
909300
909652
  }
909301
909653
  }
909302
909654
  }
909655
+ function payloadLabel(participant, index3) {
909656
+ const kind = participant?.payload.payloadKind ?? "target payload";
909657
+ return `${kind} ${participant?.targetIdSeed ?? index3.toString()}`;
909658
+ }
909303
909659
  function getBoundedGzipSize({ buffer, maxBytes, label, context: context3 }) {
909304
909660
  let decompressed;
909305
909661
  try {
@@ -909382,23 +909738,41 @@ function createFernSdkGenApiBatchRequest({ apiName, organization, cliVersion, sp
909382
909738
  if (targets2.length === 0) {
909383
909739
  throw new Error("Cannot create an empty Fern sdk-gen-api request");
909384
909740
  }
909385
- const requestTargets = targets2.map(({ generatorInvocation, sdkVersion, targetIdSeed, audiences }, index3) => {
909741
+ const apiInputs = [];
909742
+ const apiInputIds = targets2.map(({ targetIdSeed, sourceSpecIndexes }, index3) => {
909743
+ if (sourceSpecIndexes == null) {
909744
+ if (!apiInputs.some((input3) => input3.id === "default")) {
909745
+ apiInputs.push({ id: "default", specIndexes: "all" });
909746
+ }
909747
+ return "default";
909748
+ }
909749
+ const id = `target-${targetIdSeed ?? index3.toString()}`;
909750
+ apiInputs.push({ id, specIndexes: sourceSpecIndexes });
909751
+ return id;
909752
+ });
909753
+ const requestTargets = targets2.map(({ generatorInvocation, sdkVersion, apiVersion, targetIdSeed, audiences, payload }, index3) => {
909386
909754
  const language = getFernSdkGenApiLanguage(generatorInvocation.name);
909387
909755
  if (language == null) {
909388
909756
  throw new Error(`Unsupported Fern SDK generator: ${generatorInvocation.name}`);
909389
909757
  }
909390
909758
  const output2 = mapFernSdkGenApiOutput(generatorInvocation);
909759
+ const packageConfig = payload.package ?? output2.package;
909391
909760
  const targetId = (0, import_crypto10.createHash)("sha256").update(`${apiName}:${generatorInvocation.name}:${generatorInvocation.version}:${targetIdSeed ?? index3.toString()}`).digest("hex").slice(0, 20);
909392
909761
  return {
909393
909762
  targetId,
909394
- apiInputId: "default",
909763
+ apiInputId: apiInputIds[index3] ?? "default",
909395
909764
  language,
909396
- sdk: { name: apiName, version: sdkVersion },
909765
+ sdk: {
909766
+ name: apiName,
909767
+ version: sdkVersion,
909768
+ ...apiVersion != null ? { apiVersion } : {}
909769
+ },
909397
909770
  fernGenerator: {
909398
909771
  id: generatorInvocation.name,
909399
909772
  version: generatorInvocation.version
909400
909773
  },
909401
- ...output2.package != null ? { package: output2.package } : {},
909774
+ payloadKind: payload.payloadKind,
909775
+ ...packageConfig != null ? { package: packageConfig } : {},
909402
909776
  invocation: {
909403
909777
  customConfig: stripCliConfigKeys(generatorInvocation.config) ?? {},
909404
909778
  keywords: generatorInvocation.keywords ?? [],
@@ -909417,15 +909791,14 @@ function createFernSdkGenApiBatchRequest({ apiName, organization, cliVersion, sp
909417
909791
  requestedOutput: output2.requestedOutput
909418
909792
  };
909419
909793
  });
909420
- const apiInputs = [{ id: "default", specIndexes: "all" }];
909421
- const runtimeBundleHashes = targets2.map((target) => (0, import_crypto10.createHash)("sha256").update(target.runtimeBundle).digest("hex"));
909794
+ const payloadHashes = targets2.map((target) => (0, import_crypto10.createHash)("sha256").update(target.payload.body).digest("hex"));
909422
909795
  const idempotencyKey = (0, import_crypto10.createHash)("sha256").update(specsTarGzBuffer).update(JSON.stringify({
909423
909796
  protocolVersion: 2,
909424
909797
  organization,
909425
909798
  apiName,
909426
909799
  apiInputs,
909427
909800
  targets: requestTargets,
909428
- runtimeBundleHashes
909801
+ payloadHashes
909429
909802
  })).digest("hex");
909430
909803
  return {
909431
909804
  protocolVersion: 2,
@@ -910553,6 +910926,33 @@ async function downloadFileForTask({ s3PreSignedReadUrl, absolutePathToLocalOutp
910553
910926
  await (0, import_promises122.pipeline)(request7.data, (0, import_fs37.createWriteStream)(absolutePathToLocalOutput));
910554
910927
  }
910555
910928
 
910929
+ // ../generation/remote-generation/remote-workspace-runner/lib/fernSdkGenApiSourceArchive.js
910930
+ function validateFernSdkGenApiSourceCompatibility(route, sourceArchive) {
910931
+ if (route.payloadKind !== "sdk-config-v1" || route.configKind !== "sdk-config-v1") {
910932
+ return;
910933
+ }
910934
+ if (sourceArchive.specIndexes.length === 0) {
910935
+ throw new Error("SDK Config v1 requires at least one effective Fern source spec");
910936
+ }
910937
+ const seenIndexes = /* @__PURE__ */ new Set();
910938
+ for (const manifestIndex of sourceArchive.specIndexes) {
910939
+ if (seenIndexes.has(manifestIndex)) {
910940
+ throw new Error(`Fern target source selection contains duplicate manifest index ${manifestIndex}`);
910941
+ }
910942
+ seenIndexes.add(manifestIndex);
910943
+ const source2 = sourceArchive.manifest.specs[manifestIndex];
910944
+ if (source2 == null) {
910945
+ throw new Error(`Fern source manifest does not contain selected index ${manifestIndex}`);
910946
+ }
910947
+ if (!isSupportedSourceType(source2.type)) {
910948
+ throw new Error(`Generator ${route.generatorId} ${route.requestedVersion} requires SDK Config v1, but selected source ${manifestIndex} cannot be represented downstream: SDK Config generation does not support Fern source type ${source2.type} (${source2.specPath}). Use an OpenAPI, AsyncAPI, or GraphQL source for this generator version.`);
910949
+ }
910950
+ }
910951
+ }
910952
+ function isSupportedSourceType(type7) {
910953
+ return type7 === "openapi" || type7 === "asyncapi" || type7 === "graphql";
910954
+ }
910955
+
910556
910956
  // ../generation/remote-generation/remote-workspace-runner/lib/resolveAutoDiscoveredFernignorePath.js
910557
910957
  init_lib12();
910558
910958
  init_lib8();
@@ -911112,26 +911512,25 @@ var SourceUploader = class {
911112
911512
  };
911113
911513
 
911114
911514
  // ../generation/remote-generation/remote-workspace-runner/lib/runRemoteGenerationForGenerator.js
911115
- async function runRemoteGenerationForGenerator({ projectConfig, organization, workspace, interactiveTaskContext, generatorInvocation, version: version7, audiences, shouldLogS3Url, token, whitelabel, replay, irVersionOverride, absolutePathToPreview, isPreview: isPreviewOverride, fiddlePreview, pushPreviewBranch, readme, fernignorePath, skipFernignore, dynamicIrOnly, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, loginCommand, specsTarGzBuffer, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject }) {
911515
+ async function runRemoteGenerationForGenerator({ projectConfig, organization, workspace, interactiveTaskContext, generatorInvocation, version: version7, audiences, shouldLogS3Url, token, whitelabel, replay, irVersionOverride, absolutePathToPreview, isPreview: isPreviewOverride, fiddlePreview, pushPreviewBranch, readme, fernignorePath, skipFernignore, dynamicIrOnly, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, loginCommand, specsTarGzBuffer, sdkGenApiSourceArchive, sdkGenApiRoute, sdkGenApiPreparationBatch, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject }) {
911116
911516
  const fdr = createFdrService({ token: token.value });
911117
911517
  const fdrOrigin = "https://registry-dev2.buildwithfern.com";
911118
911518
  const isAirGapped = await detectAirGappedMode(`${fdrOrigin}/health`, interactiveTaskContext.logger);
911119
911519
  const packageName = generators_yml_exports.getPackageName({ generatorInvocation }) ?? (generatorInvocation.outputMode.type === "downloadFiles" ? getPackageNameFromGeneratorConfig(generatorInvocation) : void 0);
911120
911520
  const isPreview = isPreviewOverride ?? absolutePathToPreview != null;
911121
- const substituteEnvVars = (stringOrObject) => replaceEnvVariables(stringOrObject, {
911122
- onError: (e2) => {
911521
+ const resolvedWhitelabel = whitelabel == null ? void 0 : replaceEnvVariables(whitelabel, {
911522
+ onError: (error50) => {
911123
911523
  if (!isPreview && requireEnvVars) {
911124
- interactiveTaskContext.failAndThrow(void 0, e2, {
911524
+ interactiveTaskContext.failAndThrow(void 0, error50, {
911125
911525
  code: CliError.Code.EnvironmentError
911126
911526
  });
911127
911527
  }
911128
911528
  }
911129
911529
  }, { substituteAsEmpty: isPreview });
911130
- const generatorInvocationWithEnvVarSubstitutions = substituteEnvVars(generatorInvocation);
911131
911530
  const dynamicGeneratorConfig = getDynamicGeneratorConfig({
911132
911531
  apiName: workspace.definition.rootApiFile.contents.name,
911133
911532
  organization,
911134
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions
911533
+ generatorInvocation
911135
911534
  });
911136
911535
  const resolvedVersion = version7 ?? await computeSemanticVersion({ packageName, generatorInvocation });
911137
911536
  if (version7 != null) {
@@ -911182,10 +911581,43 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911182
911581
  ciProvider: detectCiProvider()
911183
911582
  }
911184
911583
  });
911185
- const venus = createVenusService({ token: token.value });
911584
+ let sdkGenApiCandidate;
911585
+ const sdkGenApiLanguage = getFernSdkGenApiLanguage(generatorInvocation.name);
911586
+ if (sdkGenApiRoute != null) {
911587
+ if (replay?.enabled === true) {
911588
+ return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support replay", void 0, {
911589
+ code: CliError.Code.ConfigError
911590
+ });
911591
+ }
911592
+ if (generateFullProject === true) {
911593
+ return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support full-project generation", void 0, { code: CliError.Code.ConfigError });
911594
+ }
911595
+ const candidate = {
911596
+ generatorInvocation,
911597
+ sdkVersion: resolvedVersion,
911598
+ specsTarGzBuffer,
911599
+ whitelabel
911600
+ };
911601
+ if (!isEligibleForFernSdkGenApi(candidate)) {
911602
+ const reason = resolvedVersion == null ? "the SDK version could not be resolved" : (0, import_autoversion2.isAutoVersion)(resolvedVersion) ? "automatic SDK versioning has not yet moved from Fiddle to the shared pipeline" : whitelabel != null ? "whitelabel generation has not yet moved from Fiddle to the shared pipeline" : specsTarGzBuffer == null ? "the source archive is unavailable" : `generator language ${generatorInvocation.language ?? "unknown"} does not match ${sdkGenApiLanguage}`;
911603
+ return interactiveTaskContext.failAndThrow(`Cannot submit SDK generation to sdk-gen-api: ${reason}`, void 0, {
911604
+ code: CliError.Code.ConfigError
911605
+ });
911606
+ }
911607
+ sdkGenApiCandidate = candidate;
911608
+ if (sdkGenApiRoute.payloadKind === "sdk-config-v1") {
911609
+ return interactiveTaskContext.failAndThrow(`Cannot submit ${candidate.generatorInvocation.name} ${candidate.generatorInvocation.version} from legacy Fern configuration. Run \`fern sdk migrate --output <path>\` to create SDK Config v1 before using this generator version.`, void 0, { code: CliError.Code.ConfigError });
911610
+ }
911611
+ if (sdkGenApiTargetIdSeed == null) {
911612
+ throw new Error("sdk-gen-api target is missing its preparation ID");
911613
+ }
911614
+ await sdkGenApiPreparationBatch?.ready(sdkGenApiTargetIdSeed);
911615
+ }
911616
+ const requiresFdrRegistration = sdkGenApiRoute?.payloadKind !== "sdk-config-v1";
911186
911617
  let generateOauthClients = false;
911187
911618
  let generatePaginatedClients = false;
911188
- if (!isAirGapped) {
911619
+ if (!isAirGapped && requiresFdrRegistration) {
911620
+ const venus = createVenusService({ token: token.value });
911189
911621
  const orgResponse = await venus.organization.get({ orgId: projectConfig.organization });
911190
911622
  if (orgResponse.ok) {
911191
911623
  if (orgResponse.body.isWhitelabled) {
@@ -911199,50 +911631,52 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911199
911631
  generatePaginatedClients = orgResponse.body.paginationEnabled ?? false;
911200
911632
  }
911201
911633
  }
911202
- const sources = workspace.getSources();
911203
911634
  let fdrApiDefinitionId;
911204
- let sourceUploads;
911205
- const apiDefinition = convertIrToFdrApi({
911206
- ir: ir3,
911207
- snippetsConfig: {
911208
- typescriptSdk: void 0,
911209
- pythonSdk: void 0,
911210
- javaSdk: void 0,
911211
- rubySdk: void 0,
911212
- goSdk: void 0,
911213
- csharpSdk: void 0,
911214
- phpSdk: void 0,
911215
- swiftSdk: void 0,
911216
- rustSdk: void 0
911217
- },
911218
- context: interactiveTaskContext
911219
- });
911220
- try {
911221
- const response = await fdr.api.register.registerApiDefinition({
911222
- orgId: FdrAPI_exports.OrgId(organization),
911223
- apiId: FdrAPI_exports.ApiId(getOriginalName(ir3.apiName)),
911224
- definition: apiDefinition,
911225
- sources: sources.length > 0 ? convertToFdrApiDefinitionSources(sources) : void 0
911635
+ if (requiresFdrRegistration) {
911636
+ const sources = workspace.getSources();
911637
+ let sourceUploads;
911638
+ const apiDefinition = convertIrToFdrApi({
911639
+ ir: ir3,
911640
+ snippetsConfig: {
911641
+ typescriptSdk: void 0,
911642
+ pythonSdk: void 0,
911643
+ javaSdk: void 0,
911644
+ rubySdk: void 0,
911645
+ goSdk: void 0,
911646
+ csharpSdk: void 0,
911647
+ phpSdk: void 0,
911648
+ swiftSdk: void 0,
911649
+ rustSdk: void 0
911650
+ },
911651
+ context: interactiveTaskContext
911226
911652
  });
911227
- fdrApiDefinitionId = response.apiDefinitionId;
911228
- sourceUploads = response.sources ?? void 0;
911229
- } catch (error50) {
911230
- const sourceUploader2 = new SourceUploader(interactiveTaskContext, sources);
911231
- if (sourceUploader2.sourceTypes.has("protobuf")) {
911232
- interactiveTaskContext.failAndThrow(`Failed to register API definition: ${JSON.stringify(error50)}`);
911653
+ try {
911654
+ const response = await fdr.api.register.registerApiDefinition({
911655
+ orgId: FdrAPI_exports.OrgId(organization),
911656
+ apiId: FdrAPI_exports.ApiId(getOriginalName(ir3.apiName)),
911657
+ definition: apiDefinition,
911658
+ sources: sources.length > 0 ? convertToFdrApiDefinitionSources(sources) : void 0
911659
+ });
911660
+ fdrApiDefinitionId = response.apiDefinitionId;
911661
+ sourceUploads = response.sources ?? void 0;
911662
+ } catch (error50) {
911663
+ const sourceUploader2 = new SourceUploader(interactiveTaskContext, sources);
911664
+ if (sourceUploader2.sourceTypes.has("protobuf")) {
911665
+ interactiveTaskContext.failAndThrow(`Failed to register API definition: ${JSON.stringify(error50)}`);
911666
+ }
911667
+ }
911668
+ const sourceUploader = new SourceUploader(interactiveTaskContext, sources);
911669
+ if (sourceUploads == null && sourceUploader.sourceTypes.has("protobuf")) {
911670
+ interactiveTaskContext.failAndThrow("Did not successfully upload Protobuf source files.", void 0, {
911671
+ code: CliError.Code.NetworkError
911672
+ });
911673
+ }
911674
+ if (sourceUploads != null) {
911675
+ interactiveTaskContext.logger.debug("Uploading source files ...");
911676
+ const sourceConfig = await sourceUploader.uploadSources(sourceUploads);
911677
+ interactiveTaskContext.logger.debug("Setting IR source configuration ...");
911678
+ ir3.sourceConfig = sourceConfig;
911233
911679
  }
911234
- }
911235
- const sourceUploader = new SourceUploader(interactiveTaskContext, sources);
911236
- if (sourceUploads == null && sourceUploader.sourceTypes.has("protobuf")) {
911237
- interactiveTaskContext.failAndThrow("Did not successfully upload Protobuf source files.", void 0, {
911238
- code: CliError.Code.NetworkError
911239
- });
911240
- }
911241
- if (sourceUploads != null) {
911242
- interactiveTaskContext.logger.debug("Uploading source files ...");
911243
- const sourceConfig = await sourceUploader.uploadSources(sourceUploads);
911244
- interactiveTaskContext.logger.debug("Setting IR source configuration ...");
911245
- ir3.sourceConfig = sourceConfig;
911246
911680
  }
911247
911681
  if (dynamicIrOnly) {
911248
911682
  interactiveTaskContext.logger.info("Dynamic IR only mode: skipping SDK generation and uploading dynamic IR only");
@@ -911293,7 +911727,7 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911293
911727
  ...ir3,
911294
911728
  fdrApiDefinitionId,
911295
911729
  publishConfig: getPublishConfig({
911296
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911730
+ generatorInvocation,
911297
911731
  version: resolvedVersion,
911298
911732
  userProvidedVersion: version7,
911299
911733
  packageName,
@@ -911303,76 +911737,56 @@ async function runRemoteGenerationForGenerator({ projectConfig, organization, wo
911303
911737
  })
911304
911738
  };
911305
911739
  let result;
911306
- let usedSdkGenApi = false;
911307
- const sdkGenApiEnabled = isFernSdkGenApiEnabled();
911308
- const sdkGenApiLanguage = getFernSdkGenApiLanguage(generatorInvocationWithEnvVarSubstitutions.name);
911309
- if (sdkGenApiEnabled && sdkGenApiLanguage != null) {
911310
- if (replay?.enabled === true) {
911311
- return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support replay", void 0, {
911312
- code: CliError.Code.ConfigError
911313
- });
911314
- }
911315
- if (generateFullProject === true) {
911316
- return interactiveTaskContext.failAndThrow("sdk-gen-api does not yet support full-project generation", void 0, { code: CliError.Code.ConfigError });
911317
- }
911318
- const candidate = {
911319
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911320
- sdkVersion: resolvedVersion,
911321
- specsTarGzBuffer,
911322
- whitelabel
911323
- };
911324
- if (!isEligibleForFernSdkGenApi(candidate)) {
911325
- 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}`;
911326
- return interactiveTaskContext.failAndThrow(`Cannot submit SDK generation to sdk-gen-api: ${reason}`, void 0, {
911327
- code: CliError.Code.ConfigError
911328
- });
911740
+ if (sdkGenApiRoute != null) {
911741
+ if (sdkGenApiCandidate == null) {
911742
+ throw new Error("sdk-gen-api target passed preflight without an eligible candidate");
911329
911743
  }
911330
- if (verify2 === true) {
911331
- interactiveTaskContext.logger.warn("sdk-gen-api does not yet run Fern's post-generation verification step");
911744
+ if (sdkGenApiRoute.payloadKind !== "fern-runtime-bundle") {
911745
+ throw new Error("Legacy Fern generation reached sdk-gen-api without a Fern runtime bundle route");
911332
911746
  }
911333
- const runtimeBundle = await prepareFernSdkGenApiRuntimeBundle({
911334
- apiName: getOriginalName(ir3.apiName),
911335
- organization,
911336
- generatorInvocation: candidate.generatorInvocation,
911337
- sdkVersion: candidate.sdkVersion,
911338
- intermediateRepresentation: enrichedIntermediateRepresentation,
911339
- irVersionOverride,
911340
- generateOauthClients,
911341
- generatePaginatedClients,
911342
- context: interactiveTaskContext
911343
- });
911344
911747
  const parameters2 = {
911345
911748
  apiName: getOriginalName(ir3.apiName),
911346
911749
  organization,
911347
911750
  cliVersion: workspace.cliVersion,
911348
- generatorInvocation: candidate.generatorInvocation,
911349
- sdkVersion: candidate.sdkVersion,
911751
+ generatorInvocation: sdkGenApiCandidate.generatorInvocation,
911752
+ sdkVersion: sdkGenApiCandidate.sdkVersion,
911753
+ apiVersion: ir3.specVersion,
911350
911754
  token,
911351
- specsTarGzBuffer: candidate.specsTarGzBuffer,
911352
- runtimeBundle,
911755
+ specsTarGzBuffer: sdkGenApiCandidate.specsTarGzBuffer,
911756
+ payload: {
911757
+ payloadKind: sdkGenApiRoute.payloadKind,
911758
+ body: await prepareFernSdkGenApiRuntimeBundle({
911759
+ apiName: getOriginalName(ir3.apiName),
911760
+ organization,
911761
+ generatorInvocation: sdkGenApiCandidate.generatorInvocation,
911762
+ sdkVersion: sdkGenApiCandidate.sdkVersion,
911763
+ intermediateRepresentation: enrichedIntermediateRepresentation,
911764
+ irVersionOverride,
911765
+ generateOauthClients,
911766
+ generatePaginatedClients,
911767
+ context: interactiveTaskContext
911768
+ })
911769
+ },
911353
911770
  absolutePathToPreview,
911354
911771
  context: interactiveTaskContext,
911355
911772
  targetIdSeed: sdkGenApiTargetIdSeed,
911773
+ sourceSpecIndexes: sdkGenApiSourceArchive?.specIndexes,
911356
911774
  audiences: audiences.type === "select" ? audiences.audiences : void 0,
911357
911775
  skipFernignore
911358
911776
  };
911359
911777
  result = await (sdkGenApiBatch?.run(parameters2) ?? runFernSdkGenApiBuild(parameters2));
911360
- usedSdkGenApi = true;
911361
911778
  } else {
911362
- sdkGenApiBatch?.skip();
911363
- }
911364
- if (!usedSdkGenApi) {
911365
911779
  const job = await createAndStartJob({
911366
911780
  projectConfig,
911367
911781
  workspace,
911368
911782
  organization,
911369
- generatorInvocation: generatorInvocationWithEnvVarSubstitutions,
911783
+ generatorInvocation,
911370
911784
  context: interactiveTaskContext,
911371
911785
  version: resolvedVersion,
911372
911786
  intermediateRepresentation: enrichedIntermediateRepresentation,
911373
911787
  shouldLogS3Url,
911374
911788
  token,
911375
- whitelabel: whitelabel != null ? substituteEnvVars(whitelabel) : void 0,
911789
+ whitelabel: resolvedWhitelabel,
911376
911790
  replay,
911377
911791
  irVersionOverride,
911378
911792
  absolutePathToPreview,
@@ -911579,10 +911993,51 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911579
911993
  effectiveOccurrenceTracker.recordOccurrences(generatorGroup.generators);
911580
911994
  }
911581
911995
  const generatorsYmlAbsolutePath = workspace.generatorsConfiguration?.absolutePathToConfiguration;
911582
- const sdkGenApiCandidateIndexes = new Set(isFernSdkGenApiEnabled() ? generatorGroup.generators.flatMap((generator, index3) => getFernSdkGenApiLanguage(generator.name) != null ? [index3] : []) : []);
911996
+ const routePreparation = prepareFernSdkGenApiRoutes({
911997
+ generators: generatorGroup.generators,
911998
+ enabled: isFernSdkGenApiEnabled(),
911999
+ requireEnvVars,
912000
+ isPreview: isPreview ?? absolutePathToPreview != null,
912001
+ verify: verify2,
912002
+ skipIfNoDiff,
912003
+ autoMerge
912004
+ });
912005
+ const sdkGenApiRoutes = routePreparation.map((result) => result.route);
912006
+ const resolvedGenerators = routePreparation.map((result) => result.generatorInvocation);
912007
+ const routeErrors = routePreparation.map((result) => result.error);
912008
+ if (automation == null) {
912009
+ throwFirstPreflightError(routeErrors, generatorGroup.generators);
912010
+ }
912011
+ const sourceRequests = resolvedGenerators.flatMap((generatorInvocation, generatorIndex) => routePreparation[generatorIndex]?.error == null ? [{ generatorIndex, generatorInvocation, sdkGenApiRoute: sdkGenApiRoutes[generatorIndex] }] : []);
912012
+ let sourceResolution = { sourceArchives: /* @__PURE__ */ new Map(), errors: /* @__PURE__ */ new Map() };
912013
+ if (sourceRequests.length > 0) {
912014
+ try {
912015
+ sourceResolution = await getSpecsTarGzBuffer?.(sourceRequests) ?? sourceResolution;
912016
+ } catch (error50) {
912017
+ sourceResolution = {
912018
+ sourceArchives: /* @__PURE__ */ new Map(),
912019
+ errors: new Map(sourceRequests.map((request7) => [request7.generatorIndex, error50]))
912020
+ };
912021
+ }
912022
+ }
912023
+ const sourcePreflight = preflightFernSdkGenApiSources({
912024
+ generators: resolvedGenerators,
912025
+ routes: sdkGenApiRoutes,
912026
+ routeErrors,
912027
+ sourceResolution
912028
+ });
912029
+ const sourceArchives = sourcePreflight.sourceArchives;
912030
+ const preflightErrors = routePreparation.map((result, index3) => result.error ?? sourcePreflight.preflightErrors[index3]);
912031
+ if (automation == null) {
912032
+ throwFirstPreflightError(preflightErrors, generatorGroup.generators);
912033
+ }
912034
+ const sdkGenApiCandidateIndexes = getFernSdkGenApiCandidateIndexes(sdkGenApiRoutes, preflightErrors);
912035
+ validateFernSdkGenApiTargetCount(sdkGenApiCandidateIndexes.size);
911583
912036
  const sdkGenApiBatch = sdkGenApiCandidateIndexes.size > 1 ? new FernSdkGenApiBatch(sdkGenApiCandidateIndexes.size) : void 0;
912037
+ const sdkGenApiPreparationBatch = sdkGenApiCandidateIndexes.size > 0 ? new FernSdkGenApiPreparationBatch([...sdkGenApiCandidateIndexes].map(String)) : void 0;
911584
912038
  const results = await Promise.all(generatorGroup.generators.map((generatorInvocation, generatorIndex) => context3.runInteractiveTask({ name: generatorInvocation.name }, (interactiveTaskContext) => generateOne({
911585
912039
  generatorInvocation,
912040
+ resolvedGeneratorInvocation: resolvedGenerators[generatorIndex] ?? generatorInvocation,
911586
912041
  interactiveTaskContext,
911587
912042
  // Closed-over state + params passed through to the per-generator worker.
911588
912043
  projectConfig,
@@ -911616,7 +912071,10 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911616
912071
  generatorsYmlAbsolutePath,
911617
912072
  occurrenceTracker: effectiveOccurrenceTracker,
911618
912073
  loginCommand,
911619
- getSpecsTarGzBuffer,
912074
+ specsTarGzArchive: sourceArchives[generatorIndex],
912075
+ sdkGenApiPreflightError: preflightErrors[generatorIndex],
912076
+ sdkGenApiRoute: sdkGenApiRoutes[generatorIndex],
912077
+ sdkGenApiPreparationBatch: sdkGenApiCandidateIndexes.has(generatorIndex) ? sdkGenApiPreparationBatch : void 0,
911620
912078
  sdkGenApiBatch: sdkGenApiCandidateIndexes.has(generatorIndex) ? sdkGenApiBatch : void 0,
911621
912079
  sdkGenApiTargetIdSeed: generatorIndex.toString(),
911622
912080
  generateFullProject,
@@ -911629,11 +912087,105 @@ async function runRemoteGenerationForAPIWorkspace({ projectConfig, organization,
911629
912087
  snippetsProducedBy
911630
912088
  };
911631
912089
  }
911632
- async function generateOne({ generatorInvocation, interactiveTaskContext, projectConfig, organization, workspace, context: context3, generatorGroup, version: version7, shouldLogS3Url, token, whitelabel, replay, absolutePathToPreview, isPreview, fiddlePreview, pushPreviewBranch, mode, fernignorePath, skipFernignore, dynamicIrOnly, validateWorkspace, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, automation, generatorsYmlAbsolutePath, occurrenceTracker, loginCommand, getSpecsTarGzBuffer, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject, onSnippetsProduced }) {
912090
+ function prepareFernSdkGenApiRoutes({ generators, enabled, requireEnvVars, isPreview, verify: verify2, skipIfNoDiff, autoMerge }) {
912091
+ return generators.map((generatorInvocation) => {
912092
+ let resolved = generatorInvocation;
912093
+ try {
912094
+ resolved = replaceEnvVariables(generatorInvocation, {
912095
+ onError: (error50) => {
912096
+ if (!isPreview && requireEnvVars) {
912097
+ throw error50;
912098
+ }
912099
+ }
912100
+ }, { substituteAsEmpty: isPreview });
912101
+ const route = selectFernSdkGenApiRoute(resolved);
912102
+ if (!enabled) {
912103
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912104
+ }
912105
+ const unsupportedOutput = getFernSdkGenApiUnsupportedOutput({
912106
+ generatorInvocation: resolved,
912107
+ verify: verify2,
912108
+ skipIfNoDiff,
912109
+ autoMerge
912110
+ });
912111
+ if (route != null && unsupportedOutput != null) {
912112
+ if (route.configKind === "legacy-fern") {
912113
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912114
+ }
912115
+ throw new Error(`Cannot route ${resolved.name} ${resolved.version} through sdk-gen-api: ${unsupportedOutput}. This generator version requires SDK Config v1, so Fern cannot fall back to legacy Fiddle generation.`);
912116
+ }
912117
+ return {
912118
+ generatorInvocation: resolved,
912119
+ route,
912120
+ error: void 0
912121
+ };
912122
+ } catch (error50) {
912123
+ if (!enabled && error50 instanceof GeneratorConfigCompatibilityError && error50.code === "INVALID_GENERATOR_VERSION") {
912124
+ return { generatorInvocation: resolved, route: void 0, error: void 0 };
912125
+ }
912126
+ const routeError = error50 instanceof GeneratorConfigCompatibilityError ? new CliError({
912127
+ message: formatGeneratorConfigCompatibilityError(error50),
912128
+ code: CliError.Code.ConfigError
912129
+ }) : error50;
912130
+ return { generatorInvocation: resolved, route: void 0, error: routeError };
912131
+ }
912132
+ });
912133
+ }
912134
+ function getFernSdkGenApiUnsupportedOutput({ generatorInvocation, verify: verify2, skipIfNoDiff, autoMerge }) {
912135
+ const unsupported = [];
912136
+ if (generatorInvocation.outputMode.type !== "downloadFiles") {
912137
+ unsupported.push(`${generatorInvocation.outputMode.type} delivery requires Fern-managed GitHub or registry credentials that sdk-gen-api cannot resolve`);
912138
+ }
912139
+ if (verify2 === true) {
912140
+ unsupported.push("verify=true is not implemented by sdk-gen-api");
912141
+ }
912142
+ if (skipIfNoDiff === true) {
912143
+ unsupported.push("skipIfNoDiff=true is not implemented by sdk-gen-api");
912144
+ }
912145
+ if (autoMerge === true) {
912146
+ unsupported.push("autoMerge=true is not implemented by sdk-gen-api");
912147
+ }
912148
+ return unsupported.length > 0 ? unsupported.join("; ") : void 0;
912149
+ }
912150
+ function preflightFernSdkGenApiSources({ generators, routes, routeErrors, sourceResolution }) {
912151
+ return {
912152
+ sourceArchives: generators.map((_5, index3) => sourceResolution.sourceArchives.get(index3)),
912153
+ preflightErrors: generators.map((_5, index3) => {
912154
+ if (routeErrors?.[index3] != null) {
912155
+ return void 0;
912156
+ }
912157
+ const route = routes[index3];
912158
+ if (route == null) {
912159
+ return void 0;
912160
+ }
912161
+ const sourceError = sourceResolution.errors.get(index3);
912162
+ if (sourceError != null) {
912163
+ return sourceError;
912164
+ }
912165
+ const sourceArchive = sourceResolution.sourceArchives.get(index3);
912166
+ if (sourceArchive == null) {
912167
+ return new Error(`Resolved source archive is unavailable for ${route.generatorId}`);
912168
+ }
912169
+ try {
912170
+ validateFernSdkGenApiSourceCompatibility(route, sourceArchive);
912171
+ return void 0;
912172
+ } catch (error50) {
912173
+ return error50;
912174
+ }
912175
+ })
912176
+ };
912177
+ }
912178
+ function getFernSdkGenApiCandidateIndexes(routes, preflightErrors) {
912179
+ return new Set(routes.flatMap((route, index3) => route != null && preflightErrors[index3] == null ? [index3] : []));
912180
+ }
912181
+ async function generateOne({ generatorInvocation, resolvedGeneratorInvocation, interactiveTaskContext, projectConfig, organization, workspace, context: context3, generatorGroup, version: version7, shouldLogS3Url, token, whitelabel, replay, absolutePathToPreview, isPreview, fiddlePreview, pushPreviewBranch, mode, fernignorePath, skipFernignore, dynamicIrOnly, validateWorkspace, retryRateLimited, requireEnvVars, automationMode, autoMerge, skipIfNoDiff, verify: verify2, noReplay, disableTelemetry, automation, generatorsYmlAbsolutePath, occurrenceTracker, loginCommand, specsTarGzArchive, sdkGenApiPreflightError, sdkGenApiRoute, sdkGenApiPreparationBatch, sdkGenApiBatch, sdkGenApiTargetIdSeed, generateFullProject, onSnippetsProduced }) {
911633
912182
  const startedAt = Date.now();
911634
912183
  try {
911635
- const settings = getBaseOpenAPIWorkspaceSettingsFromGeneratorInvocation(generatorInvocation);
911636
- const fernWorkspace = await workspace.toFernWorkspace({ context: context3 }, settings, generatorInvocation.apiOverride?.specs);
912184
+ if (sdkGenApiPreflightError != null) {
912185
+ throw sdkGenApiPreflightError;
912186
+ }
912187
+ const settings = getBaseOpenAPIWorkspaceSettingsFromGeneratorInvocation(resolvedGeneratorInvocation);
912188
+ const fernWorkspace = await workspace.toFernWorkspace({ context: context3 }, settings, resolvedGeneratorInvocation.apiOverride?.specs);
911637
912189
  if (validateWorkspace) {
911638
912190
  await validateAPIWorkspaceAndLogIssues({
911639
912191
  workspace: fernWorkspace,
@@ -911643,7 +912195,7 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911643
912195
  });
911644
912196
  }
911645
912197
  const effectiveFernignorePath = skipFernignore ? void 0 : fernignorePath ?? await resolveAutoDiscoveredFernignorePath({
911646
- generatorInvocation,
912198
+ generatorInvocation: resolvedGeneratorInvocation,
911647
912199
  context: interactiveTaskContext
911648
912200
  });
911649
912201
  const remoteTaskHandlerResponse = await runRemoteGenerationForGenerator({
@@ -911652,9 +912204,9 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911652
912204
  workspace: fernWorkspace,
911653
912205
  interactiveTaskContext,
911654
912206
  generatorInvocation: {
911655
- ...generatorInvocation,
911656
- outputMode: generatorInvocation.outputMode._visit({
911657
- downloadFiles: () => generatorInvocation.outputMode,
912207
+ ...resolvedGeneratorInvocation,
912208
+ outputMode: resolvedGeneratorInvocation.outputMode._visit({
912209
+ downloadFiles: () => resolvedGeneratorInvocation.outputMode,
911658
912210
  github: (val) => {
911659
912211
  return api_exports4.OutputMode.github({
911660
912212
  ...val,
@@ -911665,11 +912217,11 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911665
912217
  if (mode === "pull-request") {
911666
912218
  return api_exports4.OutputMode.githubV2(api_exports4.GithubOutputModeV2.pullRequest(val));
911667
912219
  }
911668
- return generatorInvocation.outputMode;
912220
+ return resolvedGeneratorInvocation.outputMode;
911669
912221
  },
911670
- publish: () => generatorInvocation.outputMode,
911671
- publishV2: () => generatorInvocation.outputMode,
911672
- _other: () => generatorInvocation.outputMode
912222
+ publish: () => resolvedGeneratorInvocation.outputMode,
912223
+ publishV2: () => resolvedGeneratorInvocation.outputMode,
912224
+ _other: () => resolvedGeneratorInvocation.outputMode
911673
912225
  })
911674
912226
  },
911675
912227
  version: version7,
@@ -911678,8 +912230,8 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911678
912230
  token,
911679
912231
  whitelabel,
911680
912232
  replay,
911681
- readme: generatorInvocation.readme,
911682
- irVersionOverride: generatorInvocation.irVersionOverride,
912233
+ readme: resolvedGeneratorInvocation.readme,
912234
+ irVersionOverride: resolvedGeneratorInvocation.irVersionOverride,
911683
912235
  absolutePathToPreview,
911684
912236
  isPreview,
911685
912237
  fiddlePreview,
@@ -911696,7 +912248,10 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911696
912248
  noReplay,
911697
912249
  disableTelemetry,
911698
912250
  loginCommand,
911699
- specsTarGzBuffer: await getSpecsTarGzBuffer?.(generatorInvocation.name),
912251
+ specsTarGzBuffer: specsTarGzArchive?.buffer,
912252
+ sdkGenApiSourceArchive: specsTarGzArchive,
912253
+ sdkGenApiRoute,
912254
+ sdkGenApiPreparationBatch,
911700
912255
  sdkGenApiBatch,
911701
912256
  sdkGenApiTargetIdSeed,
911702
912257
  generateFullProject
@@ -911738,7 +912293,12 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911738
912293
  isAutomation: automation != null
911739
912294
  });
911740
912295
  } catch (error50) {
911741
- sdkGenApiBatch?.cancel(error50);
912296
+ sdkGenApiPreparationBatch?.fail(sdkGenApiTargetIdSeed, error50, automation != null);
912297
+ if (automation != null) {
912298
+ sdkGenApiBatch?.remove(sdkGenApiTargetIdSeed, error50);
912299
+ } else {
912300
+ sdkGenApiBatch?.cancel(error50);
912301
+ }
911742
912302
  if (automation == null) {
911743
912303
  throw error50;
911744
912304
  }
@@ -911773,6 +912333,17 @@ async function generateOne({ generatorInvocation, interactiveTaskContext, projec
911773
912333
  });
911774
912334
  }
911775
912335
  }
912336
+ function throwFirstPreflightError(errors4, generators) {
912337
+ const failedIndex = errors4.findIndex((error51) => error51 != null);
912338
+ if (failedIndex < 0) {
912339
+ return;
912340
+ }
912341
+ const error50 = errors4[failedIndex];
912342
+ if (error50 instanceof CliError) {
912343
+ throw error50;
912344
+ }
912345
+ throw new Error(`Cannot prepare sdk-gen-api target ${generators[failedIndex]?.name ?? failedIndex.toString()}: ${extractErrorMessage(error50)}`, { cause: error50 });
912346
+ }
911776
912347
  async function emitGenerationAnnotations(ctx) {
911777
912348
  if (!shouldEmitGithubAnnotations()) {
911778
912349
  return;
@@ -914005,7 +914576,7 @@ var LegacyDocsPublisher = class {
914005
914576
  previewId,
914006
914577
  disableTemplates: void 0,
914007
914578
  skipUpload,
914008
- cliVersion: "5.23.3-2060-gef10ff1af19",
914579
+ cliVersion: "5.23.3-2069-g46cdcdac844",
914009
914580
  loginCommand: "fern auth login"
914010
914581
  });
914011
914582
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -930482,16 +931053,16 @@ var TestClass = class extends Node5 {
930482
931053
  };
930483
931054
 
930484
931055
  // ../../../generators/csharp/codegen/lib/context/filesystem-nuget-publish-target.js
930485
- function isRecord2(value2) {
931056
+ function isRecord3(value2) {
930486
931057
  return typeof value2 === "object" && value2 != null;
930487
931058
  }
930488
931059
  function getFilesystemNugetPublishTarget(ir3) {
930489
931060
  const publishConfig = ir3.publishConfig;
930490
- if (!isRecord2(publishConfig) || publishConfig.type !== "filesystem") {
931061
+ if (!isRecord3(publishConfig) || publishConfig.type !== "filesystem") {
930491
931062
  return void 0;
930492
931063
  }
930493
931064
  const publishTarget = publishConfig.publishTarget;
930494
- if (!isRecord2(publishTarget) || publishTarget.type !== "nuget") {
931065
+ if (!isRecord3(publishTarget) || publishTarget.type !== "nuget") {
930495
931066
  return void 0;
930496
931067
  }
930497
931068
  return {
@@ -968300,6 +968871,8 @@ async function copySnippetJsonIfNonEmpty({ src, dest }) {
968300
968871
  }
968301
968872
 
968302
968873
  // ../generation/local-generation/local-workspace-runner/lib/rawSpecs.js
968874
+ var import_node_util10 = require("util");
968875
+ init_lib17();
968303
968876
  init_lib4();
968304
968877
  init_lib8();
968305
968878
  init_lib35();
@@ -968342,7 +968915,14 @@ async function collectRawSpecs({ specs, hostOutputDir, containerBaseDir, context
968342
968915
  async function resolveAndWriteSpec({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3, audiences }) {
968343
968916
  switch (spec.type) {
968344
968917
  case "openapi":
968345
- return resolveOpenAPIOrAsyncAPI({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3, audiences });
968918
+ return resolveOpenAPIOrAsyncAPI({
968919
+ spec,
968920
+ hostOutputDir,
968921
+ containerBaseDir,
968922
+ context: context3,
968923
+ index: index3,
968924
+ audiences
968925
+ });
968346
968926
  case "openrpc":
968347
968927
  return resolveOpenRPC({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3 });
968348
968928
  case "protobuf":
@@ -968377,9 +968957,41 @@ async function resolveOpenAPIOrAsyncAPI({ spec, hostOutputDir, containerBaseDir,
968377
968957
  return {
968378
968958
  type: isAsync2 ? "asyncapi" : "openapi",
968379
968959
  specPath: toContainerPath(filename, containerBaseDir),
968380
- namespace: spec.namespace
968960
+ namespace: spec.namespace,
968961
+ apiImportSettings: mapApiImportSettings(getOpenAPISettings({ overrides: spec.settings }))
968381
968962
  };
968382
968963
  }
968964
+ var SDK_CONFIG_IMPORT_SETTING_MAPPERS = {
968965
+ respectNullableSchemas: (settings) => ({ respectNullableSchemas: settings.respectNullableSchemas }),
968966
+ useTitlesAsName: (settings) => ({ titleAsSchemaName: settings.useTitlesAsName }),
968967
+ coerceEnumsToLiterals: (settings) => ({ coerceEnumsToLiterals: settings.coerceEnumsToLiterals }),
968968
+ shouldUseIdiomaticRequestNames: (settings) => ({
968969
+ idiomaticRequestNames: settings.shouldUseIdiomaticRequestNames
968970
+ }),
968971
+ wrapReferencesToNullableInOptional: (settings) => ({
968972
+ wrapReferencesToNullableInOptional: settings.wrapReferencesToNullableInOptional
968973
+ }),
968974
+ coerceOptionalSchemasToNullable: (settings) => ({
968975
+ coerceOptionalSchemasToNullable: settings.coerceOptionalSchemasToNullable
968976
+ }),
968977
+ pathParameterOrder: (settings) => ({ pathParameterOrder: settings.pathParameterOrder }),
968978
+ onlyIncludeReferencedSchemas: (settings) => ({
968979
+ onlyIncludeReferencedSchemas: settings.onlyIncludeReferencedSchemas
968980
+ }),
968981
+ objectQueryParameters: (settings) => ({ objectQueryParameters: settings.objectQueryParameters }),
968982
+ typeDatesAsStrings: (settings) => ({ typeDatesAsStrings: settings.typeDatesAsStrings }),
968983
+ groupMultiApiEnvironments: (settings) => ({
968984
+ groupMultiApiEnvironments: settings.groupMultiApiEnvironments
968985
+ }),
968986
+ defaultIntegerFormat: (settings) => ({ defaultIntegerFormat: settings.defaultIntegerFormat })
968987
+ };
968988
+ function mapApiImportSettings(settings) {
968989
+ const mappedSettings = {};
968990
+ for (const mapSetting of Object.values(SDK_CONFIG_IMPORT_SETTING_MAPPERS)) {
968991
+ Object.assign(mappedSettings, mapSetting(settings));
968992
+ }
968993
+ return mappedSettings;
968994
+ }
968383
968995
  async function resolveOpenRPC({ spec, hostOutputDir, containerBaseDir, context: context3, index: index3 }) {
968384
968996
  const filename = `openrpc${index3}.json`;
968385
968997
  const rawContent = await (0, import_promises143.readFile)(spec.absoluteFilepath, "utf-8");
@@ -968553,30 +969165,318 @@ function matchesAudiences(operation, selectedAudiences) {
968553
969165
  function hasOperations(pathItem) {
968554
969166
  return Object.keys(pathItem).some((key2) => HTTP_METHODS3.has(key2.toLowerCase()));
968555
969167
  }
968556
- async function createSpecsTarGzBuffer({ specs, context: context3, audiences }) {
969168
+ async function createGroupedSpecsTarGzArchiveSettled({ generatorSelections, context: context3, audiences }) {
969169
+ const deduplicated = deduplicateGeneratorSelections(generatorSelections);
969170
+ const errorsByGeneratorIndex = /* @__PURE__ */ new Map();
968557
969171
  const tmpDir = await import_tmp_promise17.default.dir({ unsafeCleanup: true });
968558
969172
  try {
969173
+ const materializedRoot = import_path99.default.join(tmpDir.path, "materialized");
969174
+ await (0, import_promises143.mkdir)(materializedRoot);
969175
+ const materializedSpecs = await Promise.allSettled(deduplicated.uniqueSpecs.map(async (spec, uniqueSpecIndex) => {
969176
+ const directory = import_path99.default.join(materializedRoot, uniqueSpecIndex.toString());
969177
+ await (0, import_promises143.mkdir)(directory);
969178
+ const manifest = await collectRawSpecs({
969179
+ specs: [spec],
969180
+ hostOutputDir: AbsoluteFilePath2.of(directory),
969181
+ containerBaseDir: "/fern/specs",
969182
+ context: context3,
969183
+ audiences
969184
+ });
969185
+ const manifestEntry = manifest.specs[0];
969186
+ if (manifestEntry == null) {
969187
+ throw new Error(`Materialized source ${uniqueSpecIndex} did not produce a manifest entry`);
969188
+ }
969189
+ return { directory, manifestEntry };
969190
+ }));
969191
+ materializedSpecs.forEach((result, uniqueSpecIndex) => {
969192
+ if (result.status === "fulfilled") {
969193
+ return;
969194
+ }
969195
+ for (const generatorIndex of deduplicated.generatorIndexesByUniqueSpecIndex[uniqueSpecIndex] ?? []) {
969196
+ if (!errorsByGeneratorIndex.has(generatorIndex)) {
969197
+ errorsByGeneratorIndex.set(generatorIndex, result.reason);
969198
+ }
969199
+ }
969200
+ });
969201
+ const successfulGeneratorIndexes = new Set(generatorSelections.map((selection) => selection.generatorIndex).filter((generatorIndex) => !errorsByGeneratorIndex.has(generatorIndex)));
969202
+ if (successfulGeneratorIndexes.size === 0) {
969203
+ return { archive: void 0, errorsByGeneratorIndex };
969204
+ }
969205
+ try {
969206
+ const archive3 = await createArchiveFromMaterializedSpecs({
969207
+ materializedSpecs,
969208
+ deduplicated,
969209
+ successfulGeneratorIndexes,
969210
+ root: tmpDir.path
969211
+ });
969212
+ assertGeneratorSelectionOutcomes({ generatorSelections, archive: archive3, errorsByGeneratorIndex });
969213
+ return { archive: archive3, errorsByGeneratorIndex };
969214
+ } catch (error50) {
969215
+ for (const generatorIndex of successfulGeneratorIndexes) {
969216
+ errorsByGeneratorIndex.set(generatorIndex, error50);
969217
+ }
969218
+ return { archive: void 0, errorsByGeneratorIndex };
969219
+ }
969220
+ } finally {
969221
+ await tmpDir.cleanup();
969222
+ }
969223
+ }
969224
+ function deduplicateGeneratorSelections(generatorSelections) {
969225
+ const uniqueSpecs = [];
969226
+ const indexesBySpecKey = /* @__PURE__ */ new Map();
969227
+ const uniqueSpecIndexesByGeneratorIndex = /* @__PURE__ */ new Map();
969228
+ const generatorIndexesByUniqueSpecIndex = [];
969229
+ const orderedSelections = [...generatorSelections].sort((left3, right3) => left3.generatorIndex - right3.generatorIndex);
969230
+ for (const selection of orderedSelections) {
969231
+ if (uniqueSpecIndexesByGeneratorIndex.has(selection.generatorIndex)) {
969232
+ throw new Error(`Duplicate source selection for generator index ${selection.generatorIndex}`);
969233
+ }
969234
+ const indexes = selection.specs.map((spec) => {
969235
+ const key2 = createSpecDeduplicationKey(spec);
969236
+ const existingIndex = indexesBySpecKey.get(key2);
969237
+ if (existingIndex != null) {
969238
+ return existingIndex;
969239
+ }
969240
+ const index3 = uniqueSpecs.length;
969241
+ uniqueSpecs.push(spec);
969242
+ indexesBySpecKey.set(key2, index3);
969243
+ generatorIndexesByUniqueSpecIndex[index3] = /* @__PURE__ */ new Set();
969244
+ return index3;
969245
+ });
969246
+ for (const index3 of new Set(indexes)) {
969247
+ generatorIndexesByUniqueSpecIndex[index3]?.add(selection.generatorIndex);
969248
+ }
969249
+ uniqueSpecIndexesByGeneratorIndex.set(selection.generatorIndex, [...new Set(indexes)]);
969250
+ }
969251
+ return { uniqueSpecs, uniqueSpecIndexesByGeneratorIndex, generatorIndexesByUniqueSpecIndex };
969252
+ }
969253
+ async function createArchiveFromMaterializedSpecs({ materializedSpecs, deduplicated, successfulGeneratorIndexes, root: root6 }) {
969254
+ const contentDirectory = import_path99.default.join(root6, "content");
969255
+ await (0, import_promises143.mkdir)(contentDirectory);
969256
+ const manifest = { specs: [] };
969257
+ const archiveSpecIndexByUniqueSpecIndex = /* @__PURE__ */ new Map();
969258
+ const typeCounters = /* @__PURE__ */ new Map();
969259
+ for (const [uniqueSpecIndex, generatorIndexes] of deduplicated.generatorIndexesByUniqueSpecIndex.entries()) {
969260
+ if (![...generatorIndexes].some((generatorIndex) => successfulGeneratorIndexes.has(generatorIndex))) {
969261
+ continue;
969262
+ }
969263
+ const materialized = materializedSpecs[uniqueSpecIndex];
969264
+ if (materialized?.status !== "fulfilled") {
969265
+ throw new Error(`Successful generator references source ${uniqueSpecIndex}, which was not materialized`);
969266
+ }
969267
+ const type7 = materialized.value.manifestEntry.type;
969268
+ const typeIndex = typeCounters.get(type7) ?? 0;
969269
+ typeCounters.set(type7, typeIndex + 1);
969270
+ const manifestEntry = await copyMaterializedSpec({
969271
+ materialized: materialized.value,
969272
+ contentDirectory,
969273
+ typeIndex
969274
+ });
969275
+ archiveSpecIndexByUniqueSpecIndex.set(uniqueSpecIndex, manifest.specs.length);
969276
+ manifest.specs.push(manifestEntry);
969277
+ }
969278
+ const specIndexesByGeneratorIndex = /* @__PURE__ */ new Map();
969279
+ for (const [generatorIndex, uniqueSpecIndexes] of deduplicated.uniqueSpecIndexesByGeneratorIndex) {
969280
+ if (!successfulGeneratorIndexes.has(generatorIndex)) {
969281
+ continue;
969282
+ }
969283
+ specIndexesByGeneratorIndex.set(generatorIndex, uniqueSpecIndexes.map((uniqueSpecIndex) => {
969284
+ const archiveSpecIndex = archiveSpecIndexByUniqueSpecIndex.get(uniqueSpecIndex);
969285
+ if (archiveSpecIndex == null) {
969286
+ throw new Error(`Source ${uniqueSpecIndex} is unavailable for generator index ${generatorIndex}`);
969287
+ }
969288
+ return archiveSpecIndex;
969289
+ }));
969290
+ }
969291
+ const archive3 = await createArchiveFromDirectory({
969292
+ contentDirectory,
969293
+ tarGzPath: import_path99.default.join(root6, "specs.tar.gz"),
969294
+ manifest
969295
+ });
969296
+ return { ...archive3, specIndexesByGeneratorIndex };
969297
+ }
969298
+ async function copyMaterializedSpec({ materialized, contentDirectory, typeIndex }) {
969299
+ const sourcePrefix = `${materialized.manifestEntry.type}0`;
969300
+ const targetPrefix = `${materialized.manifestEntry.type}${typeIndex}`;
969301
+ assertSupportedMaterializedManifestEntry(materialized.manifestEntry);
969302
+ for (const entry of await (0, import_promises143.readdir)(materialized.directory, { withFileTypes: true })) {
969303
+ if (!hasSourcePrefix(entry.name) || !entry.isFile() && !entry.isDirectory()) {
969304
+ throw new Error(`Unsupported materialized source entry: ${entry.name}`);
969305
+ }
969306
+ await (0, import_promises143.cp)(import_path99.default.join(materialized.directory, entry.name), import_path99.default.join(contentDirectory, replacePrefix(entry.name)), {
969307
+ recursive: entry.isDirectory()
969308
+ });
969309
+ }
969310
+ return {
969311
+ ...materialized.manifestEntry,
969312
+ specPath: replaceContainerPathPrefix(materialized.manifestEntry.specPath),
969313
+ ...materialized.manifestEntry.overridePaths == null ? {} : {
969314
+ overridePaths: materialized.manifestEntry.overridePaths.map(replaceContainerPathPrefix)
969315
+ }
969316
+ };
969317
+ function replacePrefix(value2) {
969318
+ return `${targetPrefix}${value2.slice(sourcePrefix.length)}`;
969319
+ }
969320
+ function hasSourcePrefix(value2) {
969321
+ return value2 === sourcePrefix || value2.startsWith(`${sourcePrefix}.`) || value2.startsWith(`${sourcePrefix}-`);
969322
+ }
969323
+ function replaceContainerPathPrefix(value2) {
969324
+ const basename8 = import_path99.default.posix.basename(value2);
969325
+ if (!hasSourcePrefix(basename8)) {
969326
+ throw new Error(`Unexpected materialized source path: ${value2}`);
969327
+ }
969328
+ return import_path99.default.posix.join(import_path99.default.posix.dirname(value2), replacePrefix(basename8));
969329
+ }
969330
+ }
969331
+ var SUPPORTED_MATERIALIZED_MANIFEST_ENTRY_KEYS = /* @__PURE__ */ new Set([
969332
+ "type",
969333
+ "specPath",
969334
+ "overridePaths",
969335
+ "namespace",
969336
+ "apiImportSettings"
969337
+ ]);
969338
+ function assertSupportedMaterializedManifestEntry(entry) {
969339
+ for (const key2 of Object.keys(entry)) {
969340
+ if (!SUPPORTED_MATERIALIZED_MANIFEST_ENTRY_KEYS.has(key2)) {
969341
+ throw new Error(`Unsupported materialized manifest entry field: ${key2}`);
969342
+ }
969343
+ }
969344
+ }
969345
+ function assertGeneratorSelectionOutcomes({ generatorSelections, archive: archive3, errorsByGeneratorIndex }) {
969346
+ for (const { generatorIndex } of generatorSelections) {
969347
+ const hasArchive = archive3.specIndexesByGeneratorIndex.has(generatorIndex);
969348
+ const hasError = errorsByGeneratorIndex.has(generatorIndex);
969349
+ if (hasArchive === hasError) {
969350
+ throw new Error(`Generator index ${generatorIndex} must have exactly one source archive or materialization error outcome`);
969351
+ }
969352
+ }
969353
+ }
969354
+ var SDK_CONFIG_IMPORT_SETTING_KEYS = new Set(Object.keys(SDK_CONFIG_IMPORT_SETTING_MAPPERS));
969355
+ var DEFAULT_OPENAPI_SETTINGS = getOpenAPISettings();
969356
+ function validateSdkConfigImportSettings(specs) {
969357
+ for (const spec of specs) {
969358
+ if (spec.type !== "openapi") {
969359
+ continue;
969360
+ }
969361
+ const settings = getOpenAPISettings({ overrides: spec.settings });
969362
+ for (const key2 of Object.getOwnPropertyNames(settings)) {
969363
+ const value2 = Reflect.get(settings, key2);
969364
+ if (SDK_CONFIG_IMPORT_SETTING_KEYS.has(key2) || key2 === "audiences" && Array.isArray(value2) && value2.length === 0 || (0, import_node_util10.isDeepStrictEqual)(value2, Reflect.get(DEFAULT_OPENAPI_SETTINGS, key2))) {
969365
+ continue;
969366
+ }
969367
+ throw new Error(`SDK Config v1 cannot preserve effective OpenAPI import setting ${key2}=${JSON.stringify(value2)} for ${spec.absoluteFilepath}. Remove that setting or use a pre-cutover generator version until the shared SDK Config contract supports it.`);
969368
+ }
969369
+ }
969370
+ }
969371
+ async function createSpecsTarGzArchive({ specs, context: context3, audiences }) {
969372
+ const tmpDir = await import_tmp_promise17.default.dir({ unsafeCleanup: true });
969373
+ try {
969374
+ const contentDirectory = import_path99.default.join(tmpDir.path, "content");
969375
+ await (0, import_promises143.mkdir)(contentDirectory);
968559
969376
  const manifest = await collectRawSpecs({
968560
969377
  specs,
968561
- hostOutputDir: AbsoluteFilePath2.of(tmpDir.path),
969378
+ hostOutputDir: AbsoluteFilePath2.of(contentDirectory),
968562
969379
  containerBaseDir: "/fern/specs",
968563
969380
  context: context3,
968564
969381
  audiences
968565
969382
  });
968566
- await (0, import_promises143.writeFile)(join8(AbsoluteFilePath2.of(tmpDir.path), RelativeFilePath2.of(SPECS_MANIFEST_FILENAME)), JSON.stringify(manifest, void 0, 4));
968567
- const tarGzPath = join8(AbsoluteFilePath2.of(tmpDir.path), RelativeFilePath2.of("specs.tar.gz"));
968568
- await Kn({
968569
- gzip: true,
968570
- cwd: tmpDir.path,
968571
- file: tarGzPath,
968572
- portable: true,
968573
- filter: (entryPath) => entryPath !== "./specs.tar.gz"
968574
- }, ["."]);
968575
- return await (0, import_promises143.readFile)(tarGzPath);
969383
+ return await createArchiveFromDirectory({
969384
+ contentDirectory,
969385
+ tarGzPath: import_path99.default.join(tmpDir.path, "specs.tar.gz"),
969386
+ manifest
969387
+ });
968576
969388
  } finally {
968577
969389
  await tmpDir.cleanup();
968578
969390
  }
968579
969391
  }
969392
+ async function createArchiveFromDirectory({ contentDirectory, tarGzPath, manifest }) {
969393
+ await (0, import_promises143.writeFile)(join8(AbsoluteFilePath2.of(contentDirectory), RelativeFilePath2.of(SPECS_MANIFEST_FILENAME)), JSON.stringify(manifest, void 0, 4));
969394
+ const archiveEntries = await listDeterministicArchiveEntries(contentDirectory);
969395
+ await Kn({
969396
+ gzip: true,
969397
+ cwd: contentDirectory,
969398
+ file: tarGzPath,
969399
+ portable: true,
969400
+ mtime: /* @__PURE__ */ new Date(0),
969401
+ onWriteEntry: (entry) => {
969402
+ if (entry.stat != null) {
969403
+ entry.stat.mode = 420;
969404
+ }
969405
+ }
969406
+ }, archiveEntries);
969407
+ return { buffer: await (0, import_promises143.readFile)(tarGzPath), manifest };
969408
+ }
969409
+ async function listDeterministicArchiveEntries(root6, relativeDirectory = "") {
969410
+ const absoluteDirectory = relativeDirectory === "" ? root6 : import_path99.default.join(root6, ...relativeDirectory.split(import_path99.default.posix.sep));
969411
+ const directoryEntries = await (0, import_promises143.readdir)(absoluteDirectory, { withFileTypes: true });
969412
+ const archiveEntries = [];
969413
+ for (const entry of directoryEntries.sort((left3, right3) => compareStrings(left3.name, right3.name))) {
969414
+ const relativePath = import_path99.default.posix.join(relativeDirectory, entry.name);
969415
+ if (entry.isDirectory()) {
969416
+ archiveEntries.push(...await listDeterministicArchiveEntries(root6, relativePath));
969417
+ continue;
969418
+ }
969419
+ if (!entry.isFile()) {
969420
+ throw new Error(`Unsupported generated source archive entry: ${relativePath}`);
969421
+ }
969422
+ archiveEntries.push(relativePath);
969423
+ }
969424
+ return archiveEntries;
969425
+ }
969426
+ function compareStrings(left3, right3) {
969427
+ return left3 < right3 ? -1 : left3 > right3 ? 1 : 0;
969428
+ }
969429
+ function createSpecDeduplicationKey(spec) {
969430
+ switch (spec.type) {
969431
+ case "openapi":
969432
+ return stableStringify3({
969433
+ type: spec.type,
969434
+ path: spec.absoluteFilepath,
969435
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969436
+ overlay: spec.absoluteFilepathToOverlays,
969437
+ namespace: spec.namespace,
969438
+ settings: getOpenAPISettings({ overrides: spec.settings })
969439
+ });
969440
+ case "openrpc":
969441
+ return stableStringify3({
969442
+ type: spec.type,
969443
+ path: spec.absoluteFilepath,
969444
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969445
+ namespace: spec.namespace
969446
+ });
969447
+ case "protobuf":
969448
+ return stableStringify3({
969449
+ type: spec.type,
969450
+ root: spec.absoluteFilepathToProtobufRoot,
969451
+ target: spec.absoluteFilepathToProtobufTarget,
969452
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969453
+ dependencies: spec.dependencies,
969454
+ settings: getOpenAPISettings({ overrides: spec.settings })
969455
+ });
969456
+ case "graphql":
969457
+ return stableStringify3({
969458
+ type: spec.type,
969459
+ path: spec.absoluteFilepath,
969460
+ overrides: normalizeOverrides(spec.absoluteFilepathToOverrides),
969461
+ examples: spec.absoluteFilepathToExamples,
969462
+ namespace: spec.namespace
969463
+ });
969464
+ default:
969465
+ assertNever(spec);
969466
+ }
969467
+ }
969468
+ function stableStringify3(value2) {
969469
+ return JSON.stringify(sortJsonValue(value2));
969470
+ }
969471
+ function sortJsonValue(value2) {
969472
+ if (Array.isArray(value2)) {
969473
+ return value2.map(sortJsonValue);
969474
+ }
969475
+ if (value2 == null || typeof value2 !== "object") {
969476
+ return value2;
969477
+ }
969478
+ return Object.fromEntries(Object.entries(value2).sort(([left3], [right3]) => compareStrings(left3, right3)).map(([key2, child]) => [key2, sortJsonValue(child)]));
969479
+ }
968580
969480
 
968581
969481
  // ../generation/local-generation/local-workspace-runner/lib/runGenerator.js
968582
969482
  function extractLicenseFilePath(generatorInvocation, absolutePathToFernConfig) {
@@ -973180,11 +974080,11 @@ function getFirstUrlSegment({ path: path122 }) {
973180
974080
  }
973181
974081
 
973182
974082
  // ../docs-importers/mintlify/lib/MintlifyImporter.js
973183
- function isRecord3(value2) {
974083
+ function isRecord4(value2) {
973184
974084
  return typeof value2 === "object" && value2 != null && !Array.isArray(value2);
973185
974085
  }
973186
974086
  function hasNavigationArray(value2) {
973187
- return isRecord3(value2) && Array.isArray(value2.navigation);
974087
+ return isRecord4(value2) && Array.isArray(value2.navigation);
973188
974088
  }
973189
974089
  var MintlifyImporter = class extends DocsImporter {
973190
974090
  documentationTab = void 0;
@@ -979476,7 +980376,7 @@ var {
979476
980376
  } = signalExitWrap(processOk(process21) ? new SignalExit(process21) : new SignalExitFallback());
979477
980377
 
979478
980378
  // ../../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.17/node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
979479
- var import_node_util10 = require("util");
980379
+ var import_node_util11 = require("util");
979480
980380
 
979481
980381
  // ../../../node_modules/.pnpm/@inquirer+ansi@1.0.2/node_modules/@inquirer/ansi/dist/esm/index.js
979482
980382
  var ESC2 = "\x1B[";
@@ -979514,7 +980414,7 @@ var ScreenManager2 = class {
979514
980414
  }
979515
980415
  render(content5, bottomContent = "") {
979516
980416
  const promptLine = lastLine2(content5);
979517
- const rawPromptLine = (0, import_node_util10.stripVTControlCharacters)(promptLine);
980417
+ const rawPromptLine = (0, import_node_util11.stripVTControlCharacters)(promptLine);
979518
980418
  let prompt2 = rawPromptLine;
979519
980419
  if (this.rl.line.length > 0) {
979520
980420
  prompt2 = prompt2.slice(0, -this.rl.line.length);
@@ -980925,7 +981825,7 @@ function getAutomationContextFromEnv() {
980925
981825
  config_branch: process.env.FERN_CONFIG_BRANCH,
980926
981826
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
980927
981827
  trigger: process.env.GITHUB_EVENT_NAME,
980928
- cli_version: "5.23.3-2060-gef10ff1af19"
981828
+ cli_version: "5.23.3-2069-g46cdcdac844"
980929
981829
  };
980930
981830
  }
980931
981831
  function isAutomationMode() {
@@ -981757,7 +982657,7 @@ var CliContext = class _CliContext {
981757
982657
  if (false) {
981758
982658
  this.logger.error("CLI_VERSION is not defined");
981759
982659
  }
981760
- return "5.23.3-2060-gef10ff1af19";
982660
+ return "5.23.3-2069-g46cdcdac844";
981761
982661
  }
981762
982662
  getCliName() {
981763
982663
  if (false) {
@@ -983400,18 +984300,118 @@ function expandGroupFilter(groupNames, generatorsConfiguration) {
983400
984300
  // src/commands/generate/generateAPIWorkspace.ts
983401
984301
  init_lib20();
983402
984302
  init_lib8();
983403
- init_lib35();
983404
984303
  init_lib6();
983405
984304
  init_esm18();
983406
984305
 
983407
- // src/commands/generate/createSpecsTarGzCache.ts
983408
- function createSpecsTarGzCache(createArchive) {
983409
- let archivePromise;
983410
- return () => {
983411
- archivePromise ??= createArchive();
983412
- return archivePromise;
984306
+ // src/commands/generate/createFernSourceArchiveResolver.ts
984307
+ init_lib35();
984308
+ function createFernSourceArchiveResolver({
984309
+ workspace,
984310
+ context: context3,
984311
+ group
984312
+ }) {
984313
+ return async (requests3) => {
984314
+ const sourceArchives = /* @__PURE__ */ new Map();
984315
+ const errors4 = /* @__PURE__ */ new Map();
984316
+ if (!(workspace instanceof OSSWorkspace)) {
984317
+ for (const request7 of requests3) {
984318
+ if (requestRequiresSourceArchive(request7)) {
984319
+ errors4.set(
984320
+ request7.generatorIndex,
984321
+ new Error(
984322
+ `Generator index ${request7.generatorIndex} (${request7.generatorInvocation.name}) requires a source archive, but workspace type ${workspace.type} does not expose source specs`
984323
+ )
984324
+ );
984325
+ }
984326
+ }
984327
+ return { sourceArchives, errors: errors4 };
984328
+ }
984329
+ const settledSelections = await Promise.allSettled(
984330
+ requests3.map(async (request7) => {
984331
+ if (request7.sdkGenApiRoute == null) {
984332
+ return void 0;
984333
+ }
984334
+ const specs = await workspace.getAllSpecsForGenerator(request7.generatorInvocation.apiOverride?.specs);
984335
+ if (request7.sdkGenApiRoute.payloadKind === "sdk-config-v1") {
984336
+ validateSdkConfigImportSettings(specs);
984337
+ }
984338
+ return specs;
984339
+ })
984340
+ );
984341
+ const generatorSelections = settledSelections.flatMap((result, index3) => {
984342
+ const request7 = requests3[index3];
984343
+ if (request7 == null) {
984344
+ throw new Error(`Missing source archive request at settled index ${index3}`);
984345
+ }
984346
+ if (result.status === "rejected") {
984347
+ errors4.set(request7.generatorIndex, result.reason);
984348
+ return [];
984349
+ }
984350
+ return result.value == null ? [] : [{ generatorIndex: request7.generatorIndex, specs: result.value }];
984351
+ });
984352
+ if (generatorSelections.length > 0) {
984353
+ const settledArchive = await createGroupedSpecsTarGzArchiveSettled({
984354
+ generatorSelections,
984355
+ context: context3,
984356
+ audiences: group.audiences
984357
+ });
984358
+ for (const [generatorIndex, error50] of settledArchive.errorsByGeneratorIndex) {
984359
+ errors4.set(generatorIndex, error50);
984360
+ }
984361
+ if (settledArchive.archive != null) {
984362
+ const { specIndexesByGeneratorIndex, ...sourceArchive } = settledArchive.archive;
984363
+ for (const [generatorIndex, specIndexes] of specIndexesByGeneratorIndex) {
984364
+ sourceArchives.set(generatorIndex, { ...sourceArchive, specIndexes });
984365
+ }
984366
+ }
984367
+ }
984368
+ const rootRequests = requests3.filter(
984369
+ (request7) => request7.sdkGenApiRoute == null && generatorWantsSpecs(request7.generatorInvocation.name) && !errors4.has(request7.generatorIndex)
984370
+ );
984371
+ if (rootRequests.length > 0) {
984372
+ try {
984373
+ const archive3 = await createSpecsTarGzArchive({
984374
+ specs: workspace.allSpecs,
984375
+ context: context3,
984376
+ audiences: group.audiences
984377
+ });
984378
+ const specIndexes = archive3.manifest.specs.map((_5, index3) => index3);
984379
+ for (const request7 of rootRequests) {
984380
+ sourceArchives.set(request7.generatorIndex, { ...archive3, specIndexes });
984381
+ }
984382
+ } catch (error50) {
984383
+ for (const request7 of rootRequests) {
984384
+ errors4.set(request7.generatorIndex, error50);
984385
+ }
984386
+ }
984387
+ }
984388
+ for (const request7 of requests3) {
984389
+ if (!requestRequiresSourceArchive(request7)) {
984390
+ continue;
984391
+ }
984392
+ const hasArchive = sourceArchives.has(request7.generatorIndex);
984393
+ const hasError = errors4.has(request7.generatorIndex);
984394
+ if (hasArchive && hasError) {
984395
+ throw new Error(
984396
+ `Generator index ${request7.generatorIndex} produced both a source archive and a source preparation error`,
984397
+ { cause: errors4.get(request7.generatorIndex) }
984398
+ );
984399
+ }
984400
+ if (!hasArchive && !hasError) {
984401
+ errors4.set(
984402
+ request7.generatorIndex,
984403
+ new Error(
984404
+ `Generator index ${request7.generatorIndex} did not produce a source archive or source preparation error`
984405
+ )
984406
+ );
984407
+ }
984408
+ }
984409
+ return { sourceArchives, errors: errors4 };
983413
984410
  };
983414
984411
  }
984412
+ function requestRequiresSourceArchive(request7) {
984413
+ return request7.sdkGenApiRoute != null || generatorWantsSpecs(request7.generatorInvocation.name);
984414
+ }
983415
984415
 
983416
984416
  // src/commands/generate/packLocalOutput.ts
983417
984417
  init_lib20();
@@ -984068,21 +985068,11 @@ async function generateWorkspace({
984068
985068
  disableTelemetry: isTelemetryDisabled()
984069
985069
  });
984070
985070
  } else if (token != null) {
984071
- const ossWorkspace = workspace instanceof OSSWorkspace ? workspace : void 0;
984072
- const getCachedSpecsTarGz = ossWorkspace == null ? void 0 : createSpecsTarGzCache(
984073
- () => createSpecsTarGzBuffer({
984074
- specs: ossWorkspace.allSpecs,
984075
- context: groupContext,
984076
- audiences: group.audiences
984077
- })
984078
- );
984079
- const getSpecsTarGz = async (generatorName2) => {
984080
- const sdkGenApiNeedsSpecs = isFernSdkGenApiEnabled() && getFernSdkGenApiLanguage(generatorName2) != null;
984081
- if (getCachedSpecsTarGz == null || !generatorWantsSpecs(generatorName2) && !sdkGenApiNeedsSpecs) {
984082
- return void 0;
984083
- }
984084
- return getCachedSpecsTarGz();
984085
- };
985071
+ const getSpecsTarGz = createFernSourceArchiveResolver({
985072
+ workspace,
985073
+ context: groupContext,
985074
+ group
985075
+ });
984086
985076
  await runRemoteGenerationForAPIWorkspace({
984087
985077
  projectConfig,
984088
985078
  organization,
@@ -994973,7 +995963,7 @@ function upsertServerInJsonConfig({
994973
995963
  includeTransportType
994974
995964
  }) {
994975
995965
  const config5 = parseJsonConfig(existingContents);
994976
- const mcpServers = isRecord4(config5.mcpServers) ? config5.mcpServers : {};
995966
+ const mcpServers = isRecord5(config5.mcpServers) ? config5.mcpServers : {};
994977
995967
  config5.mcpServers = {
994978
995968
  ...mcpServers,
994979
995969
  [MCP_SERVER_NAME]: {
@@ -994990,12 +995980,12 @@ function parseJsonConfig(existingContents) {
994990
995980
  return {};
994991
995981
  }
994992
995982
  const parsed = JSON.parse(existingContents);
994993
- if (!isRecord4(parsed)) {
995983
+ if (!isRecord5(parsed)) {
994994
995984
  throw new Error("Expected the config to contain a JSON object");
994995
995985
  }
994996
995986
  return parsed;
994997
995987
  }
994998
- function isRecord4(value2) {
995988
+ function isRecord5(value2) {
994999
995989
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
995000
995990
  }
995001
995991
  var CODEX_SERVER_TABLE_PATH = `mcp_servers.${MCP_SERVER_NAME}`;
@@ -996550,7 +997540,12 @@ async function sdkPreview({
996550
997540
  absolutePathToPreview: absolutePathToOutput,
996551
997541
  isPreview: true,
996552
997542
  fiddlePreview: false,
996553
- pushPreviewBranch: false
997543
+ pushPreviewBranch: false,
997544
+ getSpecsTarGzBuffer: createFernSourceArchiveResolver({
997545
+ workspace,
997546
+ context: context3,
997547
+ group: publishGroup
997548
+ })
996554
997549
  });
996555
997550
  });
996556
997551
  if (shouldRunTwoJobs) {
@@ -996565,7 +997560,12 @@ async function sdkPreview({
996565
997560
  absolutePathToPreview: void 0,
996566
997561
  isPreview: true,
996567
997562
  fiddlePreview: true,
996568
- pushPreviewBranch: true
997563
+ pushPreviewBranch: true,
997564
+ getSpecsTarGzBuffer: createFernSourceArchiveResolver({
997565
+ workspace,
997566
+ context: context3,
997567
+ group: diffGroup
997568
+ })
996569
997569
  });
996570
997570
  });
996571
997571
  }