@fern-api/fern-api-dev 5.34.0 → 5.35.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 +164 -21
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -236720,10 +236720,28 @@ var init_GraphQLConverter = __esm({
236720
236720
  namespace;
236721
236721
  processingTypes = /* @__PURE__ */ new Set();
236722
236722
  types = {};
236723
- constructor({ context: context3, filePath, namespace }) {
236723
+ examplesByOperation = /* @__PURE__ */ new Map();
236724
+ constructor({ context: context3, filePath, namespace, examples }) {
236724
236725
  this.context = context3;
236725
236726
  this.filePath = filePath;
236726
236727
  this.namespace = namespace;
236728
+ if (examples != null) {
236729
+ for (const entry of examples) {
236730
+ const mapped = entry.examples.map((ex) => ({
236731
+ name: ex.name ?? void 0,
236732
+ description: ex.description ?? void 0,
236733
+ query: ex.query,
236734
+ variables: ex.variables ?? void 0,
236735
+ response: ex.response ?? void 0
236736
+ }));
236737
+ if (entry.operationType != null) {
236738
+ const key2 = `${entry.operationType.toLowerCase()}:${entry.operation}`;
236739
+ this.examplesByOperation.set(key2, mapped);
236740
+ } else {
236741
+ this.examplesByOperation.set(entry.operation, mapped);
236742
+ }
236743
+ }
236744
+ }
236727
236745
  }
236728
236746
  isBuiltInScalar(typeName) {
236729
236747
  return ["String", "Int", "Float", "Boolean", "ID"].includes(typeName);
@@ -236887,6 +236905,7 @@ var init_GraphQLConverter = __esm({
236887
236905
  }
236888
236906
  convertField(field5, name2, operationType) {
236889
236907
  const args = field5.args.map((arg) => this.convertArgument(arg));
236908
+ const examples = this.examplesByOperation.get(`${operationType.toLowerCase()}:${name2}`) ?? this.examplesByOperation.get(name2);
236890
236909
  return {
236891
236910
  id: this.getNamespacedOperationId(`${operationType.toLowerCase()}_${name2}`),
236892
236911
  operationType,
@@ -236896,7 +236915,7 @@ var init_GraphQLConverter = __esm({
236896
236915
  availability: void 0,
236897
236916
  arguments: args.length > 0 ? args : void 0,
236898
236917
  returnType: this.convertOutputType(field5.type),
236899
- examples: void 0,
236918
+ examples: examples != null && examples.length > 0 ? examples : void 0,
236900
236919
  snippets: void 0
236901
236920
  };
236902
236921
  }
@@ -561844,6 +561863,7 @@ var GraphQlSpecSchema = schemas_exports8.object({
561844
561863
  graphql: schemas_exports8.string(),
561845
561864
  origin: schemas_exports8.string().optional(),
561846
561865
  overrides: schemas_exports8.string().optional(),
561866
+ examples: schemas_exports8.string().optional(),
561847
561867
  name: schemas_exports8.string().optional()
561848
561868
  });
561849
561869
 
@@ -596233,7 +596253,8 @@ async function parseApiConfigurationV2Schema({ apiConfiguration, rawConfiguratio
596233
596253
  definitionLocation = {
596234
596254
  schema: {
596235
596255
  type: "graphql",
596236
- path: spec.graphql
596256
+ path: spec.graphql,
596257
+ examples: spec.examples
596237
596258
  },
596238
596259
  origin: spec.origin,
596239
596260
  overrides: spec.overrides,
@@ -659909,9 +659930,12 @@ var OSSWorkspace = class _OSSWorkspace extends BaseOpenAPIWorkspace {
659909
659930
  const graphqlSpecs = this.allSpecs.filter((spec) => spec.type === "graphql");
659910
659931
  for (const spec of graphqlSpecs) {
659911
659932
  try {
659933
+ const examples = await loadGraphQlExamples(spec.absoluteFilepathToExamples, context3);
659912
659934
  const converter = new GraphQLConverter2({
659913
659935
  context: context3,
659914
- filePath: spec.absoluteFilepath
659936
+ filePath: spec.absoluteFilepath,
659937
+ namespace: spec.namespace,
659938
+ examples
659915
659939
  });
659916
659940
  const result = await converter.convert();
659917
659941
  Object.assign(this.graphqlOperations, result.graphqlOperations);
@@ -660245,7 +660269,8 @@ var OSSWorkspace = class _OSSWorkspace extends BaseOpenAPIWorkspace {
660245
660269
  ...this.allSpecs.flatMap((spec) => {
660246
660270
  const mainPath = spec.type === "protobuf" ? spec.absoluteFilepathToProtobufTarget : spec.absoluteFilepath;
660247
660271
  const overridePaths = Array.isArray(spec.absoluteFilepathToOverrides) ? spec.absoluteFilepathToOverrides : spec.absoluteFilepathToOverrides != null ? [spec.absoluteFilepathToOverrides] : [];
660248
- return [mainPath, ...overridePaths];
660272
+ const examplesPath = spec.type === "graphql" ? spec.absoluteFilepathToExamples : void 0;
660273
+ return [mainPath, ...overridePaths, ...examplesPath != null ? [examplesPath] : []];
660249
660274
  }).filter(isNonNullish)
660250
660275
  ];
660251
660276
  }
@@ -660270,6 +660295,52 @@ var OSSWorkspace = class _OSSWorkspace extends BaseOpenAPIWorkspace {
660270
660295
  }, result);
660271
660296
  }
660272
660297
  };
660298
+ async function loadGraphQlExamples(absoluteFilepathToExamples, context3) {
660299
+ if (absoluteFilepathToExamples == null) {
660300
+ return void 0;
660301
+ }
660302
+ try {
660303
+ const contents = (await (0, import_promises39.readFile)(absoluteFilepathToExamples)).toString();
660304
+ const parsed = jsYaml.load(contents);
660305
+ if (!Array.isArray(parsed)) {
660306
+ return void 0;
660307
+ }
660308
+ for (const entry of parsed) {
660309
+ if (typeof entry !== "object" || entry == null) {
660310
+ context3.logger.warn(`Skipping invalid entry in GraphQL examples file ${absoluteFilepathToExamples}: expected object`);
660311
+ continue;
660312
+ }
660313
+ if (typeof entry.operation !== "string") {
660314
+ context3.logger.warn(`Skipping entry in GraphQL examples file ${absoluteFilepathToExamples}: missing or invalid 'operation' field`);
660315
+ continue;
660316
+ }
660317
+ if (!Array.isArray(entry.examples)) {
660318
+ context3.logger.warn(`Skipping entry for operation '${entry.operation}' in ${absoluteFilepathToExamples}: 'examples' must be an array`);
660319
+ continue;
660320
+ }
660321
+ }
660322
+ const validEntries = parsed.filter((entry) => typeof entry === "object" && entry != null && typeof entry.operation === "string" && Array.isArray(entry.examples)).map((entry) => {
660323
+ const validExamples = entry.examples.filter((ex) => {
660324
+ if (typeof ex !== "object" || ex == null || typeof ex.query !== "string") {
660325
+ context3.logger.warn(`Skipping malformed example for operation '${entry.operation}' in ${absoluteFilepathToExamples}: missing or invalid 'query' field`);
660326
+ return false;
660327
+ }
660328
+ return true;
660329
+ });
660330
+ if (entry.operationType != null) {
660331
+ const lower = entry.operationType.toLowerCase();
660332
+ if (lower !== "query" && lower !== "mutation" && lower !== "subscription") {
660333
+ context3.logger.warn(`Invalid operationType '${entry.operationType}' for operation '${entry.operation}' in ${absoluteFilepathToExamples}: must be 'query', 'mutation', or 'subscription'`);
660334
+ }
660335
+ }
660336
+ return { ...entry, examples: validExamples };
660337
+ }).filter((entry) => entry.examples.length > 0);
660338
+ return validEntries.length > 0 ? validEntries : void 0;
660339
+ } catch (error50) {
660340
+ context3.logger.error(`Failed to load GraphQL examples from ${absoluteFilepathToExamples}:`, extractErrorMessage(error50));
660341
+ return void 0;
660342
+ }
660343
+ }
660273
660344
  async function getAuthFromOverrideFiles(specs) {
660274
660345
  for (const spec of specs) {
660275
660346
  if (spec.type !== "openapi") {
@@ -661303,6 +661374,8 @@ var GraphQlSpecSchema2 = external_exports.object({
661303
661374
  origin: external_exports.string().optional(),
661304
661375
  /** Path to overrides file for the GraphQL spec. */
661305
661376
  overrides: external_exports.union([external_exports.string(), external_exports.array(external_exports.string()).nonempty()]).optional(),
661377
+ /** Path to a YAML/JSON file containing named examples for GraphQL operations. */
661378
+ examples: external_exports.string().optional(),
661306
661379
  /** Name used to group this GraphQL spec in the docs (rendered as a top-level section). */
661307
661380
  name: external_exports.string().optional()
661308
661381
  });
@@ -668495,7 +668568,7 @@ var AccessTokenPosthogManager = class {
668495
668568
  properties: {
668496
668569
  ...event,
668497
668570
  ...event.properties,
668498
- version: "5.34.0",
668571
+ version: "5.35.0",
668499
668572
  usingAccessToken: true,
668500
668573
  ...getRunIdProperties()
668501
668574
  }
@@ -668559,7 +668632,7 @@ var UserPosthogManager = class {
668559
668632
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
668560
668633
  event: "CLI",
668561
668634
  properties: {
668562
- version: "5.34.0",
668635
+ version: "5.35.0",
668563
668636
  ...event,
668564
668637
  ...event.properties,
668565
668638
  usingAccessToken: false,
@@ -673153,6 +673226,13 @@ var ApiDefinitionConverter = class {
673153
673226
  sourced: sourced.overrides
673154
673227
  });
673155
673228
  }
673229
+ if (spec.examples != null && !isNullish2(sourced.examples)) {
673230
+ result.examples = await this.resolvePath({
673231
+ absoluteFernYmlPath,
673232
+ path: spec.examples,
673233
+ sourced: sourced.examples
673234
+ });
673235
+ }
673156
673236
  if (spec.name != null) {
673157
673237
  result.name = spec.name;
673158
673238
  }
@@ -674588,6 +674668,7 @@ var LegacyApiSpecAdapter = class {
674588
674668
  type: "graphql",
674589
674669
  absoluteFilepath: spec.graphql,
674590
674670
  absoluteFilepathToOverrides: spec.overrides,
674671
+ absoluteFilepathToExamples: spec.examples,
674591
674672
  namespace: spec.name
674592
674673
  };
674593
674674
  }
@@ -825187,10 +825268,12 @@ https://buildwithfern.com/learn/docs/getting-started/project-structure#api-defin
825187
825268
  const graphqlSpecs = workspace.allSpecs.filter((spec) => spec.type === "graphql");
825188
825269
  for (const spec of graphqlSpecs) {
825189
825270
  try {
825271
+ const examples = await this.loadGraphQlExamples(spec.absoluteFilepathToExamples);
825190
825272
  const converter = new GraphQLConverter({
825191
825273
  context: this.taskContext,
825192
825274
  filePath: spec.absoluteFilepath,
825193
- namespace: spec.namespace
825275
+ namespace: spec.namespace,
825276
+ examples
825194
825277
  });
825195
825278
  const graphqlResult = await converter.convert();
825196
825279
  Object.assign(graphqlOperations, graphqlResult.graphqlOperations);
@@ -825206,6 +825289,52 @@ https://buildwithfern.com/learn/docs/getting-started/project-structure#api-defin
825206
825289
  }
825207
825290
  return { operations: graphqlOperations, types: graphqlTypes, namespacesByOperationId };
825208
825291
  }
825292
+ async loadGraphQlExamples(absoluteFilepathToExamples) {
825293
+ if (absoluteFilepathToExamples == null) {
825294
+ return void 0;
825295
+ }
825296
+ try {
825297
+ const contents = (await (0, import_promises65.readFile)(absoluteFilepathToExamples)).toString();
825298
+ const parsed = jsYaml.load(contents);
825299
+ if (!Array.isArray(parsed)) {
825300
+ return void 0;
825301
+ }
825302
+ for (const entry of parsed) {
825303
+ if (typeof entry !== "object" || entry == null) {
825304
+ this.taskContext.logger.warn(`Skipping invalid entry in GraphQL examples file ${absoluteFilepathToExamples}: expected object`);
825305
+ continue;
825306
+ }
825307
+ if (typeof entry.operation !== "string") {
825308
+ this.taskContext.logger.warn(`Skipping entry in GraphQL examples file ${absoluteFilepathToExamples}: missing or invalid 'operation' field`);
825309
+ continue;
825310
+ }
825311
+ if (!Array.isArray(entry.examples)) {
825312
+ this.taskContext.logger.warn(`Skipping entry for operation '${entry.operation}' in ${absoluteFilepathToExamples}: 'examples' must be an array`);
825313
+ continue;
825314
+ }
825315
+ }
825316
+ const validEntries = parsed.filter((entry) => typeof entry === "object" && entry != null && typeof entry.operation === "string" && Array.isArray(entry.examples)).map((entry) => {
825317
+ const validExamples = entry.examples.filter((ex) => {
825318
+ if (typeof ex !== "object" || ex == null || typeof ex.query !== "string") {
825319
+ this.taskContext.logger.warn(`Skipping malformed example for operation '${entry.operation}' in ${absoluteFilepathToExamples}: missing or invalid 'query' field`);
825320
+ return false;
825321
+ }
825322
+ return true;
825323
+ });
825324
+ if (entry.operationType != null) {
825325
+ const lower = entry.operationType.toLowerCase();
825326
+ if (lower !== "query" && lower !== "mutation" && lower !== "subscription") {
825327
+ this.taskContext.logger.warn(`Invalid operationType '${entry.operationType}' for operation '${entry.operation}' in ${absoluteFilepathToExamples}: must be 'query', 'mutation', or 'subscription'`);
825328
+ }
825329
+ }
825330
+ return { ...entry, examples: validExamples };
825331
+ }).filter((entry) => entry.examples.length > 0);
825332
+ return validEntries.length > 0 ? validEntries : void 0;
825333
+ } catch (error50) {
825334
+ this.taskContext.logger.error(`Failed to load GraphQL examples from ${absoluteFilepathToExamples}:`, String(error50));
825335
+ return void 0;
825336
+ }
825337
+ }
825209
825338
  /**
825210
825339
  * Handles librarySection navigation items by reading pre-generated MDX files
825211
825340
  * and _navigation.yml from the library's output directory.
@@ -860356,7 +860485,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
860356
860485
  var LOGS_FOLDER_NAME = "logs";
860357
860486
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
860358
860487
  function getCliSource() {
860359
- const version7 = "5.34.0";
860488
+ const version7 = "5.35.0";
860360
860489
  return `cli@${version7}`;
860361
860490
  }
860362
860491
  var DebugLogger = class {
@@ -869684,10 +869813,22 @@ async function loadSingleNamespaceAPIWorkspace({ absolutePathToWorkspace, namesp
869684
869813
  }
869685
869814
  };
869686
869815
  }
869816
+ const absoluteFilepathToExamples = definition3.schema.examples != null ? join8(absolutePathToWorkspace, RelativeFilePath2.of(definition3.schema.examples)) : void 0;
869817
+ if (definition3.schema.examples != null && absoluteFilepathToExamples != null && !await doesPathExist(absoluteFilepathToExamples)) {
869818
+ return {
869819
+ didSucceed: false,
869820
+ failures: {
869821
+ [RelativeFilePath2.of(definition3.schema.examples)]: {
869822
+ type: WorkspaceLoaderFailureType.FILE_MISSING
869823
+ }
869824
+ }
869825
+ };
869826
+ }
869687
869827
  specs.push({
869688
869828
  type: "graphql",
869689
869829
  absoluteFilepath: absoluteFilepathToGraphQL,
869690
869830
  absoluteFilepathToOverrides,
869831
+ absoluteFilepathToExamples,
869691
869832
  namespace
869692
869833
  });
869693
869834
  continue;
@@ -879216,7 +879357,7 @@ var LegacyDocsPublisher = class {
879216
879357
  previewId,
879217
879358
  disableTemplates: void 0,
879218
879359
  skipUpload,
879219
- cliVersion: "5.34.0",
879360
+ cliVersion: "5.35.0",
879220
879361
  loginCommand: "fern auth login"
879221
879362
  });
879222
879363
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -904633,7 +904774,7 @@ var EndpointSnippetGenerator3 = class {
904633
904774
  this.context.errors.scope(Scope4.PathParameters);
904634
904775
  const pathParameters = [...this.context.ir.pathParameters ?? [], ...request7.pathParameters ?? []];
904635
904776
  if (pathParameters.length > 0) {
904636
- otherArgs.push(...this.getPathParameters({ namedParameters: pathParameters, snippet: snippet2 }).map((field5) => field5.value));
904777
+ otherArgs.push(...this.getPathParameters({ namedParameters: pathParameters, snippet: snippet2, asPointer: true }).map((field5) => field5.value));
904637
904778
  }
904638
904779
  this.context.errors.unscope();
904639
904780
  this.context.errors.scope(Scope4.RequestBody);
@@ -904671,20 +904812,25 @@ var EndpointSnippetGenerator3 = class {
904671
904812
  inlinePathParameters: this.context.customConfig?.inlinePathParameters ?? true,
904672
904813
  inlineFileProperties: this.context.customConfig?.inlineFileProperties ?? true
904673
904814
  };
904815
+ const includePathParamsInRequest = this.context.includePathParametersInWrappedRequest({
904816
+ request: request7,
904817
+ inlinePathParameters
904818
+ });
904674
904819
  this.context.errors.scope(Scope4.PathParameters);
904675
904820
  const pathParameterFields = [];
904676
904821
  const pathParameters = [...this.context.ir.pathParameters ?? [], ...request7.pathParameters ?? []];
904677
904822
  if (pathParameters.length > 0) {
904678
904823
  pathParameterFields.push(...this.getPathParameters({
904679
904824
  namedParameters: pathParameters,
904680
- snippet: snippet2
904825
+ snippet: snippet2,
904826
+ asPointer: !includePathParamsInRequest
904681
904827
  }));
904682
904828
  }
904683
904829
  this.context.errors.unscope();
904684
904830
  this.context.errors.scope(Scope4.RequestBody);
904685
904831
  const filePropertyInfo = this.getFilePropertyInfo({ request: request7, snippet: snippet2 });
904686
904832
  this.context.errors.unscope();
904687
- if (!this.context.includePathParametersInWrappedRequest({ request: request7, inlinePathParameters })) {
904833
+ if (!includePathParamsInRequest) {
904688
904834
  otherArgs.push(...pathParameterFields.map((field5) => field5.value));
904689
904835
  }
904690
904836
  if (!inlineFileProperties) {
@@ -904697,10 +904843,7 @@ var EndpointSnippetGenerator3 = class {
904697
904843
  }) ? this.getInlinedRequestArg({
904698
904844
  request: request7,
904699
904845
  snippet: snippet2,
904700
- pathParameterFields: this.context.includePathParametersInWrappedRequest({
904701
- request: request7,
904702
- inlinePathParameters
904703
- }) ? pathParameterFields : [],
904846
+ pathParameterFields: includePathParamsInRequest ? pathParameterFields : [],
904704
904847
  filePropertyInfo
904705
904848
  }) : void 0;
904706
904849
  return { otherArgs, requestArg };
@@ -904802,7 +904945,7 @@ var EndpointSnippetGenerator3 = class {
904802
904945
  }
904803
904946
  return fields;
904804
904947
  }
904805
- getPathParameters({ namedParameters, snippet: snippet2 }) {
904948
+ getPathParameters({ namedParameters, snippet: snippet2, asPointer }) {
904806
904949
  const args = [];
904807
904950
  const pathParameters = this.context.associateByWireValueOrDefault({
904808
904951
  parameters: namedParameters,
@@ -904811,7 +904954,7 @@ var EndpointSnippetGenerator3 = class {
904811
904954
  for (const parameter6 of pathParameters) {
904812
904955
  args.push({
904813
904956
  name: this.context.getTypeName(parameter6.name.name),
904814
- value: this.context.dynamicTypeInstantiationMapper.convertToPointerIfPossible(parameter6)
904957
+ value: asPointer ? this.context.dynamicTypeInstantiationMapper.convertToPointerIfPossible(parameter6) : this.context.dynamicTypeInstantiationMapper.convert(parameter6)
904815
904958
  });
904816
904959
  }
904817
904960
  return args;
@@ -953954,7 +954097,7 @@ function getAutomationContextFromEnv() {
953954
954097
  config_branch: process.env.FERN_CONFIG_BRANCH,
953955
954098
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
953956
954099
  trigger: process.env.GITHUB_EVENT_NAME,
953957
- cli_version: "5.34.0"
954100
+ cli_version: "5.35.0"
953958
954101
  };
953959
954102
  }
953960
954103
  function isAutomationMode() {
@@ -954780,7 +954923,7 @@ var CliContext = class _CliContext {
954780
954923
  if (false) {
954781
954924
  this.logger.error("CLI_VERSION is not defined");
954782
954925
  }
954783
- return "5.34.0";
954926
+ return "5.35.0";
954784
954927
  }
954785
954928
  getCliName() {
954786
954929
  if (false) {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.34.0",
2
+ "version": "5.35.0",
3
3
  "repository": {
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/fern-api/fern.git",