index.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. 'use strict';
  2. // Built-in types
  3. var types = [
  4. 'object',
  5. 'number',
  6. 'string',
  7. 'symbol',
  8. 'boolean',
  9. 'date',
  10. 'function', // Weird to expose this
  11. ];
  12. function normalize(coercer, value) {
  13. if (typeof value === 'function') {
  14. if (coercer === 'function') {
  15. return value;
  16. }
  17. value = value.apply(this, slice(arguments, 2));
  18. }
  19. return coerce(this, coercer, value);
  20. }
  21. function coerce(ctx, coercer, value) {
  22. // Handle built-in types
  23. if (typeof coercer === 'string') {
  24. if (coerce[coercer]) {
  25. return coerce[coercer].call(ctx, value);
  26. }
  27. return typeOf(coercer, value);
  28. }
  29. // Handle custom coercer
  30. if (typeof coercer === 'function') {
  31. return coercer.call(ctx, value);
  32. }
  33. // Array of coercers, try in order until one returns a non-null value
  34. var result;
  35. coercer.some(function(coercer) {
  36. result = coerce(ctx, coercer, value);
  37. return result != null;
  38. });
  39. return result;
  40. }
  41. coerce.string = function(value) {
  42. if (value != null &&
  43. typeof value === 'object' &&
  44. typeof value.toString === 'function') {
  45. value = value.toString();
  46. }
  47. return typeOf('string', primitive(value));
  48. };
  49. coerce.number = function(value) {
  50. return typeOf('number', primitive(value));
  51. };
  52. coerce.boolean = function(value) {
  53. return typeOf('boolean', primitive(value));
  54. };
  55. coerce.date = function(value) {
  56. value = primitive(value);
  57. if (typeof value === 'number' && !isNaN(value) && isFinite(value)) {
  58. return new Date(value);
  59. }
  60. };
  61. function typeOf(type, value) {
  62. if (typeof value === type) {
  63. return value;
  64. }
  65. }
  66. function primitive(value) {
  67. if (value != null &&
  68. typeof value === 'object' &&
  69. typeof value.valueOf === 'function') {
  70. value = value.valueOf();
  71. }
  72. return value;
  73. }
  74. function slice(value, from) {
  75. return Array.prototype.slice.call(value, from);
  76. }
  77. // Add methods for each type
  78. types.forEach(function(type) {
  79. // Make it an array for easier concat
  80. var typeArg = [type];
  81. normalize[type] = function() {
  82. var args = slice(arguments);
  83. return normalize.apply(this, typeArg.concat(args));
  84. };
  85. });
  86. module.exports = normalize;