Commit 5901753
fix(cli): resolve allOf composition bugs in V3 OpenAPI importer (#14873)
* chore(seed): add allOf composition test fixtures
Add two test-definition fixtures exercising allOf edge cases:
- allof: default settings (extends mode)
- allof-inline: inline-all-of-schemas enabled, shares the same spec
Covers array items narrowing, primitive constraint narrowing via $ref,
required propagation, metadata inheritance, and multi-parent overlap.
* chore(internal): add allOf debug pipeline script and IR snapshots
Add debug-allof-pipeline.ts for running allof/allof-inline fixtures
through the full CLI pipeline (openapi-ir → write-definition → ir).
Include generated IR snapshots confirming remaining allOf bugs.
* test(cli): add assertion-based allOf tests reproducing SPS Commerce bugs
Add V3 importer test fixture and assertion tests for the allOf edge
cases reported in Pylon #18189 / FER-9158. Tests validate:
- Case A: array items narrowing preserves parent required status
- Case B: property-level allOf with $ref + inline primitive
- Case C: required field preservation through allOf composition
7 of 8 assertions currently fail, confirming the bugs. The task is
complete when all 8 pass.
* fix(cli): resolve allOf composition bugs in V3 OpenAPI importer
- Enhance shouldMergeAllOf path to resolve $ref elements instead of bailing out
- Add cycle detection via Set to prevent infinite loops on circular refs
- Handle property-level allOf with $ref to non-object types (e.g. enums)
by referencing the original type instead of creating synthetic copies
- Update test infrastructure to serialize IR discriminants for assertions
- Update snapshots for allof-spscommerce fixture
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: resolve biome noNonNullAssertion lint errors in SchemaOrReferenceConverter
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: add biome-ignore for pre-existing noNonNullAssertion in test file
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: update v3-sdks snapshots for allOf merge changes
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: update convertIRtoJsonSchema snapshots for allof/allof-inline
Co-Authored-By: bot_apk <apk@cognition.ai>
* update config
* Add case 6
* seed outputs
* Automated update of seed files
* fix: update convertIRtoJsonSchema snapshots for new allof types
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: thread visitedRefs across recursive SchemaConverter calls for cross-schema cycle detection
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: format SchemaConverter.ts constructor for biome
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: update ir-generator-tests test-definitions for allof-inline
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: update ir-generator-tests test-definitions for allof
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: deduplicate merged allOf refs and guard composition-keyword shortcuts
Deduplicate $ref entries in the merged allOf array after mergeWith
array-concatenation to prevent false-positive cycle detection in
diamond inheritance patterns (A → B, C; B, C → D).
Add allOf/oneOf/anyOf checks to the resolved-schema guard in
maybeConvertSingularAllOfReferenceObject so the shortcut only fires
for true scalar/enum primitives, not schemas defined via composition
keywords whose inline constraints would be silently discarded.
* fix: guard single-element allOf cycles and add versions.yml entry
Thread visitedRefs through the single-element allOf branch in
SchemaConverter to detect self-referential and indirect cycles
(e.g. A → B → A via single-element allOf chains), matching the
protection already present in the multi-element shouldMergeAllOf path.
Add the required versions.yml changelog entry for the allOf
composition fixes in this PR.
* nits
* fix(cli): address review feedback on allOf composition
- Preserve outer `inlined` status through allOf merge path instead of
hardcoding `inlined: true`
- Guard variants-flattening against $ref-resolved schemas to prevent
destructive flattening of named union types
- Seed dedup seenRefs from resolvedRefs to prevent duplicate property
declarations in diamond inheritance
- Bail out of allOf shortcut when inline elements contain `type: "null"`
to preserve nullable semantics in OpenAPI 3.1 patterns
- Add optional guard for required executionContext field in Case B test
- Remove debug script (scripts/debug-allof-pipeline.ts)
- Remove orphaned allof-spscommerce snapshot files
- Move changelog to changes/unreleased/ per release-versioning convention
* fix(cli): address remaining review comments on allOf composition
- Fix inlined: true -> inlined: this.inlined in single-element allOf path
- Propagate inlinedTypes in both allOf shortcuts in SchemaOrReferenceConverter
- Update stale test comment and remove duplicate biome-ignore
- Update v3-sdks snapshots
Co-Authored-By: judah <jsklan.development@gmail.com>
* fix(cli): separate resolvedRefs concerns and add format keyword guard
- SchemaConverter.ts: Use separate localResolvedRefs set for tracking refs
within current allOf array. Check this.visitedRefs for ancestor cycles
only. Same-array duplicate $refs now skip (continue) instead of
triggering hasCycle=true.
- SchemaOrReferenceConverter.ts: Add !s.format guard to inline elements
check and !resolved.format guard to resolved schema check in
maybeConvertSingularAllOfReferenceObject, preventing the shortcut from
discarding inline format constraints like {format: "date-time"}.
Co-Authored-By: bot_apk <apk@cognition.ai>
* style: fix biome formatting for inline format guard
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix(cli): preserve outer schema metadata in shouldMergeAllOf path
Copy TYPE_INVARIANT_KEYS (description, deprecated, example, default,
readOnly, writeOnly, etc.) from the outer this.schema into mergedSchema
before constructing mergedConverter, so metadata fields are not silently
dropped for schemas routed through the shouldMergeAllOf path.
Co-Authored-By: bot_apk <apk@cognition.ai>
* refactor(cli): replace lodash.mergeWith with per-key allOf schema merge
Replace the generic lodash.mergeWith deep merge in the shouldMergeAllOf
path with a purpose-built mergeAllOfSchemas function that uses explicit
per-key strategies for OpenAPI schema keywords:
- required: set union
- properties/items: recursive deep merge
- example/default: deep merge objects
- deprecated/readOnly/writeOnly: OR (true if any says true)
- min/max constraints: most restrictive value
- description/type/format/etc: outer schema wins
- allOf from children: flattened before merge (prevents leakage)
This eliminates the post-merge fixup code (allOf dedup block,
TYPE_INVARIANT_KEYS loop) that was the source of cascading review
issues. Also adds !s.items and array-form null-type guards to the
allOf shortcut in SchemaOrReferenceConverter.
* fix(cli): fix type errors in allOf schema merge and eliminate `as any` in tests
Use `"items" in s` instead of `s.items` to avoid TS error on NonArraySchemaObject,
and replace all `as any` casts in mergeAllOfSchemas tests with proper OpenAPI types.
* fix(cli): harden allOf merge pipeline against $ref leaks, nested flattening, and metadata loss
Filter unresolved $ref objects from nested allOf flattening to prevent
spurious top-level $ref keys corrupting merged schemas. Make
flattenNestedAllOf recursive so deeply-nested allOf structures are fully
expanded. Add oneOf/anyOf to SKIP_FROM_CHILDREN so composition keywords
from resolved child schemas don't leak into the merged result and
erroneously trigger union conversion. Propagate outer schema metadata
(description, deprecated) through the single-element allOf path for
non-object types.
* Revert seed output changes to reduce diff
---------
Co-authored-by: jsklan <jsklan.development@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
Co-authored-by: jsklan <jsklan@users.noreply.github.com>1 parent bff9e50 commit 5901753
63 files changed
Lines changed: 28901 additions & 330 deletions
File tree
- packages/cli
- api-importers
- v3-importer-commons/src/converters/schema
- __test__
- v3-importer-tests/src/__test__
- __snapshots__
- baseline-sdks
- v3-sdks
- fixtures/allof
- fern
- cli/changes/unreleased
- fern-definition/ir-to-jsonschema/src/__test__/__snapshots__
- allof-inline
- allof
- generation/ir-generator-tests/src
- dynamic-snippets/__test__/test-definitions
- ir/__test__/test-definitions
- seed
- csharp-sdk
- python-sdk
- test-definitions/fern/apis
- allof-inline
- allof
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 94 additions & 25 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
3 | 2 | | |
4 | | - | |
5 | 3 | | |
6 | 4 | | |
7 | 5 | | |
8 | 6 | | |
9 | 7 | | |
10 | 8 | | |
| 9 | + | |
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
| |||
31 | 30 | | |
32 | 31 | | |
33 | 32 | | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
55 | | - | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
56 | 65 | | |
57 | 66 | | |
58 | 67 | | |
59 | 68 | | |
60 | 69 | | |
| 70 | + | |
61 | 71 | | |
62 | 72 | | |
63 | 73 | | |
| |||
168 | 178 | | |
169 | 179 | | |
170 | 180 | | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
171 | 191 | | |
172 | | - | |
| 192 | + | |
173 | 193 | | |
174 | 194 | | |
175 | 195 | | |
176 | 196 | | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
177 | 201 | | |
178 | 202 | | |
179 | 203 | | |
180 | 204 | | |
181 | 205 | | |
182 | | - | |
| 206 | + | |
| 207 | + | |
183 | 208 | | |
184 | 209 | | |
185 | 210 | | |
186 | 211 | | |
187 | 212 | | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
188 | 228 | | |
189 | 229 | | |
190 | 230 | | |
| |||
196 | 236 | | |
197 | 237 | | |
198 | 238 | | |
199 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
200 | 243 | | |
| 244 | + | |
| 245 | + | |
201 | 246 | | |
202 | | - | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
203 | 270 | | |
204 | 271 | | |
205 | 272 | | |
206 | 273 | | |
207 | 274 | | |
208 | | - | |
209 | | - | |
210 | | - | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
211 | 282 | | |
212 | 283 | | |
213 | 284 | | |
| |||
235 | 306 | | |
236 | 307 | | |
237 | 308 | | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
| 309 | + | |
242 | 310 | | |
243 | 311 | | |
244 | 312 | | |
245 | 313 | | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
255 | 320 | | |
256 | 321 | | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
257 | 325 | | |
258 | 326 | | |
259 | 327 | | |
260 | 328 | | |
261 | 329 | | |
262 | | - | |
| 330 | + | |
| 331 | + | |
263 | 332 | | |
264 | 333 | | |
265 | 334 | | |
| |||
packages/cli/api-importers/v3-importer-commons/src/converters/schema/SchemaOrReferenceConverter.ts
Lines changed: 59 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
| 85 | + | |
90 | 86 | | |
91 | 87 | | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
96 | 126 | | |
97 | 127 | | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
103 | 147 | | |
104 | 148 | | |
| 149 | + | |
105 | 150 | | |
106 | 151 | | |
107 | 152 | | |
| |||
0 commit comments