Skip to content

Commit 4ad314d

Browse files
Copilotmrlubos
andcommitted
fix: readWrite transform drops unevaluatedProperties schemas with readOnly sibling
Add `unevaluatedProperties` to `childSchemaRelationships` as 'single' type (same as `additionalProperties`) so the pruneSchemaByScope function correctly recognizes it as a structural keyword and does not remove schemas that use it alongside readOnly properties. Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
1 parent 91bd3d9 commit 4ad314d

6 files changed

Lines changed: 112 additions & 0 deletions

File tree

packages/openapi-ts-tests/main/test/3.1.x.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,14 @@ describe(`OpenAPI ${version}`, () => {
737737
}),
738738
description: 'handles read-only types in nested response schemas',
739739
},
740+
{
741+
config: createConfig({
742+
input: 'transforms-read-write-unevaluated.yaml',
743+
output: 'transforms-read-write-unevaluated',
744+
plugins: ['@hey-api/typescript'],
745+
}),
746+
description: 'preserves unevaluatedProperties in schemas with readOnly fields',
747+
},
740748
{
741749
config: createConfig({
742750
input: 'ref-type.json',
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
export type { ClientOptions, CreateXData, CreateXResponse, CreateXResponses, DisposableEmail, DisposableEmailWritable, GetXData, GetXResponse, GetXResponses } from './types.gen';
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
export type ClientOptions = {
4+
baseUrl: `${string}://${string}` | (string & {});
5+
};
6+
7+
export type DisposableEmail = {
8+
domain: string;
9+
readonly disposable: boolean;
10+
metadata: {
11+
[key: string]: unknown;
12+
};
13+
};
14+
15+
export type DisposableEmailWritable = {
16+
domain: string;
17+
metadata: {
18+
[key: string]: unknown;
19+
};
20+
};
21+
22+
export type GetXData = {
23+
body?: never;
24+
path?: never;
25+
query?: never;
26+
url: '/x';
27+
};
28+
29+
export type GetXResponses = {
30+
/**
31+
* ok
32+
*/
33+
200: DisposableEmail;
34+
};
35+
36+
export type GetXResponse = GetXResponses[keyof GetXResponses];
37+
38+
export type CreateXData = {
39+
body: DisposableEmailWritable;
40+
path?: never;
41+
query?: never;
42+
url: '/x';
43+
};
44+
45+
export type CreateXResponses = {
46+
/**
47+
* ok
48+
*/
49+
200: DisposableEmail;
50+
};
51+
52+
export type CreateXResponse = CreateXResponses[keyof CreateXResponses];

packages/shared/src/openApi/shared/transforms/readWrite.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const schemaKeys = new Set([
4646
'patternProperties',
4747
'properties',
4848
'schema',
49+
'unevaluatedProperties',
4950
]);
5051

5152
const getComponentContext = (path: ReadonlyArray<string | number>): Scope | undefined => {

packages/shared/src/openApi/shared/utils/schemaChildRelationships.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ export const childSchemaRelationships = [
1212
['properties', 'objectMap'],
1313
['propertyNames', 'single'],
1414
['then', 'single'],
15+
['unevaluatedProperties', 'single'],
1516
] as const;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
openapi: 3.1.0
2+
info:
3+
title: readOnly map property with unevaluatedProperties
4+
version: 1.0.0
5+
paths:
6+
/x:
7+
get:
8+
operationId: getX
9+
responses:
10+
'200':
11+
description: ok
12+
content:
13+
application/json:
14+
schema:
15+
$ref: '#/components/schemas/DisposableEmail'
16+
post:
17+
operationId: createX
18+
requestBody:
19+
required: true
20+
content:
21+
application/json:
22+
schema:
23+
$ref: '#/components/schemas/DisposableEmail'
24+
responses:
25+
'200':
26+
description: ok
27+
content:
28+
application/json:
29+
schema:
30+
$ref: '#/components/schemas/DisposableEmail'
31+
components:
32+
schemas:
33+
DisposableEmail:
34+
type: object
35+
required:
36+
- domain
37+
- disposable
38+
- metadata
39+
properties:
40+
domain:
41+
type: string
42+
disposable:
43+
type: boolean
44+
readOnly: true
45+
metadata:
46+
type: object
47+
unevaluatedProperties: {}

0 commit comments

Comments
 (0)