@nocobase/plugin-workflow-custom-action-trigger 2.1.0-alpha.10 → 2.1.0-alpha.12

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 (43) hide show
  1. package/dist/client/CustomActionTrigger.d.ts +39 -2
  2. package/dist/client/index.js +1 -1
  3. package/dist/externalVersion.js +10 -10
  4. package/dist/node_modules/joi/dist/joi-browser.min.js +1 -0
  5. package/dist/node_modules/joi/lib/annotate.js +175 -0
  6. package/dist/node_modules/joi/lib/base.js +1069 -0
  7. package/dist/node_modules/joi/lib/cache.js +143 -0
  8. package/dist/node_modules/joi/lib/common.js +216 -0
  9. package/dist/node_modules/joi/lib/compile.js +283 -0
  10. package/dist/node_modules/joi/lib/errors.js +271 -0
  11. package/dist/node_modules/joi/lib/extend.js +312 -0
  12. package/dist/node_modules/joi/lib/index.d.ts +2365 -0
  13. package/dist/node_modules/joi/lib/index.js +1 -0
  14. package/dist/node_modules/joi/lib/manifest.js +476 -0
  15. package/dist/node_modules/joi/lib/messages.js +178 -0
  16. package/dist/node_modules/joi/lib/modify.js +267 -0
  17. package/dist/node_modules/joi/lib/ref.js +414 -0
  18. package/dist/node_modules/joi/lib/schemas.js +302 -0
  19. package/dist/node_modules/joi/lib/state.js +166 -0
  20. package/dist/node_modules/joi/lib/template.js +463 -0
  21. package/dist/node_modules/joi/lib/trace.js +346 -0
  22. package/dist/node_modules/joi/lib/types/alternatives.js +364 -0
  23. package/dist/node_modules/joi/lib/types/any.js +174 -0
  24. package/dist/node_modules/joi/lib/types/array.js +809 -0
  25. package/dist/node_modules/joi/lib/types/binary.js +100 -0
  26. package/dist/node_modules/joi/lib/types/boolean.js +150 -0
  27. package/dist/node_modules/joi/lib/types/date.js +233 -0
  28. package/dist/node_modules/joi/lib/types/function.js +93 -0
  29. package/dist/node_modules/joi/lib/types/keys.js +1067 -0
  30. package/dist/node_modules/joi/lib/types/link.js +168 -0
  31. package/dist/node_modules/joi/lib/types/number.js +363 -0
  32. package/dist/node_modules/joi/lib/types/object.js +22 -0
  33. package/dist/node_modules/joi/lib/types/string.js +850 -0
  34. package/dist/node_modules/joi/lib/types/symbol.js +102 -0
  35. package/dist/node_modules/joi/lib/validator.js +750 -0
  36. package/dist/node_modules/joi/lib/values.js +263 -0
  37. package/dist/node_modules/joi/node_modules/@hapi/topo/lib/index.d.ts +60 -0
  38. package/dist/node_modules/joi/node_modules/@hapi/topo/lib/index.js +225 -0
  39. package/dist/node_modules/joi/node_modules/@hapi/topo/package.json +30 -0
  40. package/dist/node_modules/joi/package.json +1 -0
  41. package/dist/server/CustomActionTrigger.d.ts +11 -0
  42. package/dist/server/CustomActionTrigger.js +19 -0
  43. package/package.json +5 -2
@@ -0,0 +1,850 @@
1
+ 'use strict';
2
+
3
+ const Assert = require('@hapi/hoek/lib/assert');
4
+ const Domain = require('@sideway/address/lib/domain');
5
+ const Email = require('@sideway/address/lib/email');
6
+ const Ip = require('@sideway/address/lib/ip');
7
+ const EscapeRegex = require('@hapi/hoek/lib/escapeRegex');
8
+ const Tlds = require('@sideway/address/lib/tlds');
9
+ const Uri = require('@sideway/address/lib/uri');
10
+
11
+ const Any = require('./any');
12
+ const Common = require('../common');
13
+
14
+
15
+ const internals = {
16
+ tlds: Tlds instanceof Set ? { tlds: { allow: Tlds, deny: null } } : false, // $lab:coverage:ignore$
17
+ base64Regex: {
18
+ // paddingRequired
19
+ true: {
20
+ // urlSafe
21
+ true: /^(?:[\w\-]{2}[\w\-]{2})*(?:[\w\-]{2}==|[\w\-]{3}=)?$/,
22
+ false: /^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/
23
+ },
24
+ false: {
25
+ true: /^(?:[\w\-]{2}[\w\-]{2})*(?:[\w\-]{2}(==)?|[\w\-]{3}=?)?$/,
26
+ false: /^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}(==)?|[A-Za-z0-9+\/]{3}=?)?$/
27
+ }
28
+ },
29
+ dataUriRegex: /^data:[\w+.-]+\/[\w+.-]+;((charset=[\w-]+|base64),)?(.*)$/,
30
+ hexRegex: {
31
+ withPrefix: /^0x[0-9a-f]+$/i,
32
+ withOptionalPrefix: /^(?:0x)?[0-9a-f]+$/i,
33
+ withoutPrefix: /^[0-9a-f]+$/i
34
+ },
35
+ ipRegex: Ip.regex({ cidr: 'forbidden' }).regex,
36
+ isoDurationRegex: /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/,
37
+
38
+ guidBrackets: {
39
+ '{': '}', '[': ']', '(': ')', '': ''
40
+ },
41
+ guidVersions: {
42
+ uuidv1: '1',
43
+ uuidv2: '2',
44
+ uuidv3: '3',
45
+ uuidv4: '4',
46
+ uuidv5: '5',
47
+ uuidv6: '6',
48
+ uuidv7: '7',
49
+ uuidv8: '8'
50
+ },
51
+ guidSeparators: new Set([undefined, true, false, '-', ':']),
52
+
53
+ normalizationForms: ['NFC', 'NFD', 'NFKC', 'NFKD']
54
+ };
55
+
56
+
57
+ module.exports = Any.extend({
58
+
59
+ type: 'string',
60
+
61
+ flags: {
62
+
63
+ insensitive: { default: false },
64
+ truncate: { default: false }
65
+ },
66
+
67
+ terms: {
68
+
69
+ replacements: { init: null }
70
+ },
71
+
72
+ coerce: {
73
+ from: 'string',
74
+ method(value, { schema, state, prefs }) {
75
+
76
+ const normalize = schema.$_getRule('normalize');
77
+ if (normalize) {
78
+ value = value.normalize(normalize.args.form);
79
+ }
80
+
81
+ const casing = schema.$_getRule('case');
82
+ if (casing) {
83
+ value = casing.args.direction === 'upper' ? value.toLocaleUpperCase() : value.toLocaleLowerCase();
84
+ }
85
+
86
+ const trim = schema.$_getRule('trim');
87
+ if (trim &&
88
+ trim.args.enabled) {
89
+
90
+ value = value.trim();
91
+ }
92
+
93
+ if (schema.$_terms.replacements) {
94
+ for (const replacement of schema.$_terms.replacements) {
95
+ value = value.replace(replacement.pattern, replacement.replacement);
96
+ }
97
+ }
98
+
99
+ const hex = schema.$_getRule('hex');
100
+ if (hex &&
101
+ hex.args.options.byteAligned &&
102
+ value.length % 2 !== 0) {
103
+
104
+ value = `0${value}`;
105
+ }
106
+
107
+ if (schema.$_getRule('isoDate')) {
108
+ const iso = internals.isoDate(value);
109
+ if (iso) {
110
+ value = iso;
111
+ }
112
+ }
113
+
114
+ if (schema._flags.truncate) {
115
+ const rule = schema.$_getRule('max');
116
+ if (rule) {
117
+ let limit = rule.args.limit;
118
+ if (Common.isResolvable(limit)) {
119
+ limit = limit.resolve(value, state, prefs);
120
+ if (!Common.limit(limit)) {
121
+ return { value, errors: schema.$_createError('any.ref', limit, { ref: rule.args.limit, arg: 'limit', reason: 'must be a positive integer' }, state, prefs) };
122
+ }
123
+ }
124
+
125
+ value = value.slice(0, limit);
126
+ }
127
+ }
128
+
129
+ return { value };
130
+ }
131
+ },
132
+
133
+ validate(value, { schema, error }) {
134
+
135
+ if (typeof value !== 'string') {
136
+ return { value, errors: error('string.base') };
137
+ }
138
+
139
+ if (value === '') {
140
+ const min = schema.$_getRule('min');
141
+ if (min &&
142
+ min.args.limit === 0) {
143
+
144
+ return;
145
+ }
146
+
147
+ return { value, errors: error('string.empty') };
148
+ }
149
+ },
150
+
151
+ rules: {
152
+
153
+ alphanum: {
154
+ method() {
155
+
156
+ return this.$_addRule('alphanum');
157
+ },
158
+ validate(value, helpers) {
159
+
160
+ if (/^[a-zA-Z0-9]+$/.test(value)) {
161
+ return value;
162
+ }
163
+
164
+ return helpers.error('string.alphanum');
165
+ }
166
+ },
167
+
168
+ base64: {
169
+ method(options = {}) {
170
+
171
+ Common.assertOptions(options, ['paddingRequired', 'urlSafe']);
172
+
173
+ options = { urlSafe: false, paddingRequired: true, ...options };
174
+ Assert(typeof options.paddingRequired === 'boolean', 'paddingRequired must be boolean');
175
+ Assert(typeof options.urlSafe === 'boolean', 'urlSafe must be boolean');
176
+
177
+ return this.$_addRule({ name: 'base64', args: { options } });
178
+ },
179
+ validate(value, helpers, { options }) {
180
+
181
+ const regex = internals.base64Regex[options.paddingRequired][options.urlSafe];
182
+ if (regex.test(value)) {
183
+ return value;
184
+ }
185
+
186
+ return helpers.error('string.base64');
187
+ }
188
+ },
189
+
190
+ case: {
191
+ method(direction) {
192
+
193
+ Assert(['lower', 'upper'].includes(direction), 'Invalid case:', direction);
194
+
195
+ return this.$_addRule({ name: 'case', args: { direction } });
196
+ },
197
+ validate(value, helpers, { direction }) {
198
+
199
+ if (direction === 'lower' && value === value.toLocaleLowerCase() ||
200
+ direction === 'upper' && value === value.toLocaleUpperCase()) {
201
+
202
+ return value;
203
+ }
204
+
205
+ return helpers.error(`string.${direction}case`);
206
+ },
207
+ convert: true
208
+ },
209
+
210
+ creditCard: {
211
+ method() {
212
+
213
+ return this.$_addRule('creditCard');
214
+ },
215
+ validate(value, helpers) {
216
+
217
+ let i = value.length;
218
+ let sum = 0;
219
+ let mul = 1;
220
+
221
+ while (i--) {
222
+ const char = value.charAt(i) * mul;
223
+ sum = sum + (char - (char > 9) * 9);
224
+ mul = mul ^ 3;
225
+ }
226
+
227
+ if (sum > 0 &&
228
+ sum % 10 === 0) {
229
+
230
+ return value;
231
+ }
232
+
233
+ return helpers.error('string.creditCard');
234
+ }
235
+ },
236
+
237
+ dataUri: {
238
+ method(options = {}) {
239
+
240
+ Common.assertOptions(options, ['paddingRequired']);
241
+
242
+ options = { paddingRequired: true, ...options };
243
+ Assert(typeof options.paddingRequired === 'boolean', 'paddingRequired must be boolean');
244
+
245
+ return this.$_addRule({ name: 'dataUri', args: { options } });
246
+ },
247
+ validate(value, helpers, { options }) {
248
+
249
+ const matches = value.match(internals.dataUriRegex);
250
+
251
+ if (matches) {
252
+ if (!matches[2]) {
253
+ return value;
254
+ }
255
+
256
+ if (matches[2] !== 'base64') {
257
+ return value;
258
+ }
259
+
260
+ const base64regex = internals.base64Regex[options.paddingRequired].false;
261
+ if (base64regex.test(matches[3])) {
262
+ return value;
263
+ }
264
+ }
265
+
266
+ return helpers.error('string.dataUri');
267
+ }
268
+ },
269
+
270
+ domain: {
271
+ method(options) {
272
+
273
+ if (options) {
274
+ Common.assertOptions(options, ['allowFullyQualified', 'allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']);
275
+ }
276
+
277
+ const address = internals.addressOptions(options);
278
+ return this.$_addRule({ name: 'domain', args: { options }, address });
279
+ },
280
+ validate(value, helpers, args, { address }) {
281
+
282
+ if (Domain.isValid(value, address)) {
283
+ return value;
284
+ }
285
+
286
+ return helpers.error('string.domain');
287
+ }
288
+ },
289
+
290
+ email: {
291
+ method(options = {}) {
292
+
293
+ Common.assertOptions(options, ['allowFullyQualified', 'allowUnicode', 'ignoreLength', 'maxDomainSegments', 'minDomainSegments', 'multiple', 'separator', 'tlds']);
294
+ Assert(options.multiple === undefined || typeof options.multiple === 'boolean', 'multiple option must be an boolean');
295
+
296
+ const address = internals.addressOptions(options);
297
+ const regex = new RegExp(`\\s*[${options.separator ? EscapeRegex(options.separator) : ','}]\\s*`);
298
+
299
+ return this.$_addRule({ name: 'email', args: { options }, regex, address });
300
+ },
301
+ validate(value, helpers, { options }, { regex, address }) {
302
+
303
+ const emails = options.multiple ? value.split(regex) : [value];
304
+ const invalids = [];
305
+ for (const email of emails) {
306
+ if (!Email.isValid(email, address)) {
307
+ invalids.push(email);
308
+ }
309
+ }
310
+
311
+ if (!invalids.length) {
312
+ return value;
313
+ }
314
+
315
+ return helpers.error('string.email', { value, invalids });
316
+ }
317
+ },
318
+
319
+ guid: {
320
+ alias: 'uuid',
321
+ method(options = {}) {
322
+
323
+ Common.assertOptions(options, ['version', 'separator']);
324
+
325
+ let versionNumbers = '';
326
+
327
+ if (options.version) {
328
+ const versions = [].concat(options.version);
329
+
330
+ Assert(versions.length >= 1, 'version must have at least 1 valid version specified');
331
+ const set = new Set();
332
+
333
+ for (let i = 0; i < versions.length; ++i) {
334
+ const version = versions[i];
335
+ Assert(typeof version === 'string', 'version at position ' + i + ' must be a string');
336
+ const versionNumber = internals.guidVersions[version.toLowerCase()];
337
+ Assert(versionNumber, 'version at position ' + i + ' must be one of ' + Object.keys(internals.guidVersions).join(', '));
338
+ Assert(!set.has(versionNumber), 'version at position ' + i + ' must not be a duplicate');
339
+
340
+ versionNumbers += versionNumber;
341
+ set.add(versionNumber);
342
+ }
343
+ }
344
+
345
+ Assert(internals.guidSeparators.has(options.separator), 'separator must be one of true, false, "-", or ":"');
346
+ const separator = options.separator === undefined ? '[:-]?' :
347
+ options.separator === true ? '[:-]' :
348
+ options.separator === false ? '[]?' : `\\${options.separator}`;
349
+
350
+ const regex = new RegExp(`^([\\[{\\(]?)[0-9A-F]{8}(${separator})[0-9A-F]{4}\\2?[${versionNumbers || '0-9A-F'}][0-9A-F]{3}\\2?[${versionNumbers ? '89AB' : '0-9A-F'}][0-9A-F]{3}\\2?[0-9A-F]{12}([\\]}\\)]?)$`, 'i');
351
+
352
+ return this.$_addRule({ name: 'guid', args: { options }, regex });
353
+ },
354
+ validate(value, helpers, args, { regex }) {
355
+
356
+ const results = regex.exec(value);
357
+
358
+ if (!results) {
359
+ return helpers.error('string.guid');
360
+ }
361
+
362
+ // Matching braces
363
+
364
+ if (internals.guidBrackets[results[1]] !== results[results.length - 1]) {
365
+ return helpers.error('string.guid');
366
+ }
367
+
368
+ return value;
369
+ }
370
+ },
371
+
372
+ hex: {
373
+ method(options = {}) {
374
+
375
+ Common.assertOptions(options, ['byteAligned', 'prefix']);
376
+
377
+ options = { byteAligned: false, prefix: false, ...options };
378
+ Assert(typeof options.byteAligned === 'boolean', 'byteAligned must be boolean');
379
+ Assert(typeof options.prefix === 'boolean' || options.prefix === 'optional', 'prefix must be boolean or "optional"');
380
+
381
+ return this.$_addRule({ name: 'hex', args: { options } });
382
+ },
383
+ validate(value, helpers, { options }) {
384
+
385
+ const re = options.prefix === 'optional' ?
386
+ internals.hexRegex.withOptionalPrefix :
387
+ options.prefix === true ?
388
+ internals.hexRegex.withPrefix :
389
+ internals.hexRegex.withoutPrefix;
390
+ if (!re.test(value)) {
391
+ return helpers.error('string.hex');
392
+ }
393
+
394
+ if (options.byteAligned &&
395
+ value.length % 2 !== 0) {
396
+
397
+ return helpers.error('string.hexAlign');
398
+ }
399
+
400
+ return value;
401
+ }
402
+ },
403
+
404
+ hostname: {
405
+ method() {
406
+
407
+ return this.$_addRule('hostname');
408
+ },
409
+ validate(value, helpers) {
410
+
411
+ if (Domain.isValid(value, { minDomainSegments: 1 }) ||
412
+ internals.ipRegex.test(value)) {
413
+
414
+ return value;
415
+ }
416
+
417
+ return helpers.error('string.hostname');
418
+ }
419
+ },
420
+
421
+ insensitive: {
422
+ method() {
423
+
424
+ return this.$_setFlag('insensitive', true);
425
+ }
426
+ },
427
+
428
+ ip: {
429
+ method(options = {}) {
430
+
431
+ Common.assertOptions(options, ['cidr', 'version']);
432
+
433
+ const { cidr, versions, regex } = Ip.regex(options);
434
+ const version = options.version ? versions : undefined;
435
+ return this.$_addRule({ name: 'ip', args: { options: { cidr, version } }, regex });
436
+ },
437
+ validate(value, helpers, { options }, { regex }) {
438
+
439
+ if (regex.test(value)) {
440
+ return value;
441
+ }
442
+
443
+ if (options.version) {
444
+ return helpers.error('string.ipVersion', { value, cidr: options.cidr, version: options.version });
445
+ }
446
+
447
+ return helpers.error('string.ip', { value, cidr: options.cidr });
448
+ }
449
+ },
450
+
451
+ isoDate: {
452
+ method() {
453
+
454
+ return this.$_addRule('isoDate');
455
+ },
456
+ validate(value, { error }) {
457
+
458
+ if (internals.isoDate(value)) {
459
+ return value;
460
+ }
461
+
462
+ return error('string.isoDate');
463
+ }
464
+ },
465
+
466
+ isoDuration: {
467
+ method() {
468
+
469
+ return this.$_addRule('isoDuration');
470
+ },
471
+ validate(value, helpers) {
472
+
473
+ if (internals.isoDurationRegex.test(value)) {
474
+ return value;
475
+ }
476
+
477
+ return helpers.error('string.isoDuration');
478
+ }
479
+ },
480
+
481
+ length: {
482
+ method(limit, encoding) {
483
+
484
+ return internals.length(this, 'length', limit, '=', encoding);
485
+ },
486
+ validate(value, helpers, { limit, encoding }, { name, operator, args }) {
487
+
488
+ const length = encoding ? Buffer && Buffer.byteLength(value, encoding) : value.length; // $lab:coverage:ignore$
489
+ if (Common.compare(length, limit, operator)) {
490
+ return value;
491
+ }
492
+
493
+ return helpers.error('string.' + name, { limit: args.limit, value, encoding });
494
+ },
495
+ args: [
496
+ {
497
+ name: 'limit',
498
+ ref: true,
499
+ assert: Common.limit,
500
+ message: 'must be a positive integer'
501
+ },
502
+ 'encoding'
503
+ ]
504
+ },
505
+
506
+ lowercase: {
507
+ method() {
508
+
509
+ return this.case('lower');
510
+ }
511
+ },
512
+
513
+ max: {
514
+ method(limit, encoding) {
515
+
516
+ return internals.length(this, 'max', limit, '<=', encoding);
517
+ },
518
+ args: ['limit', 'encoding']
519
+ },
520
+
521
+ min: {
522
+ method(limit, encoding) {
523
+
524
+ return internals.length(this, 'min', limit, '>=', encoding);
525
+ },
526
+ args: ['limit', 'encoding']
527
+ },
528
+
529
+ normalize: {
530
+ method(form = 'NFC') {
531
+
532
+ Assert(internals.normalizationForms.includes(form), 'normalization form must be one of ' + internals.normalizationForms.join(', '));
533
+
534
+ return this.$_addRule({ name: 'normalize', args: { form } });
535
+ },
536
+ validate(value, { error }, { form }) {
537
+
538
+ if (value === value.normalize(form)) {
539
+ return value;
540
+ }
541
+
542
+ return error('string.normalize', { value, form });
543
+ },
544
+ convert: true
545
+ },
546
+
547
+ pattern: {
548
+ alias: 'regex',
549
+ method(regex, options = {}) {
550
+
551
+ Assert(regex instanceof RegExp, 'regex must be a RegExp');
552
+ Assert(!regex.flags.includes('g') && !regex.flags.includes('y'), 'regex should not use global or sticky mode');
553
+
554
+ if (typeof options === 'string') {
555
+ options = { name: options };
556
+ }
557
+
558
+ Common.assertOptions(options, ['invert', 'name']);
559
+
560
+ const errorCode = ['string.pattern', options.invert ? '.invert' : '', options.name ? '.name' : '.base'].join('');
561
+ return this.$_addRule({ name: 'pattern', args: { regex, options }, errorCode });
562
+ },
563
+ validate(value, helpers, { regex, options }, { errorCode }) {
564
+
565
+ const patternMatch = regex.test(value);
566
+
567
+ if (patternMatch ^ options.invert) {
568
+ return value;
569
+ }
570
+
571
+ return helpers.error(errorCode, { name: options.name, regex, value });
572
+ },
573
+ args: ['regex', 'options'],
574
+ multi: true
575
+ },
576
+
577
+ replace: {
578
+ method(pattern, replacement) {
579
+
580
+ if (typeof pattern === 'string') {
581
+ pattern = new RegExp(EscapeRegex(pattern), 'g');
582
+ }
583
+
584
+ Assert(pattern instanceof RegExp, 'pattern must be a RegExp');
585
+ Assert(typeof replacement === 'string', 'replacement must be a String');
586
+
587
+ const obj = this.clone();
588
+
589
+ if (!obj.$_terms.replacements) {
590
+ obj.$_terms.replacements = [];
591
+ }
592
+
593
+ obj.$_terms.replacements.push({ pattern, replacement });
594
+ return obj;
595
+ }
596
+ },
597
+
598
+ token: {
599
+ method() {
600
+
601
+ return this.$_addRule('token');
602
+ },
603
+ validate(value, helpers) {
604
+
605
+ if (/^\w+$/.test(value)) {
606
+ return value;
607
+ }
608
+
609
+ return helpers.error('string.token');
610
+ }
611
+ },
612
+
613
+ trim: {
614
+ method(enabled = true) {
615
+
616
+ Assert(typeof enabled === 'boolean', 'enabled must be a boolean');
617
+
618
+ return this.$_addRule({ name: 'trim', args: { enabled } });
619
+ },
620
+ validate(value, helpers, { enabled }) {
621
+
622
+ if (!enabled ||
623
+ value === value.trim()) {
624
+
625
+ return value;
626
+ }
627
+
628
+ return helpers.error('string.trim');
629
+ },
630
+ convert: true
631
+ },
632
+
633
+ truncate: {
634
+ method(enabled = true) {
635
+
636
+ Assert(typeof enabled === 'boolean', 'enabled must be a boolean');
637
+
638
+ return this.$_setFlag('truncate', enabled);
639
+ }
640
+ },
641
+
642
+ uppercase: {
643
+ method() {
644
+
645
+ return this.case('upper');
646
+ }
647
+ },
648
+
649
+ uri: {
650
+ method(options = {}) {
651
+
652
+ Common.assertOptions(options, ['allowRelative', 'allowQuerySquareBrackets', 'domain', 'relativeOnly', 'scheme', 'encodeUri']);
653
+
654
+ if (options.domain) {
655
+ Common.assertOptions(options.domain, ['allowFullyQualified', 'allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']);
656
+ }
657
+
658
+ const { regex, scheme } = Uri.regex(options);
659
+ const domain = options.domain ? internals.addressOptions(options.domain) : null;
660
+ return this.$_addRule({ name: 'uri', args: { options }, regex, domain, scheme });
661
+ },
662
+ validate(value, helpers, { options }, { regex, domain, scheme }) {
663
+
664
+ if (['http:/', 'https:/'].includes(value)) { // scheme:/ is technically valid but makes no sense
665
+ return helpers.error('string.uri');
666
+ }
667
+
668
+ let match = regex.exec(value);
669
+
670
+ if (!match && helpers.prefs.convert && options.encodeUri) {
671
+ const encoded = encodeURI(value);
672
+ match = regex.exec(encoded);
673
+ if (match) {
674
+ value = encoded;
675
+ }
676
+ }
677
+
678
+ if (match) {
679
+ const matched = match[1] || match[2];
680
+ if (domain &&
681
+ (!options.allowRelative || matched) &&
682
+ !Domain.isValid(matched, domain)) {
683
+
684
+ return helpers.error('string.domain', { value: matched });
685
+ }
686
+
687
+ return value;
688
+ }
689
+
690
+ if (options.relativeOnly) {
691
+ return helpers.error('string.uriRelativeOnly');
692
+ }
693
+
694
+ if (options.scheme) {
695
+ return helpers.error('string.uriCustomScheme', { scheme, value });
696
+ }
697
+
698
+ return helpers.error('string.uri');
699
+ }
700
+ }
701
+ },
702
+
703
+ manifest: {
704
+
705
+ build(obj, desc) {
706
+
707
+ if (desc.replacements) {
708
+ for (const { pattern, replacement } of desc.replacements) {
709
+ obj = obj.replace(pattern, replacement);
710
+ }
711
+ }
712
+
713
+ return obj;
714
+ }
715
+ },
716
+
717
+ messages: {
718
+ 'string.alphanum': '{{#label}} must only contain alpha-numeric characters',
719
+ 'string.base': '{{#label}} must be a string',
720
+ 'string.base64': '{{#label}} must be a valid base64 string',
721
+ 'string.creditCard': '{{#label}} must be a credit card',
722
+ 'string.dataUri': '{{#label}} must be a valid dataUri string',
723
+ 'string.domain': '{{#label}} must contain a valid domain name',
724
+ 'string.email': '{{#label}} must be a valid email',
725
+ 'string.empty': '{{#label}} is not allowed to be empty',
726
+ 'string.guid': '{{#label}} must be a valid GUID',
727
+ 'string.hex': '{{#label}} must only contain hexadecimal characters',
728
+ 'string.hexAlign': '{{#label}} hex decoded representation must be byte aligned',
729
+ 'string.hostname': '{{#label}} must be a valid hostname',
730
+ 'string.ip': '{{#label}} must be a valid ip address with a {{#cidr}} CIDR',
731
+ 'string.ipVersion': '{{#label}} must be a valid ip address of one of the following versions {{#version}} with a {{#cidr}} CIDR',
732
+ 'string.isoDate': '{{#label}} must be in iso format',
733
+ 'string.isoDuration': '{{#label}} must be a valid ISO 8601 duration',
734
+ 'string.length': '{{#label}} length must be {{#limit}} characters long',
735
+ 'string.lowercase': '{{#label}} must only contain lowercase characters',
736
+ 'string.max': '{{#label}} length must be less than or equal to {{#limit}} characters long',
737
+ 'string.min': '{{#label}} length must be at least {{#limit}} characters long',
738
+ 'string.normalize': '{{#label}} must be unicode normalized in the {{#form}} form',
739
+ 'string.token': '{{#label}} must only contain alpha-numeric and underscore characters',
740
+ 'string.pattern.base': '{{#label}} with value {:[.]} fails to match the required pattern: {{#regex}}',
741
+ 'string.pattern.name': '{{#label}} with value {:[.]} fails to match the {{#name}} pattern',
742
+ 'string.pattern.invert.base': '{{#label}} with value {:[.]} matches the inverted pattern: {{#regex}}',
743
+ 'string.pattern.invert.name': '{{#label}} with value {:[.]} matches the inverted {{#name}} pattern',
744
+ 'string.trim': '{{#label}} must not have leading or trailing whitespace',
745
+ 'string.uri': '{{#label}} must be a valid uri',
746
+ 'string.uriCustomScheme': '{{#label}} must be a valid uri with a scheme matching the {{#scheme}} pattern',
747
+ 'string.uriRelativeOnly': '{{#label}} must be a valid relative uri',
748
+ 'string.uppercase': '{{#label}} must only contain uppercase characters'
749
+ }
750
+ });
751
+
752
+
753
+ // Helpers
754
+
755
+ internals.addressOptions = function (options) {
756
+
757
+ if (!options) {
758
+ return internals.tlds || options; // $lab:coverage:ignore$
759
+ }
760
+
761
+ // minDomainSegments
762
+
763
+ Assert(options.minDomainSegments === undefined ||
764
+ Number.isSafeInteger(options.minDomainSegments) && options.minDomainSegments > 0, 'minDomainSegments must be a positive integer');
765
+
766
+ // maxDomainSegments
767
+
768
+ Assert(options.maxDomainSegments === undefined ||
769
+ Number.isSafeInteger(options.maxDomainSegments) && options.maxDomainSegments > 0, 'maxDomainSegments must be a positive integer');
770
+
771
+ // tlds
772
+
773
+ if (options.tlds === false) {
774
+ return options;
775
+ }
776
+
777
+ if (options.tlds === true ||
778
+ options.tlds === undefined) {
779
+
780
+ Assert(internals.tlds, 'Built-in TLD list disabled');
781
+ return Object.assign({}, options, internals.tlds);
782
+ }
783
+
784
+ Assert(typeof options.tlds === 'object', 'tlds must be true, false, or an object');
785
+
786
+ const deny = options.tlds.deny;
787
+ if (deny) {
788
+ if (Array.isArray(deny)) {
789
+ options = Object.assign({}, options, { tlds: { deny: new Set(deny) } });
790
+ }
791
+
792
+ Assert(options.tlds.deny instanceof Set, 'tlds.deny must be an array, Set, or boolean');
793
+ Assert(!options.tlds.allow, 'Cannot specify both tlds.allow and tlds.deny lists');
794
+ internals.validateTlds(options.tlds.deny, 'tlds.deny');
795
+ return options;
796
+ }
797
+
798
+ const allow = options.tlds.allow;
799
+ if (!allow) {
800
+ return options;
801
+ }
802
+
803
+ if (allow === true) {
804
+ Assert(internals.tlds, 'Built-in TLD list disabled');
805
+ return Object.assign({}, options, internals.tlds);
806
+ }
807
+
808
+ if (Array.isArray(allow)) {
809
+ options = Object.assign({}, options, { tlds: { allow: new Set(allow) } });
810
+ }
811
+
812
+ Assert(options.tlds.allow instanceof Set, 'tlds.allow must be an array, Set, or boolean');
813
+ internals.validateTlds(options.tlds.allow, 'tlds.allow');
814
+ return options;
815
+ };
816
+
817
+
818
+ internals.validateTlds = function (set, source) {
819
+
820
+ for (const tld of set) {
821
+ Assert(Domain.isValid(tld, { minDomainSegments: 1, maxDomainSegments: 1 }), `${source} must contain valid top level domain names`);
822
+ }
823
+ };
824
+
825
+
826
+ internals.isoDate = function (value) {
827
+
828
+ if (!Common.isIsoDate(value)) {
829
+ return null;
830
+ }
831
+
832
+ if (/.*T.*[+-]\d\d$/.test(value)) { // Add missing trailing zeros to timeshift
833
+ value += '00';
834
+ }
835
+
836
+ const date = new Date(value);
837
+ if (isNaN(date.getTime())) {
838
+ return null;
839
+ }
840
+
841
+ return date.toISOString();
842
+ };
843
+
844
+
845
+ internals.length = function (schema, name, limit, operator, encoding) {
846
+
847
+ Assert(!encoding || Buffer && Buffer.isEncoding(encoding), 'Invalid encoding:', encoding); // $lab:coverage:ignore$
848
+
849
+ return schema.$_addRule({ name, method: 'length', args: { limit, encoding }, operator });
850
+ };