@amritk/generate-parsers 0.5.0 → 0.6.1
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.
- package/dist/generators/build-schema.d.ts +4 -1
- package/dist/generators/generate-files.d.ts +5 -0
- package/dist/generators/generate-parser-function.d.ts +6 -1
- package/dist/helpers/collect-imports.d.ts +6 -0
- package/dist/index.js +113 -80
- package/package.json +2 -2
- package/src/generators/build-schema.test.ts +17 -17
- package/src/generators/build-schema.ts +7 -1
- package/src/generators/generate-files.test.ts +65 -52
- package/src/generators/generate-files.ts +11 -4
- package/src/generators/generate-parser-function.test.ts +254 -258
- package/src/generators/generate-parser-function.ts +87 -58
- package/src/helpers/collect-imports.test.ts +44 -84
- package/src/helpers/collect-imports.ts +8 -1
|
@@ -14,20 +14,20 @@ describe('generate-parser-function', () => {
|
|
|
14
14
|
required: ['name'],
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const result = generateParserFunction(schema, '
|
|
17
|
+
const result = generateParserFunction(schema, 'User')
|
|
18
18
|
expect(result).toBe(
|
|
19
|
-
`export const
|
|
19
|
+
`export const parseUser = (input: unknown): User => {
|
|
20
20
|
if (!isObject(input)) return {
|
|
21
21
|
name: "",
|
|
22
22
|
};
|
|
23
23
|
const _name = input.name;
|
|
24
24
|
const _age = input.age;
|
|
25
|
-
if (typeof _name === "string" && (_age === undefined || typeof _age === "number")) return { ...input } as
|
|
25
|
+
if (typeof _name === "string" && (_age === undefined || typeof _age === "number")) return { ...input } as User;
|
|
26
26
|
return {
|
|
27
27
|
...input,
|
|
28
28
|
name: typeof _name === "string" ? _name : (_name !== undefined ? String(_name) : ""),
|
|
29
29
|
...(_age !== undefined && { age: typeof _age === "number" ? _age : (Number.isFinite(Number(_age)) ? Number(_age) : 0) }),
|
|
30
|
-
} as unknown as
|
|
30
|
+
} as unknown as User;
|
|
31
31
|
}`,
|
|
32
32
|
)
|
|
33
33
|
})
|
|
@@ -40,16 +40,16 @@ describe('generate-parser-function', () => {
|
|
|
40
40
|
},
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const result = generateParserFunction(schema, '
|
|
43
|
+
const result = generateParserFunction(schema, 'Product')
|
|
44
44
|
expect(result).toBe(
|
|
45
|
-
`export const
|
|
46
|
-
if (!isObject(input)) return {} as
|
|
45
|
+
`export const parseProduct = (input: unknown): Product => {
|
|
46
|
+
if (!isObject(input)) return {} as Product;
|
|
47
47
|
const _id = input.id;
|
|
48
|
-
if ((_id === undefined || typeof _id === "number")) return { ...input } as
|
|
48
|
+
if ((_id === undefined || typeof _id === "number")) return { ...input } as Product;
|
|
49
49
|
return {
|
|
50
50
|
...input,
|
|
51
51
|
...(_id !== undefined && { id: typeof _id === "number" ? _id : (Number.isFinite(Number(_id)) ? Number(_id) : 0) }),
|
|
52
|
-
} as unknown as
|
|
52
|
+
} as unknown as Product;
|
|
53
53
|
}`,
|
|
54
54
|
)
|
|
55
55
|
})
|
|
@@ -59,9 +59,9 @@ describe('generate-parser-function', () => {
|
|
|
59
59
|
type: 'object',
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
const result = generateParserFunction(schema, '
|
|
62
|
+
const result = generateParserFunction(schema, 'Empty')
|
|
63
63
|
expect(result).toBe(
|
|
64
|
-
'export const
|
|
64
|
+
'export const parseEmpty = (input: unknown): Empty => isObject(input) ? { ...input } as Empty : {} as Empty;',
|
|
65
65
|
)
|
|
66
66
|
})
|
|
67
67
|
|
|
@@ -87,10 +87,10 @@ describe('generate-parser-function', () => {
|
|
|
87
87
|
required: ['id', 'name'],
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
const result = generateParserFunction(schema, '
|
|
90
|
+
const result = generateParserFunction(schema, 'User')
|
|
91
91
|
|
|
92
92
|
expect(result).toBe(
|
|
93
|
-
`export const
|
|
93
|
+
`export const parseUser = (input: unknown): User => {
|
|
94
94
|
if (!isObject(input)) return {
|
|
95
95
|
id: 0,
|
|
96
96
|
name: "",
|
|
@@ -98,13 +98,13 @@ describe('generate-parser-function', () => {
|
|
|
98
98
|
const _id = input.id;
|
|
99
99
|
const _name = input.name;
|
|
100
100
|
const _email = input.email;
|
|
101
|
-
if (typeof _id === "number" && typeof _name === "string" && (_email === undefined || typeof _email === "string")) return { ...input } as
|
|
101
|
+
if (typeof _id === "number" && typeof _name === "string" && (_email === undefined || typeof _email === "string")) return { ...input } as User;
|
|
102
102
|
return {
|
|
103
103
|
...input,
|
|
104
104
|
id: typeof _id === "number" ? _id : (_id !== undefined ? (Number.isFinite(Number(_id)) ? Number(_id) : 0) : 0),
|
|
105
105
|
name: typeof _name === "string" ? _name : (_name !== undefined ? String(_name) : ""),
|
|
106
106
|
...(_email !== undefined && { email: typeof _email === "string" ? _email : String(_email) }),
|
|
107
|
-
} as unknown as
|
|
107
|
+
} as unknown as User;
|
|
108
108
|
}`,
|
|
109
109
|
)
|
|
110
110
|
})
|
|
@@ -119,21 +119,21 @@ describe('generate-parser-function', () => {
|
|
|
119
119
|
required: ['id'],
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
const result = generateParserFunction(schema, '
|
|
122
|
+
const result = generateParserFunction(schema, 'Item')
|
|
123
123
|
|
|
124
124
|
expect(result).toBe(
|
|
125
|
-
`export const
|
|
125
|
+
`export const parseItem = (input: unknown): Item => {
|
|
126
126
|
if (!isObject(input)) return {
|
|
127
127
|
id: 0,
|
|
128
128
|
};
|
|
129
129
|
const _id = input.id;
|
|
130
130
|
const _description = input.description;
|
|
131
|
-
if (typeof _id === "number" && (_description === undefined || typeof _description === "string")) return { ...input } as
|
|
131
|
+
if (typeof _id === "number" && (_description === undefined || typeof _description === "string")) return { ...input } as Item;
|
|
132
132
|
return {
|
|
133
133
|
...input,
|
|
134
134
|
id: typeof _id === "number" ? _id : (_id !== undefined ? (Number.isFinite(Number(_id)) ? Number(_id) : 0) : 0),
|
|
135
135
|
...(_description !== undefined && { description: typeof _description === "string" ? _description : String(_description) }),
|
|
136
|
-
} as unknown as
|
|
136
|
+
} as unknown as Item;
|
|
137
137
|
}`,
|
|
138
138
|
)
|
|
139
139
|
})
|
|
@@ -147,16 +147,16 @@ describe('generate-parser-function', () => {
|
|
|
147
147
|
},
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
const result = generateParserFunction(schema, '
|
|
150
|
+
const result = generateParserFunction(schema, 'Mixed')
|
|
151
151
|
|
|
152
152
|
expect(result).toBe(
|
|
153
|
-
`export const
|
|
154
|
-
if (!isObject(input)) return {} as
|
|
153
|
+
`export const parseMixed = (input: unknown): Mixed => {
|
|
154
|
+
if (!isObject(input)) return {} as Mixed;
|
|
155
155
|
const _validProp = input.validProp;
|
|
156
156
|
return {
|
|
157
157
|
...input,
|
|
158
158
|
...(_validProp !== undefined && { validProp: typeof _validProp === "string" ? _validProp : String(_validProp) }),
|
|
159
|
-
} as unknown as
|
|
159
|
+
} as unknown as Mixed;
|
|
160
160
|
}`,
|
|
161
161
|
)
|
|
162
162
|
})
|
|
@@ -169,16 +169,16 @@ describe('generate-parser-function', () => {
|
|
|
169
169
|
},
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
const result = generateParserFunction(schema, '
|
|
172
|
+
const result = generateParserFunction(schema, 'User')
|
|
173
173
|
|
|
174
174
|
expect(result).toBe(
|
|
175
|
-
`export const
|
|
176
|
-
if (!isObject(input)) return {} as
|
|
175
|
+
`export const parseUser = (input: unknown): User => {
|
|
176
|
+
if (!isObject(input)) return {} as User;
|
|
177
177
|
const _contact = input.contact;
|
|
178
178
|
return {
|
|
179
179
|
...input,
|
|
180
180
|
...(_contact !== undefined && { contact: _contact ?? undefined }),
|
|
181
|
-
} as unknown as
|
|
181
|
+
} as unknown as User;
|
|
182
182
|
}`,
|
|
183
183
|
)
|
|
184
184
|
})
|
|
@@ -192,19 +192,19 @@ describe('generate-parser-function', () => {
|
|
|
192
192
|
required: ['contact'],
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
const result = generateParserFunction(schema, '
|
|
195
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
196
196
|
|
|
197
197
|
expect(result).toBe(
|
|
198
|
-
`export const
|
|
198
|
+
`export const parseUser = (input: unknown): User => {
|
|
199
199
|
if (!isObject(input)) return {
|
|
200
|
-
contact:
|
|
200
|
+
contact: parseContact(undefined),
|
|
201
201
|
};
|
|
202
202
|
const _contact = input.contact;
|
|
203
|
-
if (
|
|
203
|
+
if (validateContactShape(_contact)) return { ...input } as User;
|
|
204
204
|
return {
|
|
205
205
|
...input,
|
|
206
|
-
contact:
|
|
207
|
-
} as unknown as
|
|
206
|
+
contact: parseContact(_contact),
|
|
207
|
+
} as unknown as User;
|
|
208
208
|
}`,
|
|
209
209
|
)
|
|
210
210
|
})
|
|
@@ -217,17 +217,17 @@ describe('generate-parser-function', () => {
|
|
|
217
217
|
},
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
const result = generateParserFunction(schema, '
|
|
220
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
221
221
|
|
|
222
222
|
expect(result).toBe(
|
|
223
|
-
`export const
|
|
224
|
-
if (!isObject(input)) return {} as
|
|
223
|
+
`export const parseUser = (input: unknown): User => {
|
|
224
|
+
if (!isObject(input)) return {} as User;
|
|
225
225
|
const _contact = input.contact;
|
|
226
|
-
if ((_contact === undefined ||
|
|
226
|
+
if ((_contact === undefined || validateContactShape(_contact))) return { ...input } as User;
|
|
227
227
|
return {
|
|
228
228
|
...input,
|
|
229
|
-
...(_contact !== undefined && { contact:
|
|
230
|
-
} as unknown as
|
|
229
|
+
...(_contact !== undefined && { contact: parseContact(_contact) }),
|
|
230
|
+
} as unknown as User;
|
|
231
231
|
}`,
|
|
232
232
|
)
|
|
233
233
|
})
|
|
@@ -244,19 +244,19 @@ describe('generate-parser-function', () => {
|
|
|
244
244
|
required: ['contacts'],
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
const result = generateParserFunction(schema, '
|
|
247
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
248
248
|
|
|
249
249
|
expect(result).toBe(
|
|
250
|
-
`export const
|
|
250
|
+
`export const parseUser = (input: unknown): User => {
|
|
251
251
|
if (!isObject(input)) return {
|
|
252
252
|
contacts: [],
|
|
253
253
|
};
|
|
254
254
|
const _contacts = input.contacts;
|
|
255
|
-
if (Array.isArray(_contacts) && _contacts.every(
|
|
255
|
+
if (Array.isArray(_contacts) && _contacts.every(validateContactShape)) return { ...input } as User;
|
|
256
256
|
return {
|
|
257
257
|
...input,
|
|
258
|
-
contacts: validateArray(_contacts,
|
|
259
|
-
} as unknown as
|
|
258
|
+
contacts: validateArray(_contacts, parseContact),
|
|
259
|
+
} as unknown as User;
|
|
260
260
|
}`,
|
|
261
261
|
)
|
|
262
262
|
})
|
|
@@ -272,17 +272,17 @@ describe('generate-parser-function', () => {
|
|
|
272
272
|
},
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
const result = generateParserFunction(schema, '
|
|
275
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
276
276
|
|
|
277
277
|
expect(result).toBe(
|
|
278
|
-
`export const
|
|
279
|
-
if (!isObject(input)) return {} as
|
|
278
|
+
`export const parseUser = (input: unknown): User => {
|
|
279
|
+
if (!isObject(input)) return {} as User;
|
|
280
280
|
const _contacts = input.contacts;
|
|
281
|
-
if ((_contacts === undefined || Array.isArray(_contacts) && _contacts.every(
|
|
281
|
+
if ((_contacts === undefined || Array.isArray(_contacts) && _contacts.every(validateContactShape))) return { ...input } as User;
|
|
282
282
|
return {
|
|
283
283
|
...input,
|
|
284
|
-
...(_contacts !== undefined && { contacts: validateArray(_contacts,
|
|
285
|
-
} as unknown as
|
|
284
|
+
...(_contacts !== undefined && { contacts: validateArray(_contacts, parseContact) }),
|
|
285
|
+
} as unknown as User;
|
|
286
286
|
}`,
|
|
287
287
|
)
|
|
288
288
|
})
|
|
@@ -298,17 +298,17 @@ describe('generate-parser-function', () => {
|
|
|
298
298
|
},
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
const result = generateParserFunction(schema, '
|
|
301
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: false })
|
|
302
302
|
|
|
303
303
|
expect(result).toBe(
|
|
304
|
-
`export const
|
|
305
|
-
if (!isObject(input)) return {} as
|
|
304
|
+
`export const parseUser = (input: unknown): User => {
|
|
305
|
+
if (!isObject(input)) return {} as User;
|
|
306
306
|
const _contacts = input.contacts;
|
|
307
|
-
if ((_contacts === undefined || Array.isArray(_contacts))) return { ...input } as
|
|
307
|
+
if ((_contacts === undefined || Array.isArray(_contacts))) return { ...input } as User;
|
|
308
308
|
return {
|
|
309
309
|
...input,
|
|
310
310
|
...(_contacts !== undefined && { contacts: Array.isArray(_contacts) ? _contacts : [] }),
|
|
311
|
-
} as unknown as
|
|
311
|
+
} as unknown as User;
|
|
312
312
|
}`,
|
|
313
313
|
)
|
|
314
314
|
})
|
|
@@ -321,10 +321,10 @@ describe('generate-parser-function', () => {
|
|
|
321
321
|
},
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
-
const result = generateParserFunction(schema, '
|
|
324
|
+
const result = generateParserFunction(schema, 'StringMap')
|
|
325
325
|
|
|
326
326
|
expect(result).toBe(
|
|
327
|
-
'export const
|
|
327
|
+
'export const parseStringMap = (input: unknown): StringMap => validateRecord(input, (value: unknown) => typeof value === "string" ? value : "") as StringMap;',
|
|
328
328
|
)
|
|
329
329
|
})
|
|
330
330
|
|
|
@@ -336,10 +336,10 @@ describe('generate-parser-function', () => {
|
|
|
336
336
|
},
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
const result = generateParserFunction(schema, '
|
|
339
|
+
const result = generateParserFunction(schema, 'ContactMap', { useRefImports: false })
|
|
340
340
|
|
|
341
341
|
expect(result).toBe(
|
|
342
|
-
`export const
|
|
342
|
+
`export const parseContactMap = (input: unknown): ContactMap => isObject(input) ? { ...input } as ContactMap : {};`,
|
|
343
343
|
)
|
|
344
344
|
})
|
|
345
345
|
|
|
@@ -351,10 +351,10 @@ describe('generate-parser-function', () => {
|
|
|
351
351
|
},
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
-
const result = generateParserFunction(schema, '
|
|
354
|
+
const result = generateParserFunction(schema, 'ContactMap', { useRefImports: true })
|
|
355
355
|
|
|
356
356
|
expect(result).toBe(
|
|
357
|
-
`export const
|
|
357
|
+
`export const parseContactMap = (input: unknown): ContactMap => validateRecord(input, parseContact) as ContactMap;`,
|
|
358
358
|
)
|
|
359
359
|
})
|
|
360
360
|
|
|
@@ -364,10 +364,10 @@ describe('generate-parser-function', () => {
|
|
|
364
364
|
additionalProperties: false,
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
const result = generateParserFunction(schema, '
|
|
367
|
+
const result = generateParserFunction(schema, 'Strict')
|
|
368
368
|
|
|
369
369
|
expect(result).toBe(
|
|
370
|
-
'export const
|
|
370
|
+
'export const parseStrict = (input: unknown): Strict => isObject(input) ? { ...input } as Strict : {} as Strict;',
|
|
371
371
|
)
|
|
372
372
|
})
|
|
373
373
|
|
|
@@ -384,10 +384,10 @@ describe('generate-parser-function', () => {
|
|
|
384
384
|
required: ['id', 'name'],
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
const result = generateParserFunction(schema, '
|
|
387
|
+
const result = generateParserFunction(schema, 'Complex')
|
|
388
388
|
|
|
389
389
|
expect(result).toBe(
|
|
390
|
-
`export const
|
|
390
|
+
`export const parseComplex = (input: unknown): Complex => {
|
|
391
391
|
if (!isObject(input)) return {
|
|
392
392
|
id: 0,
|
|
393
393
|
name: "",
|
|
@@ -397,7 +397,7 @@ describe('generate-parser-function', () => {
|
|
|
397
397
|
const _tags = input.tags;
|
|
398
398
|
const _metadata = input.metadata;
|
|
399
399
|
const _isActive = input.isActive;
|
|
400
|
-
if (typeof _id === "number" && typeof _name === "string" && (_tags === undefined || Array.isArray(_tags)) && (_metadata === undefined || isObject(_metadata)) && (_isActive === undefined || typeof _isActive === "boolean")) return { ...input } as
|
|
400
|
+
if (typeof _id === "number" && typeof _name === "string" && (_tags === undefined || Array.isArray(_tags)) && (_metadata === undefined || isObject(_metadata)) && (_isActive === undefined || typeof _isActive === "boolean")) return { ...input } as Complex;
|
|
401
401
|
return {
|
|
402
402
|
...input,
|
|
403
403
|
id: typeof _id === "number" ? _id : (_id !== undefined ? (Number.isFinite(Number(_id)) ? Number(_id) : 0) : 0),
|
|
@@ -405,7 +405,7 @@ describe('generate-parser-function', () => {
|
|
|
405
405
|
...(_tags !== undefined && { tags: Array.isArray(_tags) ? _tags : [] }),
|
|
406
406
|
...(_metadata !== undefined && { metadata: isObject(_metadata) ? _metadata : typeof _metadata === "object" && _metadata !== null ? _metadata : {} }),
|
|
407
407
|
...(_isActive !== undefined && { isActive: typeof _isActive === "boolean" ? _isActive : Boolean(_isActive) }),
|
|
408
|
-
} as unknown as
|
|
408
|
+
} as unknown as Complex;
|
|
409
409
|
}`,
|
|
410
410
|
)
|
|
411
411
|
})
|
|
@@ -418,17 +418,17 @@ describe('generate-parser-function', () => {
|
|
|
418
418
|
},
|
|
419
419
|
}
|
|
420
420
|
|
|
421
|
-
const result = generateParserFunction(schema, '
|
|
421
|
+
const result = generateParserFunction(schema, 'ApiSpec', { useRefImports: true })
|
|
422
422
|
|
|
423
423
|
expect(result).toBe(
|
|
424
|
-
`export const
|
|
425
|
-
if (!isObject(input)) return {} as
|
|
424
|
+
`export const parseApiSpec = (input: unknown): ApiSpec => {
|
|
425
|
+
if (!isObject(input)) return {} as ApiSpec;
|
|
426
426
|
const _externalDoc = input.externalDoc;
|
|
427
|
-
if ((_externalDoc === undefined ||
|
|
427
|
+
if ((_externalDoc === undefined || validateExternalDocumentationShape(_externalDoc))) return { ...input } as ApiSpec;
|
|
428
428
|
return {
|
|
429
429
|
...input,
|
|
430
|
-
...(_externalDoc !== undefined && { externalDoc:
|
|
431
|
-
} as unknown as
|
|
430
|
+
...(_externalDoc !== undefined && { externalDoc: parseExternalDocumentation(_externalDoc) }),
|
|
431
|
+
} as unknown as ApiSpec;
|
|
432
432
|
}`,
|
|
433
433
|
)
|
|
434
434
|
})
|
|
@@ -444,23 +444,23 @@ describe('generate-parser-function', () => {
|
|
|
444
444
|
required: ['contact'],
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
-
const result = generateParserFunction(schema, '
|
|
447
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
448
448
|
|
|
449
449
|
expect(result).toBe(
|
|
450
|
-
`export const
|
|
450
|
+
`export const parseUser = (input: unknown): User => {
|
|
451
451
|
if (!isObject(input)) return {
|
|
452
|
-
contact:
|
|
452
|
+
contact: parseContact(undefined),
|
|
453
453
|
};
|
|
454
454
|
const _contact = input.contact;
|
|
455
455
|
const _address = input.address;
|
|
456
456
|
const _company = input.company;
|
|
457
|
-
if (
|
|
457
|
+
if (validateContactShape(_contact) && (_address === undefined || validateAddressShape(_address)) && (_company === undefined || validateCompanyShape(_company))) return { ...input } as User;
|
|
458
458
|
return {
|
|
459
459
|
...input,
|
|
460
|
-
contact:
|
|
461
|
-
...(_address !== undefined && { address:
|
|
462
|
-
...(_company !== undefined && { company:
|
|
463
|
-
} as unknown as
|
|
460
|
+
contact: parseContact(_contact),
|
|
461
|
+
...(_address !== undefined && { address: parseAddress(_address) }),
|
|
462
|
+
...(_company !== undefined && { company: parseCompany(_company) }),
|
|
463
|
+
} as unknown as User;
|
|
464
464
|
}`,
|
|
465
465
|
)
|
|
466
466
|
})
|
|
@@ -476,10 +476,10 @@ describe('generate-parser-function', () => {
|
|
|
476
476
|
required: ['id', 'name'],
|
|
477
477
|
}
|
|
478
478
|
|
|
479
|
-
const result = generateParserFunction(schema, '
|
|
479
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
480
480
|
|
|
481
481
|
expect(result).toBe(
|
|
482
|
-
`export const
|
|
482
|
+
`export const parseUser = (input: unknown): User => {
|
|
483
483
|
if (!isObject(input)) return {
|
|
484
484
|
id: 0,
|
|
485
485
|
name: "",
|
|
@@ -487,13 +487,13 @@ describe('generate-parser-function', () => {
|
|
|
487
487
|
const _id = input.id;
|
|
488
488
|
const _contact = input.contact;
|
|
489
489
|
const _name = input.name;
|
|
490
|
-
if (typeof _id === "number" && (_contact === undefined ||
|
|
490
|
+
if (typeof _id === "number" && (_contact === undefined || validateContactShape(_contact)) && typeof _name === "string") return { ...input } as User;
|
|
491
491
|
return {
|
|
492
492
|
...input,
|
|
493
493
|
id: typeof _id === "number" ? _id : (_id !== undefined ? (Number.isFinite(Number(_id)) ? Number(_id) : 0) : 0),
|
|
494
|
-
...(_contact !== undefined && { contact:
|
|
494
|
+
...(_contact !== undefined && { contact: parseContact(_contact) }),
|
|
495
495
|
name: typeof _name === "string" ? _name : (_name !== undefined ? String(_name) : ""),
|
|
496
|
-
} as unknown as
|
|
496
|
+
} as unknown as User;
|
|
497
497
|
}`,
|
|
498
498
|
)
|
|
499
499
|
})
|
|
@@ -509,17 +509,17 @@ describe('generate-parser-function', () => {
|
|
|
509
509
|
},
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
-
const result = generateParserFunction(schema, '
|
|
512
|
+
const result = generateParserFunction(schema, 'Tagged', { useRefImports: true })
|
|
513
513
|
|
|
514
514
|
expect(result).toBe(
|
|
515
|
-
`export const
|
|
516
|
-
if (!isObject(input)) return {} as
|
|
515
|
+
`export const parseTagged = (input: unknown): Tagged => {
|
|
516
|
+
if (!isObject(input)) return {} as Tagged;
|
|
517
517
|
const _tags = input.tags;
|
|
518
|
-
if ((_tags === undefined || Array.isArray(_tags))) return { ...input } as
|
|
518
|
+
if ((_tags === undefined || Array.isArray(_tags))) return { ...input } as Tagged;
|
|
519
519
|
return {
|
|
520
520
|
...input,
|
|
521
521
|
...(_tags !== undefined && { tags: Array.isArray(_tags) ? _tags : [] }),
|
|
522
|
-
} as unknown as
|
|
522
|
+
} as unknown as Tagged;
|
|
523
523
|
}`,
|
|
524
524
|
)
|
|
525
525
|
})
|
|
@@ -534,17 +534,17 @@ describe('generate-parser-function', () => {
|
|
|
534
534
|
},
|
|
535
535
|
}
|
|
536
536
|
|
|
537
|
-
const result = generateParserFunction(schema, '
|
|
537
|
+
const result = generateParserFunction(schema, 'ItemsContainer', { useRefImports: true })
|
|
538
538
|
|
|
539
539
|
expect(result).toBe(
|
|
540
|
-
`export const
|
|
541
|
-
if (!isObject(input)) return {} as
|
|
540
|
+
`export const parseItemsContainer = (input: unknown): ItemsContainer => {
|
|
541
|
+
if (!isObject(input)) return {} as ItemsContainer;
|
|
542
542
|
const _items = input.items;
|
|
543
|
-
if ((_items === undefined || Array.isArray(_items))) return { ...input } as
|
|
543
|
+
if ((_items === undefined || Array.isArray(_items))) return { ...input } as ItemsContainer;
|
|
544
544
|
return {
|
|
545
545
|
...input,
|
|
546
546
|
...(_items !== undefined && { items: Array.isArray(_items) ? _items : [] }),
|
|
547
|
-
} as unknown as
|
|
547
|
+
} as unknown as ItemsContainer;
|
|
548
548
|
}`,
|
|
549
549
|
)
|
|
550
550
|
})
|
|
@@ -558,19 +558,19 @@ describe('generate-parser-function', () => {
|
|
|
558
558
|
},
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
-
const result = generateParserFunction(schema, '
|
|
561
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
562
562
|
|
|
563
563
|
expect(result).toBe(
|
|
564
|
-
`export const
|
|
565
|
-
if (!isObject(input)) return {} as
|
|
564
|
+
`export const parseUser = (input: unknown): User => {
|
|
565
|
+
if (!isObject(input)) return {} as User;
|
|
566
566
|
const _contact = input.contact;
|
|
567
567
|
const _age = input.age;
|
|
568
|
-
if ((_contact === undefined ||
|
|
568
|
+
if ((_contact === undefined || validateContactShape(_contact)) && (_age === undefined || typeof _age === "number")) return { ...input } as User;
|
|
569
569
|
return {
|
|
570
570
|
...input,
|
|
571
|
-
...(_contact !== undefined && { contact:
|
|
571
|
+
...(_contact !== undefined && { contact: parseContact(_contact) }),
|
|
572
572
|
...(_age !== undefined && { age: typeof _age === "number" ? _age : (Number.isFinite(Number(_age)) ? Number(_age) : 0) }),
|
|
573
|
-
} as unknown as
|
|
573
|
+
} as unknown as User;
|
|
574
574
|
}`,
|
|
575
575
|
)
|
|
576
576
|
})
|
|
@@ -581,14 +581,14 @@ describe('generate-parser-function', () => {
|
|
|
581
581
|
properties: {},
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
-
const result = generateParserFunction(schema, '
|
|
584
|
+
const result = generateParserFunction(schema, 'Empty')
|
|
585
585
|
|
|
586
586
|
expect(result).toBe(
|
|
587
|
-
`export const
|
|
588
|
-
if (!isObject(input)) return {} as
|
|
587
|
+
`export const parseEmpty = (input: unknown): Empty => {
|
|
588
|
+
if (!isObject(input)) return {} as Empty;
|
|
589
589
|
return {
|
|
590
590
|
...input,
|
|
591
|
-
} as unknown as
|
|
591
|
+
} as unknown as Empty;
|
|
592
592
|
}`,
|
|
593
593
|
)
|
|
594
594
|
})
|
|
@@ -603,14 +603,14 @@ describe('generate-parser-function', () => {
|
|
|
603
603
|
},
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
const result = generateParserFunction(schema, '
|
|
606
|
+
const result = generateParserFunction(schema, 'AllInvalid')
|
|
607
607
|
|
|
608
608
|
expect(result).toBe(
|
|
609
|
-
`export const
|
|
610
|
-
if (!isObject(input)) return {} as
|
|
609
|
+
`export const parseAllInvalid = (input: unknown): AllInvalid => {
|
|
610
|
+
if (!isObject(input)) return {} as AllInvalid;
|
|
611
611
|
return {
|
|
612
612
|
...input,
|
|
613
|
-
} as unknown as
|
|
613
|
+
} as unknown as AllInvalid;
|
|
614
614
|
}`,
|
|
615
615
|
)
|
|
616
616
|
})
|
|
@@ -623,17 +623,17 @@ describe('generate-parser-function', () => {
|
|
|
623
623
|
},
|
|
624
624
|
}
|
|
625
625
|
|
|
626
|
-
const result = generateParserFunction(schema, '
|
|
626
|
+
const result = generateParserFunction(schema, 'MyCustomType')
|
|
627
627
|
|
|
628
628
|
expect(result).toBe(
|
|
629
|
-
`export const
|
|
630
|
-
if (!isObject(input)) return {} as
|
|
629
|
+
`export const parseMyCustomType = (input: unknown): MyCustomType => {
|
|
630
|
+
if (!isObject(input)) return {} as MyCustomType;
|
|
631
631
|
const _id = input.id;
|
|
632
|
-
if ((_id === undefined || typeof _id === "number")) return { ...input } as
|
|
632
|
+
if ((_id === undefined || typeof _id === "number")) return { ...input } as MyCustomType;
|
|
633
633
|
return {
|
|
634
634
|
...input,
|
|
635
635
|
...(_id !== undefined && { id: typeof _id === "number" ? _id : (Number.isFinite(Number(_id)) ? Number(_id) : 0) }),
|
|
636
|
-
} as unknown as
|
|
636
|
+
} as unknown as MyCustomType;
|
|
637
637
|
}`,
|
|
638
638
|
)
|
|
639
639
|
})
|
|
@@ -646,17 +646,17 @@ describe('generate-parser-function', () => {
|
|
|
646
646
|
},
|
|
647
647
|
}
|
|
648
648
|
|
|
649
|
-
const result = generateParserFunction(schema, '
|
|
649
|
+
const result = generateParserFunction(schema, 'myCustomType')
|
|
650
650
|
|
|
651
651
|
expect(result).toBe(
|
|
652
|
-
`export const
|
|
653
|
-
if (!isObject(input)) return {} as
|
|
652
|
+
`export const parsemyCustomType = (input: unknown): myCustomType => {
|
|
653
|
+
if (!isObject(input)) return {} as myCustomType;
|
|
654
654
|
const _id = input.id;
|
|
655
|
-
if ((_id === undefined || typeof _id === "number")) return { ...input } as
|
|
655
|
+
if ((_id === undefined || typeof _id === "number")) return { ...input } as myCustomType;
|
|
656
656
|
return {
|
|
657
657
|
...input,
|
|
658
658
|
...(_id !== undefined && { id: typeof _id === "number" ? _id : (Number.isFinite(Number(_id)) ? Number(_id) : 0) }),
|
|
659
|
-
} as unknown as
|
|
659
|
+
} as unknown as myCustomType;
|
|
660
660
|
}`,
|
|
661
661
|
)
|
|
662
662
|
})
|
|
@@ -668,17 +668,17 @@ describe('generate-parser-function', () => {
|
|
|
668
668
|
},
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
-
const result = generateParserFunction(schema, '
|
|
671
|
+
const result = generateParserFunction(schema, 'Implicit')
|
|
672
672
|
|
|
673
673
|
expect(result).toBe(
|
|
674
|
-
`export const
|
|
675
|
-
if (!isObject(input)) return {} as
|
|
674
|
+
`export const parseImplicit = (input: unknown): Implicit => {
|
|
675
|
+
if (!isObject(input)) return {} as Implicit;
|
|
676
676
|
const _name = input.name;
|
|
677
|
-
if ((_name === undefined || typeof _name === "string")) return { ...input } as
|
|
677
|
+
if ((_name === undefined || typeof _name === "string")) return { ...input } as Implicit;
|
|
678
678
|
return {
|
|
679
679
|
...input,
|
|
680
680
|
...(_name !== undefined && { name: typeof _name === "string" ? _name : String(_name) }),
|
|
681
|
-
} as unknown as
|
|
681
|
+
} as unknown as Implicit;
|
|
682
682
|
}`,
|
|
683
683
|
)
|
|
684
684
|
})
|
|
@@ -689,10 +689,10 @@ describe('generate-parser-function', () => {
|
|
|
689
689
|
additionalProperties: true,
|
|
690
690
|
}
|
|
691
691
|
|
|
692
|
-
const result = generateParserFunction(schema, '
|
|
692
|
+
const result = generateParserFunction(schema, 'AnyAdditional')
|
|
693
693
|
|
|
694
694
|
expect(result).toBe(
|
|
695
|
-
'export const
|
|
695
|
+
'export const parseAnyAdditional = (input: unknown): AnyAdditional => isObject(input) ? { ...input } as AnyAdditional : {} as AnyAdditional;',
|
|
696
696
|
)
|
|
697
697
|
})
|
|
698
698
|
|
|
@@ -704,10 +704,10 @@ describe('generate-parser-function', () => {
|
|
|
704
704
|
},
|
|
705
705
|
}
|
|
706
706
|
|
|
707
|
-
const result = generateParserFunction(schema, '
|
|
707
|
+
const result = generateParserFunction(schema, 'MapOfStrings', { useRefImports: true })
|
|
708
708
|
|
|
709
709
|
expect(result).toBe(
|
|
710
|
-
'export const
|
|
710
|
+
'export const parseMapOfStrings = (input: unknown): MapOfStrings => validateRecord(input, (value: unknown) => typeof value === "string" ? value : "") as MapOfStrings;',
|
|
711
711
|
)
|
|
712
712
|
})
|
|
713
713
|
|
|
@@ -722,10 +722,10 @@ describe('generate-parser-function', () => {
|
|
|
722
722
|
},
|
|
723
723
|
}
|
|
724
724
|
|
|
725
|
-
const result = generateParserFunction(schema, '
|
|
725
|
+
const result = generateParserFunction(schema, 'SecurityRequirement', { useRefImports: true })
|
|
726
726
|
|
|
727
727
|
expect(result).toBe(
|
|
728
|
-
'export const
|
|
728
|
+
'export const parseSecurityRequirement = (input: unknown): SecurityRequirement => validateRecord(input, (value: unknown) => Array.isArray(value) ? value : []) as SecurityRequirement;',
|
|
729
729
|
)
|
|
730
730
|
})
|
|
731
731
|
|
|
@@ -740,17 +740,17 @@ describe('generate-parser-function', () => {
|
|
|
740
740
|
},
|
|
741
741
|
}
|
|
742
742
|
|
|
743
|
-
const result = generateParserFunction(schema, '
|
|
743
|
+
const result = generateParserFunction(schema, 'Container', { useRefImports: true })
|
|
744
744
|
|
|
745
745
|
expect(result).toBe(
|
|
746
|
-
`export const
|
|
747
|
-
if (!isObject(input)) return {} as
|
|
746
|
+
`export const parseContainer = (input: unknown): Container => {
|
|
747
|
+
if (!isObject(input)) return {} as Container;
|
|
748
748
|
const _data = input.data;
|
|
749
|
-
if ((_data === undefined || Array.isArray(_data))) return { ...input } as
|
|
749
|
+
if ((_data === undefined || Array.isArray(_data))) return { ...input } as Container;
|
|
750
750
|
return {
|
|
751
751
|
...input,
|
|
752
752
|
...(_data !== undefined && { data: Array.isArray(_data) ? _data : [] }),
|
|
753
|
-
} as unknown as
|
|
753
|
+
} as unknown as Container;
|
|
754
754
|
}`,
|
|
755
755
|
)
|
|
756
756
|
})
|
|
@@ -763,17 +763,17 @@ describe('generate-parser-function', () => {
|
|
|
763
763
|
},
|
|
764
764
|
}
|
|
765
765
|
|
|
766
|
-
const result = generateParserFunction(schema, '
|
|
766
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
767
767
|
|
|
768
768
|
expect(result).toBe(
|
|
769
|
-
`export const
|
|
770
|
-
if (!isObject(input)) return {} as
|
|
769
|
+
`export const parseUser = (input: unknown): User => {
|
|
770
|
+
if (!isObject(input)) return {} as User;
|
|
771
771
|
const _nested = input.nested;
|
|
772
|
-
if ((_nested === undefined ||
|
|
772
|
+
if ((_nested === undefined || validateTypeShape(_nested))) return { ...input } as User;
|
|
773
773
|
return {
|
|
774
774
|
...input,
|
|
775
|
-
...(_nested !== undefined && { nested:
|
|
776
|
-
} as unknown as
|
|
775
|
+
...(_nested !== undefined && { nested: parseType(_nested) }),
|
|
776
|
+
} as unknown as User;
|
|
777
777
|
}`,
|
|
778
778
|
)
|
|
779
779
|
})
|
|
@@ -793,19 +793,19 @@ describe('generate-parser-function', () => {
|
|
|
793
793
|
},
|
|
794
794
|
}
|
|
795
795
|
|
|
796
|
-
const result = generateParserFunction(schema, '
|
|
796
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
797
797
|
|
|
798
798
|
expect(result).toBe(
|
|
799
|
-
`export const
|
|
800
|
-
if (!isObject(input)) return {} as
|
|
799
|
+
`export const parseUser = (input: unknown): User => {
|
|
800
|
+
if (!isObject(input)) return {} as User;
|
|
801
801
|
const _contacts = input.contacts;
|
|
802
802
|
const _addresses = input.addresses;
|
|
803
|
-
if ((_contacts === undefined || Array.isArray(_contacts) && _contacts.every(
|
|
803
|
+
if ((_contacts === undefined || Array.isArray(_contacts) && _contacts.every(validateContactShape)) && (_addresses === undefined || Array.isArray(_addresses) && _addresses.every(validateAddressShape))) return { ...input } as User;
|
|
804
804
|
return {
|
|
805
805
|
...input,
|
|
806
|
-
...(_contacts !== undefined && { contacts: validateArray(_contacts,
|
|
807
|
-
...(_addresses !== undefined && { addresses: validateArray(_addresses,
|
|
808
|
-
} as unknown as
|
|
806
|
+
...(_contacts !== undefined && { contacts: validateArray(_contacts, parseContact) }),
|
|
807
|
+
...(_addresses !== undefined && { addresses: validateArray(_addresses, parseAddress) }),
|
|
808
|
+
} as unknown as User;
|
|
809
809
|
}`,
|
|
810
810
|
)
|
|
811
811
|
})
|
|
@@ -820,19 +820,19 @@ describe('generate-parser-function', () => {
|
|
|
820
820
|
required: [],
|
|
821
821
|
}
|
|
822
822
|
|
|
823
|
-
const result = generateParserFunction(schema, '
|
|
823
|
+
const result = generateParserFunction(schema, 'User')
|
|
824
824
|
|
|
825
825
|
expect(result).toBe(
|
|
826
|
-
`export const
|
|
827
|
-
if (!isObject(input)) return {} as
|
|
826
|
+
`export const parseUser = (input: unknown): User => {
|
|
827
|
+
if (!isObject(input)) return {} as User;
|
|
828
828
|
const _id = input.id;
|
|
829
829
|
const _name = input.name;
|
|
830
|
-
if ((_id === undefined || typeof _id === "number") && (_name === undefined || typeof _name === "string")) return { ...input } as
|
|
830
|
+
if ((_id === undefined || typeof _id === "number") && (_name === undefined || typeof _name === "string")) return { ...input } as User;
|
|
831
831
|
return {
|
|
832
832
|
...input,
|
|
833
833
|
...(_id !== undefined && { id: typeof _id === "number" ? _id : (Number.isFinite(Number(_id)) ? Number(_id) : 0) }),
|
|
834
834
|
...(_name !== undefined && { name: typeof _name === "string" ? _name : String(_name) }),
|
|
835
|
-
} as unknown as
|
|
835
|
+
} as unknown as User;
|
|
836
836
|
}`,
|
|
837
837
|
)
|
|
838
838
|
})
|
|
@@ -845,17 +845,17 @@ describe('generate-parser-function', () => {
|
|
|
845
845
|
},
|
|
846
846
|
}
|
|
847
847
|
|
|
848
|
-
const result = generateParserFunction(schema, '
|
|
848
|
+
const result = generateParserFunction(schema, 'User')
|
|
849
849
|
|
|
850
850
|
expect(result).toBe(
|
|
851
|
-
`export const
|
|
852
|
-
if (!isObject(input)) return {} as
|
|
851
|
+
`export const parseUser = (input: unknown): User => {
|
|
852
|
+
if (!isObject(input)) return {} as User;
|
|
853
853
|
const _id = input.id;
|
|
854
|
-
if ((_id === undefined || typeof _id === "number")) return { ...input } as
|
|
854
|
+
if ((_id === undefined || typeof _id === "number")) return { ...input } as User;
|
|
855
855
|
return {
|
|
856
856
|
...input,
|
|
857
857
|
...(_id !== undefined && { id: typeof _id === "number" ? _id : (Number.isFinite(Number(_id)) ? Number(_id) : 0) }),
|
|
858
|
-
} as unknown as
|
|
858
|
+
} as unknown as User;
|
|
859
859
|
}`,
|
|
860
860
|
)
|
|
861
861
|
})
|
|
@@ -868,11 +868,9 @@ describe('generate-parser-function', () => {
|
|
|
868
868
|
},
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
const result = generateParserFunction(schema, '
|
|
871
|
+
const result = generateParserFunction(schema, 'Map', { useRefImports: true })
|
|
872
872
|
|
|
873
|
-
expect(result).toBe(
|
|
874
|
-
`export const parseMapObject = (input: unknown): MapObject => validateRecord(input, parseValueObject) as MapObject;`,
|
|
875
|
-
)
|
|
873
|
+
expect(result).toBe(`export const parseMap = (input: unknown): Map => validateRecord(input, parseValue) as Map;`)
|
|
876
874
|
})
|
|
877
875
|
|
|
878
876
|
it('generates a simple object pass-through parser for allOf-only schema', () => {
|
|
@@ -883,10 +881,10 @@ describe('generate-parser-function', () => {
|
|
|
883
881
|
allOf: [{ $ref: '#/$defs/type-apikey' }, { $ref: '#/$defs/type-http-bearer' }, { $ref: '#/$defs/type-oauth2' }],
|
|
884
882
|
}
|
|
885
883
|
|
|
886
|
-
const result = generateParserFunction(schema, '
|
|
884
|
+
const result = generateParserFunction(schema, 'SecurityScheme', { useRefImports: true })
|
|
887
885
|
|
|
888
886
|
expect(result).toBe(
|
|
889
|
-
`export const
|
|
887
|
+
`export const parseSecurityScheme = (input: unknown): SecurityScheme => isObject(input) ? { ...input } as SecurityScheme : {} as SecurityScheme;`,
|
|
890
888
|
)
|
|
891
889
|
})
|
|
892
890
|
|
|
@@ -913,21 +911,21 @@ describe('generate-parser-function', () => {
|
|
|
913
911
|
},
|
|
914
912
|
}
|
|
915
913
|
|
|
916
|
-
const result = generateParserFunction(components, '
|
|
914
|
+
const result = generateParserFunction(components, 'Components', { useRefImports: true })
|
|
917
915
|
expect(result).toBe(
|
|
918
|
-
`export const
|
|
919
|
-
if (!isObject(input)) return {} as
|
|
916
|
+
`export const parseComponents = (input: unknown): Components => {
|
|
917
|
+
if (!isObject(input)) return {} as Components;
|
|
920
918
|
const _responses = input.responses;
|
|
921
919
|
const _parameters = input.parameters;
|
|
922
920
|
const _headers = input.headers;
|
|
923
921
|
const _pathItems = input.pathItems;
|
|
924
922
|
return {
|
|
925
923
|
...input,
|
|
926
|
-
...(_responses !== undefined && { responses: validateRecord(_responses,
|
|
927
|
-
...(_parameters !== undefined && { parameters: validateRecord(_parameters,
|
|
928
|
-
...(_headers !== undefined && { headers: validateRecord(_headers,
|
|
929
|
-
...(_pathItems !== undefined && { pathItems: validateRecord(_pathItems,
|
|
930
|
-
} as unknown as
|
|
924
|
+
...(_responses !== undefined && { responses: validateRecord(_responses, parseResponse) }),
|
|
925
|
+
...(_parameters !== undefined && { parameters: validateRecord(_parameters, parseParameter) }),
|
|
926
|
+
...(_headers !== undefined && { headers: validateRecord(_headers, parseHeader) }),
|
|
927
|
+
...(_pathItems !== undefined && { pathItems: validateRecord(_pathItems, parsePathItem) }),
|
|
928
|
+
} as unknown as Components;
|
|
931
929
|
}`,
|
|
932
930
|
)
|
|
933
931
|
})
|
|
@@ -939,10 +937,10 @@ describe('generate-parser-function', () => {
|
|
|
939
937
|
else: { $ref: '#/$defs/callbacks' },
|
|
940
938
|
}
|
|
941
939
|
|
|
942
|
-
const result = generateParserFunction(schema, '
|
|
940
|
+
const result = generateParserFunction(schema, 'Conditional')
|
|
943
941
|
expect(result).toBe(
|
|
944
|
-
`export const
|
|
945
|
-
hasRef(input) ?
|
|
942
|
+
`export const parseConditional = (input: unknown): Conditional | Reference =>
|
|
943
|
+
hasRef(input) ? parseReference(input) : parseCallbacks(input)
|
|
946
944
|
`,
|
|
947
945
|
)
|
|
948
946
|
})
|
|
@@ -958,20 +956,20 @@ describe('generate-parser-function', () => {
|
|
|
958
956
|
unevaluatedProperties: false,
|
|
959
957
|
}
|
|
960
958
|
|
|
961
|
-
const result = generateParserFunction(schema, '
|
|
959
|
+
const result = generateParserFunction(schema, 'Paths', { useRefImports: true })
|
|
962
960
|
|
|
963
961
|
expect(result).toBe(
|
|
964
|
-
`export const
|
|
962
|
+
`export const parsePaths = (input: unknown): Paths => {
|
|
965
963
|
if (!isObject(input)) {
|
|
966
|
-
return {} as unknown as
|
|
964
|
+
return {} as unknown as Paths;
|
|
967
965
|
}
|
|
968
966
|
const result = {
|
|
969
967
|
...input,
|
|
970
|
-
} as unknown as
|
|
968
|
+
} as unknown as Paths;
|
|
971
969
|
for (const key in input) {
|
|
972
970
|
if (/^\\//.test(key)) {
|
|
973
971
|
const value = input[key];
|
|
974
|
-
(result as Record<string, unknown>)[key] =
|
|
972
|
+
(result as Record<string, unknown>)[key] = parsePathItem(value);
|
|
975
973
|
}
|
|
976
974
|
}
|
|
977
975
|
return result;
|
|
@@ -980,7 +978,7 @@ describe('generate-parser-function', () => {
|
|
|
980
978
|
})
|
|
981
979
|
|
|
982
980
|
it('generates a simple object pass-through parser for allOf-only schema with multiple subtypes', () => {
|
|
983
|
-
// With the OpenAPI
|
|
981
|
+
// With the OpenAPI SecurityScheme dispatcher logic removed, a schema that only has
|
|
984
982
|
// allOf refs and no fixed properties generates a simple spread parser.
|
|
985
983
|
const schema: JSONSchema = {
|
|
986
984
|
type: 'object',
|
|
@@ -993,10 +991,10 @@ describe('generate-parser-function', () => {
|
|
|
993
991
|
],
|
|
994
992
|
}
|
|
995
993
|
|
|
996
|
-
const result = generateParserFunction(schema, '
|
|
994
|
+
const result = generateParserFunction(schema, 'SecurityScheme', { useRefImports: true })
|
|
997
995
|
|
|
998
996
|
expect(result).toBe(
|
|
999
|
-
`export const
|
|
997
|
+
`export const parseSecurityScheme = (input: unknown): SecurityScheme => isObject(input) ? { ...input } as SecurityScheme : {} as SecurityScheme;`,
|
|
1000
998
|
)
|
|
1001
999
|
})
|
|
1002
1000
|
|
|
@@ -1011,7 +1009,7 @@ describe('generate-parser-function', () => {
|
|
|
1011
1009
|
|
|
1012
1010
|
// This works correctly because additionalProperties is handled
|
|
1013
1011
|
expect(result).toBe(
|
|
1014
|
-
`export const parseWebhooks = (input: unknown): Webhooks => validateRecord(input,
|
|
1012
|
+
`export const parseWebhooks = (input: unknown): Webhooks => validateRecord(input, parsePathItem) as Webhooks;`,
|
|
1015
1013
|
)
|
|
1016
1014
|
expect(result).not.toContain('input as Webhooks')
|
|
1017
1015
|
})
|
|
@@ -1038,7 +1036,7 @@ describe('generate-parser-function', () => {
|
|
|
1038
1036
|
for (const key in input) {
|
|
1039
1037
|
if (/^\\//.test(key)) {
|
|
1040
1038
|
const value = input[key];
|
|
1041
|
-
(result as Record<string, unknown>)[key] =
|
|
1039
|
+
(result as Record<string, unknown>)[key] = parsePathItem(value);
|
|
1042
1040
|
}
|
|
1043
1041
|
}
|
|
1044
1042
|
return result;
|
|
@@ -1072,7 +1070,7 @@ describe('generate-parser-function', () => {
|
|
|
1072
1070
|
expect(result).toBe(`export const parseDocument = (input: unknown): Document => {
|
|
1073
1071
|
if (!isObject(input)) return {
|
|
1074
1072
|
openapi: "",
|
|
1075
|
-
info:
|
|
1073
|
+
info: parseInfo(undefined),
|
|
1076
1074
|
};
|
|
1077
1075
|
const _openapi = input.openapi;
|
|
1078
1076
|
const _info = input.info;
|
|
@@ -1084,12 +1082,12 @@ describe('generate-parser-function', () => {
|
|
|
1084
1082
|
return {
|
|
1085
1083
|
...input,
|
|
1086
1084
|
openapi: typeof _openapi === "string" ? _openapi : (_openapi !== undefined ? String(_openapi) : ""),
|
|
1087
|
-
info:
|
|
1088
|
-
...(_servers !== undefined && { servers: validateArray(_servers,
|
|
1089
|
-
...(_paths !== undefined && { paths:
|
|
1090
|
-
...(_webhooks !== undefined && { webhooks: validateRecord(_webhooks,
|
|
1091
|
-
...(_components !== undefined && { components:
|
|
1092
|
-
...(_externalDocs !== undefined && { externalDocs:
|
|
1085
|
+
info: parseInfo(_info),
|
|
1086
|
+
...(_servers !== undefined && { servers: validateArray(_servers, parseServer) }),
|
|
1087
|
+
...(_paths !== undefined && { paths: parsePaths(_paths) }),
|
|
1088
|
+
...(_webhooks !== undefined && { webhooks: validateRecord(_webhooks, parsePathItem) }),
|
|
1089
|
+
...(_components !== undefined && { components: parseComponents(_components) }),
|
|
1090
|
+
...(_externalDocs !== undefined && { externalDocs: parseExternalDocumentation(_externalDocs) }),
|
|
1093
1091
|
} as unknown as Document;
|
|
1094
1092
|
}`)
|
|
1095
1093
|
})
|
|
@@ -1119,10 +1117,10 @@ describe('generate-parser-function', () => {
|
|
|
1119
1117
|
},
|
|
1120
1118
|
}
|
|
1121
1119
|
|
|
1122
|
-
const result = generateParserFunction(schema, '
|
|
1120
|
+
const result = generateParserFunction(schema, 'Components', { useRefImports: true })
|
|
1123
1121
|
expect(result).toBe(
|
|
1124
|
-
`export const
|
|
1125
|
-
if (!isObject(input)) return {} as
|
|
1122
|
+
`export const parseComponents = (input: unknown): Components => {
|
|
1123
|
+
if (!isObject(input)) return {} as Components;
|
|
1126
1124
|
const _schemas = input.schemas;
|
|
1127
1125
|
const _responses = input.responses;
|
|
1128
1126
|
const _parameters = input.parameters;
|
|
@@ -1130,10 +1128,10 @@ describe('generate-parser-function', () => {
|
|
|
1130
1128
|
return {
|
|
1131
1129
|
...input,
|
|
1132
1130
|
...(_schemas !== undefined && { schemas: isObject(_schemas) ? _schemas : typeof _schemas === "object" && _schemas !== null ? _schemas : {} }),
|
|
1133
|
-
...(_responses !== undefined && { responses: validateRecord(_responses,
|
|
1134
|
-
...(_parameters !== undefined && { parameters: validateRecord(_parameters,
|
|
1135
|
-
...(_pathItems !== undefined && { pathItems: validateRecord(_pathItems,
|
|
1136
|
-
} as unknown as
|
|
1131
|
+
...(_responses !== undefined && { responses: validateRecord(_responses, parseResponse) }),
|
|
1132
|
+
...(_parameters !== undefined && { parameters: validateRecord(_parameters, parseParameter) }),
|
|
1133
|
+
...(_pathItems !== undefined && { pathItems: validateRecord(_pathItems, parsePathItem) }),
|
|
1134
|
+
} as unknown as Components;
|
|
1137
1135
|
}`,
|
|
1138
1136
|
)
|
|
1139
1137
|
})
|
|
@@ -1150,21 +1148,21 @@ describe('generate-parser-function', () => {
|
|
|
1150
1148
|
},
|
|
1151
1149
|
}
|
|
1152
1150
|
|
|
1153
|
-
const result = generateParserFunction(schema, '
|
|
1151
|
+
const result = generateParserFunction(schema, 'Responses', { useRefImports: true })
|
|
1154
1152
|
|
|
1155
1153
|
expect(result).toBe(
|
|
1156
|
-
`export const
|
|
1154
|
+
`export const parseResponses = (input: unknown): Responses => {
|
|
1157
1155
|
if (!isObject(input)) {
|
|
1158
|
-
return {} as unknown as
|
|
1156
|
+
return {} as unknown as Responses;
|
|
1159
1157
|
}
|
|
1160
1158
|
const result = {
|
|
1161
1159
|
...input,
|
|
1162
|
-
...(input.default && { default:
|
|
1163
|
-
} as unknown as
|
|
1160
|
+
...(input.default && { default: parseResponse(input.default) }),
|
|
1161
|
+
} as unknown as Responses;
|
|
1164
1162
|
for (const key in input) {
|
|
1165
1163
|
if (/^[1-5](?:[0-9]{2}|XX)$/.test(key)) {
|
|
1166
1164
|
const value = input[key];
|
|
1167
|
-
(result as Record<string, unknown>)[key] =
|
|
1165
|
+
(result as Record<string, unknown>)[key] = parseResponse(value);
|
|
1168
1166
|
}
|
|
1169
1167
|
}
|
|
1170
1168
|
return result;
|
|
@@ -1183,7 +1181,7 @@ describe('generate-parser-function', () => {
|
|
|
1183
1181
|
},
|
|
1184
1182
|
}
|
|
1185
1183
|
|
|
1186
|
-
const result = generateParserFunction(schema, '
|
|
1184
|
+
const result = generateParserFunction(schema, 'Responses', { useRefImports: false })
|
|
1187
1185
|
|
|
1188
1186
|
// Without useRefImports, falls back to regular object parser
|
|
1189
1187
|
expect(result).toContain('isObject(input)')
|
|
@@ -1201,13 +1199,13 @@ describe('generate-parser-function', () => {
|
|
|
1201
1199
|
},
|
|
1202
1200
|
}
|
|
1203
1201
|
|
|
1204
|
-
const result = generateParserFunction(schema, '
|
|
1202
|
+
const result = generateParserFunction(schema, 'Schema', { useRefImports: true })
|
|
1205
1203
|
|
|
1206
|
-
//
|
|
1204
|
+
// Schema is a special case that handles both boolean and object types
|
|
1207
1205
|
expect(result).toContain("if (typeof input === 'boolean')")
|
|
1208
|
-
expect(result).toContain('return input as
|
|
1206
|
+
expect(result).toContain('return input as Schema')
|
|
1209
1207
|
expect(result).toContain('if (!isObject(input))')
|
|
1210
|
-
expect(result).toContain('return {} as
|
|
1208
|
+
expect(result).toContain('return {} as Schema')
|
|
1211
1209
|
})
|
|
1212
1210
|
|
|
1213
1211
|
it('uses bracket notation for hyphenated property keys with $ref', () => {
|
|
@@ -1218,7 +1216,7 @@ describe('generate-parser-function', () => {
|
|
|
1218
1216
|
},
|
|
1219
1217
|
}
|
|
1220
1218
|
|
|
1221
|
-
const result = generateParserFunction(schema, '
|
|
1219
|
+
const result = generateParserFunction(schema, 'InfoExtensions', { useRefImports: true })
|
|
1222
1220
|
|
|
1223
1221
|
expect(result).toContain("input['x-linkedin']")
|
|
1224
1222
|
expect(result).toContain("'x-linkedin':")
|
|
@@ -1233,7 +1231,7 @@ describe('generate-parser-function', () => {
|
|
|
1233
1231
|
},
|
|
1234
1232
|
}
|
|
1235
1233
|
|
|
1236
|
-
const result = generateParserFunction(schema, '
|
|
1234
|
+
const result = generateParserFunction(schema, 'Test')
|
|
1237
1235
|
|
|
1238
1236
|
expect(result).toContain("input['x-custom']")
|
|
1239
1237
|
expect(result).toContain("'x-custom':")
|
|
@@ -1259,12 +1257,12 @@ describe('generate-parser-function', () => {
|
|
|
1259
1257
|
},
|
|
1260
1258
|
}
|
|
1261
1259
|
|
|
1262
|
-
const result = generateParserFunction(schema, '
|
|
1260
|
+
const result = generateParserFunction(schema, 'TypeHttp', { useRefImports: true })
|
|
1263
1261
|
|
|
1264
1262
|
expect(result).toContain('isObject(input)')
|
|
1265
1263
|
expect(result).toContain('type:')
|
|
1266
1264
|
expect(result).toContain('scheme:')
|
|
1267
|
-
expect(result).not.toContain('input as
|
|
1265
|
+
expect(result).not.toContain('input as TypeHttp')
|
|
1268
1266
|
})
|
|
1269
1267
|
|
|
1270
1268
|
it('generates parser for patternProperties-only schema without explicit type', () => {
|
|
@@ -1274,11 +1272,11 @@ describe('generate-parser-function', () => {
|
|
|
1274
1272
|
},
|
|
1275
1273
|
}
|
|
1276
1274
|
|
|
1277
|
-
const result = generateParserFunction(schema, '
|
|
1275
|
+
const result = generateParserFunction(schema, 'SpecificationExtensions', { useRefImports: true })
|
|
1278
1276
|
|
|
1279
1277
|
expect(result).toContain('for (const key in input)')
|
|
1280
1278
|
expect(result).toContain('...input,')
|
|
1281
|
-
expect(result).not.toContain('input as
|
|
1279
|
+
expect(result).not.toContain('input as SpecificationExtensions')
|
|
1282
1280
|
})
|
|
1283
1281
|
|
|
1284
1282
|
it('optimization: inlines variables for simple properties without fast-path', () => {
|
|
@@ -1291,7 +1289,7 @@ describe('generate-parser-function', () => {
|
|
|
1291
1289
|
},
|
|
1292
1290
|
}
|
|
1293
1291
|
|
|
1294
|
-
const result = generateParserFunction(schema, '
|
|
1292
|
+
const result = generateParserFunction(schema, 'Example')
|
|
1295
1293
|
|
|
1296
1294
|
// Should NOT cache variables when no fast-path is possible
|
|
1297
1295
|
// (in this case, fast-path exists, so variables ARE cached)
|
|
@@ -1309,14 +1307,14 @@ describe('generate-parser-function', () => {
|
|
|
1309
1307
|
required: ['name'],
|
|
1310
1308
|
}
|
|
1311
1309
|
|
|
1312
|
-
const result = generateParserFunction(schema, '
|
|
1310
|
+
const result = generateParserFunction(schema, 'User')
|
|
1313
1311
|
|
|
1314
1312
|
// Should cache variables because fast-path exists
|
|
1315
1313
|
expect(result).toContain('const _name = input.name')
|
|
1316
1314
|
expect(result).toContain('const _age = input.age')
|
|
1317
1315
|
// Should have fast-path check
|
|
1318
1316
|
expect(result).toContain('if (typeof _name === "string"')
|
|
1319
|
-
expect(result).toContain('return { ...input } as
|
|
1317
|
+
expect(result).toContain('return { ...input } as User')
|
|
1320
1318
|
})
|
|
1321
1319
|
|
|
1322
1320
|
it('optimization: removes redundant undefined checks in optional properties', () => {
|
|
@@ -1328,7 +1326,7 @@ describe('generate-parser-function', () => {
|
|
|
1328
1326
|
},
|
|
1329
1327
|
}
|
|
1330
1328
|
|
|
1331
|
-
const result = generateParserFunction(schema, '
|
|
1329
|
+
const result = generateParserFunction(schema, 'Example')
|
|
1332
1330
|
|
|
1333
1331
|
// The generated code should have the outer undefined check
|
|
1334
1332
|
expect(result).toContain('!== undefined &&')
|
|
@@ -1347,7 +1345,7 @@ describe('generate-parser-function', () => {
|
|
|
1347
1345
|
},
|
|
1348
1346
|
}
|
|
1349
1347
|
|
|
1350
|
-
const result = generateParserFunction(schema, '
|
|
1348
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
1351
1349
|
|
|
1352
1350
|
// Should still cache because $ref properties always need caching
|
|
1353
1351
|
expect(result).toContain('const _contact = input.contact')
|
|
@@ -1366,7 +1364,7 @@ describe('generate-parser-function', () => {
|
|
|
1366
1364
|
},
|
|
1367
1365
|
}
|
|
1368
1366
|
|
|
1369
|
-
const result = generateParserFunction(schema, '
|
|
1367
|
+
const result = generateParserFunction(schema, 'Code')
|
|
1370
1368
|
|
|
1371
1369
|
// Should cache because property has multiple constraints
|
|
1372
1370
|
expect(result).toContain('const _code = input.code')
|
|
@@ -1382,10 +1380,10 @@ describe('generate-parser-function', () => {
|
|
|
1382
1380
|
required: ['id'],
|
|
1383
1381
|
}
|
|
1384
1382
|
|
|
1385
|
-
const result = generateParserFunction(schema, '
|
|
1383
|
+
const result = generateParserFunction(schema, 'Item')
|
|
1386
1384
|
|
|
1387
1385
|
// Should have fast-path that returns a new shallow copy
|
|
1388
|
-
expect(result).toContain('return { ...input } as
|
|
1386
|
+
expect(result).toContain('return { ...input } as Item')
|
|
1389
1387
|
// Fast-path check should exist
|
|
1390
1388
|
expect(result).toContain('if (typeof _id')
|
|
1391
1389
|
// Should have both fast and slow paths
|
|
@@ -1401,11 +1399,11 @@ describe('generate-parser-function', () => {
|
|
|
1401
1399
|
},
|
|
1402
1400
|
}
|
|
1403
1401
|
|
|
1404
|
-
const result = generateParserFunction(schema, '
|
|
1402
|
+
const result = generateParserFunction(schema, 'User', { useRefImports: true })
|
|
1405
1403
|
|
|
1406
1404
|
// Fast-path now handles refs by calling the imported shape predicate.
|
|
1407
|
-
expect(result).toContain('
|
|
1408
|
-
expect(result).toContain('return { ...input } as
|
|
1405
|
+
expect(result).toContain('validateContactShape(_contact)')
|
|
1406
|
+
expect(result).toContain('return { ...input } as User')
|
|
1409
1407
|
// Slow path still exists for invalid input.
|
|
1410
1408
|
expect(result).toContain('return {')
|
|
1411
1409
|
})
|
|
@@ -1420,10 +1418,10 @@ describe('generate-parser-function', () => {
|
|
|
1420
1418
|
},
|
|
1421
1419
|
}
|
|
1422
1420
|
|
|
1423
|
-
const result = generateParserFunction(schema, '
|
|
1421
|
+
const result = generateParserFunction(schema, 'Optional')
|
|
1424
1422
|
|
|
1425
1423
|
// Should have fast-path for all optional
|
|
1426
|
-
expect(result).toContain('return { ...input } as
|
|
1424
|
+
expect(result).toContain('return { ...input } as Optional')
|
|
1427
1425
|
// Should use spread operators for optional properties
|
|
1428
1426
|
const spreadCount = (result.match(/\.\.\./g) || []).length
|
|
1429
1427
|
expect(spreadCount).toBeGreaterThan(0)
|
|
@@ -1440,14 +1438,14 @@ describe('generate-parser-function', () => {
|
|
|
1440
1438
|
required: ['id', 'name'],
|
|
1441
1439
|
}
|
|
1442
1440
|
|
|
1443
|
-
const result = generateParserFunction(schema, '
|
|
1441
|
+
const result = generateParserFunction(schema, 'User')
|
|
1444
1442
|
|
|
1445
1443
|
// Should cache all variables for fast-path
|
|
1446
1444
|
expect(result).toContain('const _id')
|
|
1447
1445
|
expect(result).toContain('const _name')
|
|
1448
1446
|
expect(result).toContain('const _email')
|
|
1449
1447
|
// Should have fast-path check
|
|
1450
|
-
expect(result).toContain('return { ...input } as
|
|
1448
|
+
expect(result).toContain('return { ...input } as User')
|
|
1451
1449
|
// Fast-path should check required fields and optional fields
|
|
1452
1450
|
expect(result).toContain('typeof _id === "number"')
|
|
1453
1451
|
expect(result).toContain('typeof _name === "string"')
|
|
@@ -1470,7 +1468,7 @@ describe('generate-parser-function', () => {
|
|
|
1470
1468
|
},
|
|
1471
1469
|
}
|
|
1472
1470
|
|
|
1473
|
-
const result = generateParserFunction(schema, '
|
|
1471
|
+
const result = generateParserFunction(schema, 'Mixed')
|
|
1474
1472
|
|
|
1475
1473
|
// Both should be cached because fast-path exists
|
|
1476
1474
|
expect(result).toContain('const _simple')
|
|
@@ -1614,9 +1612,9 @@ describe('generate-parser-function', () => {
|
|
|
1614
1612
|
required: ['name'],
|
|
1615
1613
|
}
|
|
1616
1614
|
|
|
1617
|
-
const result = generateParserFunction(schema, '
|
|
1615
|
+
const result = generateParserFunction(schema, 'User', { logWarnings: true })
|
|
1618
1616
|
expect(result).toBe(
|
|
1619
|
-
`export const
|
|
1617
|
+
`export const parseUser = (input: unknown): User => {
|
|
1620
1618
|
if (!isObject(input)) return {
|
|
1621
1619
|
name: "",
|
|
1622
1620
|
};
|
|
@@ -1625,15 +1623,15 @@ describe('generate-parser-function', () => {
|
|
|
1625
1623
|
const _knownKeys = new Set(["name", "age"]);
|
|
1626
1624
|
for (const _k in input) {
|
|
1627
1625
|
if (!_knownKeys.has(_k)) {
|
|
1628
|
-
console.warn(\`[
|
|
1626
|
+
console.warn(\`[User] Unknown property "\${_k}"\`);
|
|
1629
1627
|
}
|
|
1630
1628
|
}
|
|
1631
|
-
if (typeof _name === "string" && (_age === undefined || typeof _age === "number")) return { ...input } as
|
|
1629
|
+
if (typeof _name === "string" && (_age === undefined || typeof _age === "number")) return { ...input } as User;
|
|
1632
1630
|
return {
|
|
1633
1631
|
...input,
|
|
1634
1632
|
name: typeof _name === "string" ? _name : (_name !== undefined ? String(_name) : ""),
|
|
1635
1633
|
...(_age !== undefined && { age: typeof _age === "number" ? _age : (Number.isFinite(Number(_age)) ? Number(_age) : 0) }),
|
|
1636
|
-
} as unknown as
|
|
1634
|
+
} as unknown as User;
|
|
1637
1635
|
}`,
|
|
1638
1636
|
)
|
|
1639
1637
|
})
|
|
@@ -1646,7 +1644,7 @@ describe('generate-parser-function', () => {
|
|
|
1646
1644
|
},
|
|
1647
1645
|
}
|
|
1648
1646
|
|
|
1649
|
-
const result = generateParserFunction(schema, '
|
|
1647
|
+
const result = generateParserFunction(schema, 'User', { logWarnings: false })
|
|
1650
1648
|
expect(result).not.toContain('console.warn')
|
|
1651
1649
|
expect(result).not.toContain('_knownKeys')
|
|
1652
1650
|
})
|
|
@@ -1659,7 +1657,7 @@ describe('generate-parser-function', () => {
|
|
|
1659
1657
|
},
|
|
1660
1658
|
}
|
|
1661
1659
|
|
|
1662
|
-
const result = generateParserFunction(schema, '
|
|
1660
|
+
const result = generateParserFunction(schema, 'User')
|
|
1663
1661
|
expect(result).not.toContain('console.warn')
|
|
1664
1662
|
})
|
|
1665
1663
|
})
|
|
@@ -1671,9 +1669,9 @@ describe('generate-parser-function', () => {
|
|
|
1671
1669
|
properties: { name: { type: 'string' } },
|
|
1672
1670
|
required: ['name'],
|
|
1673
1671
|
}
|
|
1674
|
-
const result = generateParserFunction(schema, '
|
|
1672
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1675
1673
|
expect(result).toContain(
|
|
1676
|
-
'if (!isObject(input)) throw new Error(`[
|
|
1674
|
+
'if (!isObject(input)) throw new Error(`[User] expected object, got ${input === null ? "null" : typeof input}`)',
|
|
1677
1675
|
)
|
|
1678
1676
|
expect(result).not.toContain('if (!isObject(input)) return')
|
|
1679
1677
|
})
|
|
@@ -1684,10 +1682,8 @@ describe('generate-parser-function', () => {
|
|
|
1684
1682
|
properties: { name: { type: 'string' } },
|
|
1685
1683
|
required: ['name'],
|
|
1686
1684
|
}
|
|
1687
|
-
const result = generateParserFunction(schema, '
|
|
1688
|
-
expect(result).toContain(
|
|
1689
|
-
'if (!("name" in input)) throw new Error(\'[UserObject] missing required property "name"\')',
|
|
1690
|
-
)
|
|
1685
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1686
|
+
expect(result).toContain('if (!("name" in input)) throw new Error(\'[User] missing required property "name"\')')
|
|
1691
1687
|
})
|
|
1692
1688
|
|
|
1693
1689
|
it('throws on wrong primitive type for required property', () => {
|
|
@@ -1696,9 +1692,9 @@ describe('generate-parser-function', () => {
|
|
|
1696
1692
|
properties: { name: { type: 'string' } },
|
|
1697
1693
|
required: ['name'],
|
|
1698
1694
|
}
|
|
1699
|
-
const result = generateParserFunction(schema, '
|
|
1695
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1700
1696
|
expect(result).toContain(
|
|
1701
|
-
'if (typeof input.name !== "string") throw new Error(`[
|
|
1697
|
+
'if (typeof input.name !== "string") throw new Error(`[User] field "name" expected string, got ${typeof input.name}`)',
|
|
1702
1698
|
)
|
|
1703
1699
|
})
|
|
1704
1700
|
|
|
@@ -1707,9 +1703,9 @@ describe('generate-parser-function', () => {
|
|
|
1707
1703
|
type: 'object',
|
|
1708
1704
|
properties: { age: { type: 'number' } },
|
|
1709
1705
|
}
|
|
1710
|
-
const result = generateParserFunction(schema, '
|
|
1706
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1711
1707
|
expect(result).toContain(
|
|
1712
|
-
'if (input.age !== undefined && (typeof input.age !== "number")) throw new Error(`[
|
|
1708
|
+
'if (input.age !== undefined && (typeof input.age !== "number")) throw new Error(`[User] field "age" expected number, got ${typeof input.age}`)',
|
|
1713
1709
|
)
|
|
1714
1710
|
})
|
|
1715
1711
|
|
|
@@ -1719,7 +1715,7 @@ describe('generate-parser-function', () => {
|
|
|
1719
1715
|
properties: { role: { enum: ['admin', 'user'] } },
|
|
1720
1716
|
required: ['role'],
|
|
1721
1717
|
}
|
|
1722
|
-
const result = generateParserFunction(schema, '
|
|
1718
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1723
1719
|
expect(result).toContain('must be one of: "admin", "user"')
|
|
1724
1720
|
})
|
|
1725
1721
|
|
|
@@ -1729,7 +1725,7 @@ describe('generate-parser-function', () => {
|
|
|
1729
1725
|
properties: { code: { type: 'string', pattern: '^[A-Z]+$' } },
|
|
1730
1726
|
required: ['code'],
|
|
1731
1727
|
}
|
|
1732
|
-
const result = generateParserFunction(schema, '
|
|
1728
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1733
1729
|
expect(result).toContain('must match pattern ^[A-Z]+$')
|
|
1734
1730
|
})
|
|
1735
1731
|
|
|
@@ -1739,7 +1735,7 @@ describe('generate-parser-function', () => {
|
|
|
1739
1735
|
properties: { name: { type: 'string', minLength: 1, maxLength: 10 } },
|
|
1740
1736
|
required: ['name'],
|
|
1741
1737
|
}
|
|
1742
|
-
const result = generateParserFunction(schema, '
|
|
1738
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1743
1739
|
expect(result).toContain('must have at least 1 characters')
|
|
1744
1740
|
expect(result).toContain('must have at most 10 characters')
|
|
1745
1741
|
})
|
|
@@ -1750,7 +1746,7 @@ describe('generate-parser-function', () => {
|
|
|
1750
1746
|
properties: { age: { type: 'number', minimum: 0, maximum: 120, multipleOf: 1 } },
|
|
1751
1747
|
required: ['age'],
|
|
1752
1748
|
}
|
|
1753
|
-
const result = generateParserFunction(schema, '
|
|
1749
|
+
const result = generateParserFunction(schema, 'User', { strict: true })
|
|
1754
1750
|
expect(result).toContain('must be >= 0')
|
|
1755
1751
|
expect(result).toContain('must be <= 120')
|
|
1756
1752
|
expect(result).toContain('must be a multiple of 1')
|
|
@@ -1762,7 +1758,7 @@ describe('generate-parser-function', () => {
|
|
|
1762
1758
|
properties: { contact: { $ref: '#/$defs/contact' } },
|
|
1763
1759
|
required: ['contact'],
|
|
1764
1760
|
}
|
|
1765
|
-
const result = generateParserFunction(schema, '
|
|
1761
|
+
const result = generateParserFunction(schema, 'User', { strict: true, useRefImports: true })
|
|
1766
1762
|
// The missing-required check is still emitted, but no inline type check.
|
|
1767
1763
|
expect(result).toContain('missing required property "contact"')
|
|
1768
1764
|
expect(result).not.toContain('field "contact" expected')
|
|
@@ -1779,9 +1775,9 @@ describe('generate-parser-function', () => {
|
|
|
1779
1775
|
|
|
1780
1776
|
it('throws on non-object input for empty object schemas', () => {
|
|
1781
1777
|
const schema: JSONSchema = { type: 'object' }
|
|
1782
|
-
const result = generateParserFunction(schema, '
|
|
1778
|
+
const result = generateParserFunction(schema, 'Any', { strict: true })
|
|
1783
1779
|
expect(result).toContain('if (!isObject(input)) throw new Error')
|
|
1784
|
-
expect(result).toContain('return { ...input } as
|
|
1780
|
+
expect(result).toContain('return { ...input } as Any;')
|
|
1785
1781
|
})
|
|
1786
1782
|
|
|
1787
1783
|
it('preserves existing safe behavior when strict is not set', () => {
|
|
@@ -1790,7 +1786,7 @@ describe('generate-parser-function', () => {
|
|
|
1790
1786
|
properties: { name: { type: 'string' } },
|
|
1791
1787
|
required: ['name'],
|
|
1792
1788
|
}
|
|
1793
|
-
const result = generateParserFunction(schema, '
|
|
1789
|
+
const result = generateParserFunction(schema, 'User')
|
|
1794
1790
|
expect(result).not.toContain('throw new Error')
|
|
1795
1791
|
expect(result).toContain('if (!isObject(input)) return')
|
|
1796
1792
|
})
|