diff --git a/fern/products/openapi-def/pages/extensions/parameter-names.mdx b/fern/products/openapi-def/pages/extensions/parameter-names.mdx
index ff60bf61..ec562938 100644
--- a/fern/products/openapi-def/pages/extensions/parameter-names.mdx
+++ b/fern/products/openapi-def/pages/extensions/parameter-names.mdx
@@ -1,41 +1,55 @@
---
title: Customize parameter names
-description: Use `x-fern-parameter-name` to customize query parameter, header and path parameter naming.
+description: Use extensions to customize parameter naming in your generated SDKs.
---
- The `x-fern-parameter-name` extension allows you to customize the variable names of parameters in your generated SDKs.
+ Extensions allow you to customize how parameters are named and handled in your generated SDKs to improve readability and usability.
-## Headers
+## Header 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
+Renames a header parameter in the generated SDK for better readability.
-```yaml {8}
+```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
-
-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.
+### x-fern-sdk-header
+Marks a header to be provided in the SDK client constructor rather than per-request.
```yaml {8}
+paths:
+ "/user":
+ get:
+ parameters:
+ - in: header
+ name: X-API-Key
+ schema:
+ x-fern-sdk-header: api_key
+ type: string
+ required: true
+```
+
+## Query Parameter Extensions
+
+### x-fern-parameter-name
+Renames a query parameter in the generated SDK to be more descriptive.
+
+```yaml
paths:
"/user/search":
get:
- operationId: search_user
parameters:
- in: query
name: q
@@ -45,21 +59,61 @@ paths:
required: false
```
-## 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.
+### x-fern-sdk-variable
+Marks a query parameter to be provided in the SDK client constructor.
```yaml {8}
+paths:
+ "/user/search":
+ get:
+ parameters:
+ - in: query
+ name: org_id
+ schema:
+ x-fern-sdk-variable: organization_id
+ type: string
+ required: true
+```
+
+## Path Parameter Extensions
+
+### x-fern-parameter-name
+Renames a path parameter in the generated SDK for conciseness.
+
+```yaml
paths:
"/user/{userId}":
get:
- operationId: get_user
parameters:
- in: path
name: userId
x-fern-parameter-name: id
schema:
type: string
- required: false
+ required: true
```
+
+### x-fern-sdk-variable
+Marks a path parameter to be provided in the SDK client constructor. This is useful for values that are common across many endpoints.
+
+```yaml
+paths:
+ "/projects/{project_id}/users":
+ get:
+ parameters:
+ - in: path
+ name: project_id
+ schema:
+ x-fern-sdk-variable: project_id
+ type: string
+ pattern: "^proj_[a-zA-Z0-9]+$"
+ required: true
+```
+
+
+ When using `x-fern-sdk-variable` or `x-fern-sdk-header`, the specified value will be provided once in the client constructor rather than needing to be passed to each individual API call.
+
+
+
+ Use these extensions strategically to create a more ergonomic SDK. Consider renaming cryptic parameter names to be more descriptive, and moving commonly used values like API keys or project IDs to the client constructor.
+
\ No newline at end of file
diff --git a/fern/products/sdks/overview/python/configuration.mdx b/fern/products/sdks/overview/python/configuration.mdx
index 1c0eb6af..6b5a39a9 100644
--- a/fern/products/sdks/overview/python/configuration.mdx
+++ b/fern/products/sdks/overview/python/configuration.mdx
@@ -21,6 +21,36 @@ groups:
## SDK Configuration Options
+ Additional exports to include in the package's __init__.py file.
+
+
+
+ Configuration for the generated client class and file structure.
+
+ ```yaml
+ config:
+ client:
+ filename: "my_client.py"
+ class_name: "MyClient"
+ exported_filename: "my_client.py"
+ exported_class_name: "MyClient"
+ ```
+
+
+
+ The filename for the generated client file.
+
+
+
+ The name of the generated client class.
+
+
+
+ The filename of the exported client which will be used in code snippets.
+
+
+
+ The name of the exported client class that will be used in code snippets.
@@ -28,6 +58,18 @@ groups:
+ Whether to exclude type definitions from the package's __init__.py exports.
+
+
+
+ Headers to inject into all requests made by the client. Useful for custom authentication or tracking.
+
+ ```yaml
+ config:
+ extension_headers:
+ x-custom-header: "custom-value"
+ x-api-key: "default-key"
+ ```
@@ -40,12 +82,15 @@ groups:
+ Additional development dependencies to include in the generated package.
+ Optional feature groups that can be installed with the package.
+ Whether to generate a flat file structure instead of nested directories.
@@ -53,14 +98,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.
+ Whether to include utility functions for working with union types.
@@ -72,26 +118,18 @@ 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:
+ 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"
-```
+ ```yaml
+ config:
+ package_name: "my_custom_package"
+ ```
-
+
+ Configuration options for Pydantic model generation.
@@ -140,6 +178,7 @@ groups:
+ Custom pyproject.toml content to include in the generated package.
@@ -147,6 +186,7 @@ groups:
+ Whether to skip code formatting of the generated files.
@@ -154,6 +194,7 @@ groups:
+ Whether to include the API name in the generated package name.
@@ -166,32 +207,4 @@ groups:
Whether or not to generate TypedDicts instead of Pydantic Models for file upload request objects. Note that this flag was only introduced due to an oversight in the `use_typeddict_requests` flag implementation; it should be removed in the future.
-
-
-### client
- Configuration for the generated client class and file structure.
-
- ```yaml
- config:
- client:
- filename: "my_client.py"
- class_name: "MyClient"
- exported_filename: "my_client.py"
- exported_class_name: "MyClient"
- ```
-
-
- The filename for the generated client file.
-
-
-
- The name of the generated client class.
-
-
-
- The filename of the exported client which will be used in code snippets.
-
-
-
- The name of the exported client class that will be used in code snippets.
\ No newline at end of file
diff --git a/fern/products/sdks/overview/typescript/configuration.mdx b/fern/products/sdks/overview/typescript/configuration.mdx
index 6fc21620..0a62de6e 100644
--- a/fern/products/sdks/overview/typescript/configuration.mdx
+++ b/fern/products/sdks/overview/typescript/configuration.mdx
@@ -2,7 +2,6 @@
title: TypeScript Configuration
description: Configuration options for the Fern TypeScript SDK.
---
-
You can customize the behavior of the TypeScript SDK generator in `generators.yml`:
```yml {7-8}
@@ -23,6 +22,7 @@ Allow fields that are not defined in object schemas. This only applies to serde.
+Bundle the SDK into a single file. This is useful when you want to distribute the SDK as a single file.
@@ -96,7 +96,6 @@ config:
extraDependencies:
lodash: "3.0.2"
```
-
@@ -112,6 +111,18 @@ config:
Only applies when publishing to Github.
+
+Add custom headers to be included with every request:
+
+```yaml
+# generators.yml
+config:
+ extraHeaders:
+ x-custom-header: "custom-value"
+ x-api-version: "2023-01-01"
+```
+
+
Specify extra peer dependencies in the generated `package.json`:
@@ -130,9 +141,11 @@ 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
+ "react-dom":
+ optional: true
```
@@ -165,7 +178,6 @@ Choose whether you want to support Node.js 16 and above (`Node16`), or Node.js 1
-
Includes the content type and content length from binary responses. The user will receive an object of the following type:
```typescript
@@ -180,13 +192,15 @@ Includes the content type and content length from binary responses. The user wil
- When enabled, [`withCredentials`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials) is set to `true` when making network requests.
+When enabled, [`withCredentials`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials) is set to `true` when making network requests.
+Include an "other" variant in union types to handle unknown values from the API.
+Include utility functions on union members for type checking and value extraction.
@@ -238,7 +252,6 @@ public async post(
...
}
```
-
@@ -254,28 +267,26 @@ await service.getFoo("pathParamValue", { id: "SOME_ID" });
```typescript
await service.getFoo({ pathParamName: "pathParamValue", id: "SOME_ID" });
```
-
By default, names are based on the organization and API names in the Fern Definition:
- ```typescript
- import { AcmeApi, AcmeApiClient } from "@acme/node";
- ```
-
- `namespaceExport` customizes the exported namespace and client names:
+```typescript
+import { AcmeApi, AcmeApiClient } from "@acme/node";
+```
- ```yaml
- # generators.yml
- config:
- namespaceExport: Acme
- ```
+`namespaceExport` customizes the exported namespace and client names:
- ```typescript
- import { Acme, AcmeClient } from "@acme/node";
- ```
+```yaml
+# generators.yml
+config:
+ namespaceExport: Acme
+```
+```typescript
+import { Acme, AcmeClient } from "@acme/node";
+```
@@ -286,7 +297,7 @@ By default, names are based on the organization and API names in the Fern Defini
if (response.ok) {
console.log(response.body)
} else {
- console.error(respons.error)
+ console.error(response.error)
}
```
@@ -323,18 +334,13 @@ Prevent the generator from running any scripts such as `yarn format` or `yarn in
-
No serialization/deserialization code is generated by default. The client uses `JSON.parse()` and `JSON.stringify()` instead of the default Serde layer.
- When `noSerdeLayer: false`, the generated client includes a layer for serializing requests and deserializing responses. This has three benefits:
-
- 1. The client validates requests and response at runtime (client-side).
-
- 1. The client can support complex types like `Date` and `Set`.
-
- 1. The generated types can stray from the wire/JSON representation to be more
- idiomatic. For example, when the Serde layer is enabled (`noSerdeLayer: false`), all properties are `camelCase`, even if the server is expecting `snake_case`.
+When `noSerdeLayer: false`, the generated client includes a layer for serializing requests and deserializing responses. This has three benefits:
+1. The client validates requests and response at runtime (client-side).
+2. The client can support complex types like `Date` and `Set`.
+3. The generated types can stray from the wire/JSON representation to be more idiomatic. For example, when the Serde layer is enabled (`noSerdeLayer: false`), all properties are `camelCase`, even if the server is expecting `snake_case`.
@@ -366,8 +372,7 @@ Specify the path where the source files for the generated SDK should be placed.
-Publish your SDK to [JSR](https://jsr.io/). When enabled, the generator will
-generate a `jsr.json` as well as a GitHub workflow to publish to JSR.
+Publish your SDK to [JSR](https://jsr.io/). When enabled, the generator will generate a `jsr.json` as well as a GitHub workflow to publish to JSR.
@@ -387,10 +392,10 @@ generate a `jsr.json` as well as a GitHub workflow to publish to JSR.
User:
type: object
properties:
- user_id:
- type: string
- display_name:
- type: string
+ user_id:
+ type: string
+ display_name:
+ type: string
```
Generated TypeScript with `retainOriginalCasing: true`:
@@ -408,7 +413,29 @@ generate a `jsr.json` as well as a GitHub workflow to publish to JSR.
displayName: string;
}
```
+
+
+
+ Configure SDK variable headers to be used across endpoints. Headers provided in individual endpoint calls will override these values.
+ ```yaml
+ # generators.yml
+ config:
+ sdkVariableHeaders:
+ projectId: "project_id"
+ environment: "x-pd-environment"
+ ```
+
+ This allows configuring headers once at the client level:
+
+ ```typescript
+ const client = new Client({
+ projectId: "proj_123",
+ environment: "production"
+ });
+ ```
+
+ Any requests made through this client will automatically include the configured headers.
@@ -416,21 +443,18 @@ generate a `jsr.json` as well as a GitHub workflow to publish to JSR.
- By default, the client will throw an error if the response from the server
-doesn't match the expected type (based on how the response is modeled in the
-Fern Definition).
+ By default, the client will throw an error if the response from the server doesn't match the expected type (based on how the response is modeled in the 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`.
+* `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`.
@@ -448,7 +472,6 @@ However, when disabling the serialization layer (`no-serde: true`), they will be
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:
@@ -458,7 +481,6 @@ types:
```
*TypeScript output*:
-
```typescript
// useBigInt: true
// noSerde: false
@@ -491,54 +513,102 @@ interface ObjectWithLongAndBigInt {
+When `useBrandedStringAliases` is disabled (the default), string aliases are generated as normal TypeScript aliases:
- 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
+```typescript
+// generated code
+export type MyString = string;
+export type OtherString = string;
+```
- export type MyString = string & { __MyString: void };
- export const MyString = (value: string): MyString => value as MyString;
+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.
- export type OtherString = string & { __OtherString: void };
- export const OtherString = (value: string): OtherString => value as OtherString;
- ```
-
- ```typescript
- // consuming the generated type
+```yaml
+# fern definition
+types:
+ MyString: string
+ OtherString: string
+```
- function printMyString(s: MyString): void {
- console.log("MyString: " + s);
- }
+```typescript
+// generated code
+export type MyString = string & { __MyString: void };
+export const MyString = (value: string): MyString => value as MyString;
+```
+
- // doesn't compile, "foo" is not assignable to MyString
- printMyString("foo");
+
+ Defines custom extension behavior for SDK generation. Extension headers can be used to modify the generated code behavior:
- const otherString = OtherString("other-string");
- // doesn't compile, otherString is not assignable to MyString
- printMyString(otherString);
+ ```typescript
+ // Available extension headers
+ interface Extensions {
+ // Specify custom headers to include in all requests
+ headers?: {
+ [key: string]: string | undefined;
+ };
+ // Configure authorization token management
+ auth?: {
+ // Token provider function
+ getToken?: () => Promise;
+ // Custom auth header name (default: Authorization)
+ headerName?: string;
+ // Custom auth header prefix (default: Bearer)
+ prefix?: string;
+ };
+ // Configure request timeouts
+ timeout?: {
+ // Timeout in milliseconds
+ ms?: number;
+ };
+ // Configure base URL overrides
+ baseUrl?: {
+ // Override base URL per environment
+ [environment: string]: string;
+ };
+ // Enable fetch-style request/response interception
+ interceptors?: {
+ request?: Array<(input: RequestInfo, init?: RequestInit) => Promise<[RequestInfo, RequestInit?]>>;
+ response?: Array<(response: Response) => Promise>;
+ };
+ }
+ ```
- // compiles
- const myString = MyString("my-string");
- printMyString(myString);
- ```
+ Example configuring extensions:
+ ```typescript
+ const client = new MyApiClient({
+ extensions: {
+ headers: {
+ 'x-custom-header': 'value'
+ },
+ auth: {
+ getToken: async () => 'my-token',
+ headerName: 'X-Auth',
+ prefix: 'Token'
+ },
+ timeout: {
+ ms: 5000
+ },
+ baseUrl: {
+ production: 'https://api.example.com',
+ staging: 'https://staging-api.example.com'
+ },
+ interceptors: {
+ request: [
+ async (input, init) => {
+ // Modify request
+ return [input, init];
+ }
+ ],
+ response: [
+ async (response) => {
+ // Handle response
+ return response;
+ }
+ ]
+ }
+ }
+ });
+ ```
\ No newline at end of file