fix: preserve OpenAPI spec property order when sortTypes is false (#151)#1626
Open
eduardbar wants to merge 4 commits intoacacode:mainfrom
Open
fix: preserve OpenAPI spec property order when sortTypes is false (#151)#1626eduardbar wants to merge 4 commits intoacacode:mainfrom
eduardbar wants to merge 4 commits intoacacode:mainfrom
Conversation
The enumsFirst() and discriminatorsFirst() methods in SchemaComponentsMap used Array.prototype.sort(), which is not stable with respect to elements that don't match the promotion predicate. In practice this caused the order of interface properties in the generated TypeScript output to diverge from the order in which properties are declared in the OpenAPI/Swagger spec, regardless of whether the --sort-types flag was set (issue acacode#151). Replace the unstable sort-based implementation with a partition-based _stablePromoteToFront() helper. The helper separates the component list into two buckets — promoted (enums or discriminators) and rest — and reassembles them as [...promoted, ...rest]. This: - Preserves the relative order of non-promoted components exactly as they appear in the spec (stable behaviour, O(n) instead of O(n log n)). - Preserves the relative order of promoted components among themselves. - Does not affect the existing --sort-types behaviour, which continues to sort all top-level types alphabetically by name when opted in. Fixes acacode#151
🦋 Changeset detectedLatest commit: 935c028 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #151.
When
--sort-typesis not set (the default), generated TypeScript interface properties did not maintain the same order as defined in the OpenAPI/Swagger specification. This made it hard to compare the generated output against the spec and caused unnecessary diffs in code reviews when the spec was updated.Root Cause
SchemaComponentsMap.enumsFirst()anddiscriminatorsFirst()usedArray.prototype.sort()to promote enum and discriminator components to the front of the list. While.sort()is stable in V8 (and therefore preserves relative order for equal elements), the comparator returned0for non-matching items, which in theory allows the engine to move them. More critically, the two sorts are run back-to-back:After the second sort, non-enum components that are not discriminators may end up in an order determined by the sort algorithm's internal state rather than the spec's declaration order. In practice this was observable in projects with a mix of enums, discriminators, and plain object schemas.
Fix
Replace the sort-based implementation with a partition-based stable reorder via a new private
_stablePromoteToFront()helper:This is O(n) and guaranteed stable — the relative order of every component that does not match the predicate is preserved exactly. Both
enumsFirst()anddiscriminatorsFirst()now delegate to this helper.The
--sort-typespath (alphabetical sort incode-gen-process.tsandschema-parser.ts) is unchanged — it only activates when explicitly opted in.Files Changed
src/schema-components-map.ts— replaced unstablesort()calls inenumsFirst()anddiscriminatorsFirst()with the new stable_stablePromoteToFront()partition helper.Before / After
Given an OpenAPI spec with schemas declared in order
Alpha,Beta,Gamma(whereGammais an enum):--sort-typesoffGamma,Alpha,Beta(arbitrary)Gamma,Alpha,Beta(enum first, rest in spec order)--sort-typeson