Skip to content

Commit 9f6d043

Browse files
devin-ai-integration[bot]cdonel707devalog
authored
Add Fern SDKs vs OpenAPI Generator comparison page (#2869)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Chris McDonnell <[email protected]> Co-authored-by: Devin Logan <[email protected]>
1 parent 1ce9388 commit 9f6d043

File tree

2 files changed

+264
-0
lines changed

2 files changed

+264
-0
lines changed
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
---
2+
title: Fern vs. OpenAPI Generator
3+
description: A detailed comparison of Fern-generated SDKs versus OpenAPI Generator SDKs
4+
---
5+
6+
Fern generates production-ready SDKs with built-in OAuth token refresh, pagination, retries, typed errors, and comprehensive documentation. OpenAPI Generator produces basic API wrappers that require implementing these features yourself.
7+
8+
| Capability | Fern | OpenAPI Generator |
9+
|------------|------|-------------------|
10+
| **Documentation** | Comprehensive README + endpoint docs | Minimal (title only) |
11+
| **Authentication** | Automatic OAuth token refresh | Manual token management |
12+
| **Pagination** | Async iterators with `for await` | Manual cursor handling |
13+
| **Error handling** | Typed error classes per status code | Generic `ResponseError` |
14+
| **Resilience** | Built-in retries, timeouts, abort signals | None (requires custom code) |
15+
16+
## Documentation and onboarding
17+
18+
Fern SDKs include comprehensive documentation covering installation, authentication, types, errors, pagination, and retries. OpenAPI Generator provides minimal documentation.
19+
20+
| Feature | Fern | OpenAPI Generator |
21+
|---------|------|-------------------|
22+
| **README** | Comprehensive guide covering installation, auth, types, errors, pagination, retries, timeouts, logging, and runtime compatibility | Minimal (often just a title) |
23+
| **Endpoint documentation** | Generated `reference.md` with usage examples for every endpoint | None |
24+
| **Code examples** | Inline examples in method documentation | None |
25+
26+
## Client ergonomics
27+
28+
Fern provides a single unified client with namespaced resources. OpenAPI Generator uses separate API classes per resource.
29+
30+
| Feature | Fern | OpenAPI Generator |
31+
|---------|------|-------------------|
32+
| **Client structure** | Single unified client with namespaced resources | Separate API classes per resource |
33+
| **Method naming** | Clean, idiomatic names (`client.plant.add()`) | Verbose names (`plantApi.addPlant()`) |
34+
| **Configuration** | Centralized in client constructor | Passed to each API class |
35+
36+
<Accordion title="Code examples">
37+
<br/>
38+
39+
```typescript Fern
40+
const client = new PlantStoreClient({ clientId, clientSecret });
41+
await client.plant.add({ name: "Fern", status: "available" });
42+
await client.user.login();
43+
```
44+
45+
```typescript OpenAPI Generator
46+
const config = new Configuration({ accessToken: async () => token });
47+
const plantApi = new PlantApi(config);
48+
const userApi = new UserApi(config);
49+
await plantApi.addPlant({ plant: { name: "Fern", status: "available" } });
50+
await userApi.loginUser({ username, password });
51+
```
52+
53+
</Accordion>
54+
55+
## Authentication and token lifecycle
56+
57+
Fern includes a built-in OAuth token provider that automatically retrieves and refreshes tokens with a configurable buffer before expiration. OpenAPI Generator requires manual token management.
58+
59+
| Feature | Fern | OpenAPI Generator |
60+
|---------|------|-------------------|
61+
| **OAuth token refresh** | Automatic with `OAuthTokenProvider` | Manual implementation required |
62+
| **Token expiration handling** | Built-in buffer before expiration | Developer responsibility |
63+
| **Environment variables** | Automatic fallback to env vars | Manual configuration |
64+
65+
## Pagination
66+
67+
Fern provides async iterators for pagination with `for await` support. OpenAPI Generator returns raw responses with manual cursor tracking.
68+
69+
| Feature | Fern | OpenAPI Generator |
70+
|---------|------|-------------------|
71+
| **Async iterators** | Built-in `for await` support | None |
72+
| **Page navigation** | `hasNextPage()` / `getNextPage()` methods | Manual cursor tracking |
73+
| **Underlying response** | Accessible via `page.response` | Direct return value |
74+
75+
<Accordion title="Code examples">
76+
<br/>
77+
78+
```typescript Fern
79+
const pageableResponse = await client.plant.list();
80+
for await (const item of pageableResponse) {
81+
console.log(item);
82+
}
83+
84+
// Or manually iterate pages
85+
let page = await client.plant.list();
86+
while (page.hasNextPage()) {
87+
page = await page.getNextPage();
88+
}
89+
```
90+
91+
```typescript OpenAPI Generator
92+
let cursor: string | undefined;
93+
do {
94+
const response = await plantApi.listPlants({ cursor });
95+
for (const plant of response.plants) {
96+
console.log(plant);
97+
}
98+
cursor = response.pagination?.nextCursor;
99+
} while (cursor);
100+
```
101+
102+
</Accordion>
103+
104+
## Error handling
105+
106+
Fern generates typed error classes for specific HTTP status codes. OpenAPI Generator uses a generic `ResponseError` class.
107+
108+
| Feature | Fern | OpenAPI Generator |
109+
|---------|------|-------------------|
110+
| **Typed errors** | `BadRequestError`, `NotFoundError`, `MethodNotAllowedError` | Generic `ResponseError` |
111+
| **Error body** | Parsed and typed | Requires manual parsing |
112+
| **Raw response access** | `err.rawResponse` | `err.response` |
113+
114+
<Accordion title="Code examples">
115+
<br/>
116+
117+
```typescript Fern
118+
try {
119+
await client.plant.add({ name: "Fern", status: "available" });
120+
} catch (err) {
121+
if (err instanceof PlantStore.BadRequestError) {
122+
console.log("Invalid request:", err.body);
123+
} else if (err instanceof PlantStore.NotFoundError) {
124+
console.log("Plant not found");
125+
} else if (err instanceof PlantStoreError) {
126+
console.log("Status:", err.statusCode, "Body:", err.body);
127+
}
128+
}
129+
```
130+
131+
```typescript OpenAPI Generator
132+
try {
133+
await plantApi.addPlant({ plant });
134+
} catch (err) {
135+
if (err instanceof ResponseError) {
136+
const body = await err.response.json();
137+
if (err.response.status === 400) {
138+
console.log("Invalid request:", body);
139+
} else if (err.response.status === 404) {
140+
console.log("Plant not found");
141+
}
142+
}
143+
}
144+
```
145+
146+
</Accordion>
147+
148+
## Resilience features
149+
150+
Fern includes automatic retries with exponential backoff, configurable timeouts, and request cancellation. OpenAPI Generator requires custom implementation of these features.
151+
152+
| Feature | Fern | OpenAPI Generator |
153+
|---------|------|-------------------|
154+
| **Automatic retries** | Exponential backoff with jitter for 408, 429, 5xx | None |
155+
| **Retry-After header** | Automatically respected | Manual implementation |
156+
| **Configurable timeouts** | `timeoutInSeconds` option (default 60s) | None |
157+
| **Request cancellation** | `abortSignal` option | Possible via `initOverrides` |
158+
| **Max retries** | Configurable per-request or globally | None |
159+
160+
<Accordion title="Code examples">
161+
<br/>
162+
163+
```typescript Fern
164+
const response = await client.plant.add(
165+
{ name: "Fern", status: "available" },
166+
{
167+
maxRetries: 3,
168+
timeoutInSeconds: 30,
169+
abortSignal: controller.signal
170+
}
171+
);
172+
```
173+
174+
</Accordion>
175+
176+
## Logging and observability
177+
178+
Fern includes configurable logging with automatic redaction of auth headers, tokens, and API keys. OpenAPI Generator has no built-in logging.
179+
180+
| Feature | Fern | OpenAPI Generator |
181+
|---------|------|-------------------|
182+
| **Built-in logging** | Configurable levels (Debug/Info/Warn/Error) | None |
183+
| **Custom loggers** | Pluggable (winston, pino, etc.) | None |
184+
| **Sensitive data redaction** | Automatic for auth headers, tokens, API keys | None |
185+
| **Request/response logging** | Debug-level with redacted URLs | Manual implementation |
186+
187+
<Accordion title="Code examples">
188+
<br/>
189+
190+
```typescript Fern
191+
const client = new PlantStoreClient({
192+
clientId,
193+
clientSecret,
194+
logging: {
195+
level: logging.LogLevel.Debug,
196+
logger: new logging.ConsoleLogger(),
197+
silent: false
198+
}
199+
});
200+
```
201+
202+
</Accordion>
203+
204+
## Raw response access
205+
206+
Fern provides a `.withRawResponse()` method for accessing HTTP response details. OpenAPI Generator uses separate `*Raw()` methods.
207+
208+
| Feature | Fern | OpenAPI Generator |
209+
|---------|------|-------------------|
210+
| **Access pattern** | Single method with `.withRawResponse()` | Separate `*Raw()` methods |
211+
| **Headers access** | `rawResponse.headers` | `response.raw.headers` |
212+
| **Response body** | `data` property | `value()` method |
213+
214+
<Accordion title="Code examples">
215+
<br/>
216+
217+
```typescript Fern
218+
const { data, rawResponse } = await client.plant.add({
219+
name: "Fern",
220+
status: "available"
221+
}).withRawResponse();
222+
223+
console.log(rawResponse.headers);
224+
```
225+
226+
```typescript OpenAPI Generator
227+
const response = await plantApi.addPlantRaw({ plant });
228+
const data = await response.value();
229+
console.log(response.raw.headers);
230+
```
231+
232+
</Accordion>
233+
234+
## Runtime compatibility and packaging
235+
236+
Fern supports multiple JavaScript runtimes with ESM/CJS dual builds and automatic runtime detection. OpenAPI Generator provides ESM/CJS support.
237+
238+
| Feature | Fern | OpenAPI Generator |
239+
|---------|------|-------------------|
240+
| **Node.js** | 18+ | Supported |
241+
| **Deno** | v1.25+ | Not supported |
242+
| **Bun** | 1.0+ | Not supported |
243+
| **Cloudflare Workers** | Supported | Not supported |
244+
| **React Native** | Supported | Not supported |
245+
| **ESM/CJS builds** | Dual builds with proper exports | Basic ESM/CJS |
246+
| **Subpackage exports** | Tree-shakeable imports | None |
247+
| **Runtime detection** | Automatic | None |
248+
249+
## Testing and quality
250+
251+
Fern SDKs include unit and wire tests with linting enabled. OpenAPI Generator doesn't include tests.
252+
253+
| Feature | Fern | OpenAPI Generator |
254+
|---------|------|-------------------|
255+
| **Unit tests** | Yes | None |
256+
| **Wire tests** | Yes | None |
257+
| **Linting** | Biome (enabled) | Disabled (`/* eslint-disable */`) |
258+
| **Zero dependencies** | Yes | Yes |

fern/products/sdks/sdks.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,9 @@ navigation:
266266
- page: generators.yml
267267
path: ./reference/generators-yml-reference.mdx
268268
slug: generators-yml
269+
- section: Resources
270+
hidden: true
271+
contents:
272+
- page: Fern vs. OpenAPI Generator
273+
path: ./resources/fern-vs-openapi-generator.mdx
274+
slug: openapi-generator

0 commit comments

Comments
 (0)