From 293eb0a1df2c5a6a28ff8da1b1bd299cc6b53f46 Mon Sep 17 00:00:00 2001 From: Kapil Gowru Date: Thu, 31 Jul 2025 14:16:46 -0600 Subject: [PATCH 1/5] Create others.mdx based on issue #266 --- .../pages/extensions/others.mdx | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 fern/products/openapi-definition/pages/extensions/others.mdx diff --git a/fern/products/openapi-definition/pages/extensions/others.mdx b/fern/products/openapi-definition/pages/extensions/others.mdx new file mode 100644 index 000000000..61ed273fa --- /dev/null +++ b/fern/products/openapi-definition/pages/extensions/others.mdx @@ -0,0 +1,103 @@ +--- +title: Other Extensions +description: Other extensions supported by Fern +--- + +# Other Extensions + +Fern supports several additional OpenAPI extensions that provide enhanced functionality: + +## x-fern-sdk-variables + +The `x-fern-sdk-variables` extension allows you to define variables that will be injected into the SDK client at runtime. This is useful for values that are reused across multiple endpoints. + +```yaml +x-fern-sdk-variables: + project_id: + type: string + description: The project identifier + pattern: ^proj_[a-zA-Z0-9]+$ +``` + +The variable can then be referenced in path parameters: + +```yaml +/v1/projects/{project_id}/resources: + parameters: + - name: project_id + in: path + required: true + x-fern-sdk-variable: project_id +``` + +This allows the SDK client to inject the variable value automatically rather than requiring it as a parameter for each API call. + +## x-fern-pagination + +The `x-fern-pagination` extension configures pagination behavior for list endpoints: + +```yaml +x-fern-pagination: + cursor: $request.after + next_cursor: $response.page_info.end_cursor + results: $response.data +``` + +This tells Fern how to handle paginated responses by specifying: +- The cursor parameter in the request +- Where to find the next cursor in the response +- Where to find the results array in the response + +## x-fern-sdk-return-value + +The `x-fern-sdk-return-value` extension specifies which part of the response should be returned by the SDK: + +```yaml +x-fern-sdk-return-value: data +``` + +This is useful when the API wraps responses in a common envelope but you want the SDK to return just the relevant data. + +## x-fern-ignore + +Add `x-fern-ignore: true` to exclude an endpoint or schema from SDK generation: + +```yaml +/internal/endpoint: + x-fern-ignore: true +``` + +## x-fern-sdk-method-name + +Override the default SDK method name: + +```yaml +/users: + get: + x-fern-sdk-method-name: listUsers +``` + +## x-fern-sdk-group-name + +Group related endpoints together in the SDK: + +```yaml +/users: + get: + x-fern-sdk-group-name: users +``` + +This organizes the SDK methods into logical groups for better discoverability. + +## x-fern-headers + +Define headers that should be included with requests: + +```yaml +x-fern-headers: + X-Custom-Header: + type: string + required: true +``` + +These headers will be automatically included in SDK requests. \ No newline at end of file From 2ff7b27c5492f63d5218b6cacc87b0bcc7f6fe06 Mon Sep 17 00:00:00 2001 From: Kapil Gowru Date: Thu, 31 Jul 2025 14:16:47 -0600 Subject: [PATCH 2/5] Add Other page to navigation --- fern/products/openapi-def/openapi-def.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fern/products/openapi-def/openapi-def.yml b/fern/products/openapi-def/openapi-def.yml index 419d75e5b..a843620a7 100644 --- a/fern/products/openapi-def/openapi-def.yml +++ b/fern/products/openapi-def/openapi-def.yml @@ -4,7 +4,7 @@ navigation: - page: Authentication path: ./pages/auth.mdx - page: Servers - path: ./pages/servers.mdx + path: ./pages/servers.mdx - section: Endpoints slug: endpoints contents: @@ -17,6 +17,9 @@ navigation: - page: Server-Sent Events path: ./pages/endpoints/sse.mdx slug: sse + - page: others + title: Other + path: ./pages/extensions/others.mdx - section: Extensions slug: extensions contents: @@ -38,7 +41,7 @@ navigation: - page: Overlay Customizations path: ./pages/overrides.mdx - page: Sync your OpenAPI Specification - path: ./pages/automation.mdx + path: ./pages/automation.mdx - section: Integrate your Server Framework slug: frameworks contents: From 8eefba573a98f54d10aa95428bdae8e7c83420ff Mon Sep 17 00:00:00 2001 From: Kapil Gowru Date: Thu, 31 Jul 2025 14:16:48 -0600 Subject: [PATCH 3/5] Update parameter-names.mdx based on issue #266 --- .../pages/extensions/parameter-names.mdx | 89 +++++++++++++++---- 1 file changed, 74 insertions(+), 15 deletions(-) diff --git a/fern/products/openapi-def/pages/extensions/parameter-names.mdx b/fern/products/openapi-def/pages/extensions/parameter-names.mdx index ff60bf613..f814c0b02 100644 --- a/fern/products/openapi-def/pages/extensions/parameter-names.mdx +++ b/fern/products/openapi-def/pages/extensions/parameter-names.mdx @@ -1,37 +1,41 @@ --- title: Customize parameter names -description: Use `x-fern-parameter-name` to customize query parameter, header and path parameter naming. +description: Use extension headers to customize parameter names and behavior in your generated SDKs. --- - The `x-fern-parameter-name` extension allows you to customize the variable names of parameters in your generated SDKs. + Extension headers allow you to customize how parameters are handled in your generated SDKs, including parameter naming and injection behavior. -## Headers +## Parameter Naming Extensions -In the example below, the header `X-API-Version` is renamed to `version` in the -generated SDK. The rename makes the SDK more human readable. +### x-fern-parameter-name -```yaml {8} +Customize the variable names of parameters in your generated SDKs. + +#### Headers + +Rename HTTP headers to be more readable in the SDK: + +```yaml paths: "/user": get: operationId: list_user parameters: - in: header - name: X-API-Version + name: X-API-Version x-fern-parameter-name: version schema: type: string required: true ``` -## Query parameters +#### Query Parameters -In the example below, the query parameter `q` is renamed to `search_terms` in the -generated SDK. The rename makes the parameter more approachable for end users. +Make query parameter names more descriptive: -```yaml {8} +```yaml paths: "/user/search": get: @@ -45,12 +49,11 @@ paths: required: false ``` -## Path parameters +#### Path Parameters -In the example below, the path parameter `userId` is renamed to `id` in the -generated SDK. The rename makes the SDK less verbose. +Simplify path parameter names: -```yaml {8} +```yaml paths: "/user/{userId}": get: @@ -63,3 +66,59 @@ paths: type: string required: false ``` + +### x-fern-sdk-variables + +Define variables that can be injected into paths across multiple endpoints: + +```yaml +components: + x-fern-sdk-variables: + project_id: + type: string + description: "The project ID to use for all requests" + pattern: "^proj_[a-zA-Z0-9]+$" + +paths: + "/v1/connect/{project_id}/accounts": + parameters: + - name: project_id + in: path + required: true + schema: + type: string + x-fern-sdk-variable: project_id +``` + +This allows the SDK client to accept the variable in its constructor and automatically inject it into all relevant paths, rather than requiring it as a parameter for each individual method call. + + + The variable value provided in the SDK client constructor will be automatically inserted into any path that references that variable name. + + +### x-fern-sdk-return-value + +Specify which part of the response should be returned by the SDK method: + +```yaml +paths: + "/user/{id}": + get: + operationId: get_user + x-fern-sdk-return-value: data + responses: + 200: + content: + application/json: + schema: + type: object + properties: + data: + $ref: "#/components/schemas/User" +``` + +This extracts just the `data` field from the response before returning it to the SDK user. + + + This is useful when your API wraps response data in a container object but you want the SDK to return just the core data. + \ No newline at end of file From 7eecdc0a366f0dc38c47595932220cc59d1e0210 Mon Sep 17 00:00:00 2001 From: Kapil Gowru Date: Thu, 31 Jul 2025 14:16:48 -0600 Subject: [PATCH 4/5] Update configuration.mdx based on issue #266 --- .../sdks/overview/python/configuration.mdx | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/fern/products/sdks/overview/python/configuration.mdx b/fern/products/sdks/overview/python/configuration.mdx index 1c0eb6af7..b6e6080c4 100644 --- a/fern/products/sdks/overview/python/configuration.mdx +++ b/fern/products/sdks/overview/python/configuration.mdx @@ -21,6 +21,7 @@ groups: ## SDK Configuration Options + Additional exports to include in the package's __init__.py file. @@ -28,6 +29,7 @@ groups: + If true, types will not be exported in the package's __init__.py file. @@ -40,12 +42,15 @@ groups: + Additional development dependencies to include in the generated package. + Optional dependencies that can be installed with your package. + If true, generates a flatter file structure without nested directories. @@ -53,14 +58,15 @@ groups: - Feature flag that improves imports in the Python SDK by removing nested `resources` directory + Feature flag that improves imports in the Python SDK by removing nested `resources` directory. - Whether or not to include legacy wire tests in the generated SDK + Whether or not to include legacy wire tests in the generated SDK. + If true, includes utility functions for working with union types. @@ -72,26 +78,24 @@ groups: - -Specifies the Python package name that users will import your generated client -from. + Specifies the Python package name that users will import your generated client from. -For example, setting `package_name: "my_custom_package"` enables users to use -`my_custom_package import Client` to import your client: - -```yaml {7-10} -default-group: local -groups: - local: - generators: - - name: fernapi/fern-python + For example, setting `package_name: "my_custom_package"` enables users to use `from my_custom_package import Client` to import your client: + + ```yaml {7-10} + default-group: local + groups: + local: + generators: + - name: fernapi/fern-python version: 0.7.1 config: package_name: "my_custom_package" -``` + ``` + Configuration options for Pydantic model generation. @@ -112,8 +116,8 @@ groups: # Visit every case in the union shape = get_shape() shape.visit( - circle: lambda circle: do_something_with_circle(circle), - triangle: lambda triangle: do_something_with_triangle(triangle), + circle=lambda circle: do_something_with_circle(circle), + triangle=lambda triangle: do_something_with_triangle(triangle), ) ``` @@ -140,6 +144,7 @@ groups: + Custom pyproject.toml content to include in the generated package. @@ -147,6 +152,7 @@ groups: + If true, skips code formatting with Black. @@ -154,6 +160,7 @@ groups: + If true, includes the API name in the generated package name. @@ -194,4 +201,26 @@ groups: The name of the exported client class that will be used in code snippets. - \ No newline at end of file + + +### Extension Headers + +The Python generator (v4.24.0+) supports setting extension headers through the `x-fern-sdk-variables` field in your OpenAPI spec: + +```yaml +x-fern-sdk-variables: + project_id: + type: string + description: The ID of the project + pattern: ^proj_[a-zA-Z0-9]+$ +``` + +This allows you to define variables that will be injected into path parameters automatically when making requests. The variables are set when initializing the client: + +```python +from my_sdk import Client + +client = Client( + project_id="proj_123" # Will be injected into paths automatically +) +``` \ No newline at end of file From e1ab30bd369b2c1b22ff74968a4bd5a65f3a1862 Mon Sep 17 00:00:00 2001 From: Kapil Gowru Date: Thu, 31 Jul 2025 14:16:49 -0600 Subject: [PATCH 5/5] Update configuration.mdx based on issue #266 --- .../overview/typescript/configuration.mdx | 157 ++++-------------- 1 file changed, 32 insertions(+), 125 deletions(-) diff --git a/fern/products/sdks/overview/typescript/configuration.mdx b/fern/products/sdks/overview/typescript/configuration.mdx index 6fc216209..d5e5e36f8 100644 --- a/fern/products/sdks/overview/typescript/configuration.mdx +++ b/fern/products/sdks/overview/typescript/configuration.mdx @@ -11,7 +11,7 @@ groups: local: generators: - name: fernapi/fern-typescript-sdk - version: + version: config: namespaceExport: Acme ``` @@ -23,6 +23,7 @@ Allow fields that are not defined in object schemas. This only applies to serde. +Bundle the generated SDK code into a single file. @@ -96,7 +97,6 @@ config: extraDependencies: lodash: "3.0.2" ``` - @@ -130,12 +130,36 @@ Specify extra peer dependencies meta fields in the generated `package.json`: ```yaml # generators.yml config: - extraPeerDependencies: - react: ">=16.8.0 <19.0.0" - "react-dom": ">=16.8.0 <19.0.0" + extraPeerDependenciesMeta: + react: + optional: true ``` + +Configure SDK variables that should be passed as headers on every request: + +```yaml +# generators.yml +config: + extensionHeaders: + project_id: + name: "x-pd-project-id" + type: "string" + description: "The project ID to use for requests" +``` + +This allows users to configure these variables once when initializing the client: + +```typescript +const client = new Client({ + project_id: "proj_123" +}); +``` + +The header will be automatically included on all requests. + + Choose whether you want to include `node-fetch` to support Node.js versions before Node.js 18, or choose `native` to use the native `fetch` API available in Node.js 18 and later. @@ -184,9 +208,11 @@ Includes the content type and content length from binary responses. The user wil +Include an "other" catch-all type in union types for unknown values. +Include utility functions on union type members for type checking. @@ -422,123 +448,4 @@ Fern Definition). If `skipResponseValidation` is set to `true`, the client will never throw if the response is misshapen. Instead, the client will log the issue using `console.warn` and return the data (casted to the expected response type). -Response validation only occurs when the Serde layer is enabled (`noSerdeLayer: false`). The Serde layer is disabled by default (`noSerdeLayer: true`). - - - - -Change the type of stream that is used in the generated SDK. - -* `wrapper`: The streams use a wrapper with multiple underlying implementations to support versions of Node.js before Node.js 18. -* `web`: The streams use the web standard `ReadableStream`. - -The default is `web`. - - - - When `treatUnknownAsAny` is enabled, [unknown types from Fern are generated into TypeScript using `any` instead of the `unknown` type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type). - - - -When `useBigInt` is set to `true`, a customized JSON serializer & deserializer is used that will preserve the precision of `bigint`'s, as opposed to the native `JSON.stringify` and `JSON.parse` function which converts `bigint`'s to number's losing precision. - -When combining `useBigInt` with our serialization layer (`no-serde: false`), both the request and response properties that are marked as `long` and `bigint` in OpenAPI/Fern spec, will consistently be `bigint`'s. -However, when disabling the serialization layer (`no-serde: true`), they will be typed as `number | bigint`. - -Here's an overview of what to expect from the generated types when combining `useBigInt` and `noSerde` with the following Fern definition: - -*Fern definition*: - -```yaml -types: - ObjectWithOptionalField: - properties: - longProp: long - bigIntProp: bigint -``` - -*TypeScript output*: - -```typescript -// useBigInt: true -// noSerde: false -interface ObjectWithLongAndBigInt { - longProp: bigint; - bigIntProp: bigint; -} - -// useBigInt: true -// noSerde: true -interface ObjectWithLongAndBigInt { - longProp: bigint | number; - bigIntProp: bigint | number; -} - -// useBigInt: false -// noSerde: false -interface ObjectWithLongAndBigInt { - longProp: number; - bigIntProp: string; -} - -// useBigInt: false -// noSerde: true -interface ObjectWithLongAndBigInt { - longProp: number; - bigIntProp: string; -} -``` - - - - - When `useBrandedStringAliases` is disabled (the default), string aliases are generated as - normal TypeScript aliases: - - ```typescript - // generated code - - export type MyString = string; - - export type OtherString = string; - ``` - When `useBrandedStringAliases` is enabled, string aliases are generated as branded strings. This makes each alias feel like its own type and improves compile-time safety. - - ```yaml - # fern definition - - types: - MyString: string - OtherString: string - ``` - - ```typescript - // generated code - - export type MyString = string & { __MyString: void }; - export const MyString = (value: string): MyString => value as MyString; - - export type OtherString = string & { __OtherString: void }; - export const OtherString = (value: string): OtherString => value as OtherString; - ``` - - ```typescript - // consuming the generated type - - function printMyString(s: MyString): void { - console.log("MyString: " + s); - } - - // doesn't compile, "foo" is not assignable to MyString - printMyString("foo"); - - const otherString = OtherString("other-string"); - // doesn't compile, otherString is not assignable to MyString - printMyString(otherString); - - // compiles - const myString = MyString("my-string"); - printMyString(myString); - ``` - - \ No newline at end of file +Response validation only occurs when the Serde layer is \ No newline at end of file