UNPKG

5.45 kBJavaScriptView Raw
1// Copyright (c) 2012, Mark Cavage. All rights reserved.
2// Copyright 2015 Joyent, Inc.
3
4var assert = require('assert');
5var Stream = require('stream').Stream;
6var util = require('util');
7
8
9///--- Globals
10
11/* JSSTYLED */
12var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/;
13
14
15///--- Internal
16
17function _capitalize(str) {
18 return (str.charAt(0).toUpperCase() + str.slice(1));
19}
20
21function _toss(name, expected, oper, arg, actual) {
22 throw new assert.AssertionError({
23 message: util.format('%s (%s) is required', name, expected),
24 actual: (actual === undefined) ? typeof (arg) : actual(arg),
25 expected: expected,
26 operator: oper || '===',
27 stackStartFunction: _toss.caller
28 });
29}
30
31function _getClass(arg) {
32 return (Object.prototype.toString.call(arg).slice(8, -1));
33}
34
35function noop() {
36 // Why even bother with asserts?
37}
38
39
40///--- Exports
41
42var types = {
43 bool: {
44 check: function (arg) { return typeof (arg) === 'boolean'; }
45 },
46 func: {
47 check: function (arg) { return typeof (arg) === 'function'; }
48 },
49 string: {
50 check: function (arg) { return typeof (arg) === 'string'; }
51 },
52 object: {
53 check: function (arg) {
54 return typeof (arg) === 'object' && arg !== null;
55 }
56 },
57 number: {
58 check: function (arg) {
59 return typeof (arg) === 'number' && !isNaN(arg);
60 }
61 },
62 finite: {
63 check: function (arg) {
64 return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg);
65 }
66 },
67 buffer: {
68 check: function (arg) { return Buffer.isBuffer(arg); },
69 operator: 'Buffer.isBuffer'
70 },
71 array: {
72 check: function (arg) { return Array.isArray(arg); },
73 operator: 'Array.isArray'
74 },
75 stream: {
76 check: function (arg) { return arg instanceof Stream; },
77 operator: 'instanceof',
78 actual: _getClass
79 },
80 date: {
81 check: function (arg) { return arg instanceof Date; },
82 operator: 'instanceof',
83 actual: _getClass
84 },
85 regexp: {
86 check: function (arg) { return arg instanceof RegExp; },
87 operator: 'instanceof',
88 actual: _getClass
89 },
90 uuid: {
91 check: function (arg) {
92 return typeof (arg) === 'string' && UUID_REGEXP.test(arg);
93 },
94 operator: 'isUUID'
95 }
96};
97
98function _setExports(ndebug) {
99 var keys = Object.keys(types);
100 var out;
101
102 /* re-export standard assert */
103 if (process.env.NODE_NDEBUG) {
104 out = noop;
105 } else {
106 out = function (arg, msg) {
107 if (!arg) {
108 _toss(msg, 'true', arg);
109 }
110 };
111 }
112
113 /* standard checks */
114 keys.forEach(function (k) {
115 if (ndebug) {
116 out[k] = noop;
117 return;
118 }
119 var type = types[k];
120 out[k] = function (arg, msg) {
121 if (!type.check(arg)) {
122 _toss(msg, k, type.operator, arg, type.actual);
123 }
124 };
125 });
126
127 /* optional checks */
128 keys.forEach(function (k) {
129 var name = 'optional' + _capitalize(k);
130 if (ndebug) {
131 out[name] = noop;
132 return;
133 }
134 var type = types[k];
135 out[name] = function (arg, msg) {
136 if (arg === undefined || arg === null) {
137 return;
138 }
139 if (!type.check(arg)) {
140 _toss(msg, k, type.operator, arg, type.actual);
141 }
142 };
143 });
144
145 /* arrayOf checks */
146 keys.forEach(function (k) {
147 var name = 'arrayOf' + _capitalize(k);
148 if (ndebug) {
149 out[name] = noop;
150 return;
151 }
152 var type = types[k];
153 var expected = '[' + k + ']';
154 out[name] = function (arg, msg) {
155 if (!Array.isArray(arg)) {
156 _toss(msg, expected, type.operator, arg, type.actual);
157 }
158 var i;
159 for (i = 0; i < arg.length; i++) {
160 if (!type.check(arg[i])) {
161 _toss(msg, expected, type.operator, arg, type.actual);
162 }
163 }
164 };
165 });
166
167 /* optionalArrayOf checks */
168 keys.forEach(function (k) {
169 var name = 'optionalArrayOf' + _capitalize(k);
170 if (ndebug) {
171 out[name] = noop;
172 return;
173 }
174 var type = types[k];
175 var expected = '[' + k + ']';
176 out[name] = function (arg, msg) {
177 if (arg === undefined || arg === null) {
178 return;
179 }
180 if (!Array.isArray(arg)) {
181 _toss(msg, expected, type.operator, arg, type.actual);
182 }
183 var i;
184 for (i = 0; i < arg.length; i++) {
185 if (!type.check(arg[i])) {
186 _toss(msg, expected, type.operator, arg, type.actual);
187 }
188 }
189 };
190 });
191
192 /* re-export built-in assertions */
193 Object.keys(assert).forEach(function (k) {
194 if (k === 'AssertionError') {
195 out[k] = assert[k];
196 return;
197 }
198 if (ndebug) {
199 out[k] = noop;
200 return;
201 }
202 out[k] = assert[k];
203 });
204
205 /* export ourselves (for unit tests _only_) */
206 out._setExports = _setExports;
207
208 return out;
209}
210
211module.exports = _setExports(process.env.NODE_NDEBUG);