@postman/sdk-config 0.1.1 → 0.3.0

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.
Files changed (37) hide show
  1. package/README.md +29 -12
  2. package/dist/index.cjs +352 -145
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +3 -3
  5. package/dist/index.d.ts +3 -3
  6. package/dist/index.js +345 -146
  7. package/dist/index.js.map +1 -1
  8. package/dist/sdk-config/index.cjs +281 -109
  9. package/dist/sdk-config/index.cjs.map +1 -1
  10. package/dist/sdk-config/index.d.cts +2 -2
  11. package/dist/sdk-config/index.d.ts +2 -2
  12. package/dist/sdk-config/index.js +276 -110
  13. package/dist/sdk-config/index.js.map +1 -1
  14. package/dist/sdk-config/v1/index.cjs +281 -109
  15. package/dist/sdk-config/v1/index.cjs.map +1 -1
  16. package/dist/sdk-config/v1/index.d.cts +6903 -289
  17. package/dist/sdk-config/v1/index.d.ts +6903 -289
  18. package/dist/sdk-config/v1/index.js +276 -110
  19. package/dist/sdk-config/v1/index.js.map +1 -1
  20. package/dist/sdk-config-ir/index.cjs +126 -30
  21. package/dist/sdk-config-ir/index.cjs.map +1 -1
  22. package/dist/sdk-config-ir/index.d.cts +2 -2
  23. package/dist/sdk-config-ir/index.d.ts +2 -2
  24. package/dist/sdk-config-ir/index.js +125 -31
  25. package/dist/sdk-config-ir/index.js.map +1 -1
  26. package/dist/sdk-config-ir/v1/index.cjs +126 -30
  27. package/dist/sdk-config-ir/v1/index.cjs.map +1 -1
  28. package/dist/sdk-config-ir/v1/index.d.cts +534 -15
  29. package/dist/sdk-config-ir/v1/index.d.ts +534 -15
  30. package/dist/sdk-config-ir/v1/index.js +125 -31
  31. package/dist/sdk-config-ir/v1/index.js.map +1 -1
  32. package/dist/{typescript-DK97815_.d.cts → typescript-DNqK3T3v.d.cts} +3 -0
  33. package/dist/{typescript-DK97815_.d.ts → typescript-DNqK3T3v.d.ts} +3 -0
  34. package/docs/releasing.md +114 -0
  35. package/package.json +1 -1
  36. package/src/sdk-config/v1/README.md +91 -23
  37. package/src/sdk-config-ir/v1/README.md +91 -83
@@ -4,11 +4,30 @@
4
4
  describes portable generation intent and uses the discriminator `schemaVersion: "sdk-config/v1"`.
5
5
 
6
6
  ```ts
7
- import { parseSdkConfigV1, type SdkConfigV1 } from '@postman/sdk-config/sdk-config/v1';
8
-
9
- const config: SdkConfigV1 = parseSdkConfigV1(untrustedInput);
7
+ import {
8
+ parseSdkConfigV1,
9
+ validateSdkConfigV1,
10
+ type SdkConfigV1,
11
+ type SdkConfigV1Document,
12
+ } from '@postman/sdk-config/sdk-config/v1';
13
+
14
+ // Validate a customer-authored document while preserving omitted properties.
15
+ const document: SdkConfigV1Document = validateSdkConfigV1(untrustedInput);
16
+
17
+ // Resolve domain defaults only when preparing a runtime configuration.
18
+ const resolved: SdkConfigV1 = parseSdkConfigV1(document);
10
19
  ```
11
20
 
21
+ `validateSdkConfigV1` is the correct boundary for persisted files, migration output, and request
22
+ transport. It validates the same schema as `parseSdkConfigV1` but returns the sparse authored
23
+ document, so omitted options remain omitted. `parseSdkConfigV1` is the runtime-resolution boundary:
24
+ it materializes shared domain defaults needed while expanding a target into `SdkConfigIrV1`.
25
+
26
+ This separation is intentional. A migration must not invent `sdkVersion`, `apiVersion`, or other
27
+ default-valued settings that were absent from the legacy Fern configuration. An explicit value—even
28
+ one equal to the current default—must remain distinguishable from omission so future default changes
29
+ do not silently alter customer intent.
30
+
12
31
  ### Convert a Fern generator group
13
32
 
14
33
  The Fern CLI can convert its resolved in-memory generator group without serializing or reparsing
@@ -20,6 +39,9 @@ import { mapFernConfigToSdkConfigV1 } from '@postman/sdk-config/sdk-config/v1';
20
39
 
21
40
  const { sdkConfig, unsupportedFields } = mapFernConfigToSdkConfigV1({
22
41
  apiName: definition.rootApiFile.contents.name,
42
+ source: {
43
+ specs: [{ id: 'payments', type: 'openapi', path: './openapi.yml' }],
44
+ },
23
45
  apiVersion: definition.specVersion,
24
46
  sdkVersion,
25
47
  group: {
@@ -35,28 +57,39 @@ representation are returned in `unsupportedFields`; each issue includes a code,
35
57
  severity, reason, suggested manual action, and the SDK Config destination when one exists.
36
58
  `FernConfigMappingError.issues` uses the same structure for missing information and other fatal
37
59
  cases. Generation must not recover omitted values from legacy configuration. Differing
38
- target-specific values for a shared SDK Config block are rejected because combining them would
39
- change behavior. Optional `api` enrichment may be supplied after Fern's definition or IR has already
40
- been lowered into the public API shape.
60
+ target-specific values are retained as sparse target overrides when the public shape can represent
61
+ them. Optional `api` enrichment may be supplied after Fern's definition or IR has already been
62
+ lowered into the public API shape. Credentials and signing material remain outside SDK Config; the
63
+ mapper reports one target-level diagnostic when a Fern output contains them without logging their
64
+ values.
41
65
 
42
66
  ## Contract boundaries
43
67
 
44
68
  `SdkConfigV1` is distinct from both existing configuration contracts:
45
69
 
46
- - `SdkConfigV1` is customer-facing, may contain multiple one-language targets, and does not select
47
- the API source. A client or sdk-gen-api supplies a collection ID, specification ID, or uploaded
48
- file separately.
70
+ - `SdkConfigV1` is customer-facing, may contain multiple one-language targets, and explicitly names
71
+ the local paths or HTTP(S) URLs of the API specifications it configures. A source may be one spec
72
+ or an ordered multi-spec set, with optional namespaces, overlays, overrides, and API import
73
+ settings.
49
74
  - `SdkConfigIrV1` is the normalized, single-target internal input consumed by sdk-gen-core. A server
50
- expands one `SdkConfigV1` into one IR document per target and supplies source and operational
51
- metadata.
75
+ expands one `SdkConfigV1` into one IR document per target, uploads the declared source files, and
76
+ replaces customer paths with internal `specUrl` values without changing the IR shape.
52
77
  - The legacy Postman configuration (`BuildParameters`) is an older producer-specific input. It is
53
78
  not accepted by `parseSdkConfigV1`; legacy translators normalize it independently.
54
79
 
55
- The public schema deliberately has no `source`, `compatibility`, source-origin, artifact ID, signed
56
- URL, S3 location, credential-resolution, or server-generated publishing control fields. Unknown
57
- fields are rejected at every object boundary. Portable API, client, documentation, package, and
58
- language field schemas come from a neutral shared domain layer to prevent drift; the public and
59
- internal envelopes and their operational extensions remain separate explicit allowlists.
80
+ Each public source contains exactly one customer-owned locator: `path` for a local file or `url` for
81
+ an HTTP(S) resource. A generation client must materialize the selected resource and upload the exact
82
+ bytes for the build; the server replaces the customer locator with an internal signed `specUrl` in
83
+ SDK Config IR. Customer URLs never become generator fetch URLs. Signed URLs, S3 locations, and
84
+ server-generated artifact metadata are not valid public locators. The public schema deliberately has
85
+ no `compatibility`, source-origin, artifact ID, credential-resolution, or server-generated
86
+ publishing control fields. Unknown fields are rejected at every object boundary. Portable API,
87
+ client, documentation, package, source settings, and language field schemas come from a neutral
88
+ shared domain layer to prevent drift; the public and internal envelopes and their operational
89
+ extensions remain separate explicit allowlists.
90
+
91
+ Source `path`, `overlays`, and `overrides` values must be relative paths without parent-directory
92
+ segments. Absolute paths and `..` traversal are rejected at validation time.
60
93
 
61
94
  ## Shape
62
95
 
@@ -65,17 +98,26 @@ internal envelopes and their operational extensions remain separate explicit all
65
98
  "schemaVersion": "sdk-config/v1",
66
99
  "sdkName": "Acme SDK",
67
100
  "sdkVersion": "1.0.0",
101
+ "source": {
102
+ "specs": [{ "id": "payments", "type": "openapi", "url": "https://example.com/openapi.yml" }]
103
+ },
68
104
  "api": {},
69
105
  "client": {},
70
106
  "package": { "description": "Acme API SDK" },
71
107
  "output": { "delivery": "zip" },
72
108
  "docs": {},
73
- "generation": { "includeWatermark": true },
109
+ "generation": {
110
+ "includeWatermark": true,
111
+ "naming": { "smartCasing": true, "smartCasingDigitWordBoundary": false }
112
+ },
74
113
  "targets": [
75
114
  {
76
115
  "language": "typescript",
77
116
  "package": { "packageName": "@acme/sdk" },
78
- "generation": { "packageManager": "pnpm" }
117
+ "generation": {
118
+ "packageManager": "pnpm",
119
+ "namespaceExportName": "AcmeSDK"
120
+ }
79
121
  },
80
122
  {
81
123
  "language": "python",
@@ -92,6 +134,20 @@ Each target has exactly one `language`. A language may occur only once, so both
92
134
  targets and differing targets that conflict on the same language are rejected. `generatorVersion`
93
135
  is an optional target-only exact semantic version.
94
136
 
137
+ Field placement follows ownership rather than whichever Fern generator happens to appear first:
138
+
139
+ - API configuration and API version are global.
140
+ - Client, documentation, and common generation settings are global when identical across every
141
+ target; differing values become sparse target overrides.
142
+ - Package identity, output delivery, publication, repositories, generator version, and
143
+ language-specific generation settings remain on their target.
144
+ - SDK name and version use a global baseline with optional target overrides.
145
+
146
+ The root `output` is therefore optional. It is useful as an explicitly authored baseline, but every
147
+ target must have an effective output either from that baseline or from its own `output` block. Fern
148
+ migration writes output directly on each target because repositories and publication registries are
149
+ properties of the generated language artifact.
150
+
95
151
  ## Supported languages
96
152
 
97
153
  SdkConfig v1 is language-agnostic across every sdk-gen-core target available when this contract was
@@ -99,7 +155,7 @@ defined. Each language has an explicitly allowlisted `generation` shape:
99
155
 
100
156
  | Language | `language` value | Representative target setting |
101
157
  | ---------- | ---------------- | ----------------------------- |
102
- | TypeScript | `typescript` | `packageManager` |
158
+ | TypeScript | `typescript` | `namespaceExportName` |
103
159
  | Python | `python` | `pythonVersion` |
104
160
  | Java | `java` | `includeKotlinSnippets` |
105
161
  | Kotlin | `kotlin` | `asyncStyle` |
@@ -122,14 +178,26 @@ When a server expands the public config into single-target IR documents, it appl
122
178
 
123
179
  | Configuration | Rule |
124
180
  | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
125
- | `api`, `client`, `docs` | Shared unchanged by every target; no target override exists. |
126
- | Root `generation` | Shared generation behavior for every target. |
127
- | Target `generation` | Language-specific settings for that target; it supplements the disjoint shared settings. |
181
+ | `api` | Shared unchanged by every target; no target override exists. |
182
+ | `client`, `docs` | Sparse target properties recursively override root properties; omitted properties inherit. Arrays replace. |
183
+ | Root `generation` | Shared generation behavior inherited by every target. |
184
+ | Target `generation` | Sparse common generation properties override root values; language-specific properties configure that target. |
128
185
  | `sdkName`, `sdkVersion` | A target value wins; otherwise the root value is inherited. |
129
186
  | `package` | Target properties override root properties; omitted properties inherit. Arrays replace rather than concatenate. |
130
- | `output` | A target block replaces the complete root output block; otherwise the root block is inherited. |
187
+ | `output` | An optional root baseline is inherited; a target block replaces it completely. Every target must resolve one. |
131
188
  | `apiVersion` | Shared unchanged by every target. |
132
189
 
190
+ Target `client`, `docs`, and common `generation` blocks are intentionally sparse. This allows one
191
+ multi-language document to retain a shared baseline while expressing a Fern setting that differs
192
+ between generators—for example, a Python-specific client name. Nested objects inherit recursively,
193
+ while an explicitly supplied array replaces the inherited array.
194
+
195
+ An integration may also supply operational values at generation time. Those request values take
196
+ precedence over the persisted SDK Config for fields the integration exposes, such as SDK name,
197
+ SDK version, API version, package settings, generator version, and output intent. The SDK Config
198
+ continues to provide every field that the request does not override. Schema/domain defaults are
199
+ applied only after this merge, when the single-target `SdkConfigIrV1` is parsed.
200
+
133
201
  Package publication requirements are validated after applying package and output precedence. For
134
202
  example, a TypeScript target publishing to npm may inherit a root `packageName`, while a Python
135
203
  target must replace an inherited npm output with a PyPI-compatible output.
@@ -112,50 +112,52 @@ Translators are responsible for alias resolution, unit conversion, and inverted
112
112
 
113
113
  ## Postman `BuildParameters` migration map
114
114
 
115
- | Legacy field | SDK Config IR v1 | Notes |
116
- | ---------------------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------- |
117
- | `specUrl` | `source.specs[].specUrl` | A legacy request creates a one-element array. |
118
- | `languages[]` | `target.language` | Translators emit one IR request per target. |
119
- | `sdkName` | `target.sdkName` | Public SDK identity, not package registry identity. |
120
- | `sdkVersion` / language `sdkVersion` | `target.sdkVersion` | Language override is resolved before emitting IR. |
121
- | `apiVersion` | `target.apiVersion` | API version metadata. |
122
- | `org` | `target.organization` | Source organization metadata. |
123
- | `baseUrl` | `api.baseUrl` | Default API URL. |
124
- | `environments` | `api.environments` | Every environment has a non-empty `urls` array; a single URL becomes one entry. |
125
- | `environmentVariables` | `api.environmentVariables` | Declarations; auth/header fields reference them by name. |
126
- | `auth` + `authentication` | `api.auth` | Legacy flags and settings become typed schemes and requirements. |
127
- | `refreshToken` | `client.tokenRefresh` | Response keys map to `accessTokenField` and `refreshTokenField`. |
128
- | `retry` | `client.retry` | Millisecond units are explicit in normalized names. |
129
- | `responseHeaders` | `client.responseHeaders` | Shared across languages. |
130
- | `multiTenant` | `client.multiTenant` | Shared client behavior. |
131
- | TypeScript `httpClient` | `generation.language.typescript.httpClient` | Only `fetch` and `axios` are selectable; other languages use their generator transport. |
132
- | `additionalConstructorParameters` | `client.additionalConstructorParameters` | Merged from language options. |
133
- | `deliveryMethods` | `output.delivery` | Normalized to `files`, `zip`, or `github`; multiple deliveries produce separate IR requests. |
134
- | `fileOutput` | `output.path` or `output.fileName` | Depends on delivery type. |
135
- | `githubRef` | `output.github.branch` | Only meaningful for GitHub delivery. |
136
- | `privateRepo` | `output.github.privateRepository` | Only meaningful for GitHub delivery. |
137
- | `publishing.githubOrg` | `output.github.repository` | Translator combines the organization and repository name. |
138
- | package names and IDs | `package` | Includes npm/PyPI/NuGet/RubyGems/Crates/Composer names and Maven IDs. |
139
- | `goModuleName` | `package.modulePath` | Go publication and import identity. |
140
- | `license`, `authors`, `developers`, `homepage` | `package` | Manifest metadata. |
141
- | `documentation.url` | `docs.referenceBaseUrl` | Base URL for generated reference-file links. |
142
- | `documentation.snippets` | `docs.snippets` | `enabled` is explicit when the object is present. |
143
- | `docs[]` | `docs` | Legacy API/snippet selections are lowered to typed documentation settings. |
144
- | `includeWatermark` | `generation.includeWatermark` | Simple on/off behavior. |
145
- | `includeOptionalSnippetParameters` | `generation.includeOptionalSnippetParameters` | Simple on/off behavior. |
146
- | `inferServiceNames` | `generation.inferServiceNames` | Simple on/off behavior. |
147
- | `buildAllModels` | `generation.buildAllModels` | Simple on/off behavior. |
148
- | `deprecatedOperations.include` | `generation.includeDeprecatedOperations` | Simplified to a boolean. |
149
- | `multipleResponses.enabled` | `generation.multipleResponses` | Simplified to a boolean. |
150
- | `devContainer` | `generation.devContainer` | Simple on/off behavior. |
151
- | `ignoreFiles` / language `ignore` | `generation.ignoreFiles` | Language aliases are resolved by the translator. |
152
- | `reservedKeywords` | `generation.reservedKeywords` | Shared generator input. |
153
- | `hooks`, `hookDependencies`, `hooksLocation` | `generation.hooks` | Location and dependencies are one configurable feature. |
154
- | `customCode*`, previous artifact location | `generation.customCode` | Locations become typed generation assets. |
155
- | `workflow` | `generation.workflows[]` | The normalized shape supports more than one workflow. |
156
- | `customQueries` | `generation.customQueryPaths` | Query definitions are represented as paths. |
157
- | `analytics` | `generation.analytics` | `enabled` is explicit; timing fields use milliseconds. |
158
- | language options | `generation.language.<target>` or shared fields | Package, naming, validation, and dependency aliases are lifted out first. |
115
+ | Legacy field | SDK Config IR v1 | Notes |
116
+ | ---------------------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
117
+ | `specUrl` | `source.specs[].specUrl` | A legacy request creates a one-element array. |
118
+ | `languages[]` | `target.language` | Translators emit one IR request per target. |
119
+ | `sdkName` | `target.sdkName` | Public SDK identity, not package registry identity. |
120
+ | `sdkVersion` / language `sdkVersion` | `target.sdkVersion` | Language override is resolved before emitting IR. |
121
+ | `apiVersion` | `target.apiVersion` | API version metadata. |
122
+ | `org` | `target.organization` | Source organization metadata. |
123
+ | `baseUrl` | `api.baseUrl` | Default API URL. |
124
+ | `environments` | `api.environments` | Every environment has a non-empty `urls` array; a single URL becomes one entry. |
125
+ | `environmentVariables` | `api.environmentVariables` | Declarations; auth/header fields reference them by name. |
126
+ | `auth` + `authentication` | `api.auth` | Legacy flags and settings become typed schemes and requirements. |
127
+ | `refreshToken` | `client.tokenRefresh` | Response keys map to `accessTokenField` and `refreshTokenField`. |
128
+ | `retry` | `client.retry` | Millisecond units are explicit in normalized names. |
129
+ | `responseHeaders` | `client.responseHeaders` | Shared across languages. |
130
+ | `multiTenant` | `client.multiTenant` | Shared client behavior. |
131
+ | TypeScript `httpClient` | `generation.language.typescript.httpClient` | Only `fetch` and `axios` are selectable; other languages use their generator transport. |
132
+ | `additionalConstructorParameters` | `client.additionalConstructorParameters` | Merged from language options. |
133
+ | `deliveryMethods` | `output.delivery` | Normalized to `files`, `zip`, or `github`; multiple deliveries produce separate IR requests. |
134
+ | `fileOutput` | `output.path` or `output.fileName` | Depends on delivery type. |
135
+ | `githubRef` | `output.github.branch` | Only meaningful for GitHub delivery. |
136
+ | `privateRepo` | `output.github.privateRepository` | Only meaningful for GitHub delivery. |
137
+ | `publishing.githubOrg` | `output.github.repository` | Translator combines the organization and repository name. |
138
+ | package names and IDs | `package` | Includes npm/PyPI/NuGet/RubyGems/Crates/Composer names and Maven IDs. |
139
+ | `goModuleName` | `package.modulePath` | Go publication and import identity. |
140
+ | `license`, `authors`, `developers`, `homepage` | `package` | Manifest metadata. |
141
+ | TypeScript package privacy / JSR publication | `output.publish.isPackagePrivate` / `output.publish.publishToJsr` | NPM-specific publication options. |
142
+ | registry workflow and env-var settings | `output.publish` | Per-registry workflow toggles, credential env vars, and trusted publishing flags. |
143
+ | `documentation.url` | `docs.referenceBaseUrl` | Base URL for generated reference-file links. |
144
+ | `documentation.snippets` | `docs.snippets` | `enabled` is explicit when the object is present. |
145
+ | `docs[]` | `docs` | Legacy API/snippet selections are lowered to typed documentation settings. |
146
+ | `includeWatermark` | `generation.includeWatermark` | Simple on/off behavior. |
147
+ | `includeOptionalSnippetParameters` | `generation.includeOptionalSnippetParameters` | Simple on/off behavior. |
148
+ | `inferServiceNames` | `generation.inferServiceNames` | Simple on/off behavior. |
149
+ | `buildAllModels` | `generation.buildAllModels` | Simple on/off behavior. |
150
+ | `deprecatedOperations.include` | `generation.includeDeprecatedOperations` | Simplified to a boolean. |
151
+ | `multipleResponses.enabled` | `generation.multipleResponses` | Simplified to a boolean. |
152
+ | `devContainer` | `generation.devContainer` | Simple on/off behavior. |
153
+ | `ignoreFiles` / language `ignore` | `generation.ignoreFiles` | Language aliases are resolved by the translator. |
154
+ | `reservedKeywords` | `generation.reservedKeywords` | Shared generator input. |
155
+ | `hooks`, `hookDependencies`, `hooksLocation` | `generation.hooks` | Location and dependencies are one configurable feature. |
156
+ | `customCode*`, previous artifact location | `generation.customCode` | Locations become typed generation assets. |
157
+ | `workflow` | `generation.workflows[]` | The normalized shape supports more than one workflow. |
158
+ | `customQueries` | `generation.customQueryPaths` | Query definitions are represented as paths. |
159
+ | `analytics` | `generation.analytics` | `enabled` is explicit; timing fields use milliseconds. |
160
+ | language options | `generation.language.<target>` or shared fields | Package, naming, validation, and dependency aliases are lifted out first. |
159
161
 
160
162
  ### Postman language-option migration map
161
163
 
@@ -193,43 +195,49 @@ inputs were not restored as part of the normalized contract.
193
195
  Customer-use counts below are distinct projects observed in the 61-project configuration snapshot
194
196
  audited on 2026-07-17. Counts guide the initial contract; they are not a permanent support policy.
195
197
 
196
- | Fern field or aliases | SDK Config IR v1 | Observed projects |
197
- | --------------------------------------------------------------------------- | -------------------------------------------------- | -----------------------------------------: |
198
- | `api.specs[]` | `source.specs[]` | 53 OpenAPI, 3 AsyncAPI |
199
- | `api.specs[].namespace` | `source.specs[].namespace` | 1 |
200
- | `api.specs[].overlays` | `source.specs[].overlays` | 2 |
201
- | `api.specs[].overrides` | `source.specs[].overrides` | 39 |
202
- | `api.default-url` | `api.baseUrl` | 21 |
203
- | `api.default-environment` | `api.defaultEnvironment` | 22 |
204
- | `api.environments` | `api.environments` | 20+ |
205
- | `api.auth`, `api.auth-schemes` | `api.auth` | 27 |
206
- | `api.headers` | `api.headers` | 11+ |
207
- | generator-group `audiences` | `api.audiences` | Absent selects all audiences. |
208
- | generator `inlinePathParameters`, `inline-path-parameters`, and API setting | `client.pathParameterStyle` | 12 API; 1-3 per language |
209
- | generator `inlineFileProperties`, `inline-file-properties` | `client.filePropertyStyle` | 1-3 per language |
210
- | `inline_request_params` | `client.requestParameterStyle` | 6 Python |
211
- | `customPagerName`, `custom-pager-name`, `custom_pager_name` | `generation.naming.pagerName` | 2-5 per language |
212
- | timeout aliases in seconds or milliseconds | `client.timeoutMs` | Translator converts units. |
213
- | `skipResponseValidation`, Python `skip_validation` | `client.responseValidation` | Inverted; 12 TS, 8 Python |
214
- | `useDefaultRequestParameterValues` aliases | `client.useDefaultRequestParameterValues` | 1 |
215
- | `respectOptionalRequestBody`, `respect-optional-request-body` | `client.respectOptionalRequestBody` | Not in the project snapshot; see below |
216
- | `enable-wire-tests`, `enableWireTests`, `generateWireTests` | `generation.wireTests` | 1-15 per language |
217
- | WebSocket generation aliases | `generation.webSockets` | 3 TS, 3 Python |
218
- | `streamType`, `fileResponseType` | `generation.streams` | 1 TS |
219
- | client/exported/environment class aliases | `generation.naming` | 1-28 per language |
220
- | base API/general exception class aliases | `generation.naming.apiErrorName` / `baseErrorName` | 3-6 Java/C# |
221
- | namespace/package-prefix aliases | `package.namespace` | 1-30 per language |
222
- | output registry package names | `package.packageName` | 5-28 per registry language |
223
- | Python custom `package_name` | `package.moduleName` | 18 |
224
- | Go `module.path` | `package.modulePath` | 3 |
225
- | Maven `group` / `artifact` | `package.groupId` / `artifactId` | 7 |
226
- | custom/extra dependencies | `package.extraDependencies` and related lists | Multiple languages |
227
- | local output | `output.delivery: "files"` | 49+ |
228
- | registry output | `output.publish` plus `package` identity | 5-28 per registry language |
229
- | GitHub output | `output.delivery: "github"` and `output.github` | Translator resolves Fern owner/repo forms. |
230
- | Fern README config | `docs.readme` | 12 API names; 11 disabled-section configs |
231
- | `customReadmeSections` | `docs.readme.customSections` | Not in the project snapshot; see below |
232
- | `includeApiReference` | `docs.includeApiReference` | 10 TS |
198
+ | Fern field or aliases | SDK Config IR v1 | Observed projects |
199
+ | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -----------------------------------------: |
200
+ | `api.specs[]` | `source.specs[]` | 53 OpenAPI, 3 AsyncAPI |
201
+ | `api.specs[].namespace` | `source.specs[].namespace` | 1 |
202
+ | `api.specs[].overlays` | `source.specs[].overlays` | 2 |
203
+ | `api.specs[].overrides` | `source.specs[].overrides` | 39 |
204
+ | `api.default-url` | `api.baseUrl` | 21 |
205
+ | `api.default-environment` | `api.defaultEnvironment` | 22 |
206
+ | `api.environments` | `api.environments` | 20+ |
207
+ | `api.auth`, `api.auth-schemes` | `api.auth` | 27 |
208
+ | `api.headers` | `api.headers` | 11+ |
209
+ | generator-group `audiences` | `api.audiences` | Absent selects all audiences. |
210
+ | generator `inlinePathParameters`, `inline-path-parameters`, and API setting | `client.pathParameterStyle` | 12 API; 1-3 per language |
211
+ | generator `inlineFileProperties`, `inline-file-properties` | `client.filePropertyStyle` | 1-3 per language |
212
+ | `inline_request_params` | `client.requestParameterStyle` | 6 Python |
213
+ | `customPagerName`, `custom-pager-name`, `custom_pager_name` | `generation.naming.pagerName` | 2-5 per language |
214
+ | `smart-casing`, `smart-casing-digit-word-boundary` | `generation.naming` | Preserved only when explicitly set. |
215
+ | timeout aliases in seconds or milliseconds | `client.timeoutMs` | Translator converts units. |
216
+ | `skipResponseValidation`, Python `skip_validation` | `client.responseValidation` | Inverted; 12 TS, 8 Python |
217
+ | `useDefaultRequestParameterValues` aliases | `client.useDefaultRequestParameterValues` | 1 |
218
+ | `respectOptionalRequestBody`, `respect-optional-request-body` | `client.respectOptionalRequestBody` | Not in the project snapshot; see below |
219
+ | `enable-wire-tests`, `enableWireTests`, `generateWireTests` | `generation.wireTests` | 1-15 per language |
220
+ | WebSocket generation aliases | `generation.webSockets` | 3 TS, 3 Python |
221
+ | `streamType`, `fileResponseType` | `generation.streams` | 1 TS |
222
+ | client/exported/environment class aliases | `generation.naming` | 1-28 per language |
223
+ | base API/general exception class aliases | `generation.naming.apiErrorName` / `generation.naming.baseErrorName` | 3-6 Java/C# |
224
+ | namespace/package-prefix aliases | `package.namespace` | 1-30 per language |
225
+ | output registry package names | `package.packageName` | 5-28 per registry language |
226
+ | Python custom `package_name` | `package.moduleName` | 18 |
227
+ | Go `module.path` | `package.modulePath` | 3 |
228
+ | Maven `group` / `artifact` | `package.groupId` / `package.artifactId` | 7 |
229
+ | custom/extra dependencies | `package.extraDependencies` and related lists | Multiple languages |
230
+ | local output | `output.delivery: "files"` | 49+ |
231
+ | registry output | `output.publish` plus `package` identity | 5-28 per registry language |
232
+ | GitHub output | `output.delivery: "github"` and `output.github` | Translator resolves Fern owner/repo forms. |
233
+ | npm package privacy and JSR publication | `output.publish.isPackagePrivate` / `output.publish.publishToJsr` | NPM-only booleans |
234
+ | registry version and workflow gate | `output.publish.version` / `output.publish.shouldGeneratePublishWorkflow` | Per-registry controls |
235
+ | registry credential environment variables | `output.publish.*EnvironmentVariable` | Registry-specific env-var names |
236
+ | trusted publishing / OIDC markers | `output.publish.trustedPublishing` | npm, PyPI, and NuGet |
237
+ | Maven coordinate and signing env vars | `output.publish.coordinate` / `output.publish.signatureEnvironmentVariables` | Maven-specific |
238
+ | Fern README config | `docs.readme` | 12 API names; 11 disabled-section configs |
239
+ | `customReadmeSections` | `docs.readme.customSections` | Not in the project snapshot; see below |
240
+ | `includeApiReference` | `docs.includeApiReference` | 10 TS |
233
241
 
234
242
  The Rust language config was added after the initial audit. That audit compared existing Fern
235
243
  _customer projects_, which surfaced no Rust-specific options; comparing the Fern Rust generator's
@@ -281,10 +289,10 @@ Only options that remain language-specific stay in `generation.language`.
281
289
 
282
290
  | Language | Fern fields retained in language config | Shared mappings lifted out |
283
291
  | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
284
- | 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 |
292
+ | TypeScript | `packageManager` (1), `testFramework` (2), `namespaceExportName`, `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 |
285
293
  | 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 |
286
294
  | Java/Kotlin | Package layout (3), local dates (2), optional-nullable collapse (2), Gradle settings (7), and JVM async-client style | Maven identity, namespace, names, forward-compatible enums, inline properties, dependencies, pager, wire tests |
287
- | Go | Legacy complex models, union version (3), legacy client options (1), smart casing, and the fern root-client constructor name | Module/package identity, client name, environments, inline properties, pager, wire tests |
295
+ | Go | Legacy complex models, union version (3), legacy client options (1), and the fern root-client constructor name | Module/package identity, client name, environments, smart casing, inline properties, pager, wire tests |
288
296
  | C# | Optional wrapper, simplified dictionaries (1), explicit namespaces (7), core namespace behavior (1), exception handler (5), and the experimental explicit-nullable-optional switch | NuGet identity, namespace, class/error names, pager, wire tests |
289
297
  | PHP | Property access (2) and generated client interfaces (1) | Composer identity, namespace, client/pager names, request style, dependencies, wire tests |
290
298
  | Ruby | Require paths (2) | Gem identity, client name, dependencies, pager, wire tests |