1 | 'use strict';
|
---|
2 |
|
---|
3 | var compileSchema = require('./compile')
|
---|
4 | , resolve = require('./compile/resolve')
|
---|
5 | , Cache = require('./cache')
|
---|
6 | , SchemaObject = require('./compile/schema_obj')
|
---|
7 | , stableStringify = require('fast-json-stable-stringify')
|
---|
8 | , formats = require('./compile/formats')
|
---|
9 | , rules = require('./compile/rules')
|
---|
10 | , $dataMetaSchema = require('./data')
|
---|
11 | , util = require('./compile/util');
|
---|
12 |
|
---|
13 | module.exports = Ajv;
|
---|
14 |
|
---|
15 | Ajv.prototype.validate = validate;
|
---|
16 | Ajv.prototype.compile = compile;
|
---|
17 | Ajv.prototype.addSchema = addSchema;
|
---|
18 | Ajv.prototype.addMetaSchema = addMetaSchema;
|
---|
19 | Ajv.prototype.validateSchema = validateSchema;
|
---|
20 | Ajv.prototype.getSchema = getSchema;
|
---|
21 | Ajv.prototype.removeSchema = removeSchema;
|
---|
22 | Ajv.prototype.addFormat = addFormat;
|
---|
23 | Ajv.prototype.errorsText = errorsText;
|
---|
24 |
|
---|
25 | Ajv.prototype._addSchema = _addSchema;
|
---|
26 | Ajv.prototype._compile = _compile;
|
---|
27 |
|
---|
28 | Ajv.prototype.compileAsync = require('./compile/async');
|
---|
29 | var customKeyword = require('./keyword');
|
---|
30 | Ajv.prototype.addKeyword = customKeyword.add;
|
---|
31 | Ajv.prototype.getKeyword = customKeyword.get;
|
---|
32 | Ajv.prototype.removeKeyword = customKeyword.remove;
|
---|
33 | Ajv.prototype.validateKeyword = customKeyword.validate;
|
---|
34 |
|
---|
35 | var errorClasses = require('./compile/error_classes');
|
---|
36 | Ajv.ValidationError = errorClasses.Validation;
|
---|
37 | Ajv.MissingRefError = errorClasses.MissingRef;
|
---|
38 | Ajv.$dataMetaSchema = $dataMetaSchema;
|
---|
39 |
|
---|
40 | var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema';
|
---|
41 |
|
---|
42 | var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes', 'strictDefaults' ];
|
---|
43 | var META_SUPPORT_DATA = ['/properties'];
|
---|
44 |
|
---|
45 | /**
|
---|
46 | * Creates validator instance.
|
---|
47 | * Usage: `Ajv(opts)`
|
---|
48 | * @param {Object} opts optional options
|
---|
49 | * @return {Object} ajv instance
|
---|
50 | */
|
---|
51 | function Ajv(opts) {
|
---|
52 | if (!(this instanceof Ajv)) return new Ajv(opts);
|
---|
53 | opts = this._opts = util.copy(opts) || {};
|
---|
54 | setLogger(this);
|
---|
55 | this._schemas = {};
|
---|
56 | this._refs = {};
|
---|
57 | this._fragments = {};
|
---|
58 | this._formats = formats(opts.format);
|
---|
59 |
|
---|
60 | this._cache = opts.cache || new Cache;
|
---|
61 | this._loadingSchemas = {};
|
---|
62 | this._compilations = [];
|
---|
63 | this.RULES = rules();
|
---|
64 | this._getId = chooseGetId(opts);
|
---|
65 |
|
---|
66 | opts.loopRequired = opts.loopRequired || Infinity;
|
---|
67 | if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
|
---|
68 | if (opts.serialize === undefined) opts.serialize = stableStringify;
|
---|
69 | this._metaOpts = getMetaSchemaOptions(this);
|
---|
70 |
|
---|
71 | if (opts.formats) addInitialFormats(this);
|
---|
72 | if (opts.keywords) addInitialKeywords(this);
|
---|
73 | addDefaultMetaSchema(this);
|
---|
74 | if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
|
---|
75 | if (opts.nullable) this.addKeyword('nullable', {metaSchema: {type: 'boolean'}});
|
---|
76 | addInitialSchemas(this);
|
---|
77 | }
|
---|
78 |
|
---|
79 |
|
---|
80 |
|
---|
81 | /**
|
---|
82 | * Validate data using schema
|
---|
83 | * Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize.
|
---|
84 | * @this Ajv
|
---|
85 | * @param {String|Object} schemaKeyRef key, ref or schema object
|
---|
86 | * @param {Any} data to be validated
|
---|
87 | * @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
|
---|
88 | */
|
---|
89 | function validate(schemaKeyRef, data) {
|
---|
90 | var v;
|
---|
91 | if (typeof schemaKeyRef == 'string') {
|
---|
92 | v = this.getSchema(schemaKeyRef);
|
---|
93 | if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"');
|
---|
94 | } else {
|
---|
95 | var schemaObj = this._addSchema(schemaKeyRef);
|
---|
96 | v = schemaObj.validate || this._compile(schemaObj);
|
---|
97 | }
|
---|
98 |
|
---|
99 | var valid = v(data);
|
---|
100 | if (v.$async !== true) this.errors = v.errors;
|
---|
101 | return valid;
|
---|
102 | }
|
---|
103 |
|
---|
104 |
|
---|
105 | /**
|
---|
106 | * Create validating function for passed schema.
|
---|
107 | * @this Ajv
|
---|
108 | * @param {Object} schema schema object
|
---|
109 | * @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords.
|
---|
110 | * @return {Function} validating function
|
---|
111 | */
|
---|
112 | function compile(schema, _meta) {
|
---|
113 | var schemaObj = this._addSchema(schema, undefined, _meta);
|
---|
114 | return schemaObj.validate || this._compile(schemaObj);
|
---|
115 | }
|
---|
116 |
|
---|
117 |
|
---|
118 | /**
|
---|
119 | * Adds schema to the instance.
|
---|
120 | * @this Ajv
|
---|
121 | * @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
|
---|
122 | * @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
|
---|
123 | * @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead.
|
---|
124 | * @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
|
---|
125 | * @return {Ajv} this for method chaining
|
---|
126 | */
|
---|
127 | function addSchema(schema, key, _skipValidation, _meta) {
|
---|
128 | if (Array.isArray(schema)){
|
---|
129 | for (var i=0; i<schema.length; i++) this.addSchema(schema[i], undefined, _skipValidation, _meta);
|
---|
130 | return this;
|
---|
131 | }
|
---|
132 | var id = this._getId(schema);
|
---|
133 | if (id !== undefined && typeof id != 'string')
|
---|
134 | throw new Error('schema id must be string');
|
---|
135 | key = resolve.normalizeId(key || id);
|
---|
136 | checkUnique(this, key);
|
---|
137 | this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
|
---|
138 | return this;
|
---|
139 | }
|
---|
140 |
|
---|
141 |
|
---|
142 | /**
|
---|
143 | * Add schema that will be used to validate other schemas
|
---|
144 | * options in META_IGNORE_OPTIONS are alway set to false
|
---|
145 | * @this Ajv
|
---|
146 | * @param {Object} schema schema object
|
---|
147 | * @param {String} key optional schema key
|
---|
148 | * @param {Boolean} skipValidation true to skip schema validation, can be used to override validateSchema option for meta-schema
|
---|
149 | * @return {Ajv} this for method chaining
|
---|
150 | */
|
---|
151 | function addMetaSchema(schema, key, skipValidation) {
|
---|
152 | this.addSchema(schema, key, skipValidation, true);
|
---|
153 | return this;
|
---|
154 | }
|
---|
155 |
|
---|
156 |
|
---|
157 | /**
|
---|
158 | * Validate schema
|
---|
159 | * @this Ajv
|
---|
160 | * @param {Object} schema schema to validate
|
---|
161 | * @param {Boolean} throwOrLogError pass true to throw (or log) an error if invalid
|
---|
162 | * @return {Boolean} true if schema is valid
|
---|
163 | */
|
---|
164 | function validateSchema(schema, throwOrLogError) {
|
---|
165 | var $schema = schema.$schema;
|
---|
166 | if ($schema !== undefined && typeof $schema != 'string')
|
---|
167 | throw new Error('$schema must be a string');
|
---|
168 | $schema = $schema || this._opts.defaultMeta || defaultMeta(this);
|
---|
169 | if (!$schema) {
|
---|
170 | this.logger.warn('meta-schema not available');
|
---|
171 | this.errors = null;
|
---|
172 | return true;
|
---|
173 | }
|
---|
174 | var valid = this.validate($schema, schema);
|
---|
175 | if (!valid && throwOrLogError) {
|
---|
176 | var message = 'schema is invalid: ' + this.errorsText();
|
---|
177 | if (this._opts.validateSchema == 'log') this.logger.error(message);
|
---|
178 | else throw new Error(message);
|
---|
179 | }
|
---|
180 | return valid;
|
---|
181 | }
|
---|
182 |
|
---|
183 |
|
---|
184 | function defaultMeta(self) {
|
---|
185 | var meta = self._opts.meta;
|
---|
186 | self._opts.defaultMeta = typeof meta == 'object'
|
---|
187 | ? self._getId(meta) || meta
|
---|
188 | : self.getSchema(META_SCHEMA_ID)
|
---|
189 | ? META_SCHEMA_ID
|
---|
190 | : undefined;
|
---|
191 | return self._opts.defaultMeta;
|
---|
192 | }
|
---|
193 |
|
---|
194 |
|
---|
195 | /**
|
---|
196 | * Get compiled schema from the instance by `key` or `ref`.
|
---|
197 | * @this Ajv
|
---|
198 | * @param {String} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
|
---|
199 | * @return {Function} schema validating function (with property `schema`).
|
---|
200 | */
|
---|
201 | function getSchema(keyRef) {
|
---|
202 | var schemaObj = _getSchemaObj(this, keyRef);
|
---|
203 | switch (typeof schemaObj) {
|
---|
204 | case 'object': return schemaObj.validate || this._compile(schemaObj);
|
---|
205 | case 'string': return this.getSchema(schemaObj);
|
---|
206 | case 'undefined': return _getSchemaFragment(this, keyRef);
|
---|
207 | }
|
---|
208 | }
|
---|
209 |
|
---|
210 |
|
---|
211 | function _getSchemaFragment(self, ref) {
|
---|
212 | var res = resolve.schema.call(self, { schema: {} }, ref);
|
---|
213 | if (res) {
|
---|
214 | var schema = res.schema
|
---|
215 | , root = res.root
|
---|
216 | , baseId = res.baseId;
|
---|
217 | var v = compileSchema.call(self, schema, root, undefined, baseId);
|
---|
218 | self._fragments[ref] = new SchemaObject({
|
---|
219 | ref: ref,
|
---|
220 | fragment: true,
|
---|
221 | schema: schema,
|
---|
222 | root: root,
|
---|
223 | baseId: baseId,
|
---|
224 | validate: v
|
---|
225 | });
|
---|
226 | return v;
|
---|
227 | }
|
---|
228 | }
|
---|
229 |
|
---|
230 |
|
---|
231 | function _getSchemaObj(self, keyRef) {
|
---|
232 | keyRef = resolve.normalizeId(keyRef);
|
---|
233 | return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
|
---|
234 | }
|
---|
235 |
|
---|
236 |
|
---|
237 | /**
|
---|
238 | * Remove cached schema(s).
|
---|
239 | * If no parameter is passed all schemas but meta-schemas are removed.
|
---|
240 | * If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
|
---|
241 | * Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
|
---|
242 | * @this Ajv
|
---|
243 | * @param {String|Object|RegExp} schemaKeyRef key, ref, pattern to match key/ref or schema object
|
---|
244 | * @return {Ajv} this for method chaining
|
---|
245 | */
|
---|
246 | function removeSchema(schemaKeyRef) {
|
---|
247 | if (schemaKeyRef instanceof RegExp) {
|
---|
248 | _removeAllSchemas(this, this._schemas, schemaKeyRef);
|
---|
249 | _removeAllSchemas(this, this._refs, schemaKeyRef);
|
---|
250 | return this;
|
---|
251 | }
|
---|
252 | switch (typeof schemaKeyRef) {
|
---|
253 | case 'undefined':
|
---|
254 | _removeAllSchemas(this, this._schemas);
|
---|
255 | _removeAllSchemas(this, this._refs);
|
---|
256 | this._cache.clear();
|
---|
257 | return this;
|
---|
258 | case 'string':
|
---|
259 | var schemaObj = _getSchemaObj(this, schemaKeyRef);
|
---|
260 | if (schemaObj) this._cache.del(schemaObj.cacheKey);
|
---|
261 | delete this._schemas[schemaKeyRef];
|
---|
262 | delete this._refs[schemaKeyRef];
|
---|
263 | return this;
|
---|
264 | case 'object':
|
---|
265 | var serialize = this._opts.serialize;
|
---|
266 | var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef;
|
---|
267 | this._cache.del(cacheKey);
|
---|
268 | var id = this._getId(schemaKeyRef);
|
---|
269 | if (id) {
|
---|
270 | id = resolve.normalizeId(id);
|
---|
271 | delete this._schemas[id];
|
---|
272 | delete this._refs[id];
|
---|
273 | }
|
---|
274 | }
|
---|
275 | return this;
|
---|
276 | }
|
---|
277 |
|
---|
278 |
|
---|
279 | function _removeAllSchemas(self, schemas, regex) {
|
---|
280 | for (var keyRef in schemas) {
|
---|
281 | var schemaObj = schemas[keyRef];
|
---|
282 | if (!schemaObj.meta && (!regex || regex.test(keyRef))) {
|
---|
283 | self._cache.del(schemaObj.cacheKey);
|
---|
284 | delete schemas[keyRef];
|
---|
285 | }
|
---|
286 | }
|
---|
287 | }
|
---|
288 |
|
---|
289 |
|
---|
290 | /* @this Ajv */
|
---|
291 | function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
|
---|
292 | if (typeof schema != 'object' && typeof schema != 'boolean')
|
---|
293 | throw new Error('schema should be object or boolean');
|
---|
294 | var serialize = this._opts.serialize;
|
---|
295 | var cacheKey = serialize ? serialize(schema) : schema;
|
---|
296 | var cached = this._cache.get(cacheKey);
|
---|
297 | if (cached) return cached;
|
---|
298 |
|
---|
299 | shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
|
---|
300 |
|
---|
301 | var id = resolve.normalizeId(this._getId(schema));
|
---|
302 | if (id && shouldAddSchema) checkUnique(this, id);
|
---|
303 |
|
---|
304 | var willValidate = this._opts.validateSchema !== false && !skipValidation;
|
---|
305 | var recursiveMeta;
|
---|
306 | if (willValidate && !(recursiveMeta = id && id == resolve.normalizeId(schema.$schema)))
|
---|
307 | this.validateSchema(schema, true);
|
---|
308 |
|
---|
309 | var localRefs = resolve.ids.call(this, schema);
|
---|
310 |
|
---|
311 | var schemaObj = new SchemaObject({
|
---|
312 | id: id,
|
---|
313 | schema: schema,
|
---|
314 | localRefs: localRefs,
|
---|
315 | cacheKey: cacheKey,
|
---|
316 | meta: meta
|
---|
317 | });
|
---|
318 |
|
---|
319 | if (id[0] != '#' && shouldAddSchema) this._refs[id] = schemaObj;
|
---|
320 | this._cache.put(cacheKey, schemaObj);
|
---|
321 |
|
---|
322 | if (willValidate && recursiveMeta) this.validateSchema(schema, true);
|
---|
323 |
|
---|
324 | return schemaObj;
|
---|
325 | }
|
---|
326 |
|
---|
327 |
|
---|
328 | /* @this Ajv */
|
---|
329 | function _compile(schemaObj, root) {
|
---|
330 | if (schemaObj.compiling) {
|
---|
331 | schemaObj.validate = callValidate;
|
---|
332 | callValidate.schema = schemaObj.schema;
|
---|
333 | callValidate.errors = null;
|
---|
334 | callValidate.root = root ? root : callValidate;
|
---|
335 | if (schemaObj.schema.$async === true)
|
---|
336 | callValidate.$async = true;
|
---|
337 | return callValidate;
|
---|
338 | }
|
---|
339 | schemaObj.compiling = true;
|
---|
340 |
|
---|
341 | var currentOpts;
|
---|
342 | if (schemaObj.meta) {
|
---|
343 | currentOpts = this._opts;
|
---|
344 | this._opts = this._metaOpts;
|
---|
345 | }
|
---|
346 |
|
---|
347 | var v;
|
---|
348 | try { v = compileSchema.call(this, schemaObj.schema, root, schemaObj.localRefs); }
|
---|
349 | catch(e) {
|
---|
350 | delete schemaObj.validate;
|
---|
351 | throw e;
|
---|
352 | }
|
---|
353 | finally {
|
---|
354 | schemaObj.compiling = false;
|
---|
355 | if (schemaObj.meta) this._opts = currentOpts;
|
---|
356 | }
|
---|
357 |
|
---|
358 | schemaObj.validate = v;
|
---|
359 | schemaObj.refs = v.refs;
|
---|
360 | schemaObj.refVal = v.refVal;
|
---|
361 | schemaObj.root = v.root;
|
---|
362 | return v;
|
---|
363 |
|
---|
364 |
|
---|
365 | /* @this {*} - custom context, see passContext option */
|
---|
366 | function callValidate() {
|
---|
367 | /* jshint validthis: true */
|
---|
368 | var _validate = schemaObj.validate;
|
---|
369 | var result = _validate.apply(this, arguments);
|
---|
370 | callValidate.errors = _validate.errors;
|
---|
371 | return result;
|
---|
372 | }
|
---|
373 | }
|
---|
374 |
|
---|
375 |
|
---|
376 | function chooseGetId(opts) {
|
---|
377 | switch (opts.schemaId) {
|
---|
378 | case 'auto': return _get$IdOrId;
|
---|
379 | case 'id': return _getId;
|
---|
380 | default: return _get$Id;
|
---|
381 | }
|
---|
382 | }
|
---|
383 |
|
---|
384 | /* @this Ajv */
|
---|
385 | function _getId(schema) {
|
---|
386 | if (schema.$id) this.logger.warn('schema $id ignored', schema.$id);
|
---|
387 | return schema.id;
|
---|
388 | }
|
---|
389 |
|
---|
390 | /* @this Ajv */
|
---|
391 | function _get$Id(schema) {
|
---|
392 | if (schema.id) this.logger.warn('schema id ignored', schema.id);
|
---|
393 | return schema.$id;
|
---|
394 | }
|
---|
395 |
|
---|
396 |
|
---|
397 | function _get$IdOrId(schema) {
|
---|
398 | if (schema.$id && schema.id && schema.$id != schema.id)
|
---|
399 | throw new Error('schema $id is different from id');
|
---|
400 | return schema.$id || schema.id;
|
---|
401 | }
|
---|
402 |
|
---|
403 |
|
---|
404 | /**
|
---|
405 | * Convert array of error message objects to string
|
---|
406 | * @this Ajv
|
---|
407 | * @param {Array<Object>} errors optional array of validation errors, if not passed errors from the instance are used.
|
---|
408 | * @param {Object} options optional options with properties `separator` and `dataVar`.
|
---|
409 | * @return {String} human readable string with all errors descriptions
|
---|
410 | */
|
---|
411 | function errorsText(errors, options) {
|
---|
412 | errors = errors || this.errors;
|
---|
413 | if (!errors) return 'No errors';
|
---|
414 | options = options || {};
|
---|
415 | var separator = options.separator === undefined ? ', ' : options.separator;
|
---|
416 | var dataVar = options.dataVar === undefined ? 'data' : options.dataVar;
|
---|
417 |
|
---|
418 | var text = '';
|
---|
419 | for (var i=0; i<errors.length; i++) {
|
---|
420 | var e = errors[i];
|
---|
421 | if (e) text += dataVar + e.dataPath + ' ' + e.message + separator;
|
---|
422 | }
|
---|
423 | return text.slice(0, -separator.length);
|
---|
424 | }
|
---|
425 |
|
---|
426 |
|
---|
427 | /**
|
---|
428 | * Add custom format
|
---|
429 | * @this Ajv
|
---|
430 | * @param {String} name format name
|
---|
431 | * @param {String|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
|
---|
432 | * @return {Ajv} this for method chaining
|
---|
433 | */
|
---|
434 | function addFormat(name, format) {
|
---|
435 | if (typeof format == 'string') format = new RegExp(format);
|
---|
436 | this._formats[name] = format;
|
---|
437 | return this;
|
---|
438 | }
|
---|
439 |
|
---|
440 |
|
---|
441 | function addDefaultMetaSchema(self) {
|
---|
442 | var $dataSchema;
|
---|
443 | if (self._opts.$data) {
|
---|
444 | $dataSchema = require('./refs/data.json');
|
---|
445 | self.addMetaSchema($dataSchema, $dataSchema.$id, true);
|
---|
446 | }
|
---|
447 | if (self._opts.meta === false) return;
|
---|
448 | var metaSchema = require('./refs/json-schema-draft-07.json');
|
---|
449 | if (self._opts.$data) metaSchema = $dataMetaSchema(metaSchema, META_SUPPORT_DATA);
|
---|
450 | self.addMetaSchema(metaSchema, META_SCHEMA_ID, true);
|
---|
451 | self._refs['http://json-schema.org/schema'] = META_SCHEMA_ID;
|
---|
452 | }
|
---|
453 |
|
---|
454 |
|
---|
455 | function addInitialSchemas(self) {
|
---|
456 | var optsSchemas = self._opts.schemas;
|
---|
457 | if (!optsSchemas) return;
|
---|
458 | if (Array.isArray(optsSchemas)) self.addSchema(optsSchemas);
|
---|
459 | else for (var key in optsSchemas) self.addSchema(optsSchemas[key], key);
|
---|
460 | }
|
---|
461 |
|
---|
462 |
|
---|
463 | function addInitialFormats(self) {
|
---|
464 | for (var name in self._opts.formats) {
|
---|
465 | var format = self._opts.formats[name];
|
---|
466 | self.addFormat(name, format);
|
---|
467 | }
|
---|
468 | }
|
---|
469 |
|
---|
470 |
|
---|
471 | function addInitialKeywords(self) {
|
---|
472 | for (var name in self._opts.keywords) {
|
---|
473 | var keyword = self._opts.keywords[name];
|
---|
474 | self.addKeyword(name, keyword);
|
---|
475 | }
|
---|
476 | }
|
---|
477 |
|
---|
478 |
|
---|
479 | function checkUnique(self, id) {
|
---|
480 | if (self._schemas[id] || self._refs[id])
|
---|
481 | throw new Error('schema with key or id "' + id + '" already exists');
|
---|
482 | }
|
---|
483 |
|
---|
484 |
|
---|
485 | function getMetaSchemaOptions(self) {
|
---|
486 | var metaOpts = util.copy(self._opts);
|
---|
487 | for (var i=0; i<META_IGNORE_OPTIONS.length; i++)
|
---|
488 | delete metaOpts[META_IGNORE_OPTIONS[i]];
|
---|
489 | return metaOpts;
|
---|
490 | }
|
---|
491 |
|
---|
492 |
|
---|
493 | function setLogger(self) {
|
---|
494 | var logger = self._opts.logger;
|
---|
495 | if (logger === false) {
|
---|
496 | self.logger = {log: noop, warn: noop, error: noop};
|
---|
497 | } else {
|
---|
498 | if (logger === undefined) logger = console;
|
---|
499 | if (!(typeof logger == 'object' && logger.log && logger.warn && logger.error))
|
---|
500 | throw new Error('logger must implement log, warn and error methods');
|
---|
501 | self.logger = logger;
|
---|
502 | }
|
---|
503 | }
|
---|
504 |
|
---|
505 |
|
---|
506 | function noop() {}
|
---|