@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/lib/schemas.js ADDED
@@ -0,0 +1,304 @@
1
+ 'use strict';
2
+
3
+ const Joi = require('./index');
4
+
5
+
6
+ const internals = {};
7
+
8
+
9
+ // Preferences
10
+
11
+ internals.wrap = Joi.string()
12
+ .min(1)
13
+ .max(2)
14
+ .allow(false);
15
+
16
+
17
+ exports.preferences = Joi.object({
18
+ allowUnknown: Joi.boolean(),
19
+ abortEarly: Joi.boolean(),
20
+ artifacts: Joi.boolean(),
21
+ cache: Joi.boolean(),
22
+ context: Joi.object(),
23
+ convert: Joi.boolean(),
24
+ dateFormat: Joi.valid('date', 'iso', 'string', 'time', 'utc'),
25
+ debug: Joi.boolean(),
26
+ errors: {
27
+ escapeHtml: Joi.boolean(),
28
+ label: Joi.valid('path', 'key', false),
29
+ language: [
30
+ Joi.string(),
31
+ Joi.object().ref()
32
+ ],
33
+ render: Joi.boolean(),
34
+ stack: Joi.boolean(),
35
+ wrap: {
36
+ label: internals.wrap,
37
+ array: internals.wrap,
38
+ string: internals.wrap
39
+ }
40
+ },
41
+ externals: Joi.boolean(),
42
+ messages: Joi.object(),
43
+ noDefaults: Joi.boolean(),
44
+ nonEnumerables: Joi.boolean(),
45
+ presence: Joi.valid('required', 'optional', 'forbidden'),
46
+ skipFunctions: Joi.boolean(),
47
+ stripUnknown: Joi.object({
48
+ arrays: Joi.boolean(),
49
+ objects: Joi.boolean()
50
+ })
51
+ .or('arrays', 'objects')
52
+ .allow(true, false),
53
+ warnings: Joi.boolean()
54
+ })
55
+ .strict();
56
+
57
+
58
+ // Extensions
59
+
60
+ internals.nameRx = /^[a-zA-Z0-9]\w*$/;
61
+
62
+
63
+ internals.rule = Joi.object({
64
+ alias: Joi.array().items(Joi.string().pattern(internals.nameRx)).single(),
65
+ args: Joi.array().items(
66
+ Joi.string(),
67
+ Joi.object({
68
+ name: Joi.string().pattern(internals.nameRx).required(),
69
+ ref: Joi.boolean(),
70
+ assert: Joi.alternatives([
71
+ Joi.function(),
72
+ Joi.object().schema()
73
+ ])
74
+ .conditional('ref', { is: true, then: Joi.required() }),
75
+ normalize: Joi.function(),
76
+ message: Joi.string().when('assert', { is: Joi.function(), then: Joi.required() })
77
+ })
78
+ ),
79
+ convert: Joi.boolean(),
80
+ manifest: Joi.boolean(),
81
+ method: Joi.function().allow(false),
82
+ multi: Joi.boolean(),
83
+ validate: Joi.function(),
84
+ jsonSchema: Joi.function()
85
+ });
86
+
87
+
88
+ exports.extension = Joi.object({
89
+ type: Joi.alternatives([
90
+ Joi.string(),
91
+ Joi.object().regex()
92
+ ])
93
+ .required(),
94
+ args: Joi.function(),
95
+ cast: Joi.object().pattern(internals.nameRx, Joi.object({
96
+ from: Joi.function().maxArity(1).required(),
97
+ to: Joi.function().minArity(1).maxArity(2).required()
98
+ })),
99
+ base: Joi.object().schema()
100
+ .when('type', { is: Joi.object().regex(), then: Joi.forbidden() }),
101
+ coerce: [
102
+ Joi.function().maxArity(3),
103
+ Joi.object({ method: Joi.function().maxArity(3).required(), from: Joi.array().items(Joi.string()).single() })
104
+ ],
105
+ flags: Joi.object().pattern(internals.nameRx, Joi.object({
106
+ setter: Joi.string(),
107
+ default: Joi.any()
108
+ })),
109
+ manifest: {
110
+ build: Joi.function().arity(2)
111
+ },
112
+ messages: [Joi.object(), Joi.string()],
113
+ modifiers: Joi.object().pattern(internals.nameRx, Joi.function().minArity(1).maxArity(2)),
114
+ overrides: Joi.object().pattern(internals.nameRx, Joi.function()),
115
+ prepare: Joi.function().maxArity(3),
116
+ rebuild: Joi.function().arity(1),
117
+ rules: Joi.object().pattern(internals.nameRx, internals.rule),
118
+ jsonSchema: Joi.function(),
119
+ terms: Joi.object().pattern(internals.nameRx, Joi.object({
120
+ init: Joi.array().allow(null).required(),
121
+ manifest: Joi.object().pattern(/.+/, [
122
+ Joi.valid('schema', 'single'),
123
+ Joi.object({
124
+ mapped: Joi.object({
125
+ from: Joi.string().required(),
126
+ to: Joi.string().required()
127
+ })
128
+ .required()
129
+ })
130
+ ])
131
+ })),
132
+ validate: Joi.function().maxArity(3)
133
+ })
134
+ .strict();
135
+
136
+
137
+ exports.extensions = Joi.array().items(Joi.object(), Joi.function().arity(1)).strict();
138
+
139
+
140
+ // Manifest
141
+
142
+ internals.desc = {
143
+
144
+ buffer: Joi.object({
145
+ buffer: Joi.string()
146
+ }),
147
+
148
+ func: Joi.object({
149
+ function: Joi.function().required(),
150
+ options: {
151
+ literal: true
152
+ }
153
+ }),
154
+
155
+ override: Joi.object({
156
+ override: true
157
+ }),
158
+
159
+ ref: Joi.object({
160
+ ref: Joi.object({
161
+ type: Joi.valid('value', 'global', 'local'),
162
+ path: Joi.array().required(),
163
+ separator: Joi.string().length(1).allow(false),
164
+ ancestor: Joi.number().min(0).integer().allow('root'),
165
+ map: Joi.array().items(Joi.array().length(2)).min(1),
166
+ adjust: Joi.function(),
167
+ iterables: Joi.boolean(),
168
+ in: Joi.boolean(),
169
+ render: Joi.boolean()
170
+ })
171
+ .required()
172
+ }),
173
+
174
+ regex: Joi.object({
175
+ regex: Joi.string().min(3)
176
+ }),
177
+
178
+ special: Joi.object({
179
+ special: Joi.valid('deep').required()
180
+ }),
181
+
182
+ template: Joi.object({
183
+ template: Joi.string().required(),
184
+ options: Joi.object()
185
+ }),
186
+
187
+ value: Joi.object({
188
+ value: Joi.alternatives([Joi.object(), Joi.array()]).required()
189
+ })
190
+ };
191
+
192
+
193
+ internals.desc.entity = Joi.alternatives([
194
+ Joi.array().items(Joi.link('...')),
195
+ Joi.boolean(),
196
+ Joi.function(),
197
+ Joi.number(),
198
+ Joi.string(),
199
+ internals.desc.buffer,
200
+ internals.desc.func,
201
+ internals.desc.ref,
202
+ internals.desc.regex,
203
+ internals.desc.special,
204
+ internals.desc.template,
205
+ internals.desc.value,
206
+ Joi.link('/')
207
+ ]);
208
+
209
+
210
+ internals.desc.values = Joi.array()
211
+ .items(
212
+ null,
213
+ Joi.boolean(),
214
+ Joi.function(),
215
+ Joi.number().allow(Infinity, -Infinity, NaN),
216
+ Joi.string().allow(''),
217
+ Joi.symbol(),
218
+ internals.desc.buffer,
219
+ internals.desc.func,
220
+ internals.desc.override,
221
+ internals.desc.ref,
222
+ internals.desc.regex,
223
+ internals.desc.template,
224
+ internals.desc.value
225
+ );
226
+
227
+
228
+ internals.desc.messages = Joi.object()
229
+ .pattern(/.+/, [
230
+ Joi.string(),
231
+ internals.desc.template,
232
+ Joi.object().pattern(/.+/, [Joi.string(), internals.desc.template])
233
+ ]);
234
+
235
+
236
+ exports.description = Joi.object({
237
+ type: Joi.string().required(),
238
+ flags: Joi.object({
239
+ cast: Joi.string(),
240
+ default: Joi.any(),
241
+ description: Joi.string(),
242
+ empty: Joi.link('/'),
243
+ failover: internals.desc.entity,
244
+ id: Joi.string(),
245
+ label: Joi.string(),
246
+ only: true,
247
+ presence: ['optional', 'required', 'forbidden'],
248
+ result: ['raw', 'strip'],
249
+ strip: Joi.boolean(),
250
+ unit: Joi.string()
251
+ })
252
+ .unknown(),
253
+ preferences: {
254
+ allowUnknown: Joi.boolean(),
255
+ abortEarly: Joi.boolean(),
256
+ artifacts: Joi.boolean(),
257
+ cache: Joi.boolean(),
258
+ convert: Joi.boolean(),
259
+ dateFormat: ['date', 'iso', 'string', 'time', 'utc'],
260
+ errors: {
261
+ escapeHtml: Joi.boolean(),
262
+ label: ['path', 'key'],
263
+ language: [
264
+ Joi.string(),
265
+ internals.desc.ref
266
+ ],
267
+ wrap: {
268
+ label: internals.wrap,
269
+ array: internals.wrap
270
+ }
271
+ },
272
+ externals: Joi.boolean(),
273
+ messages: internals.desc.messages,
274
+ noDefaults: Joi.boolean(),
275
+ nonEnumerables: Joi.boolean(),
276
+ presence: ['required', 'optional', 'forbidden'],
277
+ skipFunctions: Joi.boolean(),
278
+ stripUnknown: Joi.object({
279
+ arrays: Joi.boolean(),
280
+ objects: Joi.boolean()
281
+ })
282
+ .or('arrays', 'objects')
283
+ .allow(true, false),
284
+ warnings: Joi.boolean()
285
+ },
286
+ allow: internals.desc.values,
287
+ invalid: internals.desc.values,
288
+ rules: Joi.array().min(1).items({
289
+ name: Joi.string().required(),
290
+ args: Joi.object().min(1),
291
+ keep: Joi.boolean(),
292
+ message: [
293
+ Joi.string(),
294
+ internals.desc.messages
295
+ ],
296
+ warn: Joi.boolean()
297
+ }),
298
+
299
+ // Terms
300
+
301
+ keys: Joi.object().pattern(/.*/, Joi.link('/')),
302
+ link: internals.desc.ref
303
+ })
304
+ .pattern(/^[a-z]\w*$/, Joi.any());
package/lib/state.js ADDED
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ const { clone, reach } = require('@hapi/hoek');
4
+
5
+ const Common = require('./common');
6
+
7
+
8
+ const internals = {
9
+ value: Symbol('value')
10
+ };
11
+
12
+
13
+ module.exports = internals.State = class {
14
+
15
+ constructor(path, ancestors, state) {
16
+
17
+ this.path = path;
18
+ this.ancestors = ancestors; // [parent, ..., root]
19
+
20
+ this.mainstay = state.mainstay;
21
+ this.schemas = state.schemas; // [current, ..., root]
22
+ this.debug = null;
23
+ }
24
+
25
+ localize(path, ancestors = null, schema = null) {
26
+
27
+ const state = new internals.State(path, ancestors, this);
28
+
29
+ if (schema &&
30
+ state.schemas) {
31
+
32
+ state.schemas = [internals.schemas(schema), ...state.schemas];
33
+ }
34
+
35
+ return state;
36
+ }
37
+
38
+ nest(schema, debug) {
39
+
40
+ const state = new internals.State(this.path, this.ancestors, this);
41
+ state.schemas = state.schemas && [internals.schemas(schema), ...state.schemas];
42
+ state.debug = debug;
43
+ return state;
44
+ }
45
+
46
+ shadow(value, reason) {
47
+
48
+ this.mainstay.shadow = this.mainstay.shadow || new internals.Shadow();
49
+ this.mainstay.shadow.set(this.path, value, reason);
50
+ }
51
+
52
+ snapshot() {
53
+
54
+ if (this.mainstay.shadow) {
55
+ this._snapshot = clone(this.mainstay.shadow.node(this.path));
56
+ }
57
+
58
+ this.mainstay.snapshot();
59
+ }
60
+
61
+ restore() {
62
+
63
+ if (this.mainstay.shadow) {
64
+ this.mainstay.shadow.override(this.path, this._snapshot);
65
+ this._snapshot = undefined;
66
+ }
67
+
68
+ this.mainstay.restore();
69
+ }
70
+
71
+ commit() {
72
+
73
+ if (this.mainstay.shadow) {
74
+ this.mainstay.shadow.override(this.path, this._snapshot);
75
+ this._snapshot = undefined;
76
+ }
77
+
78
+ this.mainstay.commit();
79
+ }
80
+ };
81
+
82
+
83
+ internals.schemas = function (schema) {
84
+
85
+ if (Common.isSchema(schema)) {
86
+ return { schema };
87
+ }
88
+
89
+ return schema;
90
+ };
91
+
92
+
93
+ internals.Shadow = class {
94
+
95
+ constructor() {
96
+
97
+ this._values = null;
98
+ }
99
+
100
+ set(path, value, reason) {
101
+
102
+ if (!path.length) { // No need to store root value
103
+ return;
104
+ }
105
+
106
+ if (reason === 'strip' &&
107
+ typeof path[path.length - 1] === 'number') { // Cannot store stripped array values (due to shift)
108
+
109
+ return;
110
+ }
111
+
112
+ this._values = this._values || new Map();
113
+
114
+ let node = this._values;
115
+ for (let i = 0; i < path.length; ++i) {
116
+ const segment = path[i];
117
+ let next = node.get(segment);
118
+ if (!next) {
119
+ next = new Map();
120
+ node.set(segment, next);
121
+ }
122
+
123
+ node = next;
124
+ }
125
+
126
+ node[internals.value] = value;
127
+ }
128
+
129
+ get(path) {
130
+
131
+ const node = this.node(path);
132
+ if (node) {
133
+ return node[internals.value];
134
+ }
135
+ }
136
+
137
+ node(path) {
138
+
139
+ if (!this._values) {
140
+ return;
141
+ }
142
+
143
+ return reach(this._values, path, { iterables: true });
144
+ }
145
+
146
+ override(path, node) {
147
+
148
+ if (!this._values) {
149
+ return;
150
+ }
151
+
152
+ const parents = path.slice(0, -1);
153
+ const own = path[path.length - 1];
154
+ const parent = reach(this._values, parents, { iterables: true });
155
+
156
+ if (node) {
157
+ parent.set(own, node);
158
+ return;
159
+ }
160
+
161
+ if (parent) {
162
+ parent.delete(own);
163
+ }
164
+ }
165
+ };