@beff/client 0.0.129 → 0.0.130

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.
@@ -0,0 +1,217 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { JSONSchema7Definition } from "../src/json-schema.js";
3
+ import { normalizeOpenApiSchema } from "../src/openapi-pp.js";
4
+ import {
5
+ AnyOfDiscriminatedRuntype,
6
+ BaseRefRuntype,
7
+ ConstRuntype,
8
+ ObjectRuntype,
9
+ SchemaPrintingContext,
10
+ TypeofRuntype,
11
+ } from "../src/codegen-v2.js";
12
+
13
+ const normalize = (schema: JSONSchema7Definition): JSONSchema7Definition => {
14
+ return normalizeOpenApiSchema(schema, {}, { refPathTemplate: "#/components/schemas/{name}" });
15
+ };
16
+
17
+ describe("normalizeOpenApiSchema", () => {
18
+ it("rewrites nullable object properties into optional properties", () => {
19
+ expect(
20
+ normalize({
21
+ type: "object",
22
+ properties: {
23
+ workerType: { type: "string" },
24
+ hostname: {
25
+ anyOf: [{ type: "null" }, { type: "string" }],
26
+ },
27
+ modelBackend: {
28
+ anyOf: [{ type: "string" }, { type: "null" }],
29
+ },
30
+ },
31
+ required: ["workerType", "hostname", "modelBackend"],
32
+ additionalProperties: false,
33
+ }),
34
+ ).toEqual({
35
+ type: "object",
36
+ properties: {
37
+ workerType: { type: "string" },
38
+ hostname: { type: "string" },
39
+ modelBackend: { type: "string" },
40
+ },
41
+ required: ["workerType"],
42
+ additionalProperties: false,
43
+ });
44
+ });
45
+
46
+ it("preserves explicit null-only properties", () => {
47
+ expect(
48
+ normalize({
49
+ type: "object",
50
+ properties: {
51
+ onlyNull: { type: "null" },
52
+ },
53
+ required: ["onlyNull"],
54
+ additionalProperties: false,
55
+ }),
56
+ ).toEqual({
57
+ type: "object",
58
+ properties: {
59
+ onlyNull: { type: "null" },
60
+ },
61
+ required: ["onlyNull"],
62
+ additionalProperties: false,
63
+ });
64
+ });
65
+
66
+ it("does not rewrite standalone nullable unions outside object properties", () => {
67
+ expect(
68
+ normalize({
69
+ anyOf: [{ type: "null" }, { type: "string" }],
70
+ }),
71
+ ).toEqual({
72
+ anyOf: [{ type: "null" }, { type: "string" }],
73
+ });
74
+ });
75
+
76
+ it("preserves explicit discriminators on discriminated unions", () => {
77
+ const named = {
78
+ CronSource: new ObjectRuntype(
79
+ {
80
+ type: new ConstRuntype("CRON"),
81
+ schedule: new TypeofRuntype("string"),
82
+ },
83
+ [],
84
+ ),
85
+ EventSource: new ObjectRuntype(
86
+ {
87
+ type: new ConstRuntype("EVENT"),
88
+ eventName: new TypeofRuntype("string"),
89
+ },
90
+ [],
91
+ ),
92
+ };
93
+
94
+ class TestRefRuntype extends BaseRefRuntype {
95
+ getNamedRuntypes() {
96
+ return named;
97
+ }
98
+ }
99
+
100
+ const cron = new TestRefRuntype("CronSource");
101
+ const event = new TestRefRuntype("EventSource");
102
+ const printingContext = new SchemaPrintingContext({
103
+ refPathTemplate: "#/components/schemas/{name}",
104
+ definitionContainerKey: null,
105
+ });
106
+
107
+ const schema = normalize(
108
+ new AnyOfDiscriminatedRuntype(
109
+ [cron, event],
110
+ "type",
111
+ {
112
+ EVENT: event,
113
+ CRON: cron,
114
+ },
115
+ {
116
+ EVENT: event,
117
+ CRON: cron,
118
+ },
119
+ ).schema({
120
+ path: [],
121
+ seen: {},
122
+ mode: "contextual",
123
+ printingContext,
124
+ }),
125
+ );
126
+
127
+ expect(schema).toMatchInlineSnapshot(`
128
+ {
129
+ "discriminator": {
130
+ "mapping": {
131
+ "CRON": "#/components/schemas/CronSource",
132
+ "EVENT": "#/components/schemas/EventSource",
133
+ },
134
+ "propertyName": "type",
135
+ },
136
+ "oneOf": [
137
+ {
138
+ "$ref": "#/components/schemas/EventSource",
139
+ },
140
+ {
141
+ "$ref": "#/components/schemas/CronSource",
142
+ },
143
+ ],
144
+ "type": "object",
145
+ }
146
+ `);
147
+ });
148
+
149
+ it("creates synthetic refs for inline discriminated union variants", () => {
150
+ const cron = new ObjectRuntype(
151
+ {
152
+ type: new ConstRuntype("CRON"),
153
+ schedule: new TypeofRuntype("string"),
154
+ },
155
+ [],
156
+ );
157
+ const event = new ObjectRuntype(
158
+ {
159
+ type: new ConstRuntype("EVENT"),
160
+ eventName: new TypeofRuntype("string"),
161
+ },
162
+ [],
163
+ );
164
+ const printingContext = new SchemaPrintingContext({
165
+ refPathTemplate: "#/components/schemas/{name}",
166
+ definitionContainerKey: null,
167
+ });
168
+
169
+ const schema = normalize(
170
+ new AnyOfDiscriminatedRuntype(
171
+ [cron, event],
172
+ "type",
173
+ {
174
+ EVENT: event,
175
+ CRON: cron,
176
+ },
177
+ {
178
+ EVENT: event,
179
+ CRON: cron,
180
+ },
181
+ ).schema({
182
+ path: [],
183
+ seen: {},
184
+ mode: "contextual",
185
+ printingContext,
186
+ }),
187
+ );
188
+
189
+ expect(schema).toMatchInlineSnapshot(`
190
+ {
191
+ "discriminator": {
192
+ "mapping": {
193
+ "CRON": "#/components/schemas/DiscriminatedTypeCRON1000470817",
194
+ "EVENT": "#/components/schemas/DiscriminatedTypeEVENT1000470817",
195
+ },
196
+ "propertyName": "type",
197
+ },
198
+ "oneOf": [
199
+ {
200
+ "$ref": "#/components/schemas/DiscriminatedTypeEVENT1000470817",
201
+ },
202
+ {
203
+ "$ref": "#/components/schemas/DiscriminatedTypeCRON1000470817",
204
+ },
205
+ ],
206
+ "type": "object",
207
+ }
208
+ `);
209
+
210
+ expect(Object.keys(printingContext.exportDefinitions())).toMatchInlineSnapshot(`
211
+ [
212
+ "DiscriminatedTypeEVENT1000470817",
213
+ "DiscriminatedTypeCRON1000470817",
214
+ ]
215
+ `);
216
+ });
217
+ });