json-2-joi 2.1.0 → 2.3.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/CHANGELOG.md +12 -0
- package/README.md +8 -2
- package/lib/resolver.js +20 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
### 2.3.1
|
|
2
|
+
|
|
3
|
+
- Fix `noDefaults` options validation issue.
|
|
4
|
+
|
|
5
|
+
### 2.3.0
|
|
6
|
+
|
|
7
|
+
- If `noDefaults` is set `true`, `default()` will not be set to Joi schema and allow it overridable.
|
|
8
|
+
|
|
9
|
+
### 2.2.0
|
|
10
|
+
|
|
11
|
+
- Add `forbidArrayNull`, `strictRequired` option.
|
|
12
|
+
|
|
1
13
|
### 2.1.0
|
|
2
14
|
|
|
3
15
|
- Fix the issue that `enum` is only applied to `string` type or when missing type info.
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Converts a JSON schema to a Joi schema for object validation.
|
|
|
6
6
|
|
|
7
7
|
## Change based on the forked version (enjoi):
|
|
8
8
|
|
|
9
|
-
- Provided `refineDescription(schema)`, `allowNull`, `strictEnum`, `enableEnum` options
|
|
9
|
+
- Provided `refineDescription(schema)`, `allowNull`, `forbidArrayNull`, `strictRequired`, `strictEnum`, `enableEnum` options
|
|
10
10
|
- Change cycle reference resovling without self-generating id and rely on $id if defined in JSON schema
|
|
11
11
|
- Support `const` keyword in JSON schema
|
|
12
12
|
- Support `example` setting for Joi based on JSON schema's `examples`, `default` or `enum`
|
|
@@ -49,11 +49,14 @@ Please file issues for other unsupported features.
|
|
|
49
49
|
### Options
|
|
50
50
|
|
|
51
51
|
- `subSchemas` - an (optional) object with keys representing schema ids, and values representing schemas.
|
|
52
|
+
- `extensions` - an array of extensions to pass [joi.extend](https://github.com/hapijs/joi/blob/master/API.md#extendextension).
|
|
53
|
+
- `joiOptions` - Options directly passed to Joi for instance creation. If the `noDefaults` is set `true`, `default()` will NOT be called and applied to Joi schema.
|
|
52
54
|
- `refineDescription(schema)` - an (optional) function to call to apply to the JSON schema so that it's possible to return customized description.
|
|
53
55
|
- `refineType(type, format)` - an (optional) function to call to apply to type based on the type and format of the JSON schema.
|
|
54
56
|
- `refineSchema(joiSchema, jsonSchema)` - an (optional) function to call to apply to adjust Joi schema base on the original JSON schema. Primary use case is handling `nullable` flag in OpenAPI 3.0
|
|
55
|
-
- `extensions` - an array of extensions to pass [joi.extend](https://github.com/hapijs/joi/blob/master/API.md#extendextension).
|
|
56
57
|
- `allowNull` - Default as `false`. When `true` and the field has no `enum` setting, `null` value will be allowed.
|
|
58
|
+
- `forbidArrayNull` - Default as `true`. When `false` and `allowNull` is true, `null` value will be allowed for array type field.
|
|
59
|
+
- `strictRequired` - Default as `false`. When `true`, `null` (and empty string additionally for string type) will NOT be allowed for those `required` field in object.
|
|
57
60
|
- `strictEnum` - Default as `true`. When `false`, and `allowNull` is `true`, `null` (and empty string additionally for string type) will be added to `enum` list.
|
|
58
61
|
- `enableEnum` - Default as `true`. When `false`, `enum` restriction will not be added to Joi Schema.
|
|
59
62
|
|
|
@@ -216,8 +219,11 @@ It's possible to override these options for each conversion:
|
|
|
216
219
|
* refineSchema
|
|
217
220
|
* refineDescription
|
|
218
221
|
* allowNull
|
|
222
|
+
* forbidArrayNull
|
|
223
|
+
* strictRequired
|
|
219
224
|
* strictEnum
|
|
220
225
|
* enableEnum
|
|
226
|
+
* noDefaults (Copied from `joiOptions` for the construction time)
|
|
221
227
|
|
|
222
228
|
However, the overriden options do not have impact on the `subSchemas` as they are preprocessed during Resolver construction.
|
|
223
229
|
|
package/lib/resolver.js
CHANGED
|
@@ -20,6 +20,8 @@ const optionsSchema = Joi.object({
|
|
|
20
20
|
refineSchema: Joi.func().allow(null),
|
|
21
21
|
refineDescription: Joi.func().allow(null),
|
|
22
22
|
allowNull: Joi.boolean().default(false),
|
|
23
|
+
forbidArrayNull: Joi.boolean().default(true),
|
|
24
|
+
strictRequired: Joi.boolean().default(false),
|
|
23
25
|
strictEnum: Joi.boolean().default(true),
|
|
24
26
|
enableEnum: Joi.boolean().default(true),
|
|
25
27
|
joiOptions: Joi.object().unknown(true).default({})
|
|
@@ -30,6 +32,9 @@ const overridableOptions = {
|
|
|
30
32
|
refineSchema: Joi.func().allow(null),
|
|
31
33
|
refineDescription: Joi.func().allow(null),
|
|
32
34
|
allowNull: Joi.boolean(),
|
|
35
|
+
forbidArrayNull: Joi.boolean(),
|
|
36
|
+
strictRequired: Joi.boolean(),
|
|
37
|
+
noDefaults: Joi.boolean(),
|
|
33
38
|
strictEnum: Joi.boolean(),
|
|
34
39
|
enableEnum: Joi.boolean()
|
|
35
40
|
};
|
|
@@ -59,13 +64,16 @@ function isNotEmptyObject(value) {
|
|
|
59
64
|
return isObject(value) && Object.keys(value).length > 0;
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
function allowNullIfNeeded(schema, allowNull = false) {
|
|
67
|
+
function allowNullIfNeeded(schema, { allowNull = false, forbidArrayNull = true }) {
|
|
63
68
|
if (allowNull) {
|
|
64
69
|
const definition = schema.describe();
|
|
65
70
|
if (definition.flags && definition.flags.only && definition.allow) {
|
|
66
71
|
// Already has enum restriction
|
|
67
72
|
return schema;
|
|
68
73
|
}
|
|
74
|
+
if (forbidArrayNull && schema.type === 'array') {
|
|
75
|
+
return schema;
|
|
76
|
+
}
|
|
69
77
|
return schema.allow(null);
|
|
70
78
|
}
|
|
71
79
|
return schema;
|
|
@@ -78,9 +86,9 @@ function addEnumRestriction(joiSchema, enumList, { allowNull = false, strictEnum
|
|
|
78
86
|
|
|
79
87
|
const valids = [].concat(enumList);
|
|
80
88
|
if (allowNull && !strictEnum) {
|
|
81
|
-
valids.
|
|
89
|
+
valids.splice(0, 0, null);
|
|
82
90
|
if (joiSchema.type === 'string') {
|
|
83
|
-
valids.
|
|
91
|
+
valids.splice(0, 0, '');
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
return joiSchema.valid(...valids);
|
|
@@ -154,6 +162,7 @@ class SchemaResolver {
|
|
|
154
162
|
this.subSchemas = subSchemas;
|
|
155
163
|
this.joiOptions = joiOptions;
|
|
156
164
|
this.joiSharedSchemas = new Map();
|
|
165
|
+
this.resolveOptions.noDefaults = this.joiOptions.noDefaults;
|
|
157
166
|
|
|
158
167
|
this.joi = getJoiInstance(joiOptions, extensions, joiInstance);
|
|
159
168
|
|
|
@@ -281,7 +290,7 @@ class SchemaResolver {
|
|
|
281
290
|
resolvedSchema = resolveOptions.refineSchema(resolvedSchema, schema);
|
|
282
291
|
}
|
|
283
292
|
|
|
284
|
-
if (schema.default !== undefined) {
|
|
293
|
+
if (schema.default !== undefined && !resolveOptions.noDefaults) {
|
|
285
294
|
resolvedSchema = resolvedSchema.default(schema.default)
|
|
286
295
|
}
|
|
287
296
|
|
|
@@ -349,8 +358,7 @@ class SchemaResolver {
|
|
|
349
358
|
let joischema;
|
|
350
359
|
|
|
351
360
|
const typeDefinitionMap = {
|
|
352
|
-
title: 'label'
|
|
353
|
-
default: 'default'
|
|
361
|
+
title: 'label'
|
|
354
362
|
};
|
|
355
363
|
|
|
356
364
|
const joitype = (type, options, format) => {
|
|
@@ -477,8 +485,11 @@ class SchemaResolver {
|
|
|
477
485
|
|
|
478
486
|
if (Array.isArray(jsonSchema.required) && !!~jsonSchema.required.indexOf(key)) {
|
|
479
487
|
joischema = joischema.required();
|
|
488
|
+
if (resolveOptions.strictRequired) {
|
|
489
|
+
joischema = joischema.invalid(null, '');
|
|
490
|
+
}
|
|
480
491
|
} else {
|
|
481
|
-
joischema = allowNullIfNeeded(joischema, resolveOptions
|
|
492
|
+
joischema = allowNullIfNeeded(joischema, resolveOptions);
|
|
482
493
|
}
|
|
483
494
|
|
|
484
495
|
schemas[key] = joischema;
|
|
@@ -505,10 +516,10 @@ class SchemaResolver {
|
|
|
505
516
|
resolveAsArray(value, resolveOptions, baseUri) {
|
|
506
517
|
if (Array.isArray(value)) {
|
|
507
518
|
// found an array, thus its _per type_
|
|
508
|
-
return value.map((v) => allowNullIfNeeded(this.resolve(v, resolveOptions, baseUri), resolveOptions
|
|
519
|
+
return value.map((v) => allowNullIfNeeded(this.resolve(v, resolveOptions, baseUri), resolveOptions));
|
|
509
520
|
}
|
|
510
521
|
// it's a single entity, so just resolve it normally
|
|
511
|
-
return [allowNullIfNeeded(this.resolve(value, resolveOptions, baseUri), resolveOptions
|
|
522
|
+
return [allowNullIfNeeded(this.resolve(value, resolveOptions, baseUri), resolveOptions)];
|
|
512
523
|
}
|
|
513
524
|
|
|
514
525
|
array(schema, resolveOptions, baseUri) {
|