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 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.push(null);
89
+ valids.splice(0, 0, null);
82
90
  if (joiSchema.type === 'string') {
83
- valids.push('');
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.allowNull);
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.allowNull));
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.allowNull)];
522
+ return [allowNullIfNeeded(this.resolve(value, resolveOptions, baseUri), resolveOptions)];
512
523
  }
513
524
 
514
525
  array(schema, resolveOptions, baseUri) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-2-joi",
3
- "version": "2.1.0",
3
+ "version": "2.3.1",
4
4
  "license": "Apache 2.0",
5
5
  "description": "Converts json-schema to Joi schema. (Enhanced enjoi)",
6
6
  "main": "./index.js",