@depup/joi 18.1.1-depup.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.
- package/LICENSE.md +11 -0
- package/README.md +31 -0
- package/changes.json +10 -0
- package/dist/joi-browser.min.js +1 -0
- package/lib/annotate.js +175 -0
- package/lib/base.js +1317 -0
- package/lib/cache.js +142 -0
- package/lib/common.js +234 -0
- package/lib/compile.js +283 -0
- package/lib/errors.js +271 -0
- package/lib/extend.js +317 -0
- package/lib/index.d.ts +2666 -0
- package/lib/index.js +282 -0
- package/lib/manifest.js +475 -0
- package/lib/messages.js +177 -0
- package/lib/modify.js +267 -0
- package/lib/ref.js +412 -0
- package/lib/schemas.js +304 -0
- package/lib/state.js +165 -0
- package/lib/template.js +461 -0
- package/lib/trace.js +346 -0
- package/lib/types/alternatives.js +430 -0
- package/lib/types/any.js +174 -0
- package/lib/types/array.js +937 -0
- package/lib/types/binary.js +124 -0
- package/lib/types/boolean.js +151 -0
- package/lib/types/date.js +279 -0
- package/lib/types/function.js +93 -0
- package/lib/types/keys.js +1170 -0
- package/lib/types/link.js +191 -0
- package/lib/types/number.js +399 -0
- package/lib/types/object.js +22 -0
- package/lib/types/string.js +986 -0
- package/lib/types/symbol.js +114 -0
- package/lib/validator.js +759 -0
- package/lib/values.js +262 -0
- package/package.json +68 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { assert } = require('@hapi/hoek');
|
|
4
|
+
|
|
5
|
+
const Any = require('./any');
|
|
6
|
+
const Common = require('../common');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const internals = {};
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module.exports = Any.extend({
|
|
13
|
+
|
|
14
|
+
type: 'binary',
|
|
15
|
+
|
|
16
|
+
coerce: {
|
|
17
|
+
from: ['string', 'object'],
|
|
18
|
+
method(value, { schema }) {
|
|
19
|
+
|
|
20
|
+
if (typeof value === 'string' || (value !== null && value.type === 'Buffer')) {
|
|
21
|
+
try {
|
|
22
|
+
return { value: Buffer.from(value, schema._flags.encoding) };
|
|
23
|
+
}
|
|
24
|
+
catch { }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
validate(value, { error }) {
|
|
30
|
+
|
|
31
|
+
if (!Buffer.isBuffer(value)) {
|
|
32
|
+
return { value, errors: error('binary.base') };
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
jsonSchema(schema, res, mode, options) {
|
|
37
|
+
|
|
38
|
+
res.type = 'string';
|
|
39
|
+
res.format = 'binary';
|
|
40
|
+
|
|
41
|
+
return res;
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
rules: {
|
|
45
|
+
encoding: {
|
|
46
|
+
method(encoding) {
|
|
47
|
+
|
|
48
|
+
assert(Buffer.isEncoding(encoding), 'Invalid encoding:', encoding);
|
|
49
|
+
|
|
50
|
+
return this.$_setFlag('encoding', encoding);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
length: {
|
|
55
|
+
method(limit) {
|
|
56
|
+
|
|
57
|
+
return this.$_addRule({ name: 'length', method: 'length', args: { limit }, operator: '=' });
|
|
58
|
+
},
|
|
59
|
+
validate(value, helpers, { limit }, { name, operator, args }) {
|
|
60
|
+
|
|
61
|
+
if (Common.compare(value.length, limit, operator)) {
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return helpers.error('binary.' + name, { limit: args.limit, value });
|
|
66
|
+
},
|
|
67
|
+
jsonSchema(rule, res) {
|
|
68
|
+
|
|
69
|
+
res.minLength = rule.args.limit;
|
|
70
|
+
res.maxLength = rule.args.limit;
|
|
71
|
+
return res;
|
|
72
|
+
},
|
|
73
|
+
args: [
|
|
74
|
+
{
|
|
75
|
+
name: 'limit',
|
|
76
|
+
ref: true,
|
|
77
|
+
assert: Common.limit,
|
|
78
|
+
message: 'must be a positive integer'
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
max: {
|
|
84
|
+
method(limit) {
|
|
85
|
+
|
|
86
|
+
return this.$_addRule({ name: 'max', method: 'length', args: { limit }, operator: '<=' });
|
|
87
|
+
},
|
|
88
|
+
jsonSchema(rule, res) {
|
|
89
|
+
|
|
90
|
+
res.maxLength = rule.args.limit;
|
|
91
|
+
return res;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
min: {
|
|
96
|
+
method(limit) {
|
|
97
|
+
|
|
98
|
+
return this.$_addRule({ name: 'min', method: 'length', args: { limit }, operator: '>=' });
|
|
99
|
+
},
|
|
100
|
+
jsonSchema(rule, res) {
|
|
101
|
+
|
|
102
|
+
res.minLength = rule.args.limit;
|
|
103
|
+
return res;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
cast: {
|
|
109
|
+
string: {
|
|
110
|
+
from: (value) => Buffer.isBuffer(value),
|
|
111
|
+
to(value, helpers) {
|
|
112
|
+
|
|
113
|
+
return value.toString();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
messages: {
|
|
119
|
+
'binary.base': '{{#label}} must be a buffer or a string',
|
|
120
|
+
'binary.length': '{{#label}} must be {{#limit}} bytes',
|
|
121
|
+
'binary.max': '{{#label}} must be less than or equal to {{#limit}} bytes',
|
|
122
|
+
'binary.min': '{{#label}} must be at least {{#limit}} bytes'
|
|
123
|
+
}
|
|
124
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { assert } = require('@hapi/hoek');
|
|
4
|
+
|
|
5
|
+
const Any = require('./any');
|
|
6
|
+
const Common = require('../common');
|
|
7
|
+
const Values = require('../values');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const internals = {};
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
internals.isBool = function (value) {
|
|
14
|
+
|
|
15
|
+
return typeof value === 'boolean';
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
module.exports = Any.extend({
|
|
20
|
+
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
|
|
23
|
+
flags: {
|
|
24
|
+
|
|
25
|
+
sensitive: { default: false }
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
terms: {
|
|
29
|
+
|
|
30
|
+
falsy: {
|
|
31
|
+
init: null,
|
|
32
|
+
manifest: 'values'
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
truthy: {
|
|
36
|
+
init: null,
|
|
37
|
+
manifest: 'values'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
coerce(value, { schema }) {
|
|
42
|
+
|
|
43
|
+
if (typeof value === 'boolean') {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof value === 'string') {
|
|
48
|
+
const trimmedValue = value.trim();
|
|
49
|
+
const normalized = schema._flags.sensitive ? trimmedValue : trimmedValue.toLowerCase();
|
|
50
|
+
value = normalized === 'true' ? true : (normalized === 'false' ? false : value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof value !== 'boolean') {
|
|
54
|
+
value = schema.$_terms.truthy && schema.$_terms.truthy.has(value, null, null, !schema._flags.sensitive) ||
|
|
55
|
+
(schema.$_terms.falsy && schema.$_terms.falsy.has(value, null, null, !schema._flags.sensitive) ? false : value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return { value };
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
validate(value, { error }) {
|
|
62
|
+
|
|
63
|
+
if (typeof value !== 'boolean') {
|
|
64
|
+
return { value, errors: error('boolean.base') };
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
rules: {
|
|
69
|
+
truthy: {
|
|
70
|
+
method(...values) {
|
|
71
|
+
|
|
72
|
+
Common.verifyFlat(values, 'truthy');
|
|
73
|
+
|
|
74
|
+
const obj = this.clone();
|
|
75
|
+
obj.$_terms.truthy = obj.$_terms.truthy || new Values();
|
|
76
|
+
|
|
77
|
+
for (let i = 0; i < values.length; ++i) {
|
|
78
|
+
const value = values[i];
|
|
79
|
+
|
|
80
|
+
assert(value !== undefined, 'Cannot call truthy with undefined');
|
|
81
|
+
obj.$_terms.truthy.add(value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return obj;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
falsy: {
|
|
89
|
+
method(...values) {
|
|
90
|
+
|
|
91
|
+
Common.verifyFlat(values, 'falsy');
|
|
92
|
+
|
|
93
|
+
const obj = this.clone();
|
|
94
|
+
obj.$_terms.falsy = obj.$_terms.falsy || new Values();
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < values.length; ++i) {
|
|
97
|
+
const value = values[i];
|
|
98
|
+
|
|
99
|
+
assert(value !== undefined, 'Cannot call falsy with undefined');
|
|
100
|
+
obj.$_terms.falsy.add(value);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return obj;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
sensitive: {
|
|
108
|
+
method(enabled = true) {
|
|
109
|
+
|
|
110
|
+
return this.$_setFlag('sensitive', enabled);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
cast: {
|
|
116
|
+
number: {
|
|
117
|
+
from: internals.isBool,
|
|
118
|
+
to(value, helpers) {
|
|
119
|
+
|
|
120
|
+
return value ? 1 : 0;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
string: {
|
|
124
|
+
from: internals.isBool,
|
|
125
|
+
to(value, helpers) {
|
|
126
|
+
|
|
127
|
+
return value ? 'true' : 'false';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
manifest: {
|
|
133
|
+
|
|
134
|
+
build(obj, desc) {
|
|
135
|
+
|
|
136
|
+
if (desc.truthy) {
|
|
137
|
+
obj = obj.truthy(...desc.truthy);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (desc.falsy) {
|
|
141
|
+
obj = obj.falsy(...desc.falsy);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return obj;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
messages: {
|
|
149
|
+
'boolean.base': '{{#label}} must be a boolean'
|
|
150
|
+
}
|
|
151
|
+
});
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { assert } = require('@hapi/hoek');
|
|
4
|
+
|
|
5
|
+
const Any = require('./any');
|
|
6
|
+
const Common = require('../common');
|
|
7
|
+
const Template = require('../template');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const internals = {
|
|
11
|
+
formats: ['iso', 'javascript', 'unix']
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
internals.isDate = function (value) {
|
|
16
|
+
|
|
17
|
+
return value instanceof Date;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
module.exports = Any.extend({
|
|
22
|
+
|
|
23
|
+
type: 'date',
|
|
24
|
+
|
|
25
|
+
coerce: {
|
|
26
|
+
from: ['number', 'string'],
|
|
27
|
+
method(value, { schema }) {
|
|
28
|
+
|
|
29
|
+
return { value: internals.parse(value, schema._flags.format) || value };
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
validate(value, { schema, error, prefs }) {
|
|
34
|
+
|
|
35
|
+
if (value instanceof Date &&
|
|
36
|
+
!isNaN(value.getTime())) {
|
|
37
|
+
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const format = schema._flags.format;
|
|
42
|
+
|
|
43
|
+
if (!prefs.convert ||
|
|
44
|
+
!format ||
|
|
45
|
+
typeof value !== 'string') {
|
|
46
|
+
|
|
47
|
+
return { value, errors: error('date.base') };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { value, errors: error('date.format', { format }) };
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
jsonSchema(schema, res, mode, options) {
|
|
54
|
+
|
|
55
|
+
res.type = 'string';
|
|
56
|
+
res.format = 'date-time';
|
|
57
|
+
|
|
58
|
+
return res;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
rules: {
|
|
62
|
+
|
|
63
|
+
compare: {
|
|
64
|
+
method: false,
|
|
65
|
+
validate(value, helpers, { date }, { name, operator, args }) {
|
|
66
|
+
|
|
67
|
+
const to = date === 'now' ? Date.now() : date.getTime();
|
|
68
|
+
if (Common.compare(value.getTime(), to, operator)) {
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return helpers.error('date.' + name, { limit: args.date, value });
|
|
73
|
+
},
|
|
74
|
+
args: [
|
|
75
|
+
{
|
|
76
|
+
name: 'date',
|
|
77
|
+
ref: true,
|
|
78
|
+
normalize: (date) => {
|
|
79
|
+
|
|
80
|
+
return date === 'now' ? date : internals.parse(date);
|
|
81
|
+
},
|
|
82
|
+
assert: (date) => date !== null,
|
|
83
|
+
message: 'must have a valid date format'
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
format: {
|
|
89
|
+
method(format) {
|
|
90
|
+
|
|
91
|
+
assert(internals.formats.includes(format), 'Unknown date format', format);
|
|
92
|
+
|
|
93
|
+
return this.$_setFlag('format', format);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
greater: {
|
|
98
|
+
method(date) {
|
|
99
|
+
|
|
100
|
+
return this.$_addRule({ name: 'greater', method: 'compare', args: { date }, operator: '>' });
|
|
101
|
+
},
|
|
102
|
+
jsonSchema(rule, res) {
|
|
103
|
+
|
|
104
|
+
const date = rule.args.date;
|
|
105
|
+
if (date instanceof Date) {
|
|
106
|
+
res['x-constraint'] = { ...res['x-constraint'], greater: date.toISOString() };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return res;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
iso: {
|
|
114
|
+
method() {
|
|
115
|
+
|
|
116
|
+
return this.format('iso');
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
less: {
|
|
121
|
+
method(date) {
|
|
122
|
+
|
|
123
|
+
return this.$_addRule({ name: 'less', method: 'compare', args: { date }, operator: '<' });
|
|
124
|
+
},
|
|
125
|
+
jsonSchema(rule, res) {
|
|
126
|
+
|
|
127
|
+
const date = rule.args.date;
|
|
128
|
+
if (date instanceof Date) {
|
|
129
|
+
res['x-constraint'] = { ...res['x-constraint'], less: date.toISOString() };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return res;
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
max: {
|
|
137
|
+
method(date) {
|
|
138
|
+
|
|
139
|
+
return this.$_addRule({ name: 'max', method: 'compare', args: { date }, operator: '<=' });
|
|
140
|
+
},
|
|
141
|
+
jsonSchema(rule, res) {
|
|
142
|
+
|
|
143
|
+
const date = rule.args.date;
|
|
144
|
+
if (date instanceof Date) {
|
|
145
|
+
res['x-constraint'] = { ...res['x-constraint'], max: date.toISOString() };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return res;
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
min: {
|
|
153
|
+
method(date) {
|
|
154
|
+
|
|
155
|
+
return this.$_addRule({ name: 'min', method: 'compare', args: { date }, operator: '>=' });
|
|
156
|
+
},
|
|
157
|
+
jsonSchema(rule, res) {
|
|
158
|
+
|
|
159
|
+
const date = rule.args.date;
|
|
160
|
+
if (date instanceof Date) {
|
|
161
|
+
res['x-constraint'] = { ...res['x-constraint'], min: date.toISOString() };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return res;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
timestamp: {
|
|
169
|
+
method(type = 'javascript') {
|
|
170
|
+
|
|
171
|
+
assert(['javascript', 'unix'].includes(type), '"type" must be one of "javascript, unix"');
|
|
172
|
+
|
|
173
|
+
return this.format(type);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
cast: {
|
|
179
|
+
number: {
|
|
180
|
+
from: internals.isDate,
|
|
181
|
+
to(value, helpers) {
|
|
182
|
+
|
|
183
|
+
return value.getTime();
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
string: {
|
|
187
|
+
from: internals.isDate,
|
|
188
|
+
to(value, { prefs }) {
|
|
189
|
+
|
|
190
|
+
return Template.date(value, prefs);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
messages: {
|
|
196
|
+
'date.base': '{{#label}} must be a valid date',
|
|
197
|
+
'date.format': '{{#label}} must be in {msg("date.format." + #format) || #format} format',
|
|
198
|
+
'date.greater': '{{#label}} must be greater than {{:#limit}}',
|
|
199
|
+
'date.less': '{{#label}} must be less than {{:#limit}}',
|
|
200
|
+
'date.max': '{{#label}} must be less than or equal to {{:#limit}}',
|
|
201
|
+
'date.min': '{{#label}} must be greater than or equal to {{:#limit}}',
|
|
202
|
+
|
|
203
|
+
// Messages used in date.format
|
|
204
|
+
|
|
205
|
+
'date.format.iso': 'ISO 8601 date',
|
|
206
|
+
'date.format.javascript': 'timestamp or number of milliseconds',
|
|
207
|
+
'date.format.unix': 'timestamp or number of seconds'
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
// Helpers
|
|
213
|
+
|
|
214
|
+
internals.parse = function (value, format) {
|
|
215
|
+
|
|
216
|
+
if (value instanceof Date) {
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (typeof value !== 'string' &&
|
|
221
|
+
(isNaN(value) || !isFinite(value))) {
|
|
222
|
+
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (/^\s*$/.test(value)) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ISO
|
|
231
|
+
|
|
232
|
+
if (format === 'iso') {
|
|
233
|
+
if (!Common.isIsoDate(value)) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return internals.date(value.toString());
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Normalize number string
|
|
241
|
+
|
|
242
|
+
const original = value;
|
|
243
|
+
if (typeof value === 'string' &&
|
|
244
|
+
/^[+-]?\d+(\.\d+)?$/.test(value)) {
|
|
245
|
+
|
|
246
|
+
value = parseFloat(value);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Timestamp
|
|
250
|
+
|
|
251
|
+
if (format) {
|
|
252
|
+
if (format === 'javascript') {
|
|
253
|
+
return internals.date(1 * value); // Casting to number
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (format === 'unix') {
|
|
257
|
+
return internals.date(1000 * value);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (typeof original === 'string') {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Plain
|
|
266
|
+
|
|
267
|
+
return internals.date(value);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
internals.date = function (value) {
|
|
272
|
+
|
|
273
|
+
const date = new Date(value);
|
|
274
|
+
if (!isNaN(date.getTime())) {
|
|
275
|
+
return date;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return null;
|
|
279
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { assert } = require('@hapi/hoek');
|
|
4
|
+
|
|
5
|
+
const Keys = require('./keys');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const internals = {};
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module.exports = Keys.extend({
|
|
12
|
+
|
|
13
|
+
type: 'function',
|
|
14
|
+
|
|
15
|
+
properties: {
|
|
16
|
+
typeof: 'function'
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
rules: {
|
|
20
|
+
arity: {
|
|
21
|
+
method(n) {
|
|
22
|
+
|
|
23
|
+
assert(Number.isSafeInteger(n) && n >= 0, 'n must be a positive integer');
|
|
24
|
+
|
|
25
|
+
return this.$_addRule({ name: 'arity', args: { n } });
|
|
26
|
+
},
|
|
27
|
+
validate(value, helpers, { n }) {
|
|
28
|
+
|
|
29
|
+
if (value.length === n) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return helpers.error('function.arity', { n });
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
class: {
|
|
38
|
+
method() {
|
|
39
|
+
|
|
40
|
+
return this.$_addRule('class');
|
|
41
|
+
},
|
|
42
|
+
validate(value, helpers) {
|
|
43
|
+
|
|
44
|
+
if ((/^\s*class\s/).test(value.toString())) {
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return helpers.error('function.class', { value });
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
minArity: {
|
|
53
|
+
method(n) {
|
|
54
|
+
|
|
55
|
+
assert(Number.isSafeInteger(n) && n > 0, 'n must be a strict positive integer');
|
|
56
|
+
|
|
57
|
+
return this.$_addRule({ name: 'minArity', args: { n } });
|
|
58
|
+
},
|
|
59
|
+
validate(value, helpers, { n }) {
|
|
60
|
+
|
|
61
|
+
if (value.length >= n) {
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return helpers.error('function.minArity', { n });
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
maxArity: {
|
|
70
|
+
method(n) {
|
|
71
|
+
|
|
72
|
+
assert(Number.isSafeInteger(n) && n >= 0, 'n must be a positive integer');
|
|
73
|
+
|
|
74
|
+
return this.$_addRule({ name: 'maxArity', args: { n } });
|
|
75
|
+
},
|
|
76
|
+
validate(value, helpers, { n }) {
|
|
77
|
+
|
|
78
|
+
if (value.length <= n) {
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return helpers.error('function.maxArity', { n });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
messages: {
|
|
88
|
+
'function.arity': '{{#label}} must have an arity of {{#n}}',
|
|
89
|
+
'function.class': '{{#label}} must be a class',
|
|
90
|
+
'function.maxArity': '{{#label}} must have an arity lesser or equal to {{#n}}',
|
|
91
|
+
'function.minArity': '{{#label}} must have an arity greater or equal to {{#n}}'
|
|
92
|
+
}
|
|
93
|
+
});
|