@fern-api/generator-migrations 0.0.1
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.
- package/README.md +352 -0
- package/lib/generators/typescript/migrations/1.0.0.d.ts +152 -0
- package/lib/generators/typescript/migrations/1.0.0.d.ts.map +1 -0
- package/lib/generators/typescript/migrations/1.0.0.js +166 -0
- package/lib/generators/typescript/migrations/1.0.0.js.map +1 -0
- package/lib/generators/typescript/migrations/2.0.0.d.ts +153 -0
- package/lib/generators/typescript/migrations/2.0.0.d.ts.map +1 -0
- package/lib/generators/typescript/migrations/2.0.0.js +163 -0
- package/lib/generators/typescript/migrations/2.0.0.js.map +1 -0
- package/lib/generators/typescript/migrations/3.0.0.d.ts +242 -0
- package/lib/generators/typescript/migrations/3.0.0.d.ts.map +1 -0
- package/lib/generators/typescript/migrations/3.0.0.js +250 -0
- package/lib/generators/typescript/migrations/3.0.0.js.map +1 -0
- package/lib/generators/typescript/migrations/index.d.ts +18 -0
- package/lib/generators/typescript/migrations/index.d.ts.map +1 -0
- package/lib/generators/typescript/migrations/index.js +22 -0
- package/lib/generators/typescript/migrations/index.js.map +1 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +24 -0
- package/lib/index.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# @fern-api/generator-migrations
|
|
2
|
+
|
|
3
|
+
Unified migration package for all Fern generator configurations.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package contains migrations for all Fern generators, organized by generator name. When users run `fern generator upgrade`, the CLI automatically downloads this package and applies relevant migrations to transform their `generators.yml` configuration.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
### Single Unified Package
|
|
12
|
+
|
|
13
|
+
All generator migrations are consolidated into one npm package:
|
|
14
|
+
- **Simpler maintenance**: One package to version and publish
|
|
15
|
+
- **Easier discovery**: Single source of truth for all migrations
|
|
16
|
+
- **Better for monorepo**: Fits naturally into the Fern monorepo structure
|
|
17
|
+
- **Consistent versioning**: All generators migrate together
|
|
18
|
+
|
|
19
|
+
### Migration Index
|
|
20
|
+
|
|
21
|
+
Migrations are exported as a record mapping full generator names to migration modules:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
export const migrations: Record<string, MigrationModule> = {
|
|
25
|
+
"fernapi/fern-typescript": typescriptSdkMigrations,
|
|
26
|
+
"fernapi/fern-typescript-sdk": typescriptSdkMigrations,
|
|
27
|
+
"fernapi/fern-typescript-node-sdk": typescriptSdkMigrations,
|
|
28
|
+
"fernapi/fern-typescript-browser-sdk": typescriptSdkMigrations
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
This package is consumed by the Fern CLI during generator upgrades. Users don't interact with it directly.
|
|
35
|
+
|
|
36
|
+
The CLI:
|
|
37
|
+
1. Detects a generator version change
|
|
38
|
+
2. Downloads `@fern-api/generator-migrations@latest`
|
|
39
|
+
3. Looks up migrations by generator name
|
|
40
|
+
4. Filters migrations by version range
|
|
41
|
+
5. Applies migrations sequentially
|
|
42
|
+
6. Writes the transformed config back to `generators.yml`
|
|
43
|
+
|
|
44
|
+
## Publishing
|
|
45
|
+
|
|
46
|
+
This package must be published to npm for the CLI to use it. The CLI dynamically installs `@fern-api/generator-migrations@latest` at runtime.
|
|
47
|
+
|
|
48
|
+
### When to Publish
|
|
49
|
+
|
|
50
|
+
Publish a new version when:
|
|
51
|
+
1. Adding migrations for a new generator
|
|
52
|
+
2. Adding new migration versions to existing generators
|
|
53
|
+
3. Fixing bugs in existing migrations
|
|
54
|
+
|
|
55
|
+
### Publishing Steps
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# 1. Update version in package.json
|
|
59
|
+
# Follow semver: patch for bug fixes, minor for new migrations, major for breaking changes
|
|
60
|
+
|
|
61
|
+
# 2. Build the package
|
|
62
|
+
pnpm --filter @fern-api/generator-migrations compile
|
|
63
|
+
|
|
64
|
+
# 3. Test locally (optional but recommended)
|
|
65
|
+
cd packages/generator-migrations
|
|
66
|
+
npm link
|
|
67
|
+
mkdir -p ~/.fern/migration-cache
|
|
68
|
+
cd ~/.fern/migration-cache
|
|
69
|
+
npm link @fern-api/generator-migrations
|
|
70
|
+
|
|
71
|
+
# 4. Run tests
|
|
72
|
+
pnpm --filter @fern-api/generator-migrations test
|
|
73
|
+
|
|
74
|
+
# 5. Publish to npm
|
|
75
|
+
cd packages/generator-migrations
|
|
76
|
+
npm publish --access public
|
|
77
|
+
|
|
78
|
+
# 6. Clean up local link (if used)
|
|
79
|
+
cd ~/.fern/migration-cache
|
|
80
|
+
npm unlink --no-save @fern-api/generator-migrations
|
|
81
|
+
cd packages/generator-migrations
|
|
82
|
+
npm unlink
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Version Strategy
|
|
86
|
+
|
|
87
|
+
- **Patch** (0.1.0 → 0.1.1): Bug fixes in existing migrations
|
|
88
|
+
- **Minor** (0.1.0 → 0.2.0): New migration versions added, new generators added
|
|
89
|
+
- **Major** (0.1.0 → 1.0.0): Breaking changes to migration API
|
|
90
|
+
|
|
91
|
+
The package version is independent of generator versions. It simply needs to increment when the package changes.
|
|
92
|
+
|
|
93
|
+
## Supported Generators
|
|
94
|
+
|
|
95
|
+
### TypeScript SDK
|
|
96
|
+
- `fernapi/fern-typescript`
|
|
97
|
+
- `fernapi/fern-typescript-sdk`
|
|
98
|
+
- `fernapi/fern-typescript-node-sdk`
|
|
99
|
+
- `fernapi/fern-typescript-browser-sdk`
|
|
100
|
+
|
|
101
|
+
All TypeScript SDK variants share the same migrations.
|
|
102
|
+
|
|
103
|
+
## Adding Migrations for New Generators
|
|
104
|
+
|
|
105
|
+
### 1. Create Migration Directory
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
mkdir -p src/generators/{language}/migrations
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2. Create Migration Files
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// src/generators/{language}/migrations/1.0.0.ts
|
|
115
|
+
import type { Migration } from "@fern-api/migrations-base";
|
|
116
|
+
import { migrateConfig } from "@fern-api/migrations-base";
|
|
117
|
+
|
|
118
|
+
export const migration_1_0_0: Migration = {
|
|
119
|
+
version: "1.0.0",
|
|
120
|
+
|
|
121
|
+
migrateGeneratorConfig: ({ config }) =>
|
|
122
|
+
migrateConfig(config, (draft) => {
|
|
123
|
+
// Set old defaults for backwards compatibility
|
|
124
|
+
draft.oldField ??= "old-default";
|
|
125
|
+
}),
|
|
126
|
+
|
|
127
|
+
migrateGeneratorsYml: ({ document }) => document
|
|
128
|
+
};
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 3. Create Migration Index
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// src/generators/{language}/migrations/index.ts
|
|
135
|
+
import type { MigrationModule } from "@fern-api/migrations-base";
|
|
136
|
+
import { migration_1_0_0 } from "./1.0.0.js";
|
|
137
|
+
|
|
138
|
+
const migrationModule: MigrationModule = {
|
|
139
|
+
migrations: [migration_1_0_0]
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export default migrationModule;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 4. Register in Main Index
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// src/index.ts
|
|
149
|
+
import languageMigrations from "./generators/{language}/migrations/index.js";
|
|
150
|
+
|
|
151
|
+
export const migrations: Record<string, MigrationModule> = {
|
|
152
|
+
// ... existing migrations
|
|
153
|
+
"fernapi/fern-{language}-sdk": languageMigrations
|
|
154
|
+
};
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 5. Add Tests
|
|
158
|
+
|
|
159
|
+
Create tests following the structure in `src/__test__/README.md`.
|
|
160
|
+
|
|
161
|
+
### 6. Compile and Publish
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
pnpm compile
|
|
165
|
+
npm publish
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Migration Patterns
|
|
169
|
+
|
|
170
|
+
### Setting Defaults (Most Common)
|
|
171
|
+
|
|
172
|
+
Use the nullish coalescing assignment operator (`??=`) to set values only if undefined:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
migrateConfig(config, (draft) => {
|
|
176
|
+
draft.field1 ??= false;
|
|
177
|
+
draft.field2 ??= "default-value";
|
|
178
|
+
draft.field3 ??= true;
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Renaming Fields
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
migrateConfig(config, (draft) => {
|
|
186
|
+
if (draft.oldFieldName !== undefined) {
|
|
187
|
+
draft.newFieldName = draft.oldFieldName;
|
|
188
|
+
delete draft.oldFieldName;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Removing Fields
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
migrateConfig(config, (draft) => {
|
|
197
|
+
delete draft.deprecatedField;
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Conditional Transformations
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
migrateConfig(config, (draft) => {
|
|
205
|
+
if (draft.oldFormat === "legacy") {
|
|
206
|
+
draft.newFormat = { type: "modern", legacy: true };
|
|
207
|
+
delete draft.oldFormat;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Testing
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Run all tests
|
|
216
|
+
pnpm test
|
|
217
|
+
|
|
218
|
+
# Run tests in watch mode
|
|
219
|
+
pnpm test --watch
|
|
220
|
+
|
|
221
|
+
# Update snapshots
|
|
222
|
+
pnpm test:update
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
See [src/__test__/README.md](src/__test__/README.md) for detailed testing documentation.
|
|
226
|
+
|
|
227
|
+
## Development
|
|
228
|
+
|
|
229
|
+
### Prerequisites
|
|
230
|
+
|
|
231
|
+
This package depends on:
|
|
232
|
+
- `@fern-api/migrations-base` - Core migration types and utilities
|
|
233
|
+
|
|
234
|
+
### Building
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Compile TypeScript
|
|
238
|
+
pnpm compile
|
|
239
|
+
|
|
240
|
+
# Compile with source maps for debugging
|
|
241
|
+
pnpm compile:debug
|
|
242
|
+
|
|
243
|
+
# Clean build artifacts
|
|
244
|
+
pnpm clean
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Publishing
|
|
248
|
+
|
|
249
|
+
This package is automatically published when referenced in the Fern CLI's version configuration.
|
|
250
|
+
|
|
251
|
+
## Migration Best Practices
|
|
252
|
+
|
|
253
|
+
### 1. Pure Functions
|
|
254
|
+
Always return new objects, never mutate input:
|
|
255
|
+
```typescript
|
|
256
|
+
// ✅ Good - uses migrateConfig helper
|
|
257
|
+
migrateConfig(config, (draft) => {
|
|
258
|
+
draft.field = "value";
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// ❌ Bad - mutates input
|
|
262
|
+
config.config.field = "value";
|
|
263
|
+
return config;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 2. Idempotent
|
|
267
|
+
Migrations should be safe to run multiple times:
|
|
268
|
+
```typescript
|
|
269
|
+
// ✅ Good - only sets if undefined
|
|
270
|
+
draft.field ??= "default";
|
|
271
|
+
|
|
272
|
+
// ❌ Bad - overwrites existing values
|
|
273
|
+
draft.field = "default";
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 3. Defensive Coding
|
|
277
|
+
Don't assume fields exist:
|
|
278
|
+
```typescript
|
|
279
|
+
// ✅ Good - checks before accessing
|
|
280
|
+
if (draft.nested?.field) {
|
|
281
|
+
draft.nested.field = transform(draft.nested.field);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// ❌ Bad - may throw if nested is undefined
|
|
285
|
+
draft.nested.field = transform(draft.nested.field);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 4. Preserve Unknown Fields
|
|
289
|
+
Use spread operators and Immer's draft pattern:
|
|
290
|
+
```typescript
|
|
291
|
+
// ✅ Good - Immer preserves unknown fields automatically
|
|
292
|
+
migrateConfig(config, (draft) => {
|
|
293
|
+
draft.knownField = "value";
|
|
294
|
+
// unknownField is automatically preserved
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 5. Document Intent
|
|
299
|
+
Explain why migrations are needed:
|
|
300
|
+
```typescript
|
|
301
|
+
/**
|
|
302
|
+
* Migration for version 2.0.0
|
|
303
|
+
*
|
|
304
|
+
* This release changed the default for `streamType` from "wrapper" to "web"
|
|
305
|
+
* to enable zero-dependency SDKs. For users upgrading from pre-2.0.0,
|
|
306
|
+
* we explicitly set the old default to maintain backwards compatibility.
|
|
307
|
+
*
|
|
308
|
+
* Changed defaults:
|
|
309
|
+
* - streamType: "wrapper" → "web"
|
|
310
|
+
*/
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 6. Version Alignment
|
|
314
|
+
Migration version should match the generator version it upgrades TO:
|
|
315
|
+
```typescript
|
|
316
|
+
// ✅ Good - migration upgrades TO 2.0.0
|
|
317
|
+
export const migration_2_0_0: Migration = {
|
|
318
|
+
version: "2.0.0",
|
|
319
|
+
// ...
|
|
320
|
+
};
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### 7. Test Thoroughly
|
|
324
|
+
Write tests for:
|
|
325
|
+
- Setting defaults
|
|
326
|
+
- Preserving explicit values
|
|
327
|
+
- Preserving unknown fields
|
|
328
|
+
- Edge cases (null, undefined, invalid types)
|
|
329
|
+
- Sequential application
|
|
330
|
+
- Immutability
|
|
331
|
+
|
|
332
|
+
## Related Documentation
|
|
333
|
+
|
|
334
|
+
- [CLI Migration System](../cli/cli/src/commands/upgrade/migrations/README.md)
|
|
335
|
+
- [migrations-base Package](../migrations-base/README.md)
|
|
336
|
+
- [TypeScript SDK Migrations Example](src/generators/typescript/migrations/)
|
|
337
|
+
- [Test Documentation](src/__test__/README.md)
|
|
338
|
+
|
|
339
|
+
## Contributing
|
|
340
|
+
|
|
341
|
+
When adding new migrations:
|
|
342
|
+
|
|
343
|
+
1. Create migration files following the patterns above
|
|
344
|
+
2. Write comprehensive tests
|
|
345
|
+
3. Document what changed and why
|
|
346
|
+
4. Ensure migrations are idempotent and pure
|
|
347
|
+
5. Test with real generator upgrades locally
|
|
348
|
+
6. Update this README if adding a new generator
|
|
349
|
+
|
|
350
|
+
## License
|
|
351
|
+
|
|
352
|
+
MIT
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Migration } from "@fern-api/migrations-base";
|
|
2
|
+
/**
|
|
3
|
+
* Migration for version 1.0.0
|
|
4
|
+
*
|
|
5
|
+
* ## Context
|
|
6
|
+
*
|
|
7
|
+
* Version 1.0.0 introduced new defaults to improve the developer experience and modernize
|
|
8
|
+
* the generated SDK. These changes make the SDK more ergonomic and reduce boilerplate,
|
|
9
|
+
* but could break existing code that relied on the old defaults.
|
|
10
|
+
*
|
|
11
|
+
* To ensure backwards compatibility during upgrades, this migration explicitly sets the
|
|
12
|
+
* old defaults for users upgrading from pre-1.0.0 versions. This allows their existing
|
|
13
|
+
* code to continue working without changes.
|
|
14
|
+
*
|
|
15
|
+
* ## Changed Defaults
|
|
16
|
+
*
|
|
17
|
+
* | Field | Old Default (pre-1.0.0) | New Default (1.0.0+) | Impact |
|
|
18
|
+
* |-------|-------------------------|----------------------|--------|
|
|
19
|
+
* | `inlineFileProperties` | `false` | `true` | File upload properties are now inlined into request types |
|
|
20
|
+
* | `inlinePathParameters` | `false` | `true` | Path parameters are now inlined into method signatures |
|
|
21
|
+
* | `enableInlineTypes` | `false` | `true` | Type definitions are inlined where beneficial |
|
|
22
|
+
* | `noSerdeLayer` | `false` | `true` | Serialization/deserialization layer is removed for simpler types |
|
|
23
|
+
* | `omitUndefined` | `false` | `true` | Undefined values are omitted from JSON output |
|
|
24
|
+
* | `skipResponseValidation` | `false` | `true` | Response validation is skipped for better performance |
|
|
25
|
+
* | `useLegacyExports` | `true` | `false` | Modern ESM exports are used instead of legacy CommonJS |
|
|
26
|
+
*
|
|
27
|
+
* ## Migration Strategy
|
|
28
|
+
*
|
|
29
|
+
* This migration uses the nullish coalescing assignment operator (`??=`) to only set
|
|
30
|
+
* values that are explicitly undefined. This means:
|
|
31
|
+
* - ✅ If a user has explicitly configured a field (even to the new default), that value is preserved
|
|
32
|
+
* - ✅ If a field is undefined, the old default is set for backwards compatibility
|
|
33
|
+
* - ✅ Unknown/custom fields are preserved
|
|
34
|
+
*
|
|
35
|
+
* ## Examples
|
|
36
|
+
*
|
|
37
|
+
* ### Example 1: Empty Config (Migration Applied)
|
|
38
|
+
*
|
|
39
|
+
* **Before Migration (0.9.0 → 1.0.0):**
|
|
40
|
+
* ```yaml
|
|
41
|
+
* generators:
|
|
42
|
+
* - name: fernapi/fern-typescript-sdk
|
|
43
|
+
* version: 0.9.0
|
|
44
|
+
* config: {}
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* **After Migration:**
|
|
48
|
+
* ```yaml
|
|
49
|
+
* generators:
|
|
50
|
+
* - name: fernapi/fern-typescript-sdk
|
|
51
|
+
* version: 1.0.0
|
|
52
|
+
* config:
|
|
53
|
+
* inlineFileProperties: false # Set by migration
|
|
54
|
+
* inlinePathParameters: false # Set by migration
|
|
55
|
+
* enableInlineTypes: false # Set by migration
|
|
56
|
+
* noSerdeLayer: false # Set by migration
|
|
57
|
+
* omitUndefined: false # Set by migration
|
|
58
|
+
* skipResponseValidation: false # Set by migration
|
|
59
|
+
* useLegacyExports: true # Set by migration
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* **Result:** SDK behavior remains unchanged, existing code continues to work.
|
|
63
|
+
*
|
|
64
|
+
* ### Example 2: Partially Configured (Selective Migration)
|
|
65
|
+
*
|
|
66
|
+
* **Before Migration:**
|
|
67
|
+
* ```yaml
|
|
68
|
+
* generators:
|
|
69
|
+
* - name: fernapi/fern-typescript-sdk
|
|
70
|
+
* version: 0.9.0
|
|
71
|
+
* config:
|
|
72
|
+
* inlineFileProperties: true # User explicitly wants new behavior
|
|
73
|
+
* packageName: "@acme/sdk"
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* **After Migration:**
|
|
77
|
+
* ```yaml
|
|
78
|
+
* generators:
|
|
79
|
+
* - name: fernapi/fern-typescript-sdk
|
|
80
|
+
* version: 1.0.0
|
|
81
|
+
* config:
|
|
82
|
+
* inlineFileProperties: true # Preserved (explicitly set)
|
|
83
|
+
* packageName: "@acme/sdk" # Preserved (custom field)
|
|
84
|
+
* inlinePathParameters: false # Set by migration
|
|
85
|
+
* enableInlineTypes: false # Set by migration
|
|
86
|
+
* noSerdeLayer: false # Set by migration
|
|
87
|
+
* omitUndefined: false # Set by migration
|
|
88
|
+
* skipResponseValidation: false # Set by migration
|
|
89
|
+
* useLegacyExports: true # Set by migration
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* **Result:** User's explicit choice is honored, other fields get old defaults.
|
|
93
|
+
*
|
|
94
|
+
* ### Example 3: Fully Configured (No Migration Needed)
|
|
95
|
+
*
|
|
96
|
+
* **Before Migration:**
|
|
97
|
+
* ```yaml
|
|
98
|
+
* generators:
|
|
99
|
+
* - name: fernapi/fern-typescript-sdk
|
|
100
|
+
* version: 0.9.0
|
|
101
|
+
* config:
|
|
102
|
+
* inlineFileProperties: true
|
|
103
|
+
* inlinePathParameters: true
|
|
104
|
+
* enableInlineTypes: true
|
|
105
|
+
* noSerdeLayer: true
|
|
106
|
+
* omitUndefined: true
|
|
107
|
+
* skipResponseValidation: true
|
|
108
|
+
* useLegacyExports: false
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* **After Migration:**
|
|
112
|
+
* ```yaml
|
|
113
|
+
* # No changes - all fields explicitly configured
|
|
114
|
+
* generators:
|
|
115
|
+
* - name: fernapi/fern-typescript-sdk
|
|
116
|
+
* version: 1.0.0
|
|
117
|
+
* config:
|
|
118
|
+
* inlineFileProperties: true
|
|
119
|
+
* inlinePathParameters: true
|
|
120
|
+
* enableInlineTypes: true
|
|
121
|
+
* noSerdeLayer: true
|
|
122
|
+
* omitUndefined: true
|
|
123
|
+
* skipResponseValidation: true
|
|
124
|
+
* useLegacyExports: false
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* **Result:** User gets the new defaults they explicitly configured.
|
|
128
|
+
*
|
|
129
|
+
* ## Why These Defaults Changed
|
|
130
|
+
*
|
|
131
|
+
* - **Inline properties/parameters**: Reduces type nesting and improves IDE autocomplete
|
|
132
|
+
* - **No serde layer**: Simplifies generated code and improves runtime performance
|
|
133
|
+
* - **Omit undefined**: Produces cleaner JSON payloads and matches JavaScript conventions
|
|
134
|
+
* - **Skip validation**: Improves performance by trusting the API contract
|
|
135
|
+
* - **Modern exports**: Better tree-shaking and compatibility with modern bundlers
|
|
136
|
+
*
|
|
137
|
+
* ## When to Opt Into New Defaults
|
|
138
|
+
*
|
|
139
|
+
* After upgrading and verifying your code works, consider removing the old defaults
|
|
140
|
+
* to adopt the new behavior:
|
|
141
|
+
*
|
|
142
|
+
* ```yaml
|
|
143
|
+
* generators:
|
|
144
|
+
* - name: fernapi/fern-typescript-sdk
|
|
145
|
+
* version: 1.0.0
|
|
146
|
+
* config: {} # Remove all fields to use new defaults
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* Test your code thoroughly before making this change.
|
|
150
|
+
*/
|
|
151
|
+
export declare const migration_1_0_0: Migration;
|
|
152
|
+
//# sourceMappingURL=1.0.0.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"1.0.0.d.ts","sourceRoot":"","sources":["../../../../src/generators/typescript/migrations/1.0.0.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAG3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoJG;AACH,eAAO,MAAM,eAAe,EAAE,SAiB7B,CAAC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { migrateConfig } from "@fern-api/migrations-base";
|
|
2
|
+
/**
|
|
3
|
+
* Migration for version 1.0.0
|
|
4
|
+
*
|
|
5
|
+
* ## Context
|
|
6
|
+
*
|
|
7
|
+
* Version 1.0.0 introduced new defaults to improve the developer experience and modernize
|
|
8
|
+
* the generated SDK. These changes make the SDK more ergonomic and reduce boilerplate,
|
|
9
|
+
* but could break existing code that relied on the old defaults.
|
|
10
|
+
*
|
|
11
|
+
* To ensure backwards compatibility during upgrades, this migration explicitly sets the
|
|
12
|
+
* old defaults for users upgrading from pre-1.0.0 versions. This allows their existing
|
|
13
|
+
* code to continue working without changes.
|
|
14
|
+
*
|
|
15
|
+
* ## Changed Defaults
|
|
16
|
+
*
|
|
17
|
+
* | Field | Old Default (pre-1.0.0) | New Default (1.0.0+) | Impact |
|
|
18
|
+
* |-------|-------------------------|----------------------|--------|
|
|
19
|
+
* | `inlineFileProperties` | `false` | `true` | File upload properties are now inlined into request types |
|
|
20
|
+
* | `inlinePathParameters` | `false` | `true` | Path parameters are now inlined into method signatures |
|
|
21
|
+
* | `enableInlineTypes` | `false` | `true` | Type definitions are inlined where beneficial |
|
|
22
|
+
* | `noSerdeLayer` | `false` | `true` | Serialization/deserialization layer is removed for simpler types |
|
|
23
|
+
* | `omitUndefined` | `false` | `true` | Undefined values are omitted from JSON output |
|
|
24
|
+
* | `skipResponseValidation` | `false` | `true` | Response validation is skipped for better performance |
|
|
25
|
+
* | `useLegacyExports` | `true` | `false` | Modern ESM exports are used instead of legacy CommonJS |
|
|
26
|
+
*
|
|
27
|
+
* ## Migration Strategy
|
|
28
|
+
*
|
|
29
|
+
* This migration uses the nullish coalescing assignment operator (`??=`) to only set
|
|
30
|
+
* values that are explicitly undefined. This means:
|
|
31
|
+
* - ✅ If a user has explicitly configured a field (even to the new default), that value is preserved
|
|
32
|
+
* - ✅ If a field is undefined, the old default is set for backwards compatibility
|
|
33
|
+
* - ✅ Unknown/custom fields are preserved
|
|
34
|
+
*
|
|
35
|
+
* ## Examples
|
|
36
|
+
*
|
|
37
|
+
* ### Example 1: Empty Config (Migration Applied)
|
|
38
|
+
*
|
|
39
|
+
* **Before Migration (0.9.0 → 1.0.0):**
|
|
40
|
+
* ```yaml
|
|
41
|
+
* generators:
|
|
42
|
+
* - name: fernapi/fern-typescript-sdk
|
|
43
|
+
* version: 0.9.0
|
|
44
|
+
* config: {}
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* **After Migration:**
|
|
48
|
+
* ```yaml
|
|
49
|
+
* generators:
|
|
50
|
+
* - name: fernapi/fern-typescript-sdk
|
|
51
|
+
* version: 1.0.0
|
|
52
|
+
* config:
|
|
53
|
+
* inlineFileProperties: false # Set by migration
|
|
54
|
+
* inlinePathParameters: false # Set by migration
|
|
55
|
+
* enableInlineTypes: false # Set by migration
|
|
56
|
+
* noSerdeLayer: false # Set by migration
|
|
57
|
+
* omitUndefined: false # Set by migration
|
|
58
|
+
* skipResponseValidation: false # Set by migration
|
|
59
|
+
* useLegacyExports: true # Set by migration
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* **Result:** SDK behavior remains unchanged, existing code continues to work.
|
|
63
|
+
*
|
|
64
|
+
* ### Example 2: Partially Configured (Selective Migration)
|
|
65
|
+
*
|
|
66
|
+
* **Before Migration:**
|
|
67
|
+
* ```yaml
|
|
68
|
+
* generators:
|
|
69
|
+
* - name: fernapi/fern-typescript-sdk
|
|
70
|
+
* version: 0.9.0
|
|
71
|
+
* config:
|
|
72
|
+
* inlineFileProperties: true # User explicitly wants new behavior
|
|
73
|
+
* packageName: "@acme/sdk"
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* **After Migration:**
|
|
77
|
+
* ```yaml
|
|
78
|
+
* generators:
|
|
79
|
+
* - name: fernapi/fern-typescript-sdk
|
|
80
|
+
* version: 1.0.0
|
|
81
|
+
* config:
|
|
82
|
+
* inlineFileProperties: true # Preserved (explicitly set)
|
|
83
|
+
* packageName: "@acme/sdk" # Preserved (custom field)
|
|
84
|
+
* inlinePathParameters: false # Set by migration
|
|
85
|
+
* enableInlineTypes: false # Set by migration
|
|
86
|
+
* noSerdeLayer: false # Set by migration
|
|
87
|
+
* omitUndefined: false # Set by migration
|
|
88
|
+
* skipResponseValidation: false # Set by migration
|
|
89
|
+
* useLegacyExports: true # Set by migration
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* **Result:** User's explicit choice is honored, other fields get old defaults.
|
|
93
|
+
*
|
|
94
|
+
* ### Example 3: Fully Configured (No Migration Needed)
|
|
95
|
+
*
|
|
96
|
+
* **Before Migration:**
|
|
97
|
+
* ```yaml
|
|
98
|
+
* generators:
|
|
99
|
+
* - name: fernapi/fern-typescript-sdk
|
|
100
|
+
* version: 0.9.0
|
|
101
|
+
* config:
|
|
102
|
+
* inlineFileProperties: true
|
|
103
|
+
* inlinePathParameters: true
|
|
104
|
+
* enableInlineTypes: true
|
|
105
|
+
* noSerdeLayer: true
|
|
106
|
+
* omitUndefined: true
|
|
107
|
+
* skipResponseValidation: true
|
|
108
|
+
* useLegacyExports: false
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* **After Migration:**
|
|
112
|
+
* ```yaml
|
|
113
|
+
* # No changes - all fields explicitly configured
|
|
114
|
+
* generators:
|
|
115
|
+
* - name: fernapi/fern-typescript-sdk
|
|
116
|
+
* version: 1.0.0
|
|
117
|
+
* config:
|
|
118
|
+
* inlineFileProperties: true
|
|
119
|
+
* inlinePathParameters: true
|
|
120
|
+
* enableInlineTypes: true
|
|
121
|
+
* noSerdeLayer: true
|
|
122
|
+
* omitUndefined: true
|
|
123
|
+
* skipResponseValidation: true
|
|
124
|
+
* useLegacyExports: false
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* **Result:** User gets the new defaults they explicitly configured.
|
|
128
|
+
*
|
|
129
|
+
* ## Why These Defaults Changed
|
|
130
|
+
*
|
|
131
|
+
* - **Inline properties/parameters**: Reduces type nesting and improves IDE autocomplete
|
|
132
|
+
* - **No serde layer**: Simplifies generated code and improves runtime performance
|
|
133
|
+
* - **Omit undefined**: Produces cleaner JSON payloads and matches JavaScript conventions
|
|
134
|
+
* - **Skip validation**: Improves performance by trusting the API contract
|
|
135
|
+
* - **Modern exports**: Better tree-shaking and compatibility with modern bundlers
|
|
136
|
+
*
|
|
137
|
+
* ## When to Opt Into New Defaults
|
|
138
|
+
*
|
|
139
|
+
* After upgrading and verifying your code works, consider removing the old defaults
|
|
140
|
+
* to adopt the new behavior:
|
|
141
|
+
*
|
|
142
|
+
* ```yaml
|
|
143
|
+
* generators:
|
|
144
|
+
* - name: fernapi/fern-typescript-sdk
|
|
145
|
+
* version: 1.0.0
|
|
146
|
+
* config: {} # Remove all fields to use new defaults
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* Test your code thoroughly before making this change.
|
|
150
|
+
*/
|
|
151
|
+
export const migration_1_0_0 = {
|
|
152
|
+
version: "1.0.0",
|
|
153
|
+
migrateGeneratorConfig: ({ config }) => migrateConfig(config, (draft) => {
|
|
154
|
+
// Only set old defaults if the fields are not already explicitly configured
|
|
155
|
+
// Using the nullish coalescing assignment operator (??=) to set only if undefined
|
|
156
|
+
draft.inlineFileProperties ??= false;
|
|
157
|
+
draft.inlinePathParameters ??= false;
|
|
158
|
+
draft.enableInlineTypes ??= false;
|
|
159
|
+
draft.noSerdeLayer ??= false;
|
|
160
|
+
draft.omitUndefined ??= false;
|
|
161
|
+
draft.skipResponseValidation ??= false;
|
|
162
|
+
draft.useLegacyExports ??= true;
|
|
163
|
+
}),
|
|
164
|
+
migrateGeneratorsYml: ({ document }) => document
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=1.0.0.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"1.0.0.js","sourceRoot":"","sources":["../../../../src/generators/typescript/migrations/1.0.0.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoJG;AACH,MAAM,CAAC,MAAM,eAAe,GAAc;IACtC,OAAO,EAAE,OAAO;IAEhB,sBAAsB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CACnC,aAAa,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QAC5B,4EAA4E;QAC5E,kFAAkF;QAClF,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAC;QACrC,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAC;QACrC,KAAK,CAAC,iBAAiB,KAAK,KAAK,CAAC;QAClC,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC;QAC7B,KAAK,CAAC,aAAa,KAAK,KAAK,CAAC;QAC9B,KAAK,CAAC,sBAAsB,KAAK,KAAK,CAAC;QACvC,KAAK,CAAC,gBAAgB,KAAK,IAAI,CAAC;IACpC,CAAC,CAAC;IAEN,oBAAoB,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ;CACnD,CAAC"}
|