validate-exemplar-strict.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /**
  2. * Module dependencies
  3. */
  4. var _ = require('@sailshq/lodash');
  5. var rebuild = require('./rebuild');
  6. /**
  7. * validateExemplarStrict()
  8. *
  9. * Check the specified value (`supposedExemplar`) and ensure it is
  10. * a pure RTTC exemplar. If not, throw an error.
  11. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  12. * @param {Anything} supposedExemplar
  13. * The supposed exemplar to validate.
  14. *
  15. * @param {Boolean} prohibitEmptyArrays
  16. * If enabled, if the supposed exemplar contains any empty arrays (`[]`),
  17. * then an error will be thrown (nested or at the top level). Otherwise,
  18. * (and by default) `rttc.validateExemplarStrict()` tolerates the presence
  19. * of `[]`, since most RTTC/machine tooling supports that notation by
  20. * understanding it as `['*']`, purely for backwards compatibility.
  21. * @default false
  22. *
  23. * @throws {Error} If the provided `supposedExemplar` is not a pure RTTC exemplar.
  24. * @property {String} code
  25. * This error is intentionally thrown, and always has a `code`
  26. * property of `E_INVALID_EXEMPLAR`.
  27. *
  28. * @throws {Error} If the `prohibitEmptyArrays` flag was enabled, and the provided
  29. * `supposedExemplar` contains any empty arrays (nested or at the
  30. * top level).
  31. * @property {String} code
  32. * This error is intentionally thrown, and always has a `code`
  33. * property of `E_DEPRECATED_SYNTAX`.
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  35. * Example usage:
  36. *
  37. * ```
  38. * > x
  39. * => { foo: 23, bar: 8, baz: { yeah: 'cool!', what: [Circular] } }
  40. *
  41. * > rttc.validateExemplarStrict([{a:'Whee', b: 9, c: x}])
  42. * => Error: Invalid exemplar: Only strictly JSON-serializable values can qualify to be RTTC exemplars.
  43. * at Object.validateExemplarStrict (/Users/mikermcneil/code/rttc/lib/validate-exemplar-strict.js:47:11)
  44. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  45. */
  46. module.exports = function validateExemplarStrict (supposedExemplar, prohibitEmptyArrays) {
  47. // Used below.
  48. var err;
  49. // Check for obvious bad news.
  50. if (_.isUndefined(supposedExemplar)) {
  51. err = new Error('Invalid exemplar: `undefined` is not a valid RTTC exemplar.');
  52. err.code = 'E_INVALID_EXEMPLAR';
  53. throw err;
  54. }
  55. if (_.isNull(supposedExemplar)) {
  56. err = new Error('Invalid exemplar: `null` is not a valid RTTC exemplar.');
  57. err.code = 'E_INVALID_EXEMPLAR';
  58. throw err;
  59. }
  60. if (prohibitEmptyArrays && _.isEqual(supposedExemplar, [])) {
  61. err = new Error('Invalid exemplar: Empty arrays (`[]`) are not allowed in this RTTC exemplar at any depth. (This error was thrown because `rttc.validateExemplarStrict()` with the `prohibitEmptyArrays` flag enabled. Otherwise, any occurences of `[]` would have been understood as `[\'*\']`.)');
  62. err.code = 'E_DEPRECATED_SYNTAX';
  63. throw err;
  64. }
  65. // Check for nested nulls, and ensure serializability while we're at it.
  66. var rebuiltExemplar = rebuild(
  67. supposedExemplar,
  68. function transformPrimitive (val){
  69. if (_.isNull(val)) {
  70. err = new Error('Invalid exemplar: Nested `null`s are not allowed in an RTTC exemplar.');
  71. err.code = 'E_INVALID_EXEMPLAR';
  72. throw err;
  73. }
  74. return val;
  75. },
  76. function transformDictOrArray(val, type) {
  77. if (type === 'array' && val.length === 0 && prohibitEmptyArrays) {
  78. err = new Error('Invalid exemplar: Empty arrays (`[]`) are not allowed in this RTTC exemplar at any depth. (This error was thrown because `rttc.validateExemplarStrict()` with the `prohibitEmptyArrays` flag enabled. Otherwise, any occurences of `[]` would have been understood as `[\'*\']`.)');
  79. err.code = 'E_DEPRECATED_SYNTAX';
  80. throw err;
  81. }
  82. else if (type === 'array' && val.length > 1) {
  83. err = new Error('Invalid exemplar: Multi-item arrays (at any depth) are not allowed in an RTTC exemplar.');
  84. err.code = 'E_INVALID_EXEMPLAR';
  85. throw err;
  86. }
  87. else { return val; }
  88. }
  89. );
  90. // Rebuilding the exemplar should have caused it not to change.
  91. // (if it did, it means it was circular, or that it contained things that
  92. // could not be losslessly serialized to JSON and back again)
  93. if (!_.isEqual(supposedExemplar, rebuiltExemplar)) {
  94. err = new Error('Invalid exemplar: Only strictly JSON-serializable values can qualify to be RTTC exemplars.');
  95. err.code = 'E_INVALID_EXEMPLAR';
  96. throw err;
  97. }
  98. };