Commit 4637eda
fix: preserve parameter order while ensuring path parameters win over same-named query parameters (#151)
## Summary
- Migrated snapshot tests from `toMatchSnapshot` to
`toMatchFileSnapshot` for better diff readability
- Excluded snapshot files from TypeScript type checking to prevent false
errors
- Added Kubernetes v1.28.6 OpenAPI spec as a snapshot test target
- Fixed a bug in `generatePropertySignatures` where same-named
parameters were reordered
## Problem
The previous fix for same-named path/query parameter conflicts (#150)
used `.sort()` to push path parameters to the end of the array before
reducing into a `Record`. This caused all path parameters to appear last
in the generated TypeScript interface, regardless of their position in
the OpenAPI spec.
For example, when the spec defines:
```yaml
parameters:
- $ref: '#/components/parameters/zone_id' # path parameter (first)
- name: bins
in: query # query parameter (second)
```
The previous output was:
```typescript
export interface Parameter$... {
bins?: string; // ← wrong: appeared before zone_id
zone_id: string; // ← moved to last by sort
}
```
Additionally, the Kubernetes v1.28.6 spec exposes a second pattern: both
the path parameter and the query parameter with the same name (`path`)
are defined as `$ref` references. The previous sort only resolved `in`
for inline parameters, so both references were treated as non-path and
the query parameter reference (appearing last) won.
## Fix
Replaced the sort + `Record` reduce approach with a `Map`-based
iteration that preserves insertion order:
- Parameters are processed in their original spec order
- When two parameters share the same name, the path parameter's entry
wins by overwriting the existing value at its **original position** in
the Map (JavaScript `Map` preserves insertion order on `set()` of an
existing key)
- `resolveParameterIn` now resolves `$ref` references via
`store.getParameter()` so both inline and referenced path parameters are
correctly identified
```typescript
// Before: sort-based (broke insertion order)
const sorted = [...parameters].sort((a, b) => { /* path last */ });
const typeElementMap = sorted.reduce<Record<string, string>>(...);
return Object.values(typeElementMap);
// After: Map-based (preserves spec order)
const typeElementMap = new Map<string, string>();
for (const parameter of parameters) {
const { name, typeElement } = generatePropertySignatureObject(...);
const isPath = resolveParameterIn(store, parameter) === "path";
if (!typeElementMap.has(name) || isPath) {
typeElementMap.set(name, typeElement);
}
}
return [...typeElementMap.values()];
```
## Test plan
- [x] `pnpm test:code:gen:class` — regenerate code passes
- [x] `pnpm test:code:gen:function` — regenerate code passes
- [x] `pnpm test:code:gen:currying-function` — regenerate code passes
- [x] `pnpm test:snapshot` — all 54 snapshot tests pass
- [x] New `$ref`-based path/query conflict scenario added to
`test/path-parameter/index.yml`
- [x] Kubernetes v1.28.6 snapshot added
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>1 parent 938bc6f commit 4637eda
99 files changed
Lines changed: 168043 additions & 19466 deletions
File tree
- scripts
- src
- code-templates
- class-api-client/ApiClientClass
- currying-functional-api-client/FunctionalApiClient
- functional-api-client/FunctionalApiClient
- internal
- OpenApiTools
- Walker
- components
- TsGenerator
- __tests__
- test
- __tests__
- class
- __snapshots__
- argo-rollout
- cloudflare
- format.domain
- kubernetes
- mulit-type-test.domain
- parameter
- split
- template-only
- typedef-only
- typedef-with-template
- unknown.schema.domain
- currying-functional
- __snapshots__/cloudflare
- functional
- __snapshots__
- argo-rollout
- cloudflare
- format.domain
- kubernetes
- mulit-type-test.domain
- parameter
- split
- template-only
- typedef-only
- typedef-with-template
- unknown.schema.domain
- kubernetes
- path-parameter
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
| 43 | + | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
43 | 46 | | |
44 | 47 | | |
45 | 48 | | |
| |||
Lines changed: 1 addition & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
| |||
161 | 159 | | |
162 | 160 | | |
163 | 161 | | |
164 | | - | |
| 162 | + | |
165 | 163 | | |
166 | 164 | | |
167 | 165 | | |
| |||
Lines changed: 1 addition & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
| |||
11 | 9 | | |
12 | 10 | | |
13 | 11 | | |
14 | | - | |
| 12 | + | |
15 | 13 | | |
16 | 14 | | |
17 | 15 | | |
| |||
Lines changed: 1 addition & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
| |||
13 | 11 | | |
14 | 12 | | |
15 | 13 | | |
16 | | - | |
| 14 | + | |
17 | 15 | | |
18 | 16 | | |
19 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
| |||
63 | 61 | | |
64 | 62 | | |
65 | 63 | | |
66 | | - | |
| 64 | + | |
67 | 65 | | |
68 | 66 | | |
69 | 67 | | |
| |||
79 | 77 | | |
80 | 78 | | |
81 | 79 | | |
82 | | - | |
| 80 | + | |
83 | 81 | | |
84 | 82 | | |
85 | 83 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| |||
22 | 21 | | |
23 | 22 | | |
24 | 23 | | |
25 | | - | |
| 24 | + | |
26 | 25 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
| |||
37 | 35 | | |
38 | 36 | | |
39 | 37 | | |
40 | | - | |
| 38 | + | |
41 | 39 | | |
42 | 40 | | |
43 | 41 | | |
| |||
Lines changed: 1 addition & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
6 | 4 | | |
7 | 5 | | |
8 | 6 | | |
9 | | - | |
| 7 | + | |
10 | 8 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| |||
26 | 25 | | |
27 | 26 | | |
28 | 27 | | |
29 | | - | |
| 28 | + | |
30 | 29 | | |
31 | 30 | | |
32 | 31 | | |
| |||
0 commit comments