@postman/sdk-config 0.0.0 → 0.0.2
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 +136 -6
- package/dist/index.cjs +879 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +833 -0
- package/dist/index.js.map +1 -0
- package/dist/sdk-config-ir/index.cjs +879 -0
- package/dist/sdk-config-ir/index.cjs.map +1 -0
- package/dist/sdk-config-ir/index.d.cts +2 -0
- package/dist/sdk-config-ir/index.d.ts +2 -0
- package/dist/sdk-config-ir/index.js +833 -0
- package/dist/sdk-config-ir/index.js.map +1 -0
- package/dist/sdk-config-ir/v1/index.cjs +879 -0
- package/dist/sdk-config-ir/v1/index.cjs.map +1 -0
- package/dist/sdk-config-ir/v1/index.d.cts +2458 -0
- package/dist/sdk-config-ir/v1/index.d.ts +2458 -0
- package/dist/sdk-config-ir/v1/index.js +833 -0
- package/dist/sdk-config-ir/v1/index.js.map +1 -0
- package/docs/migration.md +32 -0
- package/package.json +66 -4
- package/src/sdk-config-ir/v1/README.md +328 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# SDK Config IR v1
|
|
2
|
+
|
|
3
|
+
`SdkConfigIrV1` is the normalized contract consumed by SDK generation. It replaces two legacy
|
|
4
|
+
configuration surfaces: sdk-gen-core `BuildParameters` and a selected Fern generator invocation.
|
|
5
|
+
It is intentionally smaller than the union of both legacy schemas.
|
|
6
|
+
|
|
7
|
+
The contract lives in `@postman/sdk-config` so sdk-gen-core, sdk-gen-api, Fern CLI, and other
|
|
8
|
+
producers can share the same runtime schema and inferred TypeScript types. The schema, types,
|
|
9
|
+
tests, documentation, and JSON fixtures are versioned together.
|
|
10
|
+
|
|
11
|
+
`tests/fixtures/sdk-config-ir/v1` is the canonical source for package-level contract fixtures.
|
|
12
|
+
|
|
13
|
+
## Core request envelope
|
|
14
|
+
|
|
15
|
+
New producers send the transport discriminator alongside the existing artifact metadata:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
type SdkGenerationRequest =
|
|
19
|
+
| {
|
|
20
|
+
artifactId: number;
|
|
21
|
+
bucketName: string;
|
|
22
|
+
kind: 'legacyBuildParameters';
|
|
23
|
+
inputParams: BuildParameters;
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
artifactId: number;
|
|
27
|
+
bucketName: string;
|
|
28
|
+
kind: 'sdkConfigIr';
|
|
29
|
+
sdkConfigIr: SdkConfigIrV1;
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The existing `{ artifactId, bucketName, inputParams }` production message remains valid and is
|
|
34
|
+
normalized internally to `legacyBuildParameters`. An explicit `kind` is required for new envelope
|
|
35
|
+
messages. Valid IR requests route only to the IR bridge and never fall through to legacy generation.
|
|
36
|
+
|
|
37
|
+
## Authority and compatibility
|
|
38
|
+
|
|
39
|
+
- Normalized fields are authoritative. Generation must never read `compatibility.legacyInput` to
|
|
40
|
+
fill a missing normalized field or change behavior.
|
|
41
|
+
- `compatibility.legacyInput` temporarily retains the original `BuildParameters` or selected Fern
|
|
42
|
+
generator invocation for migration debugging.
|
|
43
|
+
- `compatibility.unsupportedFields` records legacy options that were not translated.
|
|
44
|
+
- `compatibility.outputProfile` preserves converged, Postman-legacy, or Fern-legacy output defaults
|
|
45
|
+
without introducing a permanent target flavor.
|
|
46
|
+
- `target.sourceOrigin` identifies where a request originated; it does not select output behavior.
|
|
47
|
+
- Credentials are references to externally managed secrets. Tokens and passwords do not belong in
|
|
48
|
+
normalized output or publication configuration.
|
|
49
|
+
|
|
50
|
+
## Configuration design rules
|
|
51
|
+
|
|
52
|
+
- Each behavior has one canonical home regardless of its legacy origin or language spelling.
|
|
53
|
+
- Package and publication identity belongs in `package`; publication mechanics belong in
|
|
54
|
+
`output.publish`.
|
|
55
|
+
- Shared client behavior belongs in `client`; shared generator behavior belongs in `generation`.
|
|
56
|
+
- `generation.language` contains only behavior that remains language-specific after normalization.
|
|
57
|
+
- A simple on/off option is a boolean. A feature with additional settings is an object containing a
|
|
58
|
+
required `enabled` boolean so settings can be added without changing its shape.
|
|
59
|
+
- User-defined maps are permitted only when their values have a stable schema. The temporary
|
|
60
|
+
`legacyInput.value` JSON object is the deliberate migration exception.
|
|
61
|
+
|
|
62
|
+
Examples of the boolean rule:
|
|
63
|
+
|
|
64
|
+
- Boolean: `generation.webSockets`, `generation.multipleResponses`.
|
|
65
|
+
- Configurable feature: `client.retry`, `client.tokenRefresh`, `docs.snippets`,
|
|
66
|
+
`generation.analytics`, `generation.hooks`, `generation.streams`, and `generation.wireTests`.
|
|
67
|
+
|
|
68
|
+
## Cross-origin deduplication decisions
|
|
69
|
+
|
|
70
|
+
The audit compared sdk-gen-core inputs, Fern generator schemas, and 61 customer Fern projects.
|
|
71
|
+
Legacy aliases below intentionally converge on one normalized behavior.
|
|
72
|
+
|
|
73
|
+
| Behavior | Postman input | Fern input | Canonical field |
|
|
74
|
+
| ------------------------ | ------------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
75
|
+
| Response validation | language `validateResponses` | `skipResponseValidation`, `skip_validation` | `client.responseValidation` (Fern values are inverted) |
|
|
76
|
+
| Request parameter shape | generator defaults | `inline_request_params` | `client.requestParameterStyle` |
|
|
77
|
+
| Path parameter shape | generator defaults | importer and generator `inlinePathParameters` aliases | `client.pathParameterStyle` |
|
|
78
|
+
| File property shape | generator defaults | `inlineFileProperties` aliases | `client.filePropertyStyle` |
|
|
79
|
+
| Enum representation | TypeScript `generateEnumAs` | `enum_type` and forward-compatible enum aliases | `generation.serialization.enumRepresentation` |
|
|
80
|
+
| Additional properties | generator defaults | Python/Pydantic `extra_fields` aliases | `generation.serialization.additionalProperties` |
|
|
81
|
+
| Inline models | generator defaults | `enableInlineTypes` and language aliases | `generation.serialization.inlineTypes` |
|
|
82
|
+
| Client/error/pager names | `sdkName` plus generator conventions | language-specific class-name aliases | `target.sdkName` and `generation.naming` |
|
|
83
|
+
| Package namespace | npm organization and generator conventions | namespace, package-prefix, and root-namespace aliases | `package.namespace` |
|
|
84
|
+
| Package identity | per-language package IDs | registry output and package-name aliases | `package.packageName`, `moduleName`, `modulePath`, `groupId`, or `artifactId` |
|
|
85
|
+
| Extra dependencies | language `hookDependencies` and package metadata | dependency and dev-dependency aliases | `package.extraDependencies`, `extraDevDependencies`, or `extraPeerDependencies` |
|
|
86
|
+
| Constructor parameters | language `additionalConstructorParameters` / `additionalVariables` | generator-specific constructor options | `client.additionalConstructorParameters` |
|
|
87
|
+
| Repository delivery | `deliveryMethods`, `githubRepoName`, `githubRef`, `privateRepo` | GitHub output owner/repository settings | `output.delivery` and `output.github` |
|
|
88
|
+
| Registry publication | per-language package identity plus publishing settings | registry output settings | `package` identity plus `output.publish` mechanics |
|
|
89
|
+
|
|
90
|
+
Fields are not duplicated under `generation.language` when a shared row above can represent them.
|
|
91
|
+
Translators are responsible for alias resolution, unit conversion, and inverted legacy booleans.
|
|
92
|
+
|
|
93
|
+
## Source and target boundaries
|
|
94
|
+
|
|
95
|
+
- `source.specs` is the only source shape. One spec is a one-element array.
|
|
96
|
+
- Spec order is authoritative for multi-spec builds. Optional IDs must be unique; namespaces may
|
|
97
|
+
repeat. The combination layer must reject unresolved path and component collisions.
|
|
98
|
+
- Source formats are limited to formats sdk-gen-core can consume. Other Fern inputs must be lowered
|
|
99
|
+
before submission.
|
|
100
|
+
- A Kotlin target currently uses the Java/JVM generator with Kotlin-facing documentation, snippets,
|
|
101
|
+
and examples. Its retained JVM options share the Java implementation.
|
|
102
|
+
- `target.language` is the generator identity; `generatorName` is not normalized.
|
|
103
|
+
- `target.sdkVersion` and `target.generatorVersion` are the effective versions for
|
|
104
|
+
`target.language`. Producers resolve language-specific overrides before global values and emit
|
|
105
|
+
the result on each one-language IR request; version maps do not belong under
|
|
106
|
+
`generation.language`.
|
|
107
|
+
- `target.apiVersion` retains shared API version metadata on every emitted target.
|
|
108
|
+
- `target.generatorVersion` optionally pins one exact customer-facing generator version. Omission
|
|
109
|
+
remains distinct so the orchestrator can resolve the latest supported version.
|
|
110
|
+
- Fern provenance remains available in `compatibility.legacyInput` when needed for debugging.
|
|
111
|
+
|
|
112
|
+
## Postman `BuildParameters` migration map
|
|
113
|
+
|
|
114
|
+
| Legacy field | SDK Config IR v1 | Notes |
|
|
115
|
+
| ---------------------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
116
|
+
| `specUrl` | `source.specs[].specUrl` | A legacy request creates a one-element array. |
|
|
117
|
+
| `languages[]` | `target.language` | Translators emit one IR request per target. |
|
|
118
|
+
| `sdkName` | `target.sdkName` | Public SDK identity, not package registry identity. |
|
|
119
|
+
| `sdkVersion` / language `sdkVersion` | `target.sdkVersion` | Language override is resolved before emitting IR. |
|
|
120
|
+
| `apiVersion` | `target.apiVersion` | API version metadata. |
|
|
121
|
+
| `org` | `target.organization` | Source organization metadata. |
|
|
122
|
+
| `baseUrl` | `api.baseUrl` | Default API URL. |
|
|
123
|
+
| `environments` | `api.environments` | Every environment has a non-empty `urls` array; a single URL becomes one entry. |
|
|
124
|
+
| `environmentVariables` | `api.environmentVariables` | Declarations; auth/header fields reference them by name. |
|
|
125
|
+
| `auth` + `authentication` | `api.auth` | Legacy flags and settings become typed schemes and requirements. |
|
|
126
|
+
| `refreshToken` | `client.tokenRefresh` | Response keys map to `accessTokenField` and `refreshTokenField`. |
|
|
127
|
+
| `retry` | `client.retry` | Millisecond units are explicit in normalized names. |
|
|
128
|
+
| `responseHeaders` | `client.responseHeaders` | Shared across languages. |
|
|
129
|
+
| `multiTenant` | `client.multiTenant` | Shared client behavior. |
|
|
130
|
+
| TypeScript `httpClient` | `generation.language.typescript.httpClient` | Only `fetch` and `axios` are selectable; other languages use their generator transport. |
|
|
131
|
+
| `additionalConstructorParameters` | `client.additionalConstructorParameters` | Merged from language options. |
|
|
132
|
+
| `deliveryMethods` | `output.delivery` | Normalized to `files`, `zip`, or `github`; multiple deliveries produce separate IR requests. |
|
|
133
|
+
| `fileOutput` | `output.path` or `output.fileName` | Depends on delivery type. |
|
|
134
|
+
| `githubRef` | `output.github.branch` | Only meaningful for GitHub delivery. |
|
|
135
|
+
| `privateRepo` | `output.github.privateRepository` | Only meaningful for GitHub delivery. |
|
|
136
|
+
| `publishing.githubOrg` | `output.github.repository` | Translator combines the organization and repository name. |
|
|
137
|
+
| package names and IDs | `package` | Includes npm/PyPI/NuGet/RubyGems/Crates/Composer names and Maven IDs. |
|
|
138
|
+
| `goModuleName` | `package.modulePath` | Go publication and import identity. |
|
|
139
|
+
| `license`, `authors`, `developers`, `homepage` | `package` | Manifest metadata. |
|
|
140
|
+
| `documentation.url` | `docs.referenceBaseUrl` | Base URL for generated reference-file links. |
|
|
141
|
+
| `documentation.snippets` | `docs.snippets` | `enabled` is explicit when the object is present. |
|
|
142
|
+
| `docs[]` | `docs` | Legacy API/snippet selections are lowered to typed documentation settings. |
|
|
143
|
+
| `includeWatermark` | `generation.includeWatermark` | Simple on/off behavior. |
|
|
144
|
+
| `includeOptionalSnippetParameters` | `generation.includeOptionalSnippetParameters` | Simple on/off behavior. |
|
|
145
|
+
| `inferServiceNames` | `generation.inferServiceNames` | Simple on/off behavior. |
|
|
146
|
+
| `buildAllModels` | `generation.buildAllModels` | Simple on/off behavior. |
|
|
147
|
+
| `deprecatedOperations.include` | `generation.includeDeprecatedOperations` | Simplified to a boolean. |
|
|
148
|
+
| `multipleResponses.enabled` | `generation.multipleResponses` | Simplified to a boolean. |
|
|
149
|
+
| `devContainer` | `generation.devContainer` | Simple on/off behavior. |
|
|
150
|
+
| `ignoreFiles` / language `ignore` | `generation.ignoreFiles` | Language aliases are resolved by the translator. |
|
|
151
|
+
| `reservedKeywords` | `generation.reservedKeywords` | Shared generator input. |
|
|
152
|
+
| `hooks`, `hookDependencies`, `hooksLocation` | `generation.hooks` | Location and dependencies are one configurable feature. |
|
|
153
|
+
| `customCode*`, previous artifact location | `generation.customCode` | Locations become typed generation assets. |
|
|
154
|
+
| `workflow` | `generation.workflows[]` | The normalized shape supports more than one workflow. |
|
|
155
|
+
| `customQueries` | `generation.customQueryPaths` | Query definitions are represented as paths. |
|
|
156
|
+
| `analytics` | `generation.analytics` | `enabled` is explicit; timing fields use milliseconds. |
|
|
157
|
+
| language options | `generation.language.<target>` or shared fields | Package, naming, validation, and dependency aliases are lifted out first. |
|
|
158
|
+
|
|
159
|
+
### Postman language-option migration map
|
|
160
|
+
|
|
161
|
+
| Legacy field | SDK Config IR v1 |
|
|
162
|
+
| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
163
|
+
| common `sdkVersion` | `target.sdkVersion` |
|
|
164
|
+
| common `ignore` | `generation.ignoreFiles` |
|
|
165
|
+
| common `githubRepoName` / `targetBranch` | `output.github.repository` / `output.github.branch` |
|
|
166
|
+
| common `hookDependencies` | `generation.hooks.dependencies` |
|
|
167
|
+
| `additionalConstructorParameters` / `additionalVariables` | `client.additionalConstructorParameters` |
|
|
168
|
+
| TypeScript `npmOrg` / `npmName` | `package.namespace` / `package.packageName` |
|
|
169
|
+
| TypeScript `httpClient` | `generation.language.typescript.httpClient` |
|
|
170
|
+
| TypeScript `generateEnumAs` | `generation.serialization.enumRepresentation` |
|
|
171
|
+
| TypeScript versions, compiler options, bundle, default export, naming strategy, scripts | `generation.language.typescript` |
|
|
172
|
+
| Python `pypiPackageName`, classifiers, and project URLs | `package.packageName`, `classifiers`, and `projectUrls` |
|
|
173
|
+
| Python Pydantic version and optional initialization | `generation.language.python` |
|
|
174
|
+
| Java/Kotlin `groupId` / `artifactId` | `package.groupId` / `package.artifactId` |
|
|
175
|
+
| Java/Kotlin `includeKotlinSnippets` | `generation.language.java.includeKotlinSnippets` |
|
|
176
|
+
| Java/Go/C#/Rust `validateResponses` | `client.responseValidation` |
|
|
177
|
+
| Go/CLI `goModuleName` | `package.modulePath` |
|
|
178
|
+
| C# `packageId` / `useOptionalWrapper` | `package.packageName` / `generation.language.csharp.useOptionalWrapper` |
|
|
179
|
+
| PHP `packageName` / `allowMockClient` | `package.packageName` / `generation.allowMockClient` |
|
|
180
|
+
| Rust package name and repository | `package.packageName` / `package.repository` |
|
|
181
|
+
| Swift `allowMockClient` | `generation.allowMockClient` |
|
|
182
|
+
| CLI pagination parameters / skills object | `generation.language.cli.paginationParameters` / `skills` boolean |
|
|
183
|
+
| language authors, developers, homepage, and repository | `package` metadata |
|
|
184
|
+
|
|
185
|
+
`usesFormData` is derived from the API and is not configuration. The legacy `ai` flag,
|
|
186
|
+
`generateMCP`, MCP language options, Terraform-provider options and plan modifiers, and Bash output
|
|
187
|
+
are outside the SDK Config IR v1 target set and must be reported as unsupported. Commented-out
|
|
188
|
+
custom-template and naming inputs were not restored as part of the normalized contract.
|
|
189
|
+
|
|
190
|
+
## Fern common migration map
|
|
191
|
+
|
|
192
|
+
Customer-use counts below are distinct projects observed in the 61-project configuration snapshot
|
|
193
|
+
audited on 2026-07-17. Counts guide the initial contract; they are not a permanent support policy.
|
|
194
|
+
|
|
195
|
+
| Fern field or aliases | SDK Config IR v1 | Observed projects |
|
|
196
|
+
| --------------------------------------------------------------------------- | -------------------------------------------------- | -----------------------------------------: |
|
|
197
|
+
| `api.specs[]` | `source.specs[]` | 53 OpenAPI, 3 AsyncAPI |
|
|
198
|
+
| `api.specs[].namespace` | `source.specs[].namespace` | 1 |
|
|
199
|
+
| `api.specs[].overlays` | `source.specs[].overlays` | 2 |
|
|
200
|
+
| `api.specs[].overrides` | `source.specs[].overrides` | 39 |
|
|
201
|
+
| `api.default-url` | `api.baseUrl` | 21 |
|
|
202
|
+
| `api.default-environment` | `api.defaultEnvironment` | 22 |
|
|
203
|
+
| `api.environments` | `api.environments` | 20+ |
|
|
204
|
+
| `api.auth`, `api.auth-schemes` | `api.auth` | 27 |
|
|
205
|
+
| `api.headers` | `api.headers` | 11+ |
|
|
206
|
+
| generator `inlinePathParameters`, `inline-path-parameters`, and API setting | `client.pathParameterStyle` | 12 API; 1-3 per language |
|
|
207
|
+
| generator `inlineFileProperties`, `inline-file-properties` | `client.filePropertyStyle` | 1-3 per language |
|
|
208
|
+
| `inline_request_params` | `client.requestParameterStyle` | 6 Python |
|
|
209
|
+
| `customPagerName`, `custom-pager-name`, `custom_pager_name` | `generation.naming.pagerName` | 2-5 per language |
|
|
210
|
+
| timeout aliases in seconds or milliseconds | `client.timeoutMs` | Translator converts units. |
|
|
211
|
+
| `skipResponseValidation`, Python `skip_validation` | `client.responseValidation` | Inverted; 12 TS, 8 Python |
|
|
212
|
+
| `useDefaultRequestParameterValues` aliases | `client.useDefaultRequestParameterValues` | 1 |
|
|
213
|
+
| `enable-wire-tests`, `enableWireTests`, `generateWireTests` | `generation.wireTests` | 1-15 per language |
|
|
214
|
+
| WebSocket generation aliases | `generation.webSockets` | 3 TS, 3 Python |
|
|
215
|
+
| `streamType`, `fileResponseType` | `generation.streams` | 1 TS |
|
|
216
|
+
| client/exported/environment class aliases | `generation.naming` | 1-28 per language |
|
|
217
|
+
| base API/general exception class aliases | `generation.naming.apiErrorName` / `baseErrorName` | 3-6 Java/C# |
|
|
218
|
+
| namespace/package-prefix aliases | `package.namespace` | 1-30 per language |
|
|
219
|
+
| output registry package names | `package.packageName` | 5-28 per registry language |
|
|
220
|
+
| Python custom `package_name` | `package.moduleName` | 18 |
|
|
221
|
+
| Go `module.path` | `package.modulePath` | 3 |
|
|
222
|
+
| Maven `group` / `artifact` | `package.groupId` / `artifactId` | 7 |
|
|
223
|
+
| custom/extra dependencies | `package.extraDependencies` and related lists | Multiple languages |
|
|
224
|
+
| local output | `output.delivery: "files"` | 49+ |
|
|
225
|
+
| registry output | `output.publish` plus `package` identity | 5-28 per registry language |
|
|
226
|
+
| GitHub output | `output.delivery: "github"` and `output.github` | Translator resolves Fern owner/repo forms. |
|
|
227
|
+
| Fern README config | `docs.readme` | 12 API names; 11 disabled-section configs |
|
|
228
|
+
| `includeApiReference` | `docs.includeApiReference` | 10 TS |
|
|
229
|
+
|
|
230
|
+
The Rust language config was added after the initial audit. That audit compared existing Fern
|
|
231
|
+
_customer projects_, which surfaced no Rust-specific options; comparing the Fern Rust generator's
|
|
232
|
+
own schema later surfaced four with no shared equivalent — `dateTimeType` (`DateTime<FixedOffset>`
|
|
233
|
+
versus `DateTime<Utc>` on every datetime field), `capitalizeInitialisms`, `features`, and
|
|
234
|
+
`defaultFeatures`. Crate identity, client name, and package metadata deliberately stay on the
|
|
235
|
+
shared fields.
|
|
236
|
+
|
|
237
|
+
Fern README endpoint strings such as `GET /users` are parsed into
|
|
238
|
+
`{ "method": "GET", "path": "/users" }`; the legacy string shorthand is not part of the
|
|
239
|
+
normalized contract.
|
|
240
|
+
|
|
241
|
+
### Retained Fern API-import settings
|
|
242
|
+
|
|
243
|
+
These settings remain under `source.apiImportSettings` because they affect spec conversion rather
|
|
244
|
+
than generated-language presentation.
|
|
245
|
+
|
|
246
|
+
| Fern setting | Normalized field | Observed projects |
|
|
247
|
+
| ----------------------------------------- | ------------------------------------ | ----------------: |
|
|
248
|
+
| `respect-nullable-schemas` | `respectNullableSchemas` | 10 |
|
|
249
|
+
| `title-as-schema-name` | `titleAsSchemaName` | 16 |
|
|
250
|
+
| `coerce-enums-to-literals` | `coerceEnumsToLiterals` | 14 |
|
|
251
|
+
| `idiomatic-request-names` | `idiomaticRequestNames` | 12 |
|
|
252
|
+
| `wrap-references-to-nullable-in-optional` | `wrapReferencesToNullableInOptional` | 9 |
|
|
253
|
+
| `coerce-optional-schemas-to-nullable` | `coerceOptionalSchemasToNullable` | 9 |
|
|
254
|
+
| `object-query-parameters` | `objectQueryParameters` | 9 |
|
|
255
|
+
| `only-include-referenced-schemas` | `onlyIncludeReferencedSchemas` | 4 |
|
|
256
|
+
| `group-multi-api-environments` | `groupMultiApiEnvironments` | 2 |
|
|
257
|
+
| `path-parameter-order` | `pathParameterOrder` | 2 |
|
|
258
|
+
| `type-dates-as-strings` | `typeDatesAsStrings` | 12 |
|
|
259
|
+
|
|
260
|
+
## Fern language-specific migration map
|
|
261
|
+
|
|
262
|
+
Only options that remain language-specific stay in `generation.language`.
|
|
263
|
+
|
|
264
|
+
| Language | Fern fields retained in language config | Shared mappings lifted out |
|
|
265
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
266
|
+
| TypeScript | `packageManager` (1), `testFramework` (2), `allowCustomFetcher` (13), branded aliases (1), legacy exports (1), `useBigInt`, and positive `serdeLayer` from `noSerdeLayer` (8) | Namespace, validation, inline types, dependencies, wire tests, streams, WebSockets, pager/client names |
|
|
267
|
+
| Python | Python/Pydantic versions, client filenames (13), Pydantic compatibility, frozen models (1), required optionals (2), union naming (1), field aliases (3), always-initialize optionals, TypedDict requests (3) | Package/module names, enum form, extra fields, response validation, request style, dependencies, timeout, layout, wire tests, WebSockets |
|
|
268
|
+
| Java/Kotlin | Package layout (3), local dates (2), optional-nullable collapse (2), and Gradle settings (7) | Maven identity, namespace, names, forward-compatible enums, inline properties, dependencies, pager, wire tests |
|
|
269
|
+
| Go | Legacy complex models, union version (3), and legacy client options (1) | Module/package identity, client name, inline properties, pager, wire tests |
|
|
270
|
+
| C# | Optional wrapper, simplified dictionaries (1), explicit namespaces (7), core namespace behavior (1), exception handler (5) | NuGet identity, namespace, class/error names, pager, wire tests |
|
|
271
|
+
| PHP | Property access (2) and generated client interfaces (1) | Composer identity, namespace, client/pager names, request style, dependencies, wire tests |
|
|
272
|
+
| Ruby | Require paths (2) | Gem identity, client name, dependencies, pager, wire tests |
|
|
273
|
+
| Rust | Datetime representation, initialism casing, and Cargo features/default-features | Crate identity, client name, and package metadata use shared fields. |
|
|
274
|
+
| Swift | No retained language-specific options | Shared generation behavior is sufficient for observed configs. |
|
|
275
|
+
| CLI | Pagination parameter names and the `skills` boolean | Go module and package identity use `package`. |
|
|
276
|
+
|
|
277
|
+
## Removed and deferred legacy configuration
|
|
278
|
+
|
|
279
|
+
Removed fields are not copied into another open-ended normalized bag. Translators report them in
|
|
280
|
+
`compatibility.unsupportedFields`; their original value remains available in `legacyInput` during
|
|
281
|
+
the migration.
|
|
282
|
+
|
|
283
|
+
### Removed after finding no customer use and no sdk-gen-core equivalent
|
|
284
|
+
|
|
285
|
+
- Common Fern generation: include/omit platform-header overrides. Output-profile defaults own this
|
|
286
|
+
compatibility behavior instead of a second permanent switch.
|
|
287
|
+
- Source import: optional-additional-properties defaults, environment grouping strategies,
|
|
288
|
+
discriminant removal, schema-collision recovery, forward-compatible inference, default
|
|
289
|
+
environment inference, const coercion, endpoint filters, example-depth controls, alias
|
|
290
|
+
resolution, single-schema oneOf preservation, readonly/read variants, binary-response import
|
|
291
|
+
coercion, form encoding defaults, additional-properties defaults, inline-allOf, default integer
|
|
292
|
+
formats, discriminated-union inference, request-name disambiguation, and AsyncAPI message naming.
|
|
293
|
+
- TypeScript: linter/formatter selection, consolidated type files, subpackage exports, and endpoint
|
|
294
|
+
metadata.
|
|
295
|
+
- Python: ORM/smart-union/coercion/wrapped-alias/positional-constructor/inheritance/validator
|
|
296
|
+
switches, flattened union bodies, stream chunk size, recursion limit, lazy imports, and custom
|
|
297
|
+
transport.
|
|
298
|
+
- Java/JVM: JSON include, required-builder checks, public/extensible constructors, unknown-as-node,
|
|
299
|
+
nullable annotations, and custom interceptors.
|
|
300
|
+
- C#: union implementation switches, root-client access, generated error-type toggle, interceptor
|
|
301
|
+
class, unified options, response-body redaction, solution format, and custom output paths.
|
|
302
|
+
- Go: toolchain version, import aliases, custom constructor name, error-code layout, empty wrapper,
|
|
303
|
+
byte reader, getter, union-base deduplication, and root-request export switches.
|
|
304
|
+
- Ruby: custom client module and RuboCop switches.
|
|
305
|
+
- Rust and Swift: all previously proposed language-specific switches had no observed customer use.
|
|
306
|
+
|
|
307
|
+
### Observed but deliberately deferred as bespoke or low-use
|
|
308
|
+
|
|
309
|
+
| Legacy configuration | Observed projects | Reason |
|
|
310
|
+
| ----------------------------------------------------------- | ----------------: | ------------------------------------------------------------------------ |
|
|
311
|
+
| TypeScript arbitrary `packageJson` exports/scripts | 2 | Open-ended manifest rewriting conflicts with the typed package contract. |
|
|
312
|
+
| TypeScript `outputEsm`, fetch runtime, form-data runtime | 1-2 | Runtime-specific and not required by sdk-gen-core today. |
|
|
313
|
+
| Python additional `__init__` exports / excluded exports | 3 / 6 | File-layout customization with significant generator coupling. |
|
|
314
|
+
| Python improved imports and file-upload-only TypedDict mode | 1-3 | Experimental or narrow compatibility behavior. |
|
|
315
|
+
| Java custom Gradle plugins / include-wrapper | 1 | Arbitrary build-file injection or one-customer behavior. |
|
|
316
|
+
| C# experimental fully qualified/version namespaces | 1 | Experimental one-customer behavior. |
|
|
317
|
+
| PHP arbitrary Composer autoload files | 2 | Open-ended manifest rewriting; typed dependencies remain supported. |
|
|
318
|
+
| Ruby flattened module structure | 1 | One-customer layout behavior. |
|
|
319
|
+
|
|
320
|
+
Adding one of these fields later is additive. Retaining every historical generator flag now would
|
|
321
|
+
make v1 expensive to implement and would turn temporary compatibility behavior into a permanent
|
|
322
|
+
shared contract.
|
|
323
|
+
|
|
324
|
+
## Tests and fixtures
|
|
325
|
+
|
|
326
|
+
The contract tests are grouped by root contract, source, output/publication, and normalization.
|
|
327
|
+
Valid single- and multi-spec inputs are JSON fixtures so future consumers can reuse the same
|
|
328
|
+
language-neutral examples. Invalid cases remain next to their expected validation errors.
|