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