joi-to-json 2.1.0 → 2.2.1

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/index.js CHANGED
@@ -51,6 +51,7 @@ function parse(joiObj, type = 'json') {
51
51
  }
52
52
 
53
53
  const joiBaseSpec = new convertor().toBaseSpec(joiObj.describe())
54
+ // fs.writeFileSync(`./internal_${convertor.getSupportVersion()}_${type}.json`, JSON.stringify(joiBaseSpec, null, 2))
54
55
  const parser = parsers[type]
55
56
  if (!parser) {
56
57
  throw new Error(`No parser is registered for ${type}`)
@@ -37,7 +37,13 @@ class JoiSpecConvertor {
37
37
  }
38
38
 
39
39
  _convertAlternatives(joiObj) {
40
- if (joiObj.base && joiObj.base.type === 'any') {
40
+ let isWhenCase = false
41
+ if (joiObj.alternatives.length === 1) {
42
+ const condition = joiObj.alternatives[0]
43
+ isWhenCase = !!condition.then || !!condition.otherwise
44
+ }
45
+
46
+ if (isWhenCase) {
41
47
  // when case
42
48
  joiObj.type = 'any'
43
49
  joiObj.whens = joiObj.alternatives
@@ -28,6 +28,7 @@ class JoiJsonSchemaParser {
28
28
  this._setAlternativesProperties(schema, joiSpec)
29
29
  this._setAnyProperties(schema, joiSpec)
30
30
  this._addNullTypeIfNullable(schema, joiSpec)
31
+ this._setMetaProperties(schema, joiSpec)
31
32
 
32
33
  return schema
33
34
  }
@@ -226,11 +227,6 @@ class JoiJsonSchemaParser {
226
227
  if (fieldDefn.flags && fieldDefn.flags.encoding) {
227
228
  fieldSchema.contentEncoding = fieldDefn.flags.encoding
228
229
  }
229
- _.forEach(fieldDefn.meta, (m) => {
230
- if (m.contentMediaType) {
231
- fieldSchema.contentMediaType = m.contentMediaType
232
- }
233
- })
234
230
 
235
231
  const ruleArgFieldName = this.ruleArgFieldName
236
232
 
@@ -358,10 +354,17 @@ class JoiJsonSchemaParser {
358
354
  return
359
355
  }
360
356
 
361
- if (joiSpec.matches.length === 1 && joiSpec.matches[0].switch) {
362
- schema.oneOf = _.map(joiSpec.matches[0].switch, (condition) => {
363
- return this.parse(condition.then || condition.otherwise)
364
- })
357
+ if (joiSpec.matches.length === 1) {
358
+ const match = joiSpec.matches[0]
359
+ if (match.switch) {
360
+ schema.oneOf = _.map(match.switch, (condition) => {
361
+ return this.parse(condition.then || condition.otherwise)
362
+ })
363
+ } else if (match.then || match.otherwise) {
364
+ schema.oneOf = []
365
+ if (match.then) schema.oneOf.push(this.parse(match.then))
366
+ if (match.otherwise) schema.oneOf.push(this.parse(match.otherwise))
367
+ }
365
368
  } else {
366
369
  schema.oneOf = _.map(joiSpec.matches, (match) => {
367
370
  return this.parse(match.schema)
@@ -398,6 +401,17 @@ class JoiJsonSchemaParser {
398
401
  'null'
399
402
  ]
400
403
  }
404
+
405
+ _setMetaProperties(schema, joiSpec) {
406
+ _.forEach(joiSpec.metas, (m) => {
407
+ if (m.contentMediaType) {
408
+ schema.contentMediaType = m.contentMediaType
409
+ }
410
+ if (m.format) {
411
+ schema.format = m.format
412
+ }
413
+ })
414
+ }
401
415
  }
402
416
 
403
417
  module.exports = JoiJsonSchemaParser
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash')
2
- const JoiJsonSchemaParser = require('./json')
2
+ const JoiJsonSchemaParser = require('./json-draft-04')
3
3
 
4
4
  class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
5
5
  parse(joiSpec) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joi-to-json",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "joi to JSON / OpenAPI Schema Converter",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -27,15 +27,19 @@
27
27
  "semver-compare": "^1.0.0"
28
28
  },
29
29
  "devDependencies": {
30
- "ajv": "^8.6.3",
30
+ "ajv": "^8.11.0",
31
31
  "ajv-draft-04": "^1.0.0",
32
- "eslint": "^7.32.0",
33
- "jest": "^27.2.0",
32
+ "eslint": "^8.12.0",
33
+ "jest": "^27.5.1",
34
34
  "joi-12": "npm:@commercial/joi@^12.1.0",
35
35
  "joi-13": "npm:joi@^13.7.0",
36
36
  "joi-14": "npm:joi@^14.3.1",
37
37
  "joi-15": "npm:@hapi/joi@^15.1.1",
38
38
  "joi-16": "npm:@hapi/joi@^16.1.8",
39
39
  "joi-17": "npm:joi@^17.4.2"
40
- }
40
+ },
41
+ "files": [
42
+ "lib/**/*.js",
43
+ "index.js"
44
+ ]
41
45
  }
package/.eslintrc DELETED
@@ -1,57 +0,0 @@
1
- {
2
- "globals": {},
3
- "ignorePatterns": [
4
- "test/swagger-ui/",
5
- "node_modules/"
6
- ],
7
- "rules": {
8
- "no-restricted-syntax": 0,
9
- "guard-for-in": 0,
10
- "dot-notation": 0,
11
- "camelcase": 0,
12
- "no-underscore-dangle": 0,
13
- "no-extra-parens": 0,
14
- "no-param-reassign": 0,
15
- "radix": 0,
16
- "class-methods-use-this": 0,
17
- "new-cap": 0,
18
- "global-require": 0,
19
- "comma-dangle": [
20
- "error",
21
- "never"
22
- ],
23
- "max-len": 0,
24
- "no-new": 0,
25
- "no-continue": 0,
26
- "no-return-await": 0,
27
- "arrow-body-style": 0,
28
- "quotes": [
29
- 2,
30
- "single"
31
- ],
32
- "linebreak-style": [
33
- 2,
34
- "unix"
35
- ],
36
- "no-unused-vars": [
37
- 2,
38
- {
39
- "vars": "all",
40
- "args": "after-used",
41
- "argsIgnorePattern": "^_",
42
- "varsIgnorePattern": "^_"
43
- }
44
- ],
45
- "semi": [
46
- "error",
47
- "never"
48
- ],
49
- "no-console": 0
50
- },
51
- "env": {
52
- "es6": true,
53
- "node": true,
54
- "mocha": true
55
- },
56
- "plugins": []
57
- }
@@ -1,65 +0,0 @@
1
- const joi = require('joi-12')
2
-
3
- const joiRequired = joi.defaults((schema) => schema.options({
4
- presence: 'required'
5
- }))
6
- const joiAllowUnknown = joi.defaults((schema) => schema.options({
7
- allowUnknown: true
8
- }))
9
-
10
- module.exports = joi.object().keys({
11
- guid: joi.string().guid({ version: ['uuidv2', 'uuidv4'] }),
12
- uuid: joi.string().uuid({ version: ['uuidv3', 'uuidv5'] }),
13
- nickName: joi.string().required().example('鹄思乱想').description('Hero Nickname').min(3).max(20).regex(/^[a-z]+$/, { name: 'alpha', invert: true }),
14
- avatar: joi.string().required().uri(),
15
- password: joi.forbidden(),
16
- email: joi.string().email(),
17
- ip: joi.string().ip({ version: ['ipv4', 'ipv6'] }),
18
- hostname: joi.string().hostname().insensitive(),
19
- gender: joi.string().valid('Male', 'Female', '').default('Male'),
20
- genderSpecific: joi.when('gender', {
21
- is: 'Female',
22
- then: joi.number().required(),
23
- otherwise: joi.string()
24
- }),
25
- height: joi.number().precision(2).positive().greater(0).less(200),
26
- isoDateString: joi.string().isoDate(),
27
- birthday: joi.date().iso(),
28
- birthTime: joi.date().timestamp('unix'),
29
- skills: joi.array().items(joi.alternatives().try(
30
- joi.string(),
31
- joi.object().keys({
32
- name: joi.string().example('teleport').alphanum().description('Skill Name').lowercase().required(),
33
- level: joi.number().integer().min(10).max(100).default(50).multiple(10).example(10).description('Skill Level')
34
- }).unknown(true).meta({ 'x-expandable': true, 'x-lookup': 'name' })
35
- ).required()).min(1).max(3).unique().description('Skills').meta({ 'z-ignore': true, 'x-exchangable': false }),
36
- tags: joi.array().items(joi.string().required()).length(2),
37
- retired: joi.boolean().truthy('yes').falsy('no').insensitive(true),
38
- certificate: joi.binary().encoding('base64'),
39
- notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'] }),
40
- facebookId: joi.string().allow(null),
41
- meta: joiRequired.object().keys({
42
- hash: joiRequired.string(),
43
- optional: joiRequired.string().optional()
44
- }),
45
- nested: joiAllowUnknown.object().keys({
46
- key: joiAllowUnknown.string()
47
- }),
48
- dynamicKeyHolder: joi
49
- .object()
50
- .pattern(/s/, joi.object().keys({
51
- id: joi
52
- .number()
53
- .description('Tbe ID for the reference')
54
- .example(123)
55
- .required(),
56
- name: joi
57
- .string()
58
- .allow('', null)
59
- .description('Name of something')
60
- .example('Jack')
61
- .required()
62
- }))
63
- .description('Some kind of list')
64
- .optional()
65
- })
@@ -1,65 +0,0 @@
1
- const joi = require('joi-13')
2
-
3
- const joiRequired = joi.defaults((schema) => schema.options({
4
- presence: 'required'
5
- }))
6
- const joiAllowUnknown = joi.defaults((schema) => schema.options({
7
- allowUnknown: true
8
- }))
9
-
10
- module.exports = joi.object().keys({
11
- guid: joi.string().guid({ version: ['uuidv2', 'uuidv4'] }),
12
- uuid: joi.string().uuid({ version: ['uuidv3', 'uuidv5'] }),
13
- nickName: joi.string().required().example('鹄思乱想').description('Hero Nickname').min(3).max(20).regex(/^[a-z]+$/, { name: 'alpha', invert: true }),
14
- avatar: joi.string().required().uri(),
15
- password: joi.forbidden(),
16
- email: joi.string().email(),
17
- ip: joi.string().ip({ version: ['ipv4', 'ipv6'] }),
18
- hostname: joi.string().hostname().insensitive(),
19
- gender: joi.string().valid('Male', 'Female', '').default('Male'),
20
- genderSpecific: joi.when('gender', {
21
- is: 'Female',
22
- then: joi.number().required(),
23
- otherwise: joi.string()
24
- }),
25
- height: joi.number().precision(2).positive().greater(0).less(200),
26
- isoDateString: joi.string().isoDate(),
27
- birthday: joi.date().iso(),
28
- birthTime: joi.date().timestamp('unix'),
29
- skills: joi.array().items(joi.alternatives().try(
30
- joi.string(),
31
- joi.object().keys({
32
- name: joi.string().example('teleport').alphanum().description('Skill Name').lowercase().required(),
33
- level: joi.number().integer().min(10).max(100).default(50).multiple(10).example(10).description('Skill Level')
34
- }).unknown(true).meta({ 'x-expandable': true, 'x-lookup': 'name' })
35
- ).required()).min(1).max(3).unique().description('Skills').meta({ 'z-ignore': true, 'x-exchangable': false }),
36
- tags: joi.array().items(joi.string().required()).length(2),
37
- retired: joi.boolean().truthy('yes').falsy('no').insensitive(true),
38
- certificate: joi.binary().encoding('base64'),
39
- notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'] }),
40
- facebookId: joi.string().allow(null),
41
- meta: joiRequired.object().keys({
42
- hash: joiRequired.string(),
43
- optional: joiRequired.string().optional()
44
- }),
45
- nested: joiAllowUnknown.object().keys({
46
- key: joiAllowUnknown.string()
47
- }),
48
- dynamicKeyHolder: joi
49
- .object()
50
- .pattern(/s/, joi.object().keys({
51
- id: joi
52
- .number()
53
- .description('Tbe ID for the reference')
54
- .example(123)
55
- .required(),
56
- name: joi
57
- .string()
58
- .allow('', null)
59
- .description('Name of something')
60
- .example('Jack')
61
- .required()
62
- }))
63
- .description('Some kind of list')
64
- .optional()
65
- })
@@ -1,65 +0,0 @@
1
- const joi = require('joi-14')
2
-
3
- const joiRequired = joi.defaults((schema) => schema.options({
4
- presence: 'required'
5
- }))
6
- const joiAllowUnknown = joi.defaults((schema) => schema.options({
7
- allowUnknown: true
8
- }))
9
-
10
- module.exports = joi.object().keys({
11
- guid: joi.string().guid({ version: ['uuidv2', 'uuidv4'] }),
12
- uuid: joi.string().uuid({ version: ['uuidv3', 'uuidv5'] }),
13
- nickName: joi.string().required().example('鹄思乱想').description('Hero Nickname').min(3).max(20).regex(/^[a-z]+$/, { name: 'alpha', invert: true }),
14
- avatar: joi.string().required().uri(),
15
- password: joi.forbidden(),
16
- email: joi.string().email(),
17
- ip: joi.string().ip({ version: ['ipv4', 'ipv6'] }),
18
- hostname: joi.string().hostname().insensitive(),
19
- gender: joi.string().valid('Male', 'Female', '').default('Male'),
20
- genderSpecific: joi.when('gender', {
21
- is: 'Female',
22
- then: joi.number().required(),
23
- otherwise: joi.string()
24
- }),
25
- height: joi.number().precision(2).positive().greater(0).less(200),
26
- isoDateString: joi.string().isoDate(),
27
- birthday: joi.date().iso(),
28
- birthTime: joi.date().timestamp('unix'),
29
- skills: joi.array().items(joi.alternatives().try(
30
- joi.string(),
31
- joi.object().keys({
32
- name: joi.string().example(['teleport', { parent: { sibling: 10 } }]).alphanum().description('Skill Name').lowercase().required(),
33
- level: joi.number().integer().min(10).max(100).default(50).multiple(10).example(10).description('Skill Level')
34
- }).unknown(true).meta({ 'x-expandable': true, 'x-lookup': 'name' })
35
- ).required()).min(1).max(3).unique().description('Skills').meta({ 'z-ignore': true, 'x-exchangable': false }),
36
- tags: joi.array().items(joi.string().required()).length(2),
37
- retired: joi.boolean().truthy('yes').falsy('no').insensitive(true),
38
- certificate: joi.binary().encoding('base64'),
39
- notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'] }),
40
- facebookId: joi.string().allow(null),
41
- meta: joiRequired.object().keys({
42
- hash: joiRequired.string(),
43
- optional: joiRequired.string().optional()
44
- }),
45
- nested: joiAllowUnknown.object().keys({
46
- key: joiAllowUnknown.string()
47
- }),
48
- dynamicKeyHolder: joi
49
- .object()
50
- .pattern(/s/, joi.object().keys({
51
- id: joi
52
- .number()
53
- .description('Tbe ID for the reference')
54
- .example(123)
55
- .required(),
56
- name: joi
57
- .string()
58
- .allow('', null)
59
- .description('Name of something')
60
- .example('Jack')
61
- .required()
62
- }))
63
- .description('Some kind of list')
64
- .optional()
65
- })
@@ -1,65 +0,0 @@
1
- const joi = require('joi-15')
2
-
3
- const joiRequired = joi.defaults((schema) => schema.options({
4
- presence: 'required'
5
- }))
6
- const joiAllowUnknown = joi.defaults((schema) => schema.options({
7
- allowUnknown: true
8
- }))
9
-
10
- module.exports = joi.object().keys({
11
- guid: joi.string().guid({ version: ['uuidv2', 'uuidv4'] }),
12
- uuid: joi.string().uuid({ version: ['uuidv3', 'uuidv5'] }),
13
- nickName: joi.string().required().example('鹄思乱想').description('Hero Nickname').min(3).max(20).regex(/^[a-z]+$/, { name: 'alpha', invert: true }),
14
- avatar: joi.string().required().uri(),
15
- password: joi.forbidden(),
16
- email: joi.string().email(),
17
- ip: joi.string().ip({ version: ['ipv4', 'ipv6'] }),
18
- hostname: joi.string().hostname().insensitive(),
19
- gender: joi.string().valid('Male', 'Female', '').default('Male'),
20
- genderSpecific: joi.when('gender', {
21
- is: 'Female',
22
- then: joi.number().required(),
23
- otherwise: joi.string()
24
- }),
25
- height: joi.number().precision(2).positive().greater(0).less(200),
26
- isoDateString: joi.string().isoDate(),
27
- birthday: joi.date().iso(),
28
- birthTime: joi.date().timestamp('unix'),
29
- skills: joi.array().items(joi.alternatives().try(
30
- joi.string(),
31
- joi.object().keys({
32
- name: joi.string().example(['teleport', { parent: { sibling: 10 } }]).alphanum().description('Skill Name').lowercase().required(),
33
- level: joi.number().integer().min(10).max(100).default(50).multiple(10).example(10).description('Skill Level')
34
- }).unknown(true).meta({ 'x-expandable': true, 'x-lookup': 'name' })
35
- ).required()).min(1).max(3).unique().description('Skills').meta({ 'z-ignore': true, 'x-exchangable': false }),
36
- tags: joi.array().items(joi.string().required()).length(2),
37
- retired: joi.boolean().truthy('yes').falsy('no').insensitive(true),
38
- certificate: joi.binary().encoding('base64'),
39
- notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'] }),
40
- facebookId: joi.string().allow(null),
41
- meta: joiRequired.object().keys({
42
- hash: joiRequired.string(),
43
- optional: joiRequired.string().optional()
44
- }),
45
- nested: joiAllowUnknown.object().keys({
46
- key: joiAllowUnknown.string()
47
- }),
48
- dynamicKeyHolder: joi
49
- .object()
50
- .pattern(/s/, joi.object().keys({
51
- id: joi
52
- .number()
53
- .description('Tbe ID for the reference')
54
- .example(123)
55
- .required(),
56
- name: joi
57
- .string()
58
- .allow('', null)
59
- .description('Name of something')
60
- .example('Jack')
61
- .required()
62
- }))
63
- .description('Some kind of list')
64
- .optional()
65
- })
@@ -1,73 +0,0 @@
1
- const joi = require('joi-16')
2
-
3
- const joiRequired = joi.defaults((schema) => schema.options({
4
- presence: 'required'
5
- }))
6
- const joiAllowUnknown = joi.defaults((schema) => schema.options({
7
- allowUnknown: true
8
- }))
9
-
10
- module.exports = joi.object().keys({
11
- guid: joi.string().guid({ version: ['uuidv2', 'uuidv4'] }),
12
- uuid: joi.string().uuid({ version: ['uuidv3', 'uuidv5'] }),
13
- nickName: joi.string().required().example('鹄思乱想').description('Hero Nickname').min(3).max(20).pattern(/^[a-z]+$/, { name: 'alpha', invert: true }),
14
- avatar: joi.string().required().uri(),
15
- password: joi.forbidden(),
16
- email: joi.string().email(),
17
- ip: joi.string().ip({ version: ['ipv4', 'ipv6'] }),
18
- hostname: joi.string().hostname().insensitive(),
19
- gender: joi.string().valid('Male', 'Female', '').default('Male'),
20
- genderSpecific: joi.when('gender', {
21
- is: 'Female',
22
- then: joi.number().required(),
23
- otherwise: joi.string()
24
- }),
25
- height: joi.number().precision(2).positive().greater(0).less(200),
26
- heightRank: joi.alternatives().conditional('height', {
27
- switch: [
28
- { is: 0, then: joi.string() },
29
- { is: joi.number().greater(160), then: joi.number() },
30
- { is: joi.number().greater(300), then: joi.object().keys({ name: joi.string(), level: joi.number() }) }
31
- ]
32
- }),
33
- isoDateString: joi.string().isoDate(),
34
- isoDurationString: joi.string().isoDuration(),
35
- birthday: joi.date().iso(),
36
- birthTime: joi.date().timestamp('unix'),
37
- skills: joi.array().items(joi.alternatives().try(
38
- joi.string(),
39
- joi.object().keys({
40
- name: joi.string().example('teleport').alphanum().description('Skill Name').lowercase().required(),
41
- level: joi.number().integer().min(10).max(100).default(50).multiple(10).example(10).description('Skill Level')
42
- }).unknown(true).meta({ 'x-expandable': true, 'x-lookup': 'name' })
43
- ).required()).min(1).max(3).unique().description('Skills').meta({ 'z-ignore': true, 'x-exchangable': false }),
44
- tags: joi.array().items(joi.string().required()).length(2),
45
- retired: joi.boolean().truthy('yes').falsy('no').sensitive(false),
46
- certificate: joi.binary().encoding('base64'),
47
- notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'], deprecated: true }),
48
- facebookId: joi.string().allow(null),
49
- meta: joiRequired.object().keys({
50
- hash: joiRequired.string(),
51
- optional: joiRequired.string().optional()
52
- }),
53
- nested: joiAllowUnknown.object().keys({
54
- key: joiAllowUnknown.string()
55
- }),
56
- dynamicKeyHolder: joi
57
- .object()
58
- .pattern(/s/, joi.object().keys({
59
- id: joi
60
- .number()
61
- .description('Tbe ID for the reference')
62
- .example(123)
63
- .required(),
64
- name: joi
65
- .string()
66
- .allow('', null)
67
- .description('Name of something')
68
- .example('Jack')
69
- .required()
70
- }))
71
- .description('Some kind of list')
72
- .optional()
73
- })
@@ -1,73 +0,0 @@
1
- const joi = require('joi-17')
2
-
3
- const joiRequired = joi.defaults((schema) => schema.options({
4
- presence: 'required'
5
- }))
6
- const joiAllowUnknown = joi.defaults((schema) => schema.options({
7
- allowUnknown: true
8
- }))
9
-
10
- module.exports = joi.object().keys({
11
- guid: joi.string().guid({ version: ['uuidv2', 'uuidv4'] }),
12
- uuid: joi.string().uuid({ version: ['uuidv3', 'uuidv5'] }),
13
- nickName: joi.string().required().example('鹄思乱想').description('Hero Nickname').min(3).max(20).pattern(/^[a-z]+$/, { name: 'alpha', invert: true }),
14
- avatar: joi.string().required().uri(),
15
- password: joi.forbidden(),
16
- email: joi.string().email(),
17
- ip: joi.string().ip({ version: ['ipv4', 'ipv6'] }),
18
- hostname: joi.string().hostname().insensitive(),
19
- gender: joi.string().valid('Male', 'Female', '').default('Male'),
20
- genderSpecific: joi.when('gender', {
21
- is: 'Female',
22
- then: joi.number().required(),
23
- otherwise: joi.string()
24
- }),
25
- height: joi.number().precision(2).positive().greater(0).less(200),
26
- heightRank: joi.alternatives().conditional('height', {
27
- switch: [
28
- { is: 0, then: joi.string() },
29
- { is: joi.number().greater(160), then: joi.number() },
30
- { is: joi.number().greater(300), then: joi.object().keys({ name: joi.string(), level: joi.number() }) }
31
- ]
32
- }),
33
- isoDateString: joi.string().isoDate(),
34
- isoDurationString: joi.string().isoDuration(),
35
- birthday: joi.date().iso(),
36
- birthTime: joi.date().timestamp('unix'),
37
- skills: joi.array().items(joi.alternatives().try(
38
- joi.string(),
39
- joi.object().keys({
40
- name: joi.string().example('teleport').alphanum().description('Skill Name').lowercase().required(),
41
- level: joi.number().integer().min(10).max(100).default(50).multiple(10).example(10).description('Skill Level')
42
- }).unknown(true).meta({ 'x-expandable': true, 'x-lookup': 'name' })
43
- ).required()).min(1).max(3).unique().description('Skills').meta({ 'z-ignore': true, 'x-exchangable': false }),
44
- tags: joi.array().items(joi.string().required()).length(2),
45
- retired: joi.boolean().truthy('yes').falsy('no').sensitive(false),
46
- certificate: joi.binary().encoding('base64'),
47
- notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'], deprecated: true }),
48
- facebookId: joi.string().allow(null),
49
- meta: joiRequired.object().keys({
50
- hash: joiRequired.string(),
51
- optional: joiRequired.string().optional()
52
- }),
53
- nested: joiAllowUnknown.object().keys({
54
- key: joiAllowUnknown.string()
55
- }),
56
- dynamicKeyHolder: joi
57
- .object()
58
- .pattern(/s/, joi.object().keys({
59
- id: joi
60
- .number()
61
- .description('Tbe ID for the reference')
62
- .example(123)
63
- .required(),
64
- name: joi
65
- .string()
66
- .allow('', null)
67
- .description('Name of something')
68
- .example('Jack')
69
- .required()
70
- }))
71
- .description('Some kind of list')
72
- .optional()
73
- })