diff --git a/fern/products/openapi-def/pages/extensions/parameter-names.mdx b/fern/products/openapi-def/pages/extensions/parameter-names.mdx
index ff60bf613..66a4d5123 100644
--- a/fern/products/openapi-def/pages/extensions/parameter-names.mdx
+++ b/fern/products/openapi-def/pages/extensions/parameter-names.mdx
@@ -1,18 +1,23 @@
---
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 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.
+ OpenAPI extensions allow you to customize how parameters are handled in your generated SDKs.
-## Headers
+## Renaming Parameters
-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}
+Use `x-fern-parameter-name` to customize the variable names of parameters in your generated SDKs:
+
+#### Headers
+
+Rename header parameters to make them more readable:
+
+```yaml
paths:
"/user":
get:
@@ -26,12 +31,11 @@ paths:
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,46 @@ paths:
type: string
required: false
```
+
+## SDK Variables
+
+### x-fern-sdk-variables
+
+Use `x-fern-sdk-variables` to define variables that can be set at the SDK client level and injected into requests:
+
+```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
+ pattern: "^proj_[a-zA-Z0-9]+$"
+ x-fern-sdk-variable: project_id
+```
+
+This allows users to set the variable once when instantiating the client:
+
+```python
+client = Client(project_id="proj_123")
+```
+
+Rather than passing it to every method:
+
+```python
+# No need to pass project_id to each call
+accounts = client.accounts.list()
+```
+
+
+ SDK variables help reduce repetition and make your SDK more ergonomic by allowing common parameters to be configured once at the client level.
+
\ 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 1c0eb6af7..e1f172553 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:
+ Whether to exclude type definitions from being exported in the package's __init__.py file.
@@ -40,12 +42,15 @@ groups:
+ Additional development dependencies to include in the generated package.
+ Optional dependency groups that can be installed with the package.
+ Whether to generate a flat file structure instead of nested directories.
@@ -53,18 +58,19 @@ 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.
+ When enabled, generates utility functions for working with union types.
- If true, treats path parameters as named parameters in endpoint functions.
+ If true, treats path parameters as named parameters in endpoint functions rather than using a request object.
@@ -72,39 +78,23 @@ 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 `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.
- When enabled, the generator will output a Pydantic `__root__` class that will contain utilities to visit the union. For example, for the following union type:
+ When enabled, generates a Pydantic `__root__` class containing utilities to visit unions. For example:
- ```
- types:
- Shape:
- union:
- circle: Circle
- triangle: Triangle
- ```
- you will get a generated `Shape` class that has a factory and visitor:
```python
# Use a factory to instantiate the union
Shape.factory.circle(Circle(...))
@@ -112,26 +102,23 @@ 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),
)
```
-
- When enabled, the python generator will not run Black formatting in the generated code. Black is slow so this can potentially speed up code generation quite a bit.
- By default, the generator generates pydantic models that are v1 and v2 compatible. However you can override them to:
+ Controls Pydantic version compatibility:
- `v1`: strictly use Pydantic v1
- - `v2`: strictly use Pydantic v2
+ - `v2`: strictly use Pydantic v2
- `both`: maintain compatibility with both versions
- `v1_on_v2`: use Pydantic v1 compatibility layer on v2
-
- Example:
+
```yaml
config:
pydantic_config:
- version: v1 # or v2 or "both"
+ version: v2
```
@@ -140,6 +127,7 @@ groups:
+ Custom pyproject.toml contents to include in the generated package.
@@ -147,6 +135,7 @@ groups:
+ Whether to skip code formatting on the generated files.
@@ -154,6 +143,7 @@ groups:
+ Whether to include the API name in the generated package name.
@@ -168,17 +158,48 @@ 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.
+### Extension Headers
+
+The Python generator supports extension headers through the `x-fern-sdk-variables` configuration in your OpenAPI spec. This allows you to define variables that will be included in the client configuration and injected into API paths.
+
+For example, to define a project ID variable that will be included in all paths:
+
+```yaml
+x-fern-sdk-variables:
+ project_id:
+ type: string
+ description: "The ID of the project"
+ pattern: "^proj_[a-zA-Z0-9]+$"
+```
+
+This variable can then be referenced in your paths:
+
+```yaml
+paths:
+ /v1/connect/{project_id}/accounts:
+ parameters:
+ - name: project_id
+ in: path
+ required: true
+ schema:
+ type: string
+ x-fern-sdk-variable: project_id
+```
+
+The generated client will include this variable in its configuration and automatically inject it into request paths.
+
### 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"
- ```
+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.
diff --git a/fern/products/sdks/overview/typescript/configuration.mdx b/fern/products/sdks/overview/typescript/configuration.mdx
index 6fc216209..a6173f0fa 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
```
@@ -96,7 +96,6 @@ config:
extraDependencies:
lodash: "3.0.2"
```
-
@@ -130,9 +129,40 @@ 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
+```
+
+
+
+Define custom request headers to be included in all API requests:
+
+```yaml
+# generators.yml
+config:
+ extensionHeaders:
+ x-project-id: project_id
+```
+
+The header value is derived from the variable name specified, which can be defined using `x-fern-sdk-variables` in your OpenAPI spec:
+
+```yaml
+# openapi.yml
+x-fern-sdk-variables:
+ project_id:
+ type: string
+ description: The project ID to use for all requests
+```
+
+This will generate a client that accepts the variable in its constructor:
+
+```typescript
+const client = new ApiClient({
+ projectId: "my-project-id"
+});
```
@@ -165,7 +195,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
@@ -238,7 +267,6 @@ public async post(
...
}
```
-
@@ -254,28 +282,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";
+```
@@ -294,28 +320,28 @@ By default, names are based on the organization and API names in the Fern Defini
By default, Fern's `optional<>` properties will translate to optional TypeScript properties:
- ```yaml {4}
- Person:
- properties:
- name: string
- age: optional
- ```
-
- ```typescript {3}
- interface Person {
- name: string;
- age?: number;
- }
- ```
-
- When `noOptionalProperties` is enabled, the generated properties are never optional. Instead, the type is generated with `| undefined`. As a result, users must explicitly set the property to a value or `undefined`.
-
- ```typescript {3}
- interface Person {
- name: string;
- age: number | undefined;
- }
- ```
+```yaml {4}
+Person:
+ properties:
+ name: string
+ age: optional
+```
+
+```typescript {3}
+interface Person {
+ name: string;
+ age?: number;
+}
+```
+
+When `noOptionalProperties` is enabled, the generated properties are never optional. Instead, the type is generated with `| undefined`. As a result, users must explicitly set the property to a value or `undefined`.
+
+```typescript {3}
+interface Person {
+ name: string;
+ age: number | undefined;
+}
+```
@@ -323,18 +349,15 @@ 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).
+When `noSerdeLayer: false`, the generated client includes a layer for serializing requests and deserializing responses. This has three benefits:
- 1. The client can support complex types like `Date` and `Set`.
+1. The client validates requests and response at runtime (client-side).
- 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`.
+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`.
@@ -373,46 +396,45 @@ generate a `jsr.json` as well as a GitHub workflow to publish to JSR.
When enabled, property names in the generated code retain their original casing from the API definition instead of being converted to camelCase.
- ```yaml
- # generators.yml
- config:
- retainOriginalCasing: true
- ```
-
- **Example with OpenAPI input:**
- ```yaml {7, 9}
- # OpenAPI schema
- components:
- schemas:
- User:
- type: object
- properties:
- user_id:
- type: string
- display_name:
- type: string
- ```
-
- Generated TypeScript with `retainOriginalCasing: true`:
- ```typescript {2-3}
- export interface User {
- user_id: string;
- display_name: string;
- }
- ```
-
- Generated TypeScript with default settings (`retainOriginalCasing: false`):
- ```typescript {2-3}
- export interface User {
- userId: string;
- displayName: string;
- }
- ```
+```yaml
+# generators.yml
+config:
+ retainOriginalCasing: true
+```
+
+**Example with OpenAPI input:**
+```yaml {7, 9}
+# OpenAPI schema
+components:
+ schemas:
+ User:
+ type: object
+ properties:
+ user_id:
+ type: string
+ display_name:
+ type: string
+```
+Generated TypeScript with `retainOriginalCasing: true`:
+```typescript {2-3}
+export interface User {
+ user_id: string;
+ display_name: string;
+}
+```
+
+Generated TypeScript with default settings (`retainOriginalCasing: false`):
+```typescript {2-3}
+export interface User {
+ userId: string;
+ displayName: string;
+}
+```
- Generate WebSocket clients from your AsyncAPI specs.
+Generate WebSocket clients from your AsyncAPI specs.
@@ -423,122 +445,6 @@ 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
+