Skip to content

Commit 1d24618

Browse files
Added ignoreMinAndMaxItems option (#274)
* Added ignoreMinAndMaxItems option to prevent tuples from being generated for array types * Updated normalizer with ignoreMinAndMaxItems PR review suggestions
1 parent 08ec990 commit 1d24618

File tree

8 files changed

+816
-8
lines changed

8 files changed

+816
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ See [server demo](example) and [browser demo](https://github.com/bcherny/json-sc
8787
| cwd | string | `process.cwd()` | Root directory for resolving [`$ref`](https://tools.ietf.org/id/draft-pbryan-zyp-json-ref-03.html)s |
8888
| declareExternallyReferenced | boolean | `true` | Declare external schemas referenced via `$ref`? |
8989
| enableConstEnums | boolean | `true` | Prepend enums with [`const`](https://www.typescriptlang.org/docs/handbook/enums.html#computed-and-constant-members)? |
90+
| ignoreMinAndMaxItems | boolean | `false` | Ignore maxItems and minItems for `array` types, preventing tuples being generated. |
9091
| style | object | `{ bracketSpacing: false, printWidth: 120, semi: true, singleQuote: false, tabWidth: 2, trailingComma: 'none', useTabs: false }` | A [Prettier](https://prettier.io/docs/en/options.html) configuration |
9192
| unreachableDefinitions | boolean | `false` | Generates code for `definitions` that aren't referenced by the schema. |
9293
| strictIndexSignatures | boolean | `false` | Append all index signatures with `| undefined` so that they are strictly typed. |

src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ export interface Options {
3232
* Prepend enums with [`const`](https://www.typescriptlang.org/docs/handbook/enums.html#computed-and-constant-members)?
3333
*/
3434
enableConstEnums: boolean
35+
/**
36+
* Ignore maxItems and minItems for `array` types, preventing tuples being generated.
37+
*/
38+
ignoreMinAndMaxItems: boolean
3539
/**
3640
* Append all index signatures with `| undefined` so that they are strictly typed.
3741
*
@@ -63,6 +67,7 @@ export const DEFAULT_OPTIONS: Options = {
6367
cwd: process.cwd(),
6468
declareExternallyReferenced: true,
6569
enableConstEnums: true, // by default, avoid generating code
70+
ignoreMinAndMaxItems: false,
6671
strictIndexSignatures: false,
6772
style: {
6873
bracketSpacing: false,
@@ -107,7 +112,7 @@ export async function compile(schema: JSONSchema4, name: string, options: Partia
107112
}
108113

109114
return format(
110-
generate(optimize(parse(await dereference(normalize(schema, name), _options), _options)), _options),
115+
generate(optimize(parse(await dereference(normalize(schema, name, _options), _options), _options)), _options),
111116
_options
112117
)
113118
}

src/normalizer.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import stringify = require('json-stringify-safe')
33
import {cloneDeep} from 'lodash'
44
import {JSONSchema, JSONSchemaTypeName, NormalizedJSONSchema} from './types/JSONSchema'
55
import {escapeBlockComment, justName, log, toSafeString, traverse} from './utils'
6+
import {Options} from './'
67

7-
type Rule = (schema: JSONSchema, rootSchema: JSONSchema, fileName?: string) => void
8+
type Rule = (schema: JSONSchema, rootSchema: JSONSchema, fileName: string, options: Options) => void
89
const rules = new Map<string, Rule>()
910

1011
function hasType(schema: JSONSchema, type: JSONSchemaTypeName) {
@@ -63,7 +64,21 @@ rules.set('Escape closing JSDoc Comment', schema => {
6364
escapeBlockComment(schema)
6465
})
6566

66-
rules.set('Normalise schema.minItems', schema => {
67+
rules.set('Optionally remove maxItems and minItems', (schema, _rootSchema, _fileName, options) => {
68+
if (options.ignoreMinAndMaxItems) {
69+
if ('maxItems' in schema) {
70+
delete schema.maxItems
71+
}
72+
if ('minItems' in schema) {
73+
delete schema.minItems
74+
}
75+
}
76+
})
77+
78+
rules.set('Normalise schema.minItems', (schema, _rootSchema, _fileName, options) => {
79+
if (options.ignoreMinAndMaxItems) {
80+
return
81+
}
6782
// make sure we only add the props onto array types
6883
if (isArrayType(schema)) {
6984
const {minItems} = schema
@@ -72,7 +87,10 @@ rules.set('Normalise schema.minItems', schema => {
7287
// cannot normalise maxItems because maxItems = 0 has an actual meaning
7388
})
7489

75-
rules.set('Normalize schema.items', schema => {
90+
rules.set('Normalize schema.items', (schema, _rootSchema, _fileName, options) => {
91+
if (options.ignoreMinAndMaxItems) {
92+
return
93+
}
7694
const {maxItems, minItems} = schema
7795
const hasMaxItems = typeof maxItems === 'number' && maxItems >= 0
7896
const hasMinItems = typeof minItems === 'number' && minItems > 0
@@ -97,10 +115,10 @@ rules.set('Normalize schema.items', schema => {
97115
return schema
98116
})
99117

100-
export function normalize(schema: JSONSchema, filename?: string): NormalizedJSONSchema {
118+
export function normalize(schema: JSONSchema, filename: string, options: Options): NormalizedJSONSchema {
101119
const _schema = cloneDeep(schema) as NormalizedJSONSchema
102120
rules.forEach((rule, key) => {
103-
traverse(_schema, schema => rule(schema, _schema, filename))
121+
traverse(_schema, schema => rule(schema, _schema, filename, options))
104122
log(whiteBright.bgYellow('normalizer'), `Applied rule: "${key}"`)
105123
})
106124
return _schema

test/__snapshots__/test/test.ts.md

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,153 @@ Generated by [AVA](https://ava.li).
157157
}␊
158158
`
159159

160+
## Normalise ignoreMinAndMaxItems
161+
162+
> Snapshot 1
163+
164+
`{␊
165+
"id": "foo",␊
166+
"type": "object",␊
167+
"properties": {␊
168+
"untyped": {␊
169+
"type": "object",␊
170+
"properties": {␊
171+
"unbounded": {␊
172+
"type": "array"␊
173+
},␊
174+
"minOnly": {␊
175+
"type": "array"␊
176+
},␊
177+
"maxOnly": {␊
178+
"type": "array"␊
179+
},␊
180+
"minAndMax": {␊
181+
"type": "array"␊
182+
}␊
183+
},␊
184+
"additionalProperties": false,␊
185+
"required": []␊
186+
},␊
187+
"untypedArray": {␊
188+
"type": "object",␊
189+
"properties": {␊
190+
"unbounded": {␊
191+
"type": [␊
192+
"array",␊
193+
"string"␊
194+
]␊
195+
},␊
196+
"minOnly": {␊
197+
"type": [␊
198+
"array",␊
199+
"string"␊
200+
]␊
201+
},␊
202+
"maxOnly": {␊
203+
"type": [␊
204+
"array",␊
205+
"string"␊
206+
]␊
207+
},␊
208+
"minAndMax": {␊
209+
"type": [␊
210+
"array",␊
211+
"string"␊
212+
]␊
213+
}␊
214+
},␊
215+
"additionalProperties": false,␊
216+
"required": []␊
217+
},␊
218+
"typed": {␊
219+
"type": "object",␊
220+
"properties": {␊
221+
"unbounded": {␊
222+
"items": {␊
223+
"type": "string"␊
224+
}␊
225+
},␊
226+
"minOnly": {␊
227+
"items": {␊
228+
"type": "string"␊
229+
},␊
230+
"additionalItems": {␊
231+
"type": "string"␊
232+
}␊
233+
},␊
234+
"maxOnly": {␊
235+
"items": {␊
236+
"type": "string"␊
237+
}␊
238+
},␊
239+
"minAndMax": {␊
240+
"items": {␊
241+
"type": "string"␊
242+
}␊
243+
}␊
244+
},␊
245+
"additionalProperties": false,␊
246+
"required": []␊
247+
},␊
248+
"anyOf": {␊
249+
"type": "object",␊
250+
"properties": {␊
251+
"unbounded": {␊
252+
"anyOf": [␊
253+
{␊
254+
"items": {␊
255+
"type": "string"␊
256+
}␊
257+
}␊
258+
],␊
259+
"additionalProperties": false,␊
260+
"required": []␊
261+
},␊
262+
"minOnly": {␊
263+
"anyOf": [␊
264+
{␊
265+
"items": {␊
266+
"type": "string"␊
267+
},␊
268+
"additionalItems": {␊
269+
"type": "string"␊
270+
}␊
271+
}␊
272+
],␊
273+
"additionalProperties": false,␊
274+
"required": []␊
275+
},␊
276+
"maxOnly": {␊
277+
"anyOf": [␊
278+
{␊
279+
"items": {␊
280+
"type": "string"␊
281+
}␊
282+
}␊
283+
],␊
284+
"additionalProperties": false,␊
285+
"required": []␊
286+
},␊
287+
"minAndMax": {␊
288+
"anyOf": [␊
289+
{␊
290+
"items": {␊
291+
"type": "string"␊
292+
}␊
293+
}␊
294+
],␊
295+
"additionalProperties": false,␊
296+
"required": []␊
297+
}␊
298+
},␊
299+
"additionalProperties": false,␊
300+
"required": []␊
301+
}␊
302+
},␊
303+
"additionalProperties": false,␊
304+
"required": []␊
305+
}`
306+
160307
## Normalise schema.minItems
161308

162309
> Snapshot 1
@@ -802,6 +949,115 @@ Generated by [AVA](https://ava.li).
802949
}␊
803950
`
804951

952+
## arrayIgnoreMaxMinItems.js
953+
954+
> Snapshot 1
955+
956+
`/* tslint:disable */␊
957+
/**␊
958+
* This file was automatically generated by json-schema-to-typescript.␊
959+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,␊
960+
* and run json-schema-to-typescript to regenerate this file.␊
961+
*/␊
962+
963+
export interface ArrayMaxMinItems {␊
964+
array?: {␊
965+
/**␊
966+
* minItems = 3␊
967+
*/␊
968+
withMinItems?: string[];␊
969+
/**␊
970+
* maxItems = 3␊
971+
*/␊
972+
withMaxItems?: string[];␊
973+
/**␊
974+
* minItems = 3, maxItems = 8␊
975+
*/␊
976+
withMinMaxItems?: string[];␊
977+
/**␊
978+
* maxItems = 0␊
979+
*/␊
980+
withMaxItems0?: string[];␊
981+
/**␊
982+
* minItems = 0␊
983+
*/␊
984+
withMinItems0?: string[];␊
985+
/**␊
986+
* minItems = 0, maxItems = 0␊
987+
*/␊
988+
withMinMaxItems0?: string[];␊
989+
};␊
990+
untyped?: {␊
991+
/**␊
992+
* minItems = 3␊
993+
*/␊
994+
withMinItems?: any[];␊
995+
/**␊
996+
* maxItems = 3␊
997+
*/␊
998+
withMaxItems?: any[];␊
999+
/**␊
1000+
* minItems = 3, maxItems = 8␊
1001+
*/␊
1002+
withMinMaxItems?: any[];␊
1003+
/**␊
1004+
* maxItems = 0␊
1005+
*/␊
1006+
withMaxItems0?: any[];␊
1007+
/**␊
1008+
* minItems = 0␊
1009+
*/␊
1010+
withMinItems0?: any[];␊
1011+
/**␊
1012+
* minItems = 0, maxItems = 0␊
1013+
*/␊
1014+
withMinMaxItems0?: any[];␊
1015+
};␊
1016+
tuple?: {␊
1017+
/**␊
1018+
* minItems = 2␊
1019+
*/␊
1020+
withMinItemsLessThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1021+
/**␊
1022+
* minItems = 8␊
1023+
*/␊
1024+
withMinItemsGreaterThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1025+
/**␊
1026+
* maxItems = 2␊
1027+
*/␊
1028+
withMaxItemsLessThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1029+
/**␊
1030+
* maxItems = 8␊
1031+
*/␊
1032+
withMaxItemsGreaterThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1033+
/**␊
1034+
* minItems = 4, maxItems = 8␊
1035+
*/␊
1036+
withMinItemsLessThanItemLength_and_MaxItemsGreaterThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1037+
/**␊
1038+
* minItems = 2, maxItems = 4␊
1039+
*/␊
1040+
withMinItemsLessThanItemLength_and_MaxItemsLessThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1041+
/**␊
1042+
* minItems = 8, maxItems = 10␊
1043+
*/␊
1044+
withMinItemsGreaterThanItemLength_and_MaxItemsGreaterThanItemLength?: [1, 2, 3, 4, 5, 6];␊
1045+
/**␊
1046+
* maxItems = 0␊
1047+
*/␊
1048+
withMaxItems0?: [1, 2, 3, 4, 5, 6];␊
1049+
/**␊
1050+
* minItems = 0␊
1051+
*/␊
1052+
withMinItems0?: [1, 2, 3, 4, 5, 6];␊
1053+
/**␊
1054+
* minItems = 0, maxItems = 0␊
1055+
*/␊
1056+
withMinMaxItems0?: [1, 2, 3, 4, 5, 6];␊
1057+
};␊
1058+
}␊
1059+
`
1060+
8051061
## arrayMaxMinItems.js
8061062

8071063
> Snapshot 1

test/__snapshots__/test/test.ts.snap

282 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)