joi 14.2.0 → 17.2.0

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.
Files changed (59) hide show
  1. package/LICENSE.md +10 -0
  2. package/README.md +9 -118
  3. package/dist/joi-browser.min.js +1 -0
  4. package/lib/annotate.js +175 -0
  5. package/lib/base.js +1068 -0
  6. package/lib/cache.js +143 -0
  7. package/lib/common.js +216 -0
  8. package/lib/compile.js +283 -0
  9. package/lib/errors.js +160 -269
  10. package/lib/extend.js +312 -0
  11. package/lib/index.d.ts +2200 -0
  12. package/lib/index.js +179 -347
  13. package/lib/manifest.js +476 -0
  14. package/lib/messages.js +178 -0
  15. package/lib/modify.js +267 -0
  16. package/lib/ref.js +386 -25
  17. package/lib/schemas.js +291 -15
  18. package/lib/state.js +152 -0
  19. package/lib/template.js +427 -0
  20. package/lib/trace.js +346 -0
  21. package/lib/types/alternatives.js +329 -0
  22. package/lib/types/any.js +174 -0
  23. package/lib/types/array.js +775 -0
  24. package/lib/types/binary.js +98 -0
  25. package/lib/types/boolean.js +150 -0
  26. package/lib/types/date.js +233 -0
  27. package/lib/types/function.js +93 -0
  28. package/lib/types/keys.js +1043 -0
  29. package/lib/types/link.js +168 -0
  30. package/lib/types/number.js +335 -0
  31. package/lib/types/object.js +22 -0
  32. package/lib/types/string.js +820 -0
  33. package/lib/types/symbol.js +102 -0
  34. package/lib/validator.js +650 -0
  35. package/lib/values.js +263 -0
  36. package/package.json +34 -29
  37. package/CHANGELOG.md +0 -3
  38. package/LICENSE +0 -25
  39. package/lib/cast.js +0 -64
  40. package/lib/language.js +0 -166
  41. package/lib/set.js +0 -191
  42. package/lib/types/alternatives/index.js +0 -218
  43. package/lib/types/any/index.js +0 -978
  44. package/lib/types/any/settings.js +0 -36
  45. package/lib/types/array/index.js +0 -707
  46. package/lib/types/binary/index.js +0 -100
  47. package/lib/types/boolean/index.js +0 -100
  48. package/lib/types/date/index.js +0 -182
  49. package/lib/types/func/index.js +0 -90
  50. package/lib/types/lazy/index.js +0 -82
  51. package/lib/types/number/index.js +0 -248
  52. package/lib/types/object/index.js +0 -957
  53. package/lib/types/state.js +0 -11
  54. package/lib/types/string/index.js +0 -703
  55. package/lib/types/string/ip.js +0 -54
  56. package/lib/types/string/rfc3986.js +0 -219
  57. package/lib/types/string/uri.js +0 -46
  58. package/lib/types/symbol/index.js +0 -93
  59. package/lib/types/symbols.js +0 -5
package/lib/values.js ADDED
@@ -0,0 +1,263 @@
1
+ 'use strict';
2
+
3
+ const Assert = require('@hapi/hoek/lib/assert');
4
+ const DeepEqual = require('@hapi/hoek/lib/deepEqual');
5
+
6
+ const Common = require('./common');
7
+
8
+
9
+ const internals = {};
10
+
11
+
12
+ module.exports = internals.Values = class {
13
+
14
+ constructor(values, refs) {
15
+
16
+ this._values = new Set(values);
17
+ this._refs = new Set(refs);
18
+ this._lowercase = internals.lowercases(values);
19
+
20
+ this._override = false;
21
+ }
22
+
23
+ get length() {
24
+
25
+ return this._values.size + this._refs.size;
26
+ }
27
+
28
+ add(value, refs) {
29
+
30
+ // Reference
31
+
32
+ if (Common.isResolvable(value)) {
33
+ if (!this._refs.has(value)) {
34
+ this._refs.add(value);
35
+
36
+ if (refs) { // Skipped in a merge
37
+ refs.register(value);
38
+ }
39
+ }
40
+
41
+ return;
42
+ }
43
+
44
+ // Value
45
+
46
+ if (!this.has(value, null, null, false)) {
47
+ this._values.add(value);
48
+
49
+ if (typeof value === 'string') {
50
+ this._lowercase.set(value.toLowerCase(), value);
51
+ }
52
+ }
53
+ }
54
+
55
+ static merge(target, source, remove) {
56
+
57
+ target = target || new internals.Values();
58
+
59
+ if (source) {
60
+ if (source._override) {
61
+ return source.clone();
62
+ }
63
+
64
+ for (const item of [...source._values, ...source._refs]) {
65
+ target.add(item);
66
+ }
67
+ }
68
+
69
+ if (remove) {
70
+ for (const item of [...remove._values, ...remove._refs]) {
71
+ target.remove(item);
72
+ }
73
+ }
74
+
75
+ return target.length ? target : null;
76
+ }
77
+
78
+ remove(value) {
79
+
80
+ // Reference
81
+
82
+ if (Common.isResolvable(value)) {
83
+ this._refs.delete(value);
84
+ return;
85
+ }
86
+
87
+ // Value
88
+
89
+ this._values.delete(value);
90
+
91
+ if (typeof value === 'string') {
92
+ this._lowercase.delete(value.toLowerCase());
93
+ }
94
+ }
95
+
96
+ has(value, state, prefs, insensitive) {
97
+
98
+ return !!this.get(value, state, prefs, insensitive);
99
+ }
100
+
101
+ get(value, state, prefs, insensitive) {
102
+
103
+ if (!this.length) {
104
+ return false;
105
+ }
106
+
107
+ // Simple match
108
+
109
+ if (this._values.has(value)) {
110
+ return { value };
111
+ }
112
+
113
+ // Case insensitive string match
114
+
115
+ if (typeof value === 'string' &&
116
+ value &&
117
+ insensitive) {
118
+
119
+ const found = this._lowercase.get(value.toLowerCase());
120
+ if (found) {
121
+ return { value: found };
122
+ }
123
+ }
124
+
125
+ if (!this._refs.size &&
126
+ typeof value !== 'object') {
127
+
128
+ return false;
129
+ }
130
+
131
+ // Objects
132
+
133
+ if (typeof value === 'object') {
134
+ for (const item of this._values) {
135
+ if (DeepEqual(item, value)) {
136
+ return { value: item };
137
+ }
138
+ }
139
+ }
140
+
141
+ // References
142
+
143
+ if (state) {
144
+ for (const ref of this._refs) {
145
+ const resolved = ref.resolve(value, state, prefs, null, { in: true });
146
+ if (resolved === undefined) {
147
+ continue;
148
+ }
149
+
150
+ const items = !ref.in || typeof resolved !== 'object'
151
+ ? [resolved]
152
+ : Array.isArray(resolved) ? resolved : Object.keys(resolved);
153
+
154
+ for (const item of items) {
155
+ if (typeof item !== typeof value) {
156
+ continue;
157
+ }
158
+
159
+ if (insensitive &&
160
+ value &&
161
+ typeof value === 'string') {
162
+
163
+ if (item.toLowerCase() === value.toLowerCase()) {
164
+ return { value: item, ref };
165
+ }
166
+ }
167
+ else {
168
+ if (DeepEqual(item, value)) {
169
+ return { value: item, ref };
170
+ }
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ return false;
177
+ }
178
+
179
+ override() {
180
+
181
+ this._override = true;
182
+ }
183
+
184
+ values(options) {
185
+
186
+ if (options &&
187
+ options.display) {
188
+
189
+ const values = [];
190
+
191
+ for (const item of [...this._values, ...this._refs]) {
192
+ if (item !== undefined) {
193
+ values.push(item);
194
+ }
195
+ }
196
+
197
+ return values;
198
+ }
199
+
200
+ return Array.from([...this._values, ...this._refs]);
201
+ }
202
+
203
+ clone() {
204
+
205
+ const set = new internals.Values(this._values, this._refs);
206
+ set._override = this._override;
207
+ return set;
208
+ }
209
+
210
+ concat(source) {
211
+
212
+ Assert(!source._override, 'Cannot concat override set of values');
213
+
214
+ const set = new internals.Values([...this._values, ...source._values], [...this._refs, ...source._refs]);
215
+ set._override = this._override;
216
+ return set;
217
+ }
218
+
219
+ describe() {
220
+
221
+ const normalized = [];
222
+
223
+ if (this._override) {
224
+ normalized.push({ override: true });
225
+ }
226
+
227
+ for (const value of this._values.values()) {
228
+ normalized.push(value && typeof value === 'object' ? { value } : value);
229
+ }
230
+
231
+ for (const value of this._refs.values()) {
232
+ normalized.push(value.describe());
233
+ }
234
+
235
+ return normalized;
236
+ }
237
+ };
238
+
239
+
240
+ internals.Values.prototype[Common.symbols.values] = true;
241
+
242
+
243
+ // Aliases
244
+
245
+ internals.Values.prototype.slice = internals.Values.prototype.clone;
246
+
247
+
248
+ // Helpers
249
+
250
+ internals.lowercases = function (from) {
251
+
252
+ const map = new Map();
253
+
254
+ if (from) {
255
+ for (const value of from) {
256
+ if (typeof value === 'string') {
257
+ map.set(value.toLowerCase(), value);
258
+ }
259
+ }
260
+ }
261
+
262
+ return map;
263
+ };
package/package.json CHANGED
@@ -1,31 +1,36 @@
1
1
  {
2
- "name": "joi",
3
- "description": "Object schema validation",
4
- "version": "14.2.0",
5
- "homepage": "https://github.com/hapijs/joi",
6
- "repository": "git://github.com/hapijs/joi",
7
- "main": "lib/index.js",
8
- "keywords": [
9
- "hapi",
10
- "schema",
11
- "validation"
12
- ],
13
- "dependencies": {
14
- "hoek": "6.x.x",
15
- "isemail": "3.x.x",
16
- "topo": "3.x.x"
17
- },
18
- "devDependencies": {
19
- "code": "5.x.x",
20
- "hapitoc": "1.x.x",
21
- "lab": "18.x.x"
22
- },
23
- "scripts": {
24
- "test": "lab -t 100 -a code -L",
25
- "test-debug": "lab -a code",
26
- "test-cov-html": "lab -r html -o coverage.html -a code",
27
- "toc": "hapitoc && node docs/check-errors-list.js",
28
- "version": "npm run toc && git add API.md README.md"
29
- },
30
- "license": "BSD-3-Clause"
2
+ "name": "joi",
3
+ "description": "Object schema validation",
4
+ "version": "17.2.0",
5
+ "repository": "git://github.com/sideway/joi",
6
+ "main": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "browser": "dist/joi-browser.min.js",
9
+ "files": [
10
+ "lib/**/*",
11
+ "dist/*"
12
+ ],
13
+ "keywords": [
14
+ "schema",
15
+ "validation"
16
+ ],
17
+ "dependencies": {
18
+ "@hapi/address": "^4.1.0",
19
+ "@hapi/formula": "^2.0.0",
20
+ "@hapi/hoek": "^9.0.0",
21
+ "@hapi/pinpoint": "^2.0.0",
22
+ "@hapi/topo": "^5.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@hapi/bourne": "2.x.x",
26
+ "@hapi/code": "8.x.x",
27
+ "@hapi/lab": "23.x.x",
28
+ "@hapi/joi-legacy-test": "npm:@hapi/joi@15.x.x"
29
+ },
30
+ "scripts": {
31
+ "prepublishOnly": "cd browser && npm install && npm run build",
32
+ "test": "lab -t 100 -a @hapi/code -L -Y",
33
+ "test-cov-html": "lab -r html -o coverage.html -a @hapi/code"
34
+ },
35
+ "license": "BSD-3-Clause"
31
36
  }
package/CHANGELOG.md DELETED
@@ -1,3 +0,0 @@
1
- Breaking changes are documented using GitHub issues, see [issues labeled "release notes"](https://github.com/hapijs/joi/issues?q=is%3Aissue+label%3A%22release+notes%22).
2
-
3
- If you want changes of a specific minor or patch release, you can browse the [GitHub milestones](https://github.com/hapijs/joi/milestones?state=closed&direction=asc&sort=due_date).
package/LICENSE DELETED
@@ -1,25 +0,0 @@
1
- Copyright (c) 2012-2018, Project contributors
2
- Copyright (c) 2012-2014, Walmart
3
- All rights reserved.
4
-
5
- Redistribution and use in source and binary forms, with or without
6
- modification, are permitted provided that the following conditions are met:
7
- * Redistributions of source code must retain the above copyright
8
- notice, this list of conditions and the following disclaimer.
9
- * Redistributions in binary form must reproduce the above copyright
10
- notice, this list of conditions and the following disclaimer in the
11
- documentation and/or other materials provided with the distribution.
12
- * The names of any contributors may not be used to endorse or promote
13
- products derived from this software without specific prior written
14
- permission.
15
-
16
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
20
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/lib/cast.js DELETED
@@ -1,64 +0,0 @@
1
- 'use strict';
2
-
3
- // Load modules
4
-
5
- const Hoek = require('hoek');
6
- const Ref = require('./ref');
7
-
8
- // Type modules are delay-loaded to prevent circular dependencies
9
-
10
-
11
- // Declare internals
12
-
13
- const internals = {};
14
-
15
-
16
- exports.schema = function (Joi, config) {
17
-
18
- if (config !== undefined && config !== null && typeof config === 'object') {
19
-
20
- if (config.isJoi) {
21
- return config;
22
- }
23
-
24
- if (Array.isArray(config)) {
25
- return Joi.alternatives().try(config);
26
- }
27
-
28
- if (config instanceof RegExp) {
29
- return Joi.string().regex(config);
30
- }
31
-
32
- if (config instanceof Date) {
33
- return Joi.date().valid(config);
34
- }
35
-
36
- return Joi.object().keys(config);
37
- }
38
-
39
- if (typeof config === 'string') {
40
- return Joi.string().valid(config);
41
- }
42
-
43
- if (typeof config === 'number') {
44
- return Joi.number().valid(config);
45
- }
46
-
47
- if (typeof config === 'boolean') {
48
- return Joi.boolean().valid(config);
49
- }
50
-
51
- if (Ref.isRef(config)) {
52
- return Joi.valid(config);
53
- }
54
-
55
- Hoek.assert(config === null, 'Invalid schema content:', config);
56
-
57
- return Joi.valid(null);
58
- };
59
-
60
-
61
- exports.ref = function (id) {
62
-
63
- return Ref.isRef(id) ? id : Ref.create(id);
64
- };
package/lib/language.js DELETED
@@ -1,166 +0,0 @@
1
- 'use strict';
2
-
3
- // Load modules
4
-
5
-
6
- // Declare internals
7
-
8
- const internals = {};
9
-
10
-
11
- exports.errors = {
12
- root: 'value',
13
- key: '"{{!label}}" ',
14
- messages: {
15
- wrapArrays: true
16
- },
17
- any: {
18
- unknown: 'is not allowed',
19
- invalid: 'contains an invalid value',
20
- empty: 'is not allowed to be empty',
21
- required: 'is required',
22
- allowOnly: 'must be one of {{valids}}',
23
- default: 'threw an error when running default method'
24
- },
25
- alternatives: {
26
- base: 'not matching any of the allowed alternatives',
27
- child: null
28
- },
29
- array: {
30
- base: 'must be an array',
31
- includes: 'at position {{pos}} does not match any of the allowed types',
32
- includesSingle: 'single value of "{{!label}}" does not match any of the allowed types',
33
- includesOne: 'at position {{pos}} fails because {{reason}}',
34
- includesOneSingle: 'single value of "{{!label}}" fails because {{reason}}',
35
- includesRequiredUnknowns: 'does not contain {{unknownMisses}} required value(s)',
36
- includesRequiredKnowns: 'does not contain {{knownMisses}}',
37
- includesRequiredBoth: 'does not contain {{knownMisses}} and {{unknownMisses}} other required value(s)',
38
- excludes: 'at position {{pos}} contains an excluded value',
39
- excludesSingle: 'single value of "{{!label}}" contains an excluded value',
40
- hasKnown: 'does not contain at least one required match for type "{{!patternLabel}}"',
41
- hasUnknown: 'does not contain at least one required match',
42
- min: 'must contain at least {{limit}} items',
43
- max: 'must contain less than or equal to {{limit}} items',
44
- length: 'must contain {{limit}} items',
45
- ordered: 'at position {{pos}} fails because {{reason}}',
46
- orderedLength: 'at position {{pos}} fails because array must contain at most {{limit}} items',
47
- ref: 'references "{{ref}}" which is not a positive integer',
48
- sparse: 'must not be a sparse array',
49
- unique: 'position {{pos}} contains a duplicate value'
50
- },
51
- boolean: {
52
- base: 'must be a boolean'
53
- },
54
- binary: {
55
- base: 'must be a buffer or a string',
56
- min: 'must be at least {{limit}} bytes',
57
- max: 'must be less than or equal to {{limit}} bytes',
58
- length: 'must be {{limit}} bytes'
59
- },
60
- date: {
61
- base: 'must be a number of milliseconds or valid date string',
62
- strict: 'must be a valid date',
63
- min: 'must be larger than or equal to "{{limit}}"',
64
- max: 'must be less than or equal to "{{limit}}"',
65
- less: 'must be less than "{{limit}}"',
66
- greater: 'must be greater than "{{limit}}"',
67
- isoDate: 'must be a valid ISO 8601 date',
68
- timestamp: {
69
- javascript: 'must be a valid timestamp or number of milliseconds',
70
- unix: 'must be a valid timestamp or number of seconds'
71
- },
72
- ref: 'references "{{ref}}" which is not a date'
73
- },
74
- function: {
75
- base: 'must be a Function',
76
- arity: 'must have an arity of {{n}}',
77
- minArity: 'must have an arity greater or equal to {{n}}',
78
- maxArity: 'must have an arity lesser or equal to {{n}}',
79
- ref: 'must be a Joi reference',
80
- class: 'must be a class'
81
- },
82
- lazy: {
83
- base: '!!schema error: lazy schema must be set',
84
- schema: '!!schema error: lazy schema function must return a schema'
85
- },
86
- object: {
87
- base: 'must be an object',
88
- child: '!!child "{{!child}}" fails because {{reason}}',
89
- min: 'must have at least {{limit}} children',
90
- max: 'must have less than or equal to {{limit}} children',
91
- length: 'must have {{limit}} children',
92
- allowUnknown: '!!"{{!child}}" is not allowed',
93
- with: '!!"{{mainWithLabel}}" missing required peer "{{peerWithLabel}}"',
94
- without: '!!"{{mainWithLabel}}" conflict with forbidden peer "{{peerWithLabel}}"',
95
- missing: 'must contain at least one of {{peersWithLabels}}',
96
- xor: 'contains a conflict between exclusive peers {{peersWithLabels}}',
97
- oxor: 'contains a conflict between optional exclusive peers {{peersWithLabels}}',
98
- and: 'contains {{presentWithLabels}} without its required peers {{missingWithLabels}}',
99
- nand: '!!"{{mainWithLabel}}" must not exist simultaneously with {{peersWithLabels}}',
100
- assert: '!!"{{ref}}" validation failed because "{{ref}}" failed to {{message}}',
101
- rename: {
102
- multiple: 'cannot rename child "{{from}}" because multiple renames are disabled and another key was already renamed to "{{to}}"',
103
- override: 'cannot rename child "{{from}}" because override is disabled and target "{{to}}" exists',
104
- regex: {
105
- multiple: 'cannot rename children {{from}} because multiple renames are disabled and another key was already renamed to "{{to}}"',
106
- override: 'cannot rename children {{from}} because override is disabled and target "{{to}}" exists'
107
- }
108
- },
109
- type: 'must be an instance of "{{type}}"',
110
- schema: 'must be a Joi instance'
111
- },
112
- number: {
113
- base: 'must be a number',
114
- unsafe: 'must be a safe number',
115
- min: 'must be larger than or equal to {{limit}}',
116
- max: 'must be less than or equal to {{limit}}',
117
- less: 'must be less than {{limit}}',
118
- greater: 'must be greater than {{limit}}',
119
- integer: 'must be an integer',
120
- negative: 'must be a negative number',
121
- positive: 'must be a positive number',
122
- precision: 'must have no more than {{limit}} decimal places',
123
- ref: 'references "{{ref}}" which is not a number',
124
- multiple: 'must be a multiple of {{multiple}}',
125
- port: 'must be a valid port'
126
- },
127
- string: {
128
- base: 'must be a string',
129
- min: 'length must be at least {{limit}} characters long',
130
- max: 'length must be less than or equal to {{limit}} characters long',
131
- length: 'length must be {{limit}} characters long',
132
- alphanum: 'must only contain alpha-numeric characters',
133
- token: 'must only contain alpha-numeric and underscore characters',
134
- regex: {
135
- base: 'with value "{{!value}}" fails to match the required pattern: {{pattern}}',
136
- name: 'with value "{{!value}}" fails to match the {{name}} pattern',
137
- invert: {
138
- base: 'with value "{{!value}}" matches the inverted pattern: {{pattern}}',
139
- name: 'with value "{{!value}}" matches the inverted {{name}} pattern'
140
- }
141
- },
142
- email: 'must be a valid email',
143
- uri: 'must be a valid uri',
144
- uriRelativeOnly: 'must be a valid relative uri',
145
- uriCustomScheme: 'must be a valid uri with a scheme matching the {{scheme}} pattern',
146
- isoDate: 'must be a valid ISO 8601 date',
147
- guid: 'must be a valid GUID',
148
- hex: 'must only contain hexadecimal characters',
149
- hexAlign: 'hex decoded representation must be byte aligned',
150
- base64: 'must be a valid base64 string',
151
- dataUri: 'must be a valid dataUri string',
152
- hostname: 'must be a valid hostname',
153
- normalize: 'must be unicode normalized in the {{form}} form',
154
- lowercase: 'must only contain lowercase characters',
155
- uppercase: 'must only contain uppercase characters',
156
- trim: 'must not have leading or trailing whitespace',
157
- creditCard: 'must be a credit card',
158
- ref: 'references "{{ref}}" which is not a number',
159
- ip: 'must be a valid ip address with a {{cidr}} CIDR',
160
- ipVersion: 'must be a valid ip address of one of the following versions {{version}} with a {{cidr}} CIDR'
161
- },
162
- symbol: {
163
- base: 'must be a symbol',
164
- map: 'must be one of {{map}}'
165
- }
166
- };