schemas.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. 'use strict';
  2. const Joi = require('./index');
  3. const internals = {};
  4. // Preferences
  5. internals.wrap = Joi.string()
  6. .min(1)
  7. .max(2)
  8. .allow(false);
  9. exports.preferences = Joi.object({
  10. allowUnknown: Joi.boolean(),
  11. abortEarly: Joi.boolean(),
  12. artifacts: Joi.boolean(),
  13. cache: Joi.boolean(),
  14. context: Joi.object(),
  15. convert: Joi.boolean(),
  16. dateFormat: Joi.valid('date', 'iso', 'string', 'time', 'utc'),
  17. debug: Joi.boolean(),
  18. errors: {
  19. escapeHtml: Joi.boolean(),
  20. label: Joi.valid('path', 'key', false),
  21. language: [
  22. Joi.string(),
  23. Joi.object().ref()
  24. ],
  25. render: Joi.boolean(),
  26. stack: Joi.boolean(),
  27. wrap: {
  28. label: internals.wrap,
  29. array: internals.wrap,
  30. string: internals.wrap
  31. }
  32. },
  33. externals: Joi.boolean(),
  34. messages: Joi.object(),
  35. noDefaults: Joi.boolean(),
  36. nonEnumerables: Joi.boolean(),
  37. presence: Joi.valid('required', 'optional', 'forbidden'),
  38. skipFunctions: Joi.boolean(),
  39. stripUnknown: Joi.object({
  40. arrays: Joi.boolean(),
  41. objects: Joi.boolean()
  42. })
  43. .or('arrays', 'objects')
  44. .allow(true, false),
  45. warnings: Joi.boolean()
  46. })
  47. .strict();
  48. // Extensions
  49. internals.nameRx = /^[a-zA-Z0-9]\w*$/;
  50. internals.rule = Joi.object({
  51. alias: Joi.array().items(Joi.string().pattern(internals.nameRx)).single(),
  52. args: Joi.array().items(
  53. Joi.string(),
  54. Joi.object({
  55. name: Joi.string().pattern(internals.nameRx).required(),
  56. ref: Joi.boolean(),
  57. assert: Joi.alternatives([
  58. Joi.function(),
  59. Joi.object().schema()
  60. ])
  61. .conditional('ref', { is: true, then: Joi.required() }),
  62. normalize: Joi.function(),
  63. message: Joi.string().when('assert', { is: Joi.function(), then: Joi.required() })
  64. })
  65. ),
  66. convert: Joi.boolean(),
  67. manifest: Joi.boolean(),
  68. method: Joi.function().allow(false),
  69. multi: Joi.boolean(),
  70. validate: Joi.function()
  71. });
  72. exports.extension = Joi.object({
  73. type: Joi.alternatives([
  74. Joi.string(),
  75. Joi.object().regex()
  76. ])
  77. .required(),
  78. args: Joi.function(),
  79. cast: Joi.object().pattern(internals.nameRx, Joi.object({
  80. from: Joi.function().maxArity(1).required(),
  81. to: Joi.function().minArity(1).maxArity(2).required()
  82. })),
  83. base: Joi.object().schema()
  84. .when('type', { is: Joi.object().regex(), then: Joi.forbidden() }),
  85. coerce: [
  86. Joi.function().maxArity(3),
  87. Joi.object({ method: Joi.function().maxArity(3).required(), from: Joi.array().items(Joi.string()).single() })
  88. ],
  89. flags: Joi.object().pattern(internals.nameRx, Joi.object({
  90. setter: Joi.string(),
  91. default: Joi.any()
  92. })),
  93. manifest: {
  94. build: Joi.function().arity(2)
  95. },
  96. messages: [Joi.object(), Joi.string()],
  97. modifiers: Joi.object().pattern(internals.nameRx, Joi.function().minArity(1).maxArity(2)),
  98. overrides: Joi.object().pattern(internals.nameRx, Joi.function()),
  99. prepare: Joi.function().maxArity(3),
  100. rebuild: Joi.function().arity(1),
  101. rules: Joi.object().pattern(internals.nameRx, internals.rule),
  102. terms: Joi.object().pattern(internals.nameRx, Joi.object({
  103. init: Joi.array().allow(null).required(),
  104. manifest: Joi.object().pattern(/.+/, [
  105. Joi.valid('schema', 'single'),
  106. Joi.object({
  107. mapped: Joi.object({
  108. from: Joi.string().required(),
  109. to: Joi.string().required()
  110. })
  111. .required()
  112. })
  113. ])
  114. })),
  115. validate: Joi.function().maxArity(3)
  116. })
  117. .strict();
  118. exports.extensions = Joi.array().items(Joi.object(), Joi.function().arity(1)).strict();
  119. // Manifest
  120. internals.desc = {
  121. buffer: Joi.object({
  122. buffer: Joi.string()
  123. }),
  124. func: Joi.object({
  125. function: Joi.function().required(),
  126. options: {
  127. literal: true
  128. }
  129. }),
  130. override: Joi.object({
  131. override: true
  132. }),
  133. ref: Joi.object({
  134. ref: Joi.object({
  135. type: Joi.valid('value', 'global', 'local'),
  136. path: Joi.array().required(),
  137. separator: Joi.string().length(1).allow(false),
  138. ancestor: Joi.number().min(0).integer().allow('root'),
  139. map: Joi.array().items(Joi.array().length(2)).min(1),
  140. adjust: Joi.function(),
  141. iterables: Joi.boolean(),
  142. in: Joi.boolean(),
  143. render: Joi.boolean()
  144. })
  145. .required()
  146. }),
  147. regex: Joi.object({
  148. regex: Joi.string().min(3)
  149. }),
  150. special: Joi.object({
  151. special: Joi.valid('deep').required()
  152. }),
  153. template: Joi.object({
  154. template: Joi.string().required(),
  155. options: Joi.object()
  156. }),
  157. value: Joi.object({
  158. value: Joi.alternatives([Joi.object(), Joi.array()]).required()
  159. })
  160. };
  161. internals.desc.entity = Joi.alternatives([
  162. Joi.array().items(Joi.link('...')),
  163. Joi.boolean(),
  164. Joi.function(),
  165. Joi.number(),
  166. Joi.string(),
  167. internals.desc.buffer,
  168. internals.desc.func,
  169. internals.desc.ref,
  170. internals.desc.regex,
  171. internals.desc.special,
  172. internals.desc.template,
  173. internals.desc.value,
  174. Joi.link('/')
  175. ]);
  176. internals.desc.values = Joi.array()
  177. .items(
  178. null,
  179. Joi.boolean(),
  180. Joi.function(),
  181. Joi.number().allow(Infinity, -Infinity),
  182. Joi.string().allow(''),
  183. Joi.symbol(),
  184. internals.desc.buffer,
  185. internals.desc.func,
  186. internals.desc.override,
  187. internals.desc.ref,
  188. internals.desc.regex,
  189. internals.desc.template,
  190. internals.desc.value
  191. );
  192. internals.desc.messages = Joi.object()
  193. .pattern(/.+/, [
  194. Joi.string(),
  195. internals.desc.template,
  196. Joi.object().pattern(/.+/, [Joi.string(), internals.desc.template])
  197. ]);
  198. exports.description = Joi.object({
  199. type: Joi.string().required(),
  200. flags: Joi.object({
  201. cast: Joi.string(),
  202. default: Joi.any(),
  203. description: Joi.string(),
  204. empty: Joi.link('/'),
  205. failover: internals.desc.entity,
  206. id: Joi.string(),
  207. label: Joi.string(),
  208. only: true,
  209. presence: ['optional', 'required', 'forbidden'],
  210. result: ['raw', 'strip'],
  211. strip: Joi.boolean(),
  212. unit: Joi.string()
  213. })
  214. .unknown(),
  215. preferences: {
  216. allowUnknown: Joi.boolean(),
  217. abortEarly: Joi.boolean(),
  218. artifacts: Joi.boolean(),
  219. cache: Joi.boolean(),
  220. convert: Joi.boolean(),
  221. dateFormat: ['date', 'iso', 'string', 'time', 'utc'],
  222. errors: {
  223. escapeHtml: Joi.boolean(),
  224. label: ['path', 'key'],
  225. language: [
  226. Joi.string(),
  227. internals.desc.ref
  228. ],
  229. wrap: {
  230. label: internals.wrap,
  231. array: internals.wrap
  232. }
  233. },
  234. externals: Joi.boolean(),
  235. messages: internals.desc.messages,
  236. noDefaults: Joi.boolean(),
  237. nonEnumerables: Joi.boolean(),
  238. presence: ['required', 'optional', 'forbidden'],
  239. skipFunctions: Joi.boolean(),
  240. stripUnknown: Joi.object({
  241. arrays: Joi.boolean(),
  242. objects: Joi.boolean()
  243. })
  244. .or('arrays', 'objects')
  245. .allow(true, false),
  246. warnings: Joi.boolean()
  247. },
  248. allow: internals.desc.values,
  249. invalid: internals.desc.values,
  250. rules: Joi.array().min(1).items({
  251. name: Joi.string().required(),
  252. args: Joi.object().min(1),
  253. keep: Joi.boolean(),
  254. message: [
  255. Joi.string(),
  256. internals.desc.messages
  257. ],
  258. warn: Joi.boolean()
  259. }),
  260. // Terms
  261. keys: Joi.object().pattern(/.*/, Joi.link('/')),
  262. link: internals.desc.ref
  263. })
  264. .pattern(/^[a-z]\w*$/, Joi.any());