@depup/hapi 18.1.0-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/.npmignore +4 -0
- package/LICENSE +26 -0
- package/README.md +47 -0
- package/lib/auth.js +545 -0
- package/lib/compression.js +107 -0
- package/lib/config.js +436 -0
- package/lib/core.js +680 -0
- package/lib/cors.js +207 -0
- package/lib/ext.js +94 -0
- package/lib/handler.js +165 -0
- package/lib/headers.js +200 -0
- package/lib/index.js +11 -0
- package/lib/methods.js +123 -0
- package/lib/request.js +623 -0
- package/lib/response.js +730 -0
- package/lib/route.js +519 -0
- package/lib/security.js +84 -0
- package/lib/server.js +557 -0
- package/lib/streams.js +37 -0
- package/lib/toolkit.js +201 -0
- package/lib/transmit.js +369 -0
- package/lib/validation.js +198 -0
- package/npm-shrinkwrap.json +2456 -0
- package/package.json +132 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Zlib = require('zlib');
|
|
4
|
+
|
|
5
|
+
const Accept = require('accept');
|
|
6
|
+
const Bounce = require('bounce');
|
|
7
|
+
const Hoek = require('hoek');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const internals = {
|
|
11
|
+
common: ['gzip, deflate', 'deflate, gzip', 'gzip', 'deflate', 'gzip, deflate, br']
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
exports = module.exports = internals.Compression = class {
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
|
|
19
|
+
this.encodings = ['identity', 'gzip', 'deflate'];
|
|
20
|
+
this._encoders = {
|
|
21
|
+
identity: null,
|
|
22
|
+
gzip: (options) => Zlib.createGzip(options),
|
|
23
|
+
deflate: (options) => Zlib.createDeflate(options)
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
this._decoders = {
|
|
27
|
+
gzip: (options) => Zlib.createGunzip(options),
|
|
28
|
+
deflate: (options) => Zlib.createInflate(options)
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
this._updateCommons();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_updateCommons() {
|
|
35
|
+
|
|
36
|
+
this._common = new Map();
|
|
37
|
+
internals.common.forEach((header) => {
|
|
38
|
+
|
|
39
|
+
this._common.set(header, Accept.encoding(header, this.encodings));
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
addEncoder(encoding, encoder) {
|
|
44
|
+
|
|
45
|
+
Hoek.assert(this._encoders[encoding] === undefined, `Cannot override existing encoder for ${encoding}`);
|
|
46
|
+
Hoek.assert(typeof encoder === 'function', `Invalid encoder function for ${encoding}`);
|
|
47
|
+
this._encoders[encoding] = encoder;
|
|
48
|
+
this.encodings.unshift(encoding);
|
|
49
|
+
this._updateCommons();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
addDecoder(encoding, decoder) {
|
|
53
|
+
|
|
54
|
+
Hoek.assert(this._decoders[encoding] === undefined, `Cannot override existing decoder for ${encoding}`);
|
|
55
|
+
Hoek.assert(typeof decoder === 'function', `Invalid decoder function for ${encoding}`);
|
|
56
|
+
this._decoders[encoding] = decoder;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
accept(request) {
|
|
60
|
+
|
|
61
|
+
const header = request.headers['accept-encoding'];
|
|
62
|
+
const common = this._common.get(header);
|
|
63
|
+
if (common) {
|
|
64
|
+
return common;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
return Accept.encoding(header, this.encodings);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
Bounce.rethrow(err, 'system');
|
|
72
|
+
err.header = header;
|
|
73
|
+
request._log(['accept-encoding', 'error'], err);
|
|
74
|
+
return 'identity';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
encoding(response, length) {
|
|
79
|
+
|
|
80
|
+
const request = response.request;
|
|
81
|
+
if (!request._core.settings.compression ||
|
|
82
|
+
(length !== null && length < request._core.settings.compression.minBytes)) {
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const mime = request._core.mime.type(response.headers['content-type'] || 'application/octet-stream');
|
|
88
|
+
if (!mime.compressible) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
response.vary('accept-encoding');
|
|
93
|
+
|
|
94
|
+
if (response.headers['content-encoding']) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (request.info.acceptEncoding === 'identity' ? null : request.info.acceptEncoding);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
encoder(request, encoding) {
|
|
102
|
+
|
|
103
|
+
const encoder = this._encoders[encoding];
|
|
104
|
+
Hoek.assert(encoder !== undefined, `Unknown encoding ${encoding}`);
|
|
105
|
+
return encoder(request.route.settings.compression[encoding]);
|
|
106
|
+
}
|
|
107
|
+
};
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Os = require('os');
|
|
4
|
+
|
|
5
|
+
const Joi = require('joi');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const internals = {};
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
exports.symbol = Symbol('hapi-response');
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
exports.apply = function (type, options, ...message) {
|
|
15
|
+
|
|
16
|
+
const result = Joi.validate(options, internals[type]);
|
|
17
|
+
|
|
18
|
+
if (result.error) {
|
|
19
|
+
throw new Error(`Invalid ${type} options ${message.length ? '(' + message.join(' ') + ')' : ''} ${result.error.annotate()}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return result.value;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
exports.enable = function (options) {
|
|
27
|
+
|
|
28
|
+
const settings = (options ? Object.assign({}, options) : {}); // Shallow cloned
|
|
29
|
+
|
|
30
|
+
if (settings.security === true) {
|
|
31
|
+
settings.security = {};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (settings.cors === true) {
|
|
35
|
+
settings.cors = {};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return settings;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
internals.access = Joi.object({
|
|
43
|
+
entity: Joi.valid('user', 'app', 'any'),
|
|
44
|
+
scope: [false, Joi.array().items(Joi.string()).single().min(1)]
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
internals.auth = Joi.alternatives([
|
|
49
|
+
Joi.string(),
|
|
50
|
+
internals.access.keys({
|
|
51
|
+
mode: Joi.valid('required', 'optional', 'try'),
|
|
52
|
+
strategy: Joi.string(),
|
|
53
|
+
strategies: Joi.array().items(Joi.string()).min(1),
|
|
54
|
+
access: Joi.array().items(internals.access.min(1)).single().min(1),
|
|
55
|
+
payload: [
|
|
56
|
+
Joi.valid('required', 'optional'),
|
|
57
|
+
Joi.boolean()
|
|
58
|
+
]
|
|
59
|
+
})
|
|
60
|
+
.without('strategy', 'strategies')
|
|
61
|
+
.without('access', ['scope', 'entity'])
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
internals.event = Joi.object({
|
|
66
|
+
method: Joi.array().items(Joi.func()).single(),
|
|
67
|
+
options: Joi.object({
|
|
68
|
+
before: Joi.array().items(Joi.string()).single(),
|
|
69
|
+
after: Joi.array().items(Joi.string()).single(),
|
|
70
|
+
bind: Joi.any(),
|
|
71
|
+
sandbox: Joi.valid('server', 'plugin')
|
|
72
|
+
})
|
|
73
|
+
.default({})
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
internals.exts = Joi.array().items(internals.event.keys({ type: Joi.string().required() })).single();
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
internals.failAction = Joi.alternatives([
|
|
81
|
+
Joi.valid('error', 'log', 'ignore'),
|
|
82
|
+
Joi.func()
|
|
83
|
+
])
|
|
84
|
+
.default('error');
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
internals.routeBase = Joi.object({
|
|
88
|
+
app: Joi.object().allow(null),
|
|
89
|
+
auth: internals.auth.allow(false),
|
|
90
|
+
bind: Joi.object().allow(null),
|
|
91
|
+
cache: Joi.object({
|
|
92
|
+
expiresIn: Joi.number(),
|
|
93
|
+
expiresAt: Joi.string(),
|
|
94
|
+
privacy: Joi.valid('default', 'public', 'private'),
|
|
95
|
+
statuses: Joi.array().items(Joi.number().integer().min(200)).min(1).single().default([200, 204]),
|
|
96
|
+
otherwise: Joi.string().default('no-cache')
|
|
97
|
+
})
|
|
98
|
+
.allow(false)
|
|
99
|
+
.default(),
|
|
100
|
+
compression: Joi.object()
|
|
101
|
+
.pattern(/.+/, Joi.object())
|
|
102
|
+
.default(),
|
|
103
|
+
cors: Joi.object({
|
|
104
|
+
origin: Joi.array().min(1).allow('ignore').default(['*']),
|
|
105
|
+
maxAge: Joi.number().default(86400),
|
|
106
|
+
headers: Joi.array().items(Joi.string()).default(['Accept', 'Authorization', 'Content-Type', 'If-None-Match']),
|
|
107
|
+
additionalHeaders: Joi.array().items(Joi.string()).default([]),
|
|
108
|
+
exposedHeaders: Joi.array().items(Joi.string()).default(['WWW-Authenticate', 'Server-Authorization']),
|
|
109
|
+
additionalExposedHeaders: Joi.array().items(Joi.string()).default([]),
|
|
110
|
+
credentials: Joi.boolean().when('origin', { is: 'ignore', then: false }).default(false)
|
|
111
|
+
})
|
|
112
|
+
.allow(false, true)
|
|
113
|
+
.default(false),
|
|
114
|
+
ext: Joi.object({
|
|
115
|
+
onPreAuth: Joi.array().items(internals.event).single(),
|
|
116
|
+
onCredentials: Joi.array().items(internals.event).single(),
|
|
117
|
+
onPostAuth: Joi.array().items(internals.event).single(),
|
|
118
|
+
onPreHandler: Joi.array().items(internals.event).single(),
|
|
119
|
+
onPostHandler: Joi.array().items(internals.event).single(),
|
|
120
|
+
onPreResponse: Joi.array().items(internals.event).single()
|
|
121
|
+
})
|
|
122
|
+
.default({}),
|
|
123
|
+
files: Joi.object({
|
|
124
|
+
relativeTo: Joi.string().regex(/^([\/\.])|([A-Za-z]:\\)|(\\\\)/).default('.')
|
|
125
|
+
})
|
|
126
|
+
.default(),
|
|
127
|
+
json: Joi.object({
|
|
128
|
+
replacer: Joi.alternatives(Joi.func(), Joi.array()).allow(null).default(null),
|
|
129
|
+
space: Joi.number().allow(null).default(null),
|
|
130
|
+
suffix: Joi.string().allow(null).default(null),
|
|
131
|
+
escape: Joi.boolean().default(false)
|
|
132
|
+
})
|
|
133
|
+
.default(),
|
|
134
|
+
jsonp: Joi.string(),
|
|
135
|
+
log: Joi.object({
|
|
136
|
+
collect: Joi.boolean().default(false)
|
|
137
|
+
})
|
|
138
|
+
.default(),
|
|
139
|
+
payload: Joi.object({
|
|
140
|
+
output: Joi.valid('data', 'stream', 'file').default('data'),
|
|
141
|
+
parse: Joi.boolean().allow('gunzip').default(true),
|
|
142
|
+
multipart: Joi.object({
|
|
143
|
+
output: Joi.valid('data', 'stream', 'file', 'annotated').required()
|
|
144
|
+
})
|
|
145
|
+
.allow(false),
|
|
146
|
+
allow: Joi.array().items(Joi.string()).single(),
|
|
147
|
+
override: Joi.string(),
|
|
148
|
+
protoAction: Joi.valid('error', 'remove', 'ignore').default('error'),
|
|
149
|
+
maxBytes: Joi.number().integer().positive().default(1024 * 1024),
|
|
150
|
+
uploads: Joi.string().default(Os.tmpdir()),
|
|
151
|
+
failAction: internals.failAction,
|
|
152
|
+
timeout: Joi.number().integer().positive().allow(false).default(10 * 1000),
|
|
153
|
+
defaultContentType: Joi.string().default('application/json'),
|
|
154
|
+
compression: Joi.object()
|
|
155
|
+
.pattern(/.+/, Joi.object())
|
|
156
|
+
.default()
|
|
157
|
+
})
|
|
158
|
+
.default(),
|
|
159
|
+
plugins: Joi.object(),
|
|
160
|
+
response: Joi.object({
|
|
161
|
+
disconnectStatusCode: Joi.number().integer().min(400).default(499),
|
|
162
|
+
emptyStatusCode: Joi.valid(200, 204).default(200),
|
|
163
|
+
failAction: internals.failAction,
|
|
164
|
+
modify: Joi.boolean(),
|
|
165
|
+
options: Joi.object().default(),
|
|
166
|
+
ranges: Joi.boolean().default(true),
|
|
167
|
+
sample: Joi.number().min(0).max(100).when('modify', { is: true, then: Joi.forbidden() }),
|
|
168
|
+
schema: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(true, false),
|
|
169
|
+
status: Joi.object().pattern(/\d\d\d/, Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(true, false))
|
|
170
|
+
})
|
|
171
|
+
.default()
|
|
172
|
+
.assert('options.stripUnknown', Joi.when('modify', { is: true, otherwise: false }), 'meet requirement of having peer modify set to true'),
|
|
173
|
+
security: Joi.object({
|
|
174
|
+
hsts: Joi.alternatives([
|
|
175
|
+
Joi.object({
|
|
176
|
+
maxAge: Joi.number(),
|
|
177
|
+
includeSubdomains: Joi.boolean(),
|
|
178
|
+
includeSubDomains: Joi.boolean(),
|
|
179
|
+
preload: Joi.boolean()
|
|
180
|
+
}),
|
|
181
|
+
Joi.boolean(),
|
|
182
|
+
Joi.number()
|
|
183
|
+
])
|
|
184
|
+
.default(15768000),
|
|
185
|
+
xframe: Joi.alternatives([
|
|
186
|
+
Joi.boolean(),
|
|
187
|
+
Joi.valid('sameorigin', 'deny'),
|
|
188
|
+
Joi.object({
|
|
189
|
+
rule: Joi.valid('sameorigin', 'deny', 'allow-from'),
|
|
190
|
+
source: Joi.string()
|
|
191
|
+
})
|
|
192
|
+
])
|
|
193
|
+
.default('deny'),
|
|
194
|
+
xss: Joi.boolean().default(true),
|
|
195
|
+
noOpen: Joi.boolean().default(true),
|
|
196
|
+
noSniff: Joi.boolean().default(true),
|
|
197
|
+
referrer: Joi.alternatives([
|
|
198
|
+
Joi.boolean().valid(false),
|
|
199
|
+
Joi.valid('', 'no-referrer', 'no-referrer-when-downgrade',
|
|
200
|
+
'unsafe-url', 'same-origin', 'origin', 'strict-origin',
|
|
201
|
+
'origin-when-cross-origin', 'strict-origin-when-cross-origin')
|
|
202
|
+
])
|
|
203
|
+
.default(false)
|
|
204
|
+
})
|
|
205
|
+
.allow(null, false, true)
|
|
206
|
+
.default(false),
|
|
207
|
+
state: Joi.object({
|
|
208
|
+
parse: Joi.boolean().default(true),
|
|
209
|
+
failAction: internals.failAction
|
|
210
|
+
})
|
|
211
|
+
.default(),
|
|
212
|
+
timeout: Joi.object({
|
|
213
|
+
socket: Joi.number().integer().positive().allow(false),
|
|
214
|
+
server: Joi.number().integer().positive().allow(false).default(false)
|
|
215
|
+
})
|
|
216
|
+
.default(),
|
|
217
|
+
validate: Joi.object({
|
|
218
|
+
headers: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, true),
|
|
219
|
+
params: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, true),
|
|
220
|
+
query: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
|
|
221
|
+
payload: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
|
|
222
|
+
state: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
|
|
223
|
+
failAction: internals.failAction,
|
|
224
|
+
errorFields: Joi.object(),
|
|
225
|
+
options: Joi.object().default()
|
|
226
|
+
})
|
|
227
|
+
.default()
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
internals.server = Joi.object({
|
|
232
|
+
address: Joi.string().hostname(),
|
|
233
|
+
app: Joi.object().allow(null),
|
|
234
|
+
autoListen: Joi.boolean(),
|
|
235
|
+
cache: Joi.allow(null), // Validated elsewhere
|
|
236
|
+
compression: Joi.object({
|
|
237
|
+
minBytes: Joi.number().min(1).integer().default(1024)
|
|
238
|
+
})
|
|
239
|
+
.allow(false)
|
|
240
|
+
.default(),
|
|
241
|
+
debug: Joi.object({
|
|
242
|
+
request: Joi.array().items(Joi.string()).single().allow(false).default(['implementation']),
|
|
243
|
+
log: Joi.array().items(Joi.string()).single().allow(false)
|
|
244
|
+
})
|
|
245
|
+
.allow(false)
|
|
246
|
+
.default(),
|
|
247
|
+
host: Joi.string().hostname().allow(null),
|
|
248
|
+
listener: Joi.any(),
|
|
249
|
+
load: Joi.object({
|
|
250
|
+
sampleInterval: Joi.number().integer().min(0).default(0),
|
|
251
|
+
concurrent: Joi.number().integer().min(0).default(0)
|
|
252
|
+
})
|
|
253
|
+
.unknown()
|
|
254
|
+
.default(),
|
|
255
|
+
mime: Joi.object().allow(null).default(null),
|
|
256
|
+
operations: Joi.object({
|
|
257
|
+
cleanStop: Joi.boolean().default(true)
|
|
258
|
+
})
|
|
259
|
+
.default(),
|
|
260
|
+
plugins: Joi.object(),
|
|
261
|
+
port: Joi.alternatives([
|
|
262
|
+
Joi.number().integer().min(0), // TCP port
|
|
263
|
+
Joi.string().regex(/\//), // Unix domain socket
|
|
264
|
+
Joi.string().regex(/^\\\\\.\\pipe\\/) // Windows named pipe
|
|
265
|
+
])
|
|
266
|
+
.allow(null),
|
|
267
|
+
query: Joi.object({
|
|
268
|
+
parser: Joi.func()
|
|
269
|
+
})
|
|
270
|
+
.default(),
|
|
271
|
+
router: Joi.object({
|
|
272
|
+
isCaseSensitive: Joi.boolean().default(true),
|
|
273
|
+
stripTrailingSlash: Joi.boolean().default(false)
|
|
274
|
+
})
|
|
275
|
+
.default(),
|
|
276
|
+
routes: internals.routeBase.default(),
|
|
277
|
+
state: Joi.object(), // Cookie defaults
|
|
278
|
+
tls: Joi.alternatives([
|
|
279
|
+
Joi.object().allow(null),
|
|
280
|
+
Joi.boolean()
|
|
281
|
+
]),
|
|
282
|
+
uri: Joi.string().regex(/[^/]$/)
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
internals.vhost = Joi.alternatives([
|
|
287
|
+
Joi.string().hostname(),
|
|
288
|
+
Joi.array().items(Joi.string().hostname()).min(1)
|
|
289
|
+
]);
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
internals.handler = Joi.alternatives([
|
|
293
|
+
Joi.func(),
|
|
294
|
+
Joi.object().length(1)
|
|
295
|
+
]);
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
internals.route = Joi.object({
|
|
299
|
+
method: Joi.string().regex(/^[a-zA-Z0-9!#\$%&'\*\+\-\.^_`\|~]+$/).required(),
|
|
300
|
+
path: Joi.string().required(),
|
|
301
|
+
rules: Joi.object(),
|
|
302
|
+
vhost: internals.vhost,
|
|
303
|
+
|
|
304
|
+
// Validated in route construction
|
|
305
|
+
|
|
306
|
+
handler: Joi.any(),
|
|
307
|
+
options: Joi.any(),
|
|
308
|
+
config: Joi.any() // Backwards compatibility
|
|
309
|
+
})
|
|
310
|
+
.without('config', 'options');
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
internals.pre = [
|
|
314
|
+
Joi.func(),
|
|
315
|
+
Joi.object({
|
|
316
|
+
method: Joi.alternatives(Joi.string(), Joi.func()).required(),
|
|
317
|
+
assign: Joi.string(),
|
|
318
|
+
mode: Joi.valid('serial', 'parallel'),
|
|
319
|
+
failAction: internals.failAction
|
|
320
|
+
})
|
|
321
|
+
];
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
internals.routeConfig = internals.routeBase.keys({
|
|
325
|
+
description: Joi.string(),
|
|
326
|
+
id: Joi.string(),
|
|
327
|
+
isInternal: Joi.boolean(),
|
|
328
|
+
notes: [
|
|
329
|
+
Joi.string(),
|
|
330
|
+
Joi.array().items(Joi.string())
|
|
331
|
+
],
|
|
332
|
+
pre: Joi.array().items(internals.pre.concat(Joi.array().items(internals.pre).min(1))),
|
|
333
|
+
tags: [
|
|
334
|
+
Joi.string(),
|
|
335
|
+
Joi.array().items(Joi.string())
|
|
336
|
+
]
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
internals.cacheConfig = Joi.alternatives([
|
|
341
|
+
Joi.func(),
|
|
342
|
+
Joi.object({
|
|
343
|
+
name: Joi.string().invalid('_default'),
|
|
344
|
+
shared: Joi.boolean(),
|
|
345
|
+
provider: [
|
|
346
|
+
Joi.func(),
|
|
347
|
+
{
|
|
348
|
+
constructor: Joi.func().required(),
|
|
349
|
+
options: Joi.object({
|
|
350
|
+
partition: Joi.string().default('hapi-cache')
|
|
351
|
+
})
|
|
352
|
+
.unknown() // Catbox client validates other keys
|
|
353
|
+
.default({})
|
|
354
|
+
}
|
|
355
|
+
],
|
|
356
|
+
engine: Joi.object()
|
|
357
|
+
})
|
|
358
|
+
.xor('provider', 'engine')
|
|
359
|
+
]);
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
internals.cache = Joi.array().items(internals.cacheConfig).min(1).single();
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
internals.cachePolicy = Joi.object({
|
|
366
|
+
cache: Joi.string().allow(null).allow(''),
|
|
367
|
+
segment: Joi.string(),
|
|
368
|
+
shared: Joi.boolean()
|
|
369
|
+
})
|
|
370
|
+
.unknown(); // Catbox policy validates other keys
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
internals.method = Joi.object({
|
|
374
|
+
bind: Joi.object().allow(null),
|
|
375
|
+
generateKey: Joi.func(),
|
|
376
|
+
cache: internals.cachePolicy
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
internals.methodObject = Joi.object({
|
|
381
|
+
name: Joi.string().required(),
|
|
382
|
+
method: Joi.func().required(),
|
|
383
|
+
options: Joi.object()
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
internals.register = Joi.object({
|
|
388
|
+
once: true,
|
|
389
|
+
routes: Joi.object({
|
|
390
|
+
prefix: Joi.string().regex(/^\/.+/),
|
|
391
|
+
vhost: internals.vhost
|
|
392
|
+
})
|
|
393
|
+
.default({})
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
internals.semver = Joi.string();
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
internals.plugin = internals.register.keys({
|
|
401
|
+
options: Joi.any(),
|
|
402
|
+
plugin: Joi.object({
|
|
403
|
+
register: Joi.func().required(),
|
|
404
|
+
name: Joi.string().when('pkg.name', { is: Joi.exist(), otherwise: Joi.required() }),
|
|
405
|
+
version: Joi.string(),
|
|
406
|
+
multiple: Joi.boolean().default(false),
|
|
407
|
+
dependencies: [
|
|
408
|
+
Joi.array().items(Joi.string()).single(),
|
|
409
|
+
Joi.object().pattern(/.+/, internals.semver)
|
|
410
|
+
],
|
|
411
|
+
once: true,
|
|
412
|
+
requirements: Joi.object({
|
|
413
|
+
hapi: Joi.string(),
|
|
414
|
+
node: Joi.string()
|
|
415
|
+
})
|
|
416
|
+
.default(),
|
|
417
|
+
pkg: Joi.object({
|
|
418
|
+
name: Joi.string(),
|
|
419
|
+
version: Joi.string().default('0.0.0')
|
|
420
|
+
})
|
|
421
|
+
.unknown()
|
|
422
|
+
.default({})
|
|
423
|
+
})
|
|
424
|
+
.unknown()
|
|
425
|
+
})
|
|
426
|
+
.without('once', 'options')
|
|
427
|
+
.unknown();
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
internals.rules = Joi.object({
|
|
431
|
+
validate: Joi.object({
|
|
432
|
+
schema: Joi.alternatives(Joi.object(), Joi.array()).required(),
|
|
433
|
+
options: Joi.object()
|
|
434
|
+
.default({ allowUnknown: true })
|
|
435
|
+
})
|
|
436
|
+
});
|