@fern-api/fern-api-dev 5.94.0 → 5.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli.cjs +90 -26
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -59707,7 +59707,8 @@ var init_HttpReferencedRequestBodySchema2 = __esm({
59707
59707
  init_core();
59708
59708
  init_WithDocsSchema2();
59709
59709
  HttpReferencedRequestBodySchema = schemas_exports.object({
59710
- type: schemas_exports.string()
59710
+ type: schemas_exports.string(),
59711
+ optional: schemas_exports.boolean().optional()
59711
59712
  }).extend(WithDocsSchema);
59712
59713
  }
59713
59714
  });
@@ -75053,7 +75054,8 @@ var init_BodyRequest2 = __esm({
75053
75054
  init_ReferencedRequestBodyType2();
75054
75055
  BodyRequest = schemas_exports3.objectWithoutOptionalProperties({
75055
75056
  pathParameters: schemas_exports3.list(NamedParameter).optional(),
75056
- body: ReferencedRequestBodyType2.optional()
75057
+ body: ReferencedRequestBodyType2.optional(),
75058
+ bodyRequired: schemas_exports3.boolean().optional()
75057
75059
  });
75058
75060
  }
75059
75061
  });
@@ -79073,7 +79075,8 @@ var init_HttpRequestBodyReference2 = __esm({
79073
79075
  init_WithDocs3();
79074
79076
  init_WithV2Examples2();
79075
79077
  HttpRequestBodyReference = schemas_exports3.objectWithoutOptionalProperties({
79076
- requestBodyType: schemas_exports3.lazy(() => TypeReference3)
79078
+ requestBodyType: schemas_exports3.lazy(() => TypeReference3),
79079
+ required: schemas_exports3.boolean().optional()
79077
79080
  }).extend(WithDocs).extend(WithContentType).extend(WithV2Examples);
79078
79081
  }
79079
79082
  });
@@ -147069,9 +147072,10 @@ function buildEndpoint({ endpoint: endpoint3, declarationFile, context: context3
147069
147072
  });
147070
147073
  }
147071
147074
  });
147072
- if (endpoint3.examples.length > 0) {
147075
+ const examples = filterExamplesThatOmitTheBody({ endpoint: endpoint3, context: context3 });
147076
+ if (examples.length > 0) {
147073
147077
  convertedEndpoint.examples = convertEndpointExamples({
147074
- endpointExamples: endpoint3.examples,
147078
+ endpointExamples: examples,
147075
147079
  context: context3,
147076
147080
  pathParameterRenames
147077
147081
  });
@@ -147115,6 +147119,21 @@ function convertEndpointAuth({ endpoint: endpoint3, context: context3 }) {
147115
147119
  }
147116
147120
  return endpoint3.security;
147117
147121
  }
147122
+ function filterExamplesThatOmitTheBody({ endpoint: endpoint3, context: context3 }) {
147123
+ if (endpoint3.request == null || !isOptionalJsonBody(endpoint3.request)) {
147124
+ return endpoint3.examples;
147125
+ }
147126
+ return endpoint3.examples.filter((example) => {
147127
+ const rawExample = example.type === "full" ? void 0 : example.value;
147128
+ const name2 = example.type === "full" ? example.name : rawExample?.name;
147129
+ const hasRequest = example.type === "full" ? example.request != null : rawExample?.request != null;
147130
+ if (hasRequest) {
147131
+ return true;
147132
+ }
147133
+ context3.logger.debug(`Skipping the example${name2 != null ? ` "${name2}"` : ""} for ${endpoint3.method} ${endpoint3.path}: it has no request body, and the SDKs describe the body as required.`);
147134
+ return false;
147135
+ });
147136
+ }
147118
147137
  function convertEndpointExamples({ endpointExamples, context: context3, pathParameterRenames }) {
147119
147138
  return endpointExamples.map((endpointExample) => {
147120
147139
  try {
@@ -147178,15 +147197,16 @@ function getRequest({ endpoint: endpoint3, declarationFile, context: context3, r
147178
147197
  requestValue.docs = request7.description;
147179
147198
  }
147180
147199
  const canCollapse = typeof requestValue.body === "string" && requestValue["path-parameters"] == null && requestValue["query-parameters"] == null && requestValue.headers == null && requestValue.name == null && requestValue.docs == null && (requestValue["content-type"] == null || requestValue["content-type"] === "application/json");
147181
- if (context3.options.respectOptionalRequestBody && isOptionalJsonBody(request7)) {
147182
- requestValue.body = typeof requestTypeReference === "string" ? wrapTypeReferenceInOptional(requestTypeReference) : {
147183
- ...requestTypeReference,
147184
- type: wrapTypeReferenceInOptional(requestTypeReference.type)
147185
- };
147200
+ const mayOmitBody = isOptionalJsonBody(request7);
147201
+ if (mayOmitBody) {
147202
+ if (canCollapse) {
147203
+ delete requestValue["content-type"];
147204
+ }
147205
+ requestValue.body = typeof requestTypeReference === "string" ? { type: requestTypeReference, optional: true } : { ...requestTypeReference, optional: true };
147186
147206
  }
147187
147207
  return {
147188
147208
  schemaIdsToExclude: [],
147189
- value: canCollapse ? requestValue.body : requestValue
147209
+ value: canCollapse && !mayOmitBody ? requestValue.body : requestValue
147190
147210
  };
147191
147211
  }
147192
147212
  const propertyToDeclarationFile = /* @__PURE__ */ new Map();
@@ -147442,9 +147462,6 @@ function getRequest({ endpoint: endpoint3, declarationFile, context: context3, r
147442
147462
  function isOptionalJsonBody(request7) {
147443
147463
  return request7.type === "json" && request7.required !== true;
147444
147464
  }
147445
- function wrapTypeReferenceInOptional(typeReference2) {
147446
- return typeReference2.startsWith("optional<") ? typeReference2 : `optional<${typeReference2}>`;
147447
- }
147448
147465
  function endpointRequestSupportsInlinedPathParameters({ context: context3, request: request7 }) {
147449
147466
  if (!context3.options.inlinePathParameters) {
147450
147467
  return false;
@@ -149301,6 +149318,9 @@ var init_OpenApiIrConverterContext = __esm({
149301
149318
  // ../api-importers/openapi/openapi-ir-to-fern/lib/convert.js
149302
149319
  function convert(opts) {
149303
149320
  const context3 = new OpenApiIrConverterContext(opts);
149321
+ if (context3.options.respectOptionalRequestBody) {
149322
+ context3.logger.warn("The `respect-optional-request-body` setting is deprecated and no longer has any effect. A request body that OpenAPI does not mark as required is now always described as omittable in the IR, and each SDK generator opts in to that behaviour through its own configuration.");
149323
+ }
149304
149324
  return buildFernDefinition(context3);
149305
149325
  }
149306
149326
  var init_convert = __esm({
@@ -272644,9 +272664,11 @@ function getMultipartPartEncodingFromContentType2(contentType) {
272644
272664
  return encoding;
272645
272665
  }
272646
272666
  function convertReferenceHttpRequestBody({ requestBody, file: file4, contentType }) {
272667
+ const isOmittable = typeof requestBody !== "string" && requestBody.optional === true;
272647
272668
  return {
272648
272669
  docs: typeof requestBody !== "string" ? requestBody.docs : void 0,
272649
272670
  requestBodyType: file4.parseTypeReference(requestBody),
272671
+ required: isOmittable ? false : void 0,
272650
272672
  contentType,
272651
272673
  v2Examples: void 0
272652
272674
  };
@@ -275488,7 +275510,8 @@ function convertExampleRequestBody({ endpoint: endpoint3, example, typeResolver,
275488
275510
  }
275489
275511
  if (!isInlineRequestBody(requestType)) {
275490
275512
  const rawTypeBeingExemplified = typeof requestType !== "string" ? requestType.type : requestType;
275491
- if (example.request === void 0 && isOptionalType({ rawType: rawTypeBeingExemplified, typeResolver, file: file4 })) {
275513
+ const isOmittable = typeof requestType !== "string" && requestType.optional === true || isOptionalType({ rawType: rawTypeBeingExemplified, typeResolver, file: file4 });
275514
+ if (example.request === void 0 && isOmittable) {
275492
275515
  return void 0;
275493
275516
  }
275494
275517
  return ExampleRequestBody.reference(convertTypeReferenceExample({
@@ -276777,7 +276800,7 @@ var init_DynamicSnippetsConverter = __esm({
276777
276800
  pathParameters: [...endpoint3.servicePathParameters, ...endpoint3.pathParameters]
276778
276801
  });
276779
276802
  if (endpoint3.sdkRequest == null && endpoint3.requestBody == null) {
276780
- return dynamic_exports.Request.body({ pathParameters, body: void 0 });
276803
+ return dynamic_exports.Request.body({ pathParameters, body: void 0, bodyRequired: void 0 });
276781
276804
  }
276782
276805
  if (endpoint3.sdkRequest == null) {
276783
276806
  throw new CliError({
@@ -276789,7 +276812,10 @@ var init_DynamicSnippetsConverter = __esm({
276789
276812
  case "justRequestBody":
276790
276813
  return dynamic_exports.Request.body({
276791
276814
  pathParameters,
276792
- body: this.convertReferencedRequestBodyType({ body: endpoint3.sdkRequest.shape.value })
276815
+ body: this.convertReferencedRequestBodyType({ body: endpoint3.sdkRequest.shape.value }),
276816
+ // carried over from the SDK IR so a snippet generator, which never sees that IR,
276817
+ // can tell an omittable body from a required one. Absent means required.
276818
+ bodyRequired: endpoint3.requestBody?.type === "reference" ? endpoint3.requestBody.required : void 0
276793
276819
  });
276794
276820
  case "wrapper":
276795
276821
  return this.convertInlinedRequest({
@@ -328164,6 +328190,17 @@ var init_fern_schema = __esm({
328164
328190
  },
328165
328191
  type: {
328166
328192
  type: "string"
328193
+ },
328194
+ optional: {
328195
+ oneOf: [
328196
+ {
328197
+ type: "boolean"
328198
+ },
328199
+ {
328200
+ type: "null"
328201
+ }
328202
+ ],
328203
+ description: "Whether the endpoint may be called without a request body. When true, an example may\nomit `request`, and the generated SDK lets the caller omit the body. Populated from\n`requestBody.required` when importing from OpenAPI.\n\nThis is distinct from writing `body: optional<Foo>`, which says the body's *value* may\nbe null. Here the body itself may be absent, so the request carries neither content nor\na `Content-Type` header. It maps to `required: false` on the IR's request body reference."
328167
328204
  }
328168
328205
  },
328169
328206
  required: [
@@ -328364,7 +328401,7 @@ var init_fern_schema = __esm({
328364
328401
  type: "null"
328365
328402
  }
328366
328403
  ],
328367
- description: "Whether the endpoint may be called without a request body. When true, an\nexample may omit `request`. Populated from `requestBody.required` when\nimporting from OpenAPI.\n\nThis is read by example validation only: it is not carried into the IR, so it\ndoes not make the request parameter optional in a generated SDK."
328404
+ description: "Whether the endpoint may be called without a request body. When true, an\nexample may omit `request`. Populated from `requestBody.required` when\nimporting from OpenAPI.\n\nThis is read by example validation only: it is not carried into the IR, so it\ndoes not make the request parameter optional in a generated SDK.\n\nNote the asymmetry with the identically named field on\n`HttpReferencedRequestBodySchema`, which does reach the IR as `required: false`. An\ninline body has no single type to mark omittable, so its `optional` stays\nvalidation-only."
328368
328405
  }
328369
328406
  },
328370
328407
  additionalProperties: false
@@ -332621,6 +332658,17 @@ var init_package_yml_schema = __esm({
332621
332658
  },
332622
332659
  type: {
332623
332660
  type: "string"
332661
+ },
332662
+ optional: {
332663
+ oneOf: [
332664
+ {
332665
+ type: "boolean"
332666
+ },
332667
+ {
332668
+ type: "null"
332669
+ }
332670
+ ],
332671
+ description: "Whether the endpoint may be called without a request body. When true, an example may\nomit `request`, and the generated SDK lets the caller omit the body. Populated from\n`requestBody.required` when importing from OpenAPI.\n\nThis is distinct from writing `body: optional<Foo>`, which says the body's *value* may\nbe null. Here the body itself may be absent, so the request carries neither content nor\na `Content-Type` header. It maps to `required: false` on the IR's request body reference."
332624
332672
  }
332625
332673
  },
332626
332674
  required: [
@@ -332821,7 +332869,7 @@ var init_package_yml_schema = __esm({
332821
332869
  type: "null"
332822
332870
  }
332823
332871
  ],
332824
- description: "Whether the endpoint may be called without a request body. When true, an\nexample may omit `request`. Populated from `requestBody.required` when\nimporting from OpenAPI.\n\nThis is read by example validation only: it is not carried into the IR, so it\ndoes not make the request parameter optional in a generated SDK."
332872
+ description: "Whether the endpoint may be called without a request body. When true, an\nexample may omit `request`. Populated from `requestBody.required` when\nimporting from OpenAPI.\n\nThis is read by example validation only: it is not carried into the IR, so it\ndoes not make the request parameter optional in a generated SDK.\n\nNote the asymmetry with the identically named field on\n`HttpReferencedRequestBodySchema`, which does reach the IR as `required: false`. An\ninline body has no single type to mark omittable, so its `optional` stays\nvalidation-only."
332825
332873
  }
332826
332874
  },
332827
332875
  additionalProperties: false
@@ -355375,6 +355423,13 @@ var init_RequestBodyConverter = __esm({
355375
355423
  this.streamingExtension = streamingExtension;
355376
355424
  this.queryParameters = queryParameters ?? [];
355377
355425
  }
355426
+ /**
355427
+ * Absent means required, so only an explicit `requestBody.required: false` is carried through.
355428
+ * Generators ignore it unless they opt in, which keeps the field additive for existing users.
355429
+ */
355430
+ get bodyRequired() {
355431
+ return this.required === false ? false : void 0;
355432
+ }
355378
355433
  convert() {
355379
355434
  if (this.streamingExtension?.type == "streamCondition") {
355380
355435
  return this.convertStreamConditionRequestBody();
@@ -355439,6 +355494,7 @@ var init_RequestBodyConverter = __esm({
355439
355494
  contentType,
355440
355495
  docs: this.description,
355441
355496
  requestBodyType: convertedSchema.type,
355497
+ required: this.bodyRequired,
355442
355498
  v2Examples: this.convertMediaTypeObjectExamples({
355443
355499
  mediaTypeObject,
355444
355500
  exampleGenerationStrategy: "request"
@@ -355475,6 +355531,7 @@ var init_RequestBodyConverter = __esm({
355475
355531
  contentType,
355476
355532
  docs: this.description,
355477
355533
  requestBodyType: convertedSchema.type,
355534
+ required: this.bodyRequired,
355478
355535
  v2Examples: this.convertMediaTypeObjectExamples({
355479
355536
  mediaTypeObject,
355480
355537
  exampleGenerationStrategy: "request"
@@ -355528,6 +355585,7 @@ var init_RequestBodyConverter = __esm({
355528
355585
  contentType,
355529
355586
  docs: this.description,
355530
355587
  requestBodyType: TypeReference2.unknown(),
355588
+ required: this.bodyRequired,
355531
355589
  v2Examples
355532
355590
  }),
355533
355591
  streamRequestBody: void 0,
@@ -355732,6 +355790,7 @@ var init_RequestBodyConverter = __esm({
355732
355790
  contentType,
355733
355791
  docs: this.description,
355734
355792
  requestBodyType: convertedSchema.type,
355793
+ required: this.bodyRequired,
355735
355794
  v2Examples: this.convertMediaTypeObjectExamples({
355736
355795
  mediaTypeObject: modifiedMediaTypeObject,
355737
355796
  exampleGenerationStrategy: "request"
@@ -690356,6 +690415,9 @@ function validateRequest({ example, endpoint: endpoint3, typeResolver, exampleRe
690356
690415
  return { severity: val.severity ?? "fatal", message: val.message };
690357
690416
  }));
690358
690417
  } else {
690418
+ if (example === void 0 && typeof body !== "string" && body.optional === true) {
690419
+ return violations;
690420
+ }
690359
690421
  const bodyViolations = examples_exports6.validateTypeReferenceExample({
690360
690422
  rawTypeReference: typeof body === "string" ? body : body.type,
690361
690423
  example,
@@ -694260,7 +694322,7 @@ var OpenApiSettingsSchema2 = BaseApiSettingsSchema2.extend({
694260
694322
  useReadVariantForResponses: external_exports.boolean().optional(),
694261
694323
  /** Enables respecting forward compatible enums in OpenAPI specifications. Defaults to false. */
694262
694324
  respectForwardCompatibleEnums: external_exports.boolean().optional(),
694263
- /** Enables making a JSON request body that OpenAPI does not mark as required optional in the generated SDK, so callers may omit the body. Defaults to false. */
694325
+ /** Deprecated and no longer has any effect. A request body that OpenAPI does not mark as required is always described as omittable in the IR, and each SDK generator opts into that behaviour through its own configuration. */
694264
694326
  respectOptionalRequestBody: external_exports.boolean().optional(),
694265
694327
  /** Enables using the `bytes` type for binary responses in OpenAPI specifications. Defaults to a file stream. */
694266
694328
  useBytesForBinaryResponse: external_exports.boolean().optional(),
@@ -702921,7 +702983,7 @@ var AccessTokenPosthogManager = class {
702921
702983
  properties: {
702922
702984
  ...event,
702923
702985
  ...event.properties,
702924
- version: "5.94.0",
702986
+ version: "5.95.0",
702925
702987
  usingAccessToken: true,
702926
702988
  ...getRunIdProperties()
702927
702989
  }
@@ -702987,7 +703049,7 @@ var UserPosthogManager = class {
702987
703049
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
702988
703050
  event: "CLI",
702989
703051
  properties: {
702990
- version: "5.94.0",
703052
+ version: "5.95.0",
702991
703053
  ...event,
702992
703054
  ...event.properties,
702993
703055
  usingAccessToken: false,
@@ -884153,7 +884215,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
884153
884215
  var LOGS_FOLDER_NAME = "logs";
884154
884216
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
884155
884217
  function getCliSource() {
884156
- const version7 = "5.94.0";
884218
+ const version7 = "5.95.0";
884157
884219
  return `cli@${version7}`;
884158
884220
  }
884159
884221
  var DebugLogger = class {
@@ -909469,7 +909531,7 @@ var LegacyDocsPublisher = class {
909469
909531
  previewId,
909470
909532
  disableTemplates: void 0,
909471
909533
  skipUpload,
909472
- cliVersion: "5.94.0",
909534
+ cliVersion: "5.95.0",
909473
909535
  loginCommand: "fern auth login"
909474
909536
  });
909475
909537
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -973883,6 +973945,8 @@ var MethodConverter2 = class extends AbstractConverter {
973883
973945
  contentType: "application/proto",
973884
973946
  docs: void 0,
973885
973947
  requestBodyType: requestBodyType.reference,
973948
+ // a gRPC method always carries a request message, and absent means required
973949
+ required: void 0,
973886
973950
  v2Examples: void 0
973887
973951
  }),
973888
973952
  requestExample: void 0
@@ -976387,7 +976451,7 @@ function getAutomationContextFromEnv() {
976387
976451
  config_branch: process.env.FERN_CONFIG_BRANCH,
976388
976452
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
976389
976453
  trigger: process.env.GITHUB_EVENT_NAME,
976390
- cli_version: "5.94.0"
976454
+ cli_version: "5.95.0"
976391
976455
  };
976392
976456
  }
976393
976457
  function isAutomationMode() {
@@ -977219,7 +977283,7 @@ var CliContext = class _CliContext {
977219
977283
  if (false) {
977220
977284
  this.logger.error("CLI_VERSION is not defined");
977221
977285
  }
977222
- return "5.94.0";
977286
+ return "5.95.0";
977223
977287
  }
977224
977288
  getCliName() {
977225
977289
  if (false) {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.94.0",
2
+ "version": "5.95.0",
3
3
  "repository": {
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/fern-api/fern.git",