UNPKG

181 kBJavaScriptView Raw
1/*!
2 * Fortune.js
3 * Version 5.5.9
4 * MIT License
5 * http://fortune.js.org
6 */
7(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
8(function (Buffer){
9'use strict'
10
11var deepEqual = require('../../common/deep_equal')
12var message = require('../../common/message')
13var find = require('../../common/array/find')
14var generateId = require('../../common/generate_id')
15
16var errors = require('../../common/errors')
17var BadRequestError = errors.BadRequestError
18
19var keys = require('../../common/keys')
20var primaryKey = keys.primary
21var typeKey = keys.type
22var isArrayKey = keys.isArray
23
24// For complex types.
25var matchCheck = [
26 [ Date, function (a, b) { return a.getTime() === b.getTime() } ],
27 [ Buffer, function (a, b) { return a.equals(b) } ],
28 [ Object, function (a, b) { return deepEqual(a, b) } ]
29]
30
31// For comparing sort order.
32var comparisons = [
33 [ Number, function (a, b) { return a - b } ],
34 [ String, function (a, b) { return a === b ? 0 : a > b ? 1 : -1 } ],
35 [ Boolean, function (a, b) { return a === b ? 0 : a ? 1 : -1 } ],
36 [ Date, function (a, b) { return a.getTime() - b.getTime() } ],
37 [ Buffer, Buffer.compare ],
38
39 // There is no comparison here that makes sense, so this should simply be a
40 // no-op by default.
41 [ Object, function () { return 0 } ]
42]
43
44
45// Browser-safe ID generation.
46exports.generateId = generateId
47
48
49exports.applyOptions = function (fields, records, options, meta) {
50 var count, record, field, isInclude, isExclude, language, memoizedRecords
51 var i, j
52
53 if (!options) options = {}
54 if (!meta) meta = {}
55
56 language = meta.language
57
58 // Apply filters.
59 if (options) {
60 memoizedRecords = records
61 records = []
62 for (i = 0, j = memoizedRecords.length; i < j; i++) {
63 record = memoizedRecords[i]
64 if (match(fields, options, record))
65 records.push(record)
66 }
67 }
68
69 count = records.length
70
71 if ('fields' in options) {
72 isInclude = !find(Object.keys(options.fields),
73 function (field) { return !options.fields[field] })
74 isExclude = !find(Object.keys(options.fields),
75 function (field) { return options.fields[field] })
76
77 if (!isInclude && !isExclude)
78 throw new BadRequestError(message('FieldsFormat', language))
79
80 for (i = 0, j = records.length; i < j; i++) {
81 record = records[i]
82 for (field in record) {
83 if (field === primaryKey) continue
84 if ((isInclude && !(options.fields.hasOwnProperty(field))) ||
85 (isExclude && options.fields.hasOwnProperty(field)))
86 delete record[field]
87 }
88 }
89 }
90
91 if ('sort' in options)
92 records = records.sort(compare(fields, options.sort))
93
94 if ('limit' in options || 'offset' in options)
95 records = records.slice(options.offset, options.limit ?
96 (options.offset || 0) + options.limit : records.length)
97
98 records.count = count
99
100 return records
101}
102
103
104function check (type, a, b) {
105 var matcher
106
107 if (b === null) return a === null
108 if (!type) return a === b
109 if (type.compare) return type.compare(a, b) === 0
110
111 matcher = find(matchCheck, function (pair) {
112 return pair[0] === type.prototype.constructor
113 })
114 if (matcher) return matcher[1](a, b)
115
116 return a === b
117}
118
119
120function checkValue (fieldDefinition, a) {
121 return function (b) {
122 return fieldDefinition[isArrayKey] ?
123 find(a, function (a) {
124 return check(fieldDefinition[typeKey], b, a)
125 }) : check(fieldDefinition[typeKey], b, a)
126 }
127}
128
129function match (fields, options, record) {
130 var key
131
132 for (key in options)
133 switch (key) {
134 case 'and':
135 if (!matchByLogicalAnd(fields, options[key], record)) return false
136 break
137 case 'or':
138 if (!matchByLogicalOr(fields, options[key], record)) return false
139 break
140 case 'not':
141 if (match(fields, options[key], record)) return false
142 break
143 case 'range':
144 if (!matchByRange(fields, options[key], record)) return false
145 break
146 case 'match':
147 if (!matchByField(fields, options[key], record)) return false
148 break
149 case 'exists':
150 if (!matchByExistence(fields, options[key], record)) return false
151 break
152 default:
153 }
154
155 return true
156}
157
158function matchByLogicalAnd (fields, clauses, record) {
159 var i
160
161 for (i = 0; i < clauses.length; i++)
162 if (!match(fields, clauses[i], record)) return false
163
164 return true
165}
166
167function matchByLogicalOr (fields, clauses, record) {
168 var i
169
170 for (i = 0; i < clauses.length; i++)
171 if (match(fields, clauses[i], record)) return true
172
173 return false
174}
175
176function matchByField (fields, match, record) {
177 var field, matches
178
179 for (field in match) {
180 matches = match[field]
181 if (!Array.isArray(matches)) matches = [ matches ]
182 if (find(matches, checkValue(fields[field], record[field])) === void 0)
183 return false
184 }
185
186 return true
187}
188
189
190function matchByExistence (fields, exists, record) {
191 var field, value, isArray
192
193 for (field in exists) {
194 value = record[field]
195 isArray = fields[field][isArrayKey]
196 if (exists[field]) {
197 if (!value) return false
198 if (isArray && !value.length) return false
199 }
200 else {
201 if (value && !isArray) return false
202 if (isArray && value.length) return false
203 }
204 }
205
206 return true
207}
208
209
210function matchByRange (fields, ranges, record) {
211 var compare = {}
212 var field, fieldDefinition, fieldType, fieldIsArray, range, value
213
214 for (field in ranges) {
215 fieldDefinition = fields[field]
216 fieldType = fieldDefinition[typeKey]
217 fieldIsArray = fieldDefinition[isArrayKey]
218
219 // Skip for singular link fields.
220 if (!fieldType && !fieldIsArray) continue
221
222 range = ranges[field]
223 value = record[field]
224
225 if (value == null) return false
226 if (fieldIsArray) value = value ? value.length : 0
227
228 if (!compare[field])
229 compare[field] = !fieldIsArray ? fieldType.compare ||
230 find(comparisons, findByType(fieldType))[1] :
231 find(comparisons, findByType(Number))[1]
232
233 if (range[0] !== null && compare[field](value, range[0]) < 0)
234 return false
235
236 if (range[1] !== null && compare[field](range[1], value) < 0)
237 return false
238 }
239
240 return true
241}
242
243
244function findByType (type) {
245 return function (pair) {
246 return pair[0] === type.prototype.constructor
247 }
248}
249
250
251function compare (fields, sort) {
252 var field, compare, a, b, isAscending,
253 fieldDefinition, fieldIsArray, fieldType, result
254
255 return function (x, y) {
256 for (field in sort) {
257 a = x[field]
258 b = y[field]
259 isAscending = sort[field]
260 fieldDefinition = fields[field]
261 fieldIsArray = fieldDefinition[isArrayKey]
262 fieldType = fieldDefinition[typeKey]
263
264 if (a === null) return 1
265 if (b === null) return -1
266
267 result = 0
268
269 if (fieldIsArray) result = a.length - b.length
270 else if (fieldType) {
271 compare = fieldType.compare ||
272 find(comparisons, findByType(fieldType))[1]
273 if (!compare) throw new Error('Missing "compare" function.')
274 result = compare(a, b)
275 }
276
277 if (result === 0) continue
278
279 return isAscending ? result : -result
280 }
281
282 return 0
283 }
284}
285
286}).call(this,require("buffer").Buffer)
287},{"../../common/array/find":8,"../../common/deep_equal":19,"../../common/errors":20,"../../common/generate_id":22,"../../common/keys":24,"../../common/message":25,"buffer":47}],2:[function(require,module,exports){
288'use strict'
289
290var common = require('../common')
291var generateId = common.generateId
292
293
294exports.inputRecord = function (type, record) {
295 var recordTypes = this.recordTypes
296 var primaryKey = this.keys.primary
297 var isArrayKey = this.keys.isArray
298 var fields = recordTypes[type]
299 var fieldsArray = Object.getOwnPropertyNames(fields)
300 var result = {}
301 var i, j, field
302
303 // Ensure that ID exists on the record.
304 result[primaryKey] = primaryKey in record ?
305 record[primaryKey] : generateId()
306
307 for (i = 0, j = fieldsArray.length; i < j; i++) {
308 field = fieldsArray[i]
309 if (!record.hasOwnProperty(field)) {
310 result[field] = fields[field][isArrayKey] ? [] : null
311 continue
312 }
313
314 result[field] = record[field]
315 }
316
317 return result
318}
319
320
321exports.outputRecord = function (type, record) {
322 var recordTypes = this.recordTypes
323 var primaryKey = this.keys.primary
324 var isArrayKey = this.keys.isArray
325 var denormalizedInverseKey = this.keys.denormalizedInverse
326 var fields = recordTypes[type]
327 var fieldsArray = Object.getOwnPropertyNames(fields)
328 var result = {}
329 var i, j, field, hasField, value
330
331 // Ensure that ID exists on the record.
332 result[primaryKey] = record[primaryKey]
333
334 for (i = 0, j = fieldsArray.length; i < j; i++) {
335 field = fieldsArray[i]
336 hasField = record.hasOwnProperty(field)
337 value = hasField ? record[field] :
338 fields[field][isArrayKey] ? [] : null
339
340 // Do not enumerate denormalized fields.
341 if (fields[field][denormalizedInverseKey]) {
342 Object.defineProperty(result, field, {
343 configurable: true, writable: true, value: value
344 })
345 continue
346 }
347
348 if (hasField) result[field] = value
349 }
350
351 return result
352}
353
354},{"../common":1}],3:[function(require,module,exports){
355'use strict'
356
357var applyUpdate = require('../../../common/apply_update')
358var map = require('../../../common/array/map')
359var promise = require('../../../common/promise')
360
361var common = require('../common')
362var applyOptions = common.applyOptions
363
364var helpers = require('./helpers')
365var inputRecord = helpers.inputRecord
366var outputRecord = helpers.outputRecord
367
368
369/**
370 * Memory adapter.
371 */
372module.exports = function (Adapter) {
373 function MemoryAdapter (properties) {
374 Adapter.call(this, properties)
375 if (!this.options) this.options = {}
376 if (!('recordsPerType' in this.options))
377 this.options.recordsPerType = 1000
378 }
379
380 MemoryAdapter.prototype = new Adapter()
381
382 MemoryAdapter.prototype.connect = function () {
383 var Promise = promise.Promise
384 var recordTypes = this.recordTypes
385 var type
386
387 this.db = {}
388
389 for (type in recordTypes)
390 this.db[type] = {}
391
392 return Promise.resolve()
393 }
394
395
396 MemoryAdapter.prototype.disconnect = function () {
397 var Promise = promise.Promise
398
399 delete this.db
400 return Promise.resolve()
401 }
402
403
404 MemoryAdapter.prototype.find = function (type, ids, options, meta) {
405 var Promise = promise.Promise
406 var self = this
407 var recordTypes = self.recordTypes
408 var fields = recordTypes[type]
409 var collection = self.db[type]
410 var records = []
411 var i, j, id, record
412
413 if (ids && !ids.length) return Adapter.prototype.find.call(self)
414
415 if (ids) for (i = 0, j = ids.length; i < j; i++) {
416 id = ids[i]
417 if (collection.hasOwnProperty(id)) {
418 record = collection[id]
419
420 // LRU update.
421 delete collection[id]
422 collection[id] = record
423
424 records.push(outputRecord.call(self, type, record))
425 }
426 }
427
428 else for (id in collection)
429 records.push(outputRecord.call(self, type, collection[id]))
430
431 return Promise.resolve(applyOptions(fields, records, options, meta))
432 }
433
434
435 MemoryAdapter.prototype.create = function (type, records, meta) {
436 var Promise = promise.Promise
437 var self = this
438 var message = self.message
439 var recordsPerType = self.options.recordsPerType
440 var primaryKey = self.keys.primary
441 var ConflictError = self.errors.ConflictError
442 var collection = self.db[type]
443 var i, j, record, id, ids, language
444
445 if (!meta) meta = {}
446 language = meta.language
447
448 records = map(records, function (record) {
449 return inputRecord.call(self, type, record)
450 })
451
452 // First check for collisions.
453 for (i = 0, j = records.length; i < j; i++) {
454 record = records[i]
455 id = record[primaryKey]
456
457 if (collection.hasOwnProperty(id))
458 return Promise.reject(new ConflictError(
459 message('RecordExists', language, { id: id })))
460 }
461
462 // Then save it to memory.
463 for (i = 0, j = records.length; i < j; i++) {
464 record = records[i]
465 collection[record[primaryKey]] = record
466 }
467
468 // Clear least recently used records.
469 if (recordsPerType) {
470 ids = Object.keys(collection)
471
472 if (ids.length > recordsPerType) {
473 ids = ids.slice(0, ids.length - recordsPerType)
474
475 for (i = 0, j = ids.length; i < j; i++)
476 delete collection[ids[i]]
477 }
478 }
479
480 return Promise.resolve(map(records, function (record) {
481 return outputRecord.call(self, type, record)
482 }))
483 }
484
485
486 MemoryAdapter.prototype.update = function (type, updates) {
487 var Promise = promise.Promise
488 var self = this
489 var primaryKey = self.keys.primary
490 var collection = self.db[type]
491 var count = 0
492 var i, j, update, id, record
493
494 if (!updates.length) return Adapter.prototype.update.call(self)
495
496 for (i = 0, j = updates.length; i < j; i++) {
497 update = updates[i]
498 id = update[primaryKey]
499 record = collection[id]
500
501 if (!record) continue
502
503 count++
504 record = outputRecord.call(self, type, record)
505
506 applyUpdate(record, update)
507
508 // LRU update.
509 delete collection[id]
510
511 collection[id] = inputRecord.call(self, type, record)
512 }
513
514 return Promise.resolve(count)
515 }
516
517
518 MemoryAdapter.prototype.delete = function (type, ids) {
519 var Promise = promise.Promise
520 var collection = this.db[type]
521 var count = 0
522 var i, j, id
523
524 if (ids && !ids.length) return Adapter.prototype.delete.call(this)
525
526 if (ids) for (i = 0, j = ids.length; i < j; i++) {
527 id = ids[i]
528 if (collection[id]) {
529 delete collection[id]
530 count++
531 }
532 }
533
534 else for (id in collection) {
535 delete collection[id]
536 count++
537 }
538
539 return Promise.resolve(count)
540 }
541
542 // Expose utility functions.
543 MemoryAdapter.common = common
544
545 // Expose features for introspection.
546 MemoryAdapter.features = {
547 logicalOperators: true
548 }
549
550 return MemoryAdapter
551}
552
553},{"../../../common/apply_update":6,"../../../common/array/map":10,"../../../common/promise":28,"../common":1,"./helpers":2}],4:[function(require,module,exports){
554'use strict'
555
556var assign = require('../common/assign')
557var promise = require('../common/promise')
558var memoryAdapter = require('./adapters/memory')
559
560
561/**
562 * Adapter is an abstract base class containing methods to be implemented. All
563 * records returned by the adapter must have the primary key `id`. The primary
564 * key **MUST** be a string or a number.
565 *
566 * It has one static property, `defaultAdapter` which is a reference to the
567 * memory adapter.
568 */
569function Adapter (properties) {
570 assign(this, properties)
571}
572
573
574/**
575 * The Adapter should not be instantiated directly, since the constructor
576 * function accepts dependencies. The keys which are injected are:
577 *
578 * - `recordTypes`: an object which enumerates record types and their
579 * definitions.
580 * - `options`: the options passed to the adapter.
581 * - `common`: an object containing all internal utilities.
582 * - `errors`: same as static property on Fortune class.
583 * - `keys`: an object which enumerates reserved constants for record type
584 * - `message`: a function with the signature (`id`, `language`, `data`).
585 *
586 * These keys are accessible on the instance (`this`).
587 *
588 * An adapter may expose a `features` static property, which is an object
589 * that can contain boolean flags. These are used mainly for checking which
590 * additional features may be tested.
591 *
592 * - `logicalOperators`: whether or not `and` and `or` queries are supported.
593 */
594Adapter.prototype.constructor = function () {
595 // This exists here only for documentation purposes.
596}
597
598delete Adapter.prototype.constructor
599
600
601/**
602 * The responsibility of this method is to ensure that the record types
603 * defined are consistent with the backing data store. If there is any
604 * mismatch it should either try to reconcile differences or fail.
605 * This method **SHOULD NOT** be called manually, and it should not accept
606 * any parameters. This is the time to do setup tasks like create tables,
607 * ensure indexes, etc. On successful completion, it should resolve to no
608 * value.
609 *
610 * @return {Promise}
611 */
612Adapter.prototype.connect = function () {
613 var Promise = promise.Promise
614 return Promise.resolve()
615}
616
617
618/**
619 * Close the database connection.
620 *
621 * @return {Promise}
622 */
623Adapter.prototype.disconnect = function () {
624 var Promise = promise.Promise
625 return Promise.resolve()
626}
627
628
629/**
630 * Create records. A successful response resolves to the newly created
631 * records.
632 *
633 * **IMPORTANT**: the record must have initial values for each field defined
634 * in the record type. For non-array fields, it should be `null`, and for
635 * array fields it should be `[]` (empty array). Note that not all fields in
636 * the record type may be enumerable, such as denormalized inverse fields, so
637 * it may be necessary to iterate over fields using
638 * `Object.getOwnPropertyNames`.
639 *
640 * @param {String} type
641 * @param {Object[]} records
642 * @param {Object} [meta]
643 * @return {Promise}
644 */
645Adapter.prototype.create = function () {
646 var Promise = promise.Promise
647 return Promise.resolve([])
648}
649
650
651/**
652 * Find records by IDs and options. If IDs is undefined, it should try to
653 * return all records. However, if IDs is an empty array, it should be a
654 * no-op. The format of the options may be as follows:
655 *
656 * ```js
657 * {
658 * sort: { ... },
659 * fields: { ... },
660 * exists: { ... },
661 * match: { ... },
662 * range: { ... },
663 *
664 * // Limit results to this number. Zero means no limit.
665 * limit: 0,
666 *
667 * // Offset results by this much from the beginning.
668 * offset: 0,
669 *
670 * // The logical operator "and", may be nested. Optional feature.
671 * and: { ... },
672 *
673 * // The logical operator "or", may be nested. Optional feature.
674 * or: { ... },
675 *
676 * // Reserved field for custom querying.
677 * query: null
678 * }
679 * ```
680 *
681 * For the fields `exists`, `match`, and `range`, the logical operator should
682 * be "and". The `query` field may be used on a per adapter basis to provide
683 * custom querying functionality.
684 *
685 * The syntax of the `sort` object is as follows:
686 *
687 * ```js
688 * {
689 * age: false, // descending
690 * name: true // ascending
691 * }
692 * ```
693 *
694 * Fields can be specified to be either included or omitted, but not both.
695 * Use the values `true` to include, or `false` to omit. The syntax of the
696 * `fields` object is as follows:
697 *
698 * ```js
699 * {
700 * name: true, // include this field
701 * age: true // also include this field
702 * }
703 * ```
704 *
705 * The `exists` object specifies if a field should exist or not (`true` or
706 * `false`). For array fields, it should check for non-zero length.
707 *
708 * ```js
709 * {
710 * name: true, // check if this fields exists
711 * age: false // check if this field doesn't exist
712 * }
713 * ```
714 *
715 * The syntax of the `match` object is straightforward:
716 *
717 * ```js
718 * {
719 * name: 'value', // exact match or containment if array
720 * friends: [ 'joe', 'bob' ] // match any one of these values
721 * }
722 * ```
723 *
724 * The `range` object is used to filter between lower and upper bounds. It
725 * should take precedence over `match`. For array fields, it should apply on
726 * the length of the array. For singular link fields, it should not apply.
727 *
728 * ```js
729 * {
730 * range: { // Ranges should be inclusive.
731 * age: [ 18, null ], // From 18 and above.
732 * name: [ 'a', 'd' ], // Starting with letters A through C.
733 * createdAt: [ null, new Date(2016, 0) ] // Dates until 2016.
734 * }
735 * }
736 * ```
737 *
738 * The return value of the promise should be an array, and the array **MUST**
739 * have a `count` property that is the total number of records without limit
740 * and offset.
741 *
742 * @param {String} type
743 * @param {String[]|Number[]} [ids]
744 * @param {Object} [options]
745 * @param {Object} [meta]
746 * @return {Promise}
747 */
748Adapter.prototype.find = function () {
749 var Promise = promise.Promise
750 var results = []
751 results.count = 0
752 return Promise.resolve(results)
753}
754
755
756/**
757 * Update records by IDs. Success should resolve to the number of records
758 * updated. The `updates` parameter should be an array of objects that
759 * correspond to updates by IDs. Each update object must be as follows:
760 *
761 * ```js
762 * {
763 * // ID to update. Required.
764 * id: 1,
765 *
766 * // Replace a value of a field. Use a `null` value to unset a field.
767 * replace: { name: 'Bob' },
768 *
769 * // Append values to an array field. If the value is an array, all of
770 * // the values should be pushed.
771 * push: { pets: 1 },
772 *
773 * // Remove values from an array field. If the value is an array, all of
774 * // the values should be removed.
775 * pull: { friends: [ 2, 3 ] },
776 *
777 * // The `operate` field is specific to the adapter. This should take
778 * // precedence over all of the above. Warning: using this may bypass
779 * // field definitions and referential integrity. Use at your own risk.
780 * operate: null
781 * }
782 * ```
783 *
784 * Things to consider:
785 *
786 * - `push` and `pull` can not be applied to non-arrays.
787 * - The same value in the same field should not exist in both `push` and
788 * `pull`.
789 *
790 * @param {String} type
791 * @param {Object[]} updates
792 * @param {Object} [meta]
793 * @return {Promise}
794 */
795Adapter.prototype.update = function () {
796 var Promise = promise.Promise
797 return Promise.resolve(0)
798}
799
800
801/**
802 * Delete records by IDs, or delete the entire collection if IDs are
803 * undefined or empty. Success should resolve to the number of records
804 * deleted.
805 *
806 * @param {String} type
807 * @param {String[]|Number[]} [ids]
808 * @param {Object} [meta]
809 * @return {Promise}
810 */
811Adapter.prototype.delete = function () {
812 var Promise = promise.Promise
813 return Promise.resolve(0)
814}
815
816
817/**
818 * Begin a transaction to write to the data store. This method is optional
819 * to implement, but useful for ACID. It should resolve to an object
820 * containing all of the adapter methods.
821 *
822 * @return {Promise}
823 */
824Adapter.prototype.beginTransaction = function () {
825 var Promise = promise.Promise
826 return Promise.resolve(this)
827}
828
829
830/**
831 * End a transaction. This method is optional to implement.
832 * It should return a Promise with no value if the transaction is
833 * completed successfully, or reject the promise if it failed.
834 *
835 * @param {Error} [error] - If an error is passed, roll back the transaction.
836 * @return {Promise}
837 */
838Adapter.prototype.endTransaction = function () {
839 var Promise = promise.Promise
840 return Promise.resolve()
841}
842
843
844/**
845 * Apply operators on a record, then return the record. If you make use of
846 * update operators, you should implement this method so that the internal
847 * implementation of update requests get records in the correct state. This
848 * method is optional to implement.
849 *
850 * @param {Object} record
851 * @param {Object} operators - The `operate` field on an `update` object.
852 * @return {Object}
853 */
854Adapter.prototype.applyOperators = function (record) {
855 return record
856}
857
858
859// Expose the default adapter.
860Adapter.DefaultAdapter = memoryAdapter(Adapter)
861
862// Expose features object.
863Adapter.features = {}
864
865module.exports = Adapter
866
867},{"../common/assign":14,"../common/promise":28,"./adapters/memory":3}],5:[function(require,module,exports){
868'use strict'
869
870var Adapter = require('./')
871var common = require('../common')
872var errors = require('../common/errors')
873var keys = require('../common/keys')
874var promise = require('../common/promise')
875
876
877/**
878 * A singleton for the adapter. For internal use.
879 */
880function AdapterSingleton (properties) {
881 var CustomAdapter, input
882
883 input = Array.isArray(properties.adapter) ?
884 properties.adapter : [ properties.adapter ]
885
886 if (typeof input[0] !== 'function')
887 throw new TypeError('The adapter must be a function.')
888
889 CustomAdapter = Adapter.prototype
890 .isPrototypeOf(input[0].prototype) ? input[0] : input[0](Adapter)
891
892 if (!Adapter.prototype.isPrototypeOf(CustomAdapter.prototype))
893 throw new TypeError('The adapter must inherit the Adapter class.')
894
895 return new CustomAdapter({
896 options: input[1] || {},
897 recordTypes: properties.recordTypes,
898 features: CustomAdapter.features,
899 common: common,
900 errors: errors,
901 keys: keys,
902 message: properties.message,
903 Promise: promise.Promise
904 })
905}
906
907
908module.exports = AdapterSingleton
909
910},{"../common":23,"../common/errors":20,"../common/keys":24,"../common/promise":28,"./":4}],6:[function(require,module,exports){
911'use strict'
912
913var pull = require('./array/pull')
914
915
916/**
917 * Given a record and an update object, apply the update on the record. Note
918 * that the `operate` object is unapplied here.
919 *
920 * @param {Object} record
921 * @param {Object} update
922 */
923module.exports = function applyUpdate (record, update) {
924 var field
925
926 for (field in update.replace)
927 record[field] = update.replace[field]
928
929 for (field in update.push)
930 record[field] = record[field] ?
931 record[field].concat(update.push[field]) :
932 [].concat(update.push[field])
933
934 for (field in update.pull)
935 record[field] = record[field] ?
936 pull(record[field], update.pull[field]) : []
937}
938
939},{"./array/pull":11}],7:[function(require,module,exports){
940'use strict'
941
942/**
943 * A more performant `Array.prototype.filter`.
944 *
945 * @param {*[]} array
946 * @param {Function} fn
947 * @return {Boolean}
948 */
949module.exports = function filter (array, fn) {
950 var i, j, k = [], l = 0
951
952 for (i = 0, j = array.length; i < j; i++)
953 if (fn(array[i], i, array))
954 k[l++] = array[i]
955
956 return k
957}
958
959},{}],8:[function(require,module,exports){
960'use strict'
961
962/**
963 * A more performant `Array.prototype.find`.
964 *
965 * @param {*[]} array
966 * @param {Function} fn
967 * @return {*}
968 */
969module.exports = function find (array, fn) {
970 var i, j, value, result
971
972 for (i = 0, j = array.length; i < j; i++) {
973 value = array[i]
974 result = fn(value)
975 if (result) return value
976 }
977
978 return void 0
979}
980
981},{}],9:[function(require,module,exports){
982'use strict'
983
984/**
985 * A more performant `Array.prototype.includes`.
986 *
987 * @param {*[]} array
988 * @param {*} value
989 * @return {Boolean}
990 */
991module.exports = function includes (array, value) {
992 var i, j
993
994 for (i = 0, j = array.length; i < j; i++)
995 if (array[i] === value) return true
996
997 return false
998}
999
1000},{}],10:[function(require,module,exports){
1001'use strict'
1002
1003/**
1004 * A more performant `Array.prototype.map`.
1005 *
1006 * @param {*[]} array
1007 * @param {Function} fn
1008 * @return {Boolean}
1009 */
1010module.exports = function map (array, fn) {
1011 var i, j, k = [], l = 0
1012
1013 for (i = 0, j = array.length; i < j; i++)
1014 k[l++] = fn(array[i], i, array)
1015
1016 return k
1017}
1018
1019},{}],11:[function(require,module,exports){
1020'use strict'
1021
1022
1023/**
1024 * Pull primitive values from an array.
1025 *
1026 * @param {*[]} array
1027 * @param {*|*[]} values
1028 * @return {*[]}
1029 */
1030module.exports = function pull (array, values) {
1031 var hash = {}, clone = [], value
1032 var i, j
1033
1034 if (Array.isArray(values))
1035 for (i = 0, j = values.length; i < j; i++)
1036 hash[values[i]] = true
1037 else hash[values] = true
1038
1039 // Need to iterate backwards.
1040 for (i = array.length; i--;) {
1041 value = array[i]
1042 if (!hash.hasOwnProperty(value))
1043 // Unshift because it is iterating backwards.
1044 clone.unshift(value)
1045 }
1046
1047 return clone
1048}
1049
1050},{}],12:[function(require,module,exports){
1051'use strict'
1052
1053/**
1054 * A more performant `Array.prototype.reduce`.
1055 *
1056 * @param {*[]} array
1057 * @param {Function} fn
1058 * @param {*} [initialValue]
1059 * @return {Boolean}
1060 */
1061module.exports = function reduce (array, fn, initialValue) {
1062 var i, j, k = initialValue
1063
1064 for (i = 0, j = array.length; i < j; i++)
1065 k = fn(k, array[i], i, array)
1066
1067 return k
1068}
1069
1070},{}],13:[function(require,module,exports){
1071'use strict'
1072
1073/**
1074 * Return an array with unique values. Values must be primitive, and the array
1075 * may not be sparse.
1076 *
1077 * @param {Array}
1078 * @return {Array}
1079 */
1080module.exports = function unique (a) {
1081 var seen = {}
1082 var result = []
1083 var i, j, k
1084
1085 for (i = 0, j = a.length; i < j; i++) {
1086 k = a[i]
1087 if (seen.hasOwnProperty(k)) continue
1088 result.push(k)
1089 seen[k] = true
1090 }
1091
1092 return result
1093}
1094
1095},{}],14:[function(require,module,exports){
1096'use strict'
1097
1098/**
1099 * Like `Object.assign`, but faster and more restricted in what it does.
1100 *
1101 * @param {Object} target
1102 * @return {Object}
1103 */
1104module.exports = function assign (target) {
1105 var i, j, key, source
1106
1107 for (i = 1, j = arguments.length; i < j; i++) {
1108 source = arguments[i]
1109
1110 if (source == null) continue
1111
1112 for (key in source)
1113 target[key] = source[key]
1114 }
1115
1116 return target
1117}
1118
1119},{}],15:[function(require,module,exports){
1120'use strict'
1121
1122module.exports = function castToNumber (id) {
1123 // Stolen from jQuery source code:
1124 // https://api.jquery.com/jQuery.isNumeric/
1125 var float = Number.parseFloat(id)
1126 return id - float + 1 >= 0 ? float : id
1127}
1128
1129},{}],16:[function(require,module,exports){
1130(function (Buffer){
1131'use strict'
1132
1133var errors = require('./errors')
1134var message = require('./message')
1135var castToNumber = require('./cast_to_number')
1136var BadRequestError = errors.BadRequestError
1137var buffer = Buffer.from || function (input, encoding) {
1138 return new Buffer(input, encoding)
1139}
1140
1141
1142var castByType = [
1143 [ Number, function (x) { return parseFloat(x) } ],
1144
1145 [ Date, function (x, options) {
1146 if (typeof x === 'string') {
1147 x = Date.parse(x)
1148 if (Number.isNaN(x)) throw new BadRequestError(
1149 message('DateISO8601', options.language))
1150 }
1151
1152 x = new Date(x)
1153 if (Number.isNaN(x.getTime())) throw new BadRequestError(
1154 message('DateInvalid', options.language))
1155
1156 return x
1157 } ],
1158
1159 [ Buffer, function (x, options) {
1160 var bufferEncoding = options && options.bufferEncoding ?
1161 options.bufferEncoding : 'base64'
1162
1163 if (typeof x !== 'string') throw new BadRequestError(
1164 message('BufferEncoding', options.language, {
1165 bufferEncoding: bufferEncoding
1166 }))
1167
1168 return buffer(x, bufferEncoding)
1169 } ],
1170
1171 [ Boolean, function (x) {
1172 if (typeof x === 'string')
1173 return (/^(?:true|1|yes|t|y)$/i).test(x)
1174 return Boolean(x)
1175 } ],
1176
1177 [ Object, function (x, options) {
1178 if (typeof x === 'string') return JSON.parse(x)
1179 if (typeof x === 'object') return x
1180 throw new BadRequestError(message('JSONParse', options.language))
1181 } ],
1182
1183 [ String, function (x) { return '' + x } ]
1184]
1185
1186
1187/**
1188 * Cast a value to the given type. Skip if type is missing or value is null.
1189 *
1190 * @param {*} value
1191 * @param {Function} type - Constructor function.
1192 * @param {Object} [options]
1193 * @return {*}
1194 */
1195module.exports = function castValue (value, type, options) {
1196 var i, j, pair, cast
1197
1198 // Special case for empty string: it should be null.
1199 if (value === '') return null
1200
1201 if (type)
1202 for (i = 0, j = castByType.length; i < j; i++) {
1203 pair = castByType[i]
1204 if (pair[0] === type) {
1205 cast = pair[1]
1206 break
1207 }
1208 }
1209 else return castToNumber(value)
1210
1211 return cast && value !== null ? cast(value, options) : value
1212}
1213
1214}).call(this,require("buffer").Buffer)
1215},{"./cast_to_number":15,"./errors":20,"./message":25,"buffer":47}],17:[function(require,module,exports){
1216'use strict'
1217
1218/**
1219 * A fast deep clone function, which covers mostly serializable objects.
1220 *
1221 * @param {*}
1222 * @return {*}
1223 */
1224module.exports = function clone (input) {
1225 var output, key, value, isArray
1226
1227 if (Array.isArray(input)) isArray = true
1228 else if (input == null || Object.getPrototypeOf(input) !== Object.prototype)
1229 return input
1230
1231 output = isArray ? [] : {}
1232
1233 for (key in input) {
1234 value = input[key]
1235 output[key] = value !== null && value !== undefined &&
1236 Object.getPrototypeOf(value) === Object.prototype ||
1237 Array.isArray(value) ? clone(value) : value
1238 }
1239
1240 return output
1241}
1242
1243},{}],18:[function(require,module,exports){
1244'use strict'
1245
1246var hasSymbol = typeof Symbol === 'function'
1247var i, j, key
1248var privateKeys = [
1249 // This is set on the field definition object internally if it is an
1250 // automatically generated denormalized field.
1251 'denormalizedInverse',
1252
1253 // Used to map update objects to records.
1254 'updateRecord',
1255
1256 // Used to map update objects to a hash of linked records.
1257 'linkedHash'
1258]
1259
1260// The primary key that must exist per record, can not be user defined.
1261exports.primary = 'id'
1262
1263// The names of certain reserved keys per field definition.
1264exports.type = 'type'
1265exports.link = 'link'
1266exports.inverse = 'inverse'
1267exports.isArray = 'isArray'
1268
1269// Should be reserved for private use.
1270for (i = 0, j = privateKeys.length; i < j; i++) {
1271 key = privateKeys[i]
1272 exports[key] = hasSymbol ? Symbol(key) : '__' + key + '__'
1273}
1274
1275// Events.
1276exports.change = 'change'
1277exports.sync = 'sync'
1278exports.connect = 'connect'
1279exports.disconnect = 'disconnect'
1280exports.failure = 'failure'
1281
1282// Methods.
1283exports.find = 'find'
1284exports.create = 'create'
1285exports.update = 'update'
1286exports.delete = 'delete'
1287
1288},{}],19:[function(require,module,exports){
1289(function (Buffer){
1290'use strict'
1291
1292/**
1293 * A fast recursive equality check, which covers limited use cases.
1294 *
1295 * @param {Object}
1296 * @param {Object}
1297 * @return {Boolean}
1298 */
1299function deepEqual (a, b) {
1300 var key, value, compare, aLength = 0, bLength = 0
1301
1302 // If they are the same object, don't need to go further.
1303 if (a === b) return true
1304
1305 // Both objects must be defined.
1306 if (!a || !b) return false
1307
1308 // Objects must be of the same type.
1309 if (a.prototype !== b.prototype) return false
1310
1311 for (key in a) {
1312 aLength++
1313 value = a[key]
1314 compare = b[key]
1315
1316 if (typeof value === 'object') {
1317 if (typeof compare !== 'object' || !deepEqual(value, compare))
1318 return false
1319 continue
1320 }
1321
1322 if (Buffer.isBuffer(value)) {
1323 if (!Buffer.isBuffer(compare) || !value.equals(compare))
1324 return false
1325 continue
1326 }
1327
1328 if (value && typeof value.getTime === 'function') {
1329 if (!compare || typeof compare.getTime !== 'function' ||
1330 value.getTime() !== compare.getTime())
1331 return false
1332 continue
1333 }
1334
1335 if (value !== compare) return false
1336 }
1337
1338 for (key in b) bLength++
1339
1340 // Keys must be of same length.
1341 return aLength === bLength
1342}
1343
1344
1345module.exports = deepEqual
1346
1347}).call(this,{"isBuffer":require("../../node_modules/is-buffer/index.js")})
1348},{"../../node_modules/is-buffer/index.js":51}],20:[function(require,module,exports){
1349'use strict'
1350
1351var responseClass = require('./response_classes')
1352
1353exports.BadRequestError = responseClass.BadRequestError
1354exports.UnauthorizedError = responseClass.UnauthorizedError
1355exports.ForbiddenError = responseClass.ForbiddenError
1356exports.NotFoundError = responseClass.NotFoundError
1357exports.MethodError = responseClass.MethodError
1358exports.NotAcceptableError = responseClass.NotAcceptableError
1359exports.ConflictError = responseClass.ConflictError
1360exports.UnsupportedError = responseClass.UnsupportedError
1361exports.UnprocessableError = responseClass.UnprocessableError
1362exports.nativeErrors = responseClass.nativeErrors
1363
1364},{"./response_classes":29}],21:[function(require,module,exports){
1365'use strict'
1366
1367var constants = require('./constants')
1368
1369exports.change = constants.change
1370exports.sync = constants.sync
1371exports.connect = constants.connect
1372exports.disconnect = constants.disconnect
1373exports.failure = constants.failure
1374
1375},{"./constants":18}],22:[function(require,module,exports){
1376'use strict'
1377
1378// Modified base64 with "+" as "-" and "/" as "_".
1379var charset =
1380 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
1381 'abcdefghijklmnopqrstuvwxyz' +
1382 '0123456789-_'
1383
1384var charsetLength = charset.length
1385
1386// Should be a multiple of 3 to avoid padding characters.
1387var keyLength = 3 * 5
1388
1389module.exports = function generateId () {
1390 var i, array = []
1391
1392 for (i = 0; i < keyLength; i++)
1393 array.push(charset.charAt(Math.floor(Math.random() * charsetLength)))
1394
1395 return array.join('')
1396}
1397
1398},{}],23:[function(require,module,exports){
1399'use strict'
1400
1401module.exports = {
1402 // Keys
1403 constants: require('./constants'),
1404 keys: require('./keys'),
1405 events: require('./events'),
1406 methods: require('./methods'),
1407
1408 // Utility functions
1409 assign: require('./assign'),
1410 castToNumber: require('./cast_to_number'),
1411 castValue: require('./cast_value'),
1412 clone: require('./clone'),
1413 deepEqual: require('./deep_equal'),
1414 generateId: require('./generate_id'),
1415 applyUpdate: require('./apply_update'),
1416
1417 // i18n
1418 message: require('./message'),
1419
1420 // Typed responses
1421 responses: require('./response_classes'),
1422 errors: require('./errors'),
1423 successes: require('./success'),
1424
1425 // Arrays
1426 filter: require('./array/filter'),
1427 find: require('./array/find'),
1428 includes: require('./array/includes'),
1429 map: require('./array/map'),
1430 pull: require('./array/pull'),
1431 reduce: require('./array/reduce'),
1432 unique: require('./array/unique')
1433}
1434
1435},{"./apply_update":6,"./array/filter":7,"./array/find":8,"./array/includes":9,"./array/map":10,"./array/pull":11,"./array/reduce":12,"./array/unique":13,"./assign":14,"./cast_to_number":15,"./cast_value":16,"./clone":17,"./constants":18,"./deep_equal":19,"./errors":20,"./events":21,"./generate_id":22,"./keys":24,"./message":25,"./methods":27,"./response_classes":29,"./success":30}],24:[function(require,module,exports){
1436'use strict'
1437
1438var constants = require('./constants')
1439
1440exports.primary = constants.primary
1441exports.type = constants.type
1442exports.link = constants.link
1443exports.isArray = constants.isArray
1444exports.inverse = constants.inverse
1445exports.denormalizedInverse = constants.denormalizedInverse
1446
1447},{"./constants":18}],25:[function(require,module,exports){
1448'use strict'
1449
1450var languages = {
1451 en: require('./messages/en')
1452}
1453
1454var key
1455for (key in languages)
1456 message[key] = languages[key]
1457
1458module.exports = message
1459
1460
1461/**
1462 * Message function for i18n.
1463 *
1464 * @param {String} id
1465 * @param {String} language
1466 * @param {Object} [data]
1467 * @return {String}
1468 */
1469function message (id, language, data) {
1470 var genericMessage = 'GenericError'
1471 var self = this || message
1472 var str, key, subtag
1473
1474 if (!self.hasOwnProperty(language)) {
1475 subtag = language && language.match(/.+?(?=-)/)
1476 if (subtag) subtag = subtag[0]
1477 if (self.hasOwnProperty(subtag)) language = subtag
1478 else language = self.defaultLanguage
1479 }
1480
1481 str = self[language].hasOwnProperty(id) ?
1482 self[language][id] :
1483 self[language][genericMessage] || self.en[genericMessage]
1484
1485 if (typeof str === 'string')
1486 for (key in data)
1487 str = str.replace('{' + key + '}', data[key])
1488
1489 if (typeof str === 'function')
1490 str = str(data)
1491
1492 return str
1493}
1494
1495// Assign fallback language to "en".
1496Object.defineProperty(message, 'defaultLanguage', {
1497 value: 'en', writable: true
1498})
1499
1500},{"./messages/en":26}],26:[function(require,module,exports){
1501
1502module.exports = {
1503 GenericError: function(d) { return "An internal error occurred."; },
1504 MalformedRequest: function(d) { return "The request was malformed."; },
1505 InvalidBody: function(d) { return "The request body is invalid."; },
1506 SerializerNotFound: function(d) { return "The serializer for \"" + d.id + "\" does not exist."; },
1507 InputOnly: function(d) { return "Input only."; },
1508 InvalidID: function(d) { return "An ID is invalid."; },
1509 DateISO8601: function(d) { return "Date string must be an ISO 8601 formatted string."; },
1510 DateInvalid: function(d) { return "Date value is invalid."; },
1511 BufferEncoding: function(d) { return "Buffer value must be a " + d.bufferEncoding + "-encoded string."; },
1512 JSONParse: function(d) { return "Could not parse value as JSON."; },
1513 MissingPayload: function(d) { return "Payload is missing."; },
1514 SpecifiedIDs: function(d) { return "IDs should not be specified."; },
1515 InvalidURL: function(d) { return "Invalid URL."; },
1516 RelatedRecordNotFound: function(d) { return "A related record for the field \"" + d.field + "\" was not found."; },
1517 CreateRecordsInvalid: function(d) { return "There are no valid records to be created."; },
1518 CreateRecordsFail: function(d) { return "Records could not be created."; },
1519 CreateRecordMissingID: function(d) { return "An ID on a created record is missing."; },
1520 DeleteRecordsMissingID: function(d) { return "IDs are required for deleting records."; },
1521 DeleteRecordsInvalid: function(d) { return "A record to be deleted could not be found."; },
1522 DeleteRecordsFail: function(d) { return "Not all records specified could be deleted."; },
1523 UnspecifiedType: function(d) { return "The type is unspecified."; },
1524 InvalidType: function(d) { return "The requested type \"" + d.type + "\" is not a valid type."; },
1525 InvalidLink: function(d) { return "The field \"" + d.field + "\" does not define a link."; },
1526 InvalidMethod: function(d) { return "The method \"" + d.method + "\" is unrecognized."; },
1527 CollisionToOne: function(d) { return "Multiple records can not have the same to-one link value on the field \"" + d.field + "\"."; },
1528 CollisionDuplicate: function(d) { return "Duplicate ID \"" + d.id + "\" in the field \"" + d.field + "\"."; },
1529 UpdateRecordMissing: function(d) { return "A record to be updated could not be found."; },
1530 UpdateRecordsInvalid: function(d) { return "There are no valid updates."; },
1531 UpdateRecordMissingID: function(d) { return "An ID on an update is missing."; },
1532 EnforceArrayType: function(d) { return "The value of \"" + d.key + "\" is invalid, it must be an array with values of type \"" + d.type + "\"."; },
1533 EnforceArray: function(d) { return "The value of \"" + d.key + "\" is invalid, it must be an array."; },
1534 EnforceSameID: function(d) { return "An ID of \"" + d.key + "\" is invalid, it cannot be the same ID of the record."; },
1535 EnforceSingular: function(d) { return "The value of \"" + d.key + "\" can not be an array, it must be a singular value."; },
1536 EnforceValue: function(d) { return "The value of \"" + d.key + "\" is invalid, it must be a \"" + d.type + "\"."; },
1537 EnforceValueArray: function(d) { return "A value in the array of \"" + d.key + "\" is invalid, it must be a \"" + d.type + "\"."; },
1538 FieldsFormat: function(d) { return "Fields format is invalid. It may either be inclusive or exclusive, but not both."; },
1539 RecordExists: function(d) { return "A record with ID \"" + d.id + "\" already exists."; }
1540}
1541
1542},{}],27:[function(require,module,exports){
1543'use strict'
1544
1545var constants = require('./constants')
1546
1547exports.find = constants.find
1548exports.create = constants.create
1549exports.update = constants.update
1550exports.delete = constants.delete
1551
1552},{"./constants":18}],28:[function(require,module,exports){
1553'use strict'
1554
1555// This object exists as a container for the Promise implementation. By
1556// default, it's the native one.
1557exports.Promise = Promise
1558
1559},{}],29:[function(require,module,exports){
1560'use strict'
1561
1562var errorClass = require('error-class')
1563var assign = require('./assign')
1564
1565
1566// Successes.
1567exports.OK = function OK (hash) { assign(this, hash) }
1568exports.Created = function Created (hash) { assign(this, hash) }
1569exports.Empty = function Empty (hash) { assign(this, hash) }
1570
1571
1572// Errors.
1573exports.BadRequestError = errorClass('BadRequestError')
1574exports.UnauthorizedError = errorClass('UnauthorizedError')
1575exports.ForbiddenError = errorClass('ForbiddenError')
1576exports.NotFoundError = errorClass('NotFoundError')
1577exports.MethodError = errorClass('MethodError')
1578exports.NotAcceptableError = errorClass('NotAcceptableError')
1579exports.ConflictError = errorClass('ConflictError')
1580exports.UnsupportedError = errorClass('UnsupportedError')
1581exports.UnprocessableError = errorClass('UnprocessableError')
1582
1583
1584// White-list native error types. The list is gathered from here:
1585// https://developer.mozilla.org/en-US/docs/Web/JavaScript/
1586// Reference/Global_Objects/Error
1587exports.nativeErrors = [
1588 Error, TypeError, ReferenceError, RangeError,
1589 SyntaxError, EvalError, URIError
1590]
1591
1592},{"./assign":14,"error-class":48}],30:[function(require,module,exports){
1593'use strict'
1594
1595var responseClass = require('./response_classes')
1596
1597exports.OK = responseClass.OK
1598exports.Created = responseClass.Created
1599exports.Empty = responseClass.Empty
1600
1601},{"./response_classes":29}],31:[function(require,module,exports){
1602'use strict'
1603
1604window.fortune = require('./')
1605
1606},{"./":32}],32:[function(require,module,exports){
1607'use strict'
1608
1609var EventLite = require('event-lite')
1610
1611// Local modules.
1612var memoryAdapter = require('./adapter/adapters/memory')
1613var AdapterSingleton = require('./adapter/singleton')
1614var validate = require('./record_type/validate')
1615var ensureTypes = require('./record_type/ensure_types')
1616var promise = require('./common/promise')
1617var internalRequest = require('./request')
1618var middlewares = internalRequest.middlewares
1619
1620// Static re-exports.
1621var Adapter = require('./adapter')
1622var common = require('./common')
1623var assign = common.assign
1624var methods = common.methods
1625var events = common.events
1626
1627
1628/**
1629 * This is the default export of the `fortune` package. It implements a
1630 * [subset of `EventEmitter`](https://www.npmjs.com/package/event-lite), and it
1631 * has a few static properties attached to it that may be useful to access:
1632 *
1633 * - `Adapter`: abstract base class for the Adapter.
1634 * - `adapters`: included adapters, defaults to memory adapter.
1635 * - `errors`: custom error types, useful for throwing errors in I/O hooks.
1636 * - `methods`: a hash that maps to string constants. Available are: `find`,
1637 * `create`, `update`, and `delete`.
1638 * - `events`: names for events on the Fortune instance. Available are:
1639 * `change`, `sync`, `connect`, `disconnect`, `failure`.
1640 * - `message`: a function which accepts the arguments (`id`, `language`,
1641 * `data`). It has properties keyed by two-letter language codes, which by
1642 * default includes only `en`.
1643 * - `Promise`: assign this to set the Promise implementation that Fortune
1644 * will use.
1645 */
1646function Fortune (recordTypes, options) {
1647 if (!(this instanceof Fortune))
1648 return new Fortune(recordTypes, options)
1649
1650 this.constructor(recordTypes, options)
1651}
1652
1653
1654// Inherit from EventLite class.
1655Fortune.prototype = new EventLite()
1656
1657
1658/**
1659 * Create a new instance, the only required input is record type definitions.
1660 * The first argument must be an object keyed by name, valued by definition
1661 * objects.
1662 *
1663 * Here are some example field definitions:
1664 *
1665 * ```js
1666 * {
1667 * // Top level keys are names of record types.
1668 * person: {
1669 * // Data types may be singular or plural.
1670 * name: String, // Singular string value.
1671 * luckyNumbers: Array(Number), // Array of numbers.
1672 *
1673 * // Relationships may be singular or plural. They must specify which
1674 * // record type it refers to, and may also specify an inverse field
1675 * // which is optional but recommended.
1676 * pets: [ Array('animal'), 'owner' ], // Has many.
1677 * employer: [ 'organization', 'employees' ], // Belongs to.
1678 * likes: Array('thing'), // Has many (no inverse).
1679 * doing: 'activity', // Belongs to (no inverse).
1680 *
1681 * // Reflexive relationships are relationships in which the record type,
1682 * // the first position, is of the same type.
1683 * following: [ Array('person'), 'followers' ],
1684 * followers: [ Array('person'), 'following' ],
1685 *
1686 * // Mutual relationships are relationships in which the inverse,
1687 * // the second position, is defined to be the same field on the same
1688 * // record type.
1689 * friends: [ Array('person'), 'friends' ],
1690 * spouse: [ 'person', 'spouse' ]
1691 * }
1692 * }
1693 * ```
1694 *
1695 * The above shows the shorthand which will be transformed internally to a
1696 * more verbose data structure. The internal structure is as follows:
1697 *
1698 * ```js
1699 * {
1700 * person: {
1701 * // A singular value.
1702 * name: { type: String },
1703 *
1704 * // An array containing values of a single type.
1705 * luckyNumbers: { type: Number, isArray: true },
1706 *
1707 * // Creates a to-many link to `animal` record type. If the field `owner`
1708 * // on the `animal` record type is not an array, this is a many-to-one
1709 * // relationship, otherwise it is many-to-many.
1710 * pets: { link: 'animal', isArray: true, inverse: 'owner' },
1711 *
1712 * // The `min` and `max` keys are open to interpretation by the specific
1713 * // adapter, which may introspect the field definition.
1714 * thing: { type: Number, min: 0, max: 100 },
1715 *
1716 * // Nested field definitions are invalid. Use `Object` type instead.
1717 * nested: { thing: { ... } } // Will throw an error.
1718 * }
1719 * }
1720 * ```
1721 *
1722 * The allowed native types are `String`, `Number`, `Boolean`, `Date`,
1723 * `Object`, and `Buffer`. Note that the `Object` type should be a JSON
1724 * serializable object that may be persisted. The only other allowed type is
1725 * a `Function`, which may be used to define custom types.
1726 *
1727 * A custom type function should accept one argument, the value, and return a
1728 * boolean based on whether the value is valid for the type or not. It may
1729 * optionally have a method `compare`, used for sorting in the built-in
1730 * adapters. The `compare` method should have the same signature as the native
1731 * `Array.prototype.sort`.
1732 *
1733 * A custom type function must inherit one of the allowed native types. For
1734 * example:
1735 *
1736 * ```js
1737 * function Integer (x) { return (x | 0) === x }
1738 * Integer.prototype = new Number()
1739 * ```
1740 *
1741 * The options object may contain the following keys:
1742 *
1743 * - `adapter`: configuration array for the adapter. The default type is the
1744 * memory adapter. If the value is not an array, its settings will be
1745 * considered omitted.
1746 *
1747 * ```js
1748 * {
1749 * adapter: [
1750 * // Must be a class that extends `Fortune.Adapter`, or a function
1751 * // that accepts the Adapter class and returns a subclass. Required.
1752 * Adapter => { ... },
1753 *
1754 * // An options object that is specific to the adapter. Optional.
1755 * { ... }
1756 * ]
1757 * }
1758 * ```
1759 *
1760 * - `hooks`: keyed by type name, valued by an array containing an `input`
1761 * and/or `output` function at indices `0` and `1` respectively.
1762 *
1763 * A hook function takes at least two arguments, the internal `context`
1764 * object and a single `record`. A special case is the `update` argument for
1765 * the `update` method.
1766 *
1767 * There are only two kinds of hooks, before a record is written (input),
1768 * and after a record is read (output), both are optional. If an error occurs
1769 * within a hook function, it will be forwarded to the response. Use typed
1770 * errors to provide the appropriate feedback.
1771 *
1772 * For a create request, the input hook may return the second argument
1773 * `record` either synchronously, or asynchronously as a Promise. The return
1774 * value of a delete request is inconsequential, but it may return a value or
1775 * a Promise. The `update` method accepts a `update` object as a third
1776 * parameter, which may be returned synchronously or as a Promise.
1777 *
1778 * An example hook to apply a timestamp on a record before creation, and
1779 * displaying the timestamp in the server's locale:
1780 *
1781 * ```js
1782 * {
1783 * recordType: [
1784 * (context, record, update) => {
1785 * switch (context.request.method) {
1786 * case 'create':
1787 * record.timestamp = new Date()
1788 * return record
1789 * case 'update': return update
1790 * case 'delete': return null
1791 * }
1792 * },
1793 * (context, record) => {
1794 * record.timestamp = record.timestamp.toLocaleString()
1795 * return record
1796 * }
1797 * ]
1798 * }
1799 * ```
1800 *
1801 * Requests to update a record will **NOT** have the updates already applied
1802 * to the record.
1803 *
1804 * Another feature of the input hook is that it will have access to a
1805 * temporary field `context.transaction`. This is useful for ensuring that
1806 * bulk write operations are all or nothing. Each request is treated as a
1807 * single transaction.
1808 *
1809 * - `documentation`: an object mapping names to descriptions. Note that there
1810 * is only one namepspace, so field names can only have one description.
1811 * This is optional, but useful for the HTML serializer, which also emits
1812 * this information as micro-data.
1813 *
1814 * ```js
1815 * {
1816 * documentation: {
1817 * recordType: 'Description of a type.',
1818 * fieldName: 'Description of a field.',
1819 * anotherFieldName: {
1820 * en: 'Two letter language code indicates localized description.'
1821 * }
1822 * }
1823 * }
1824 * ```
1825 *
1826 * - `settings`: internal settings to configure.
1827 *
1828 * ```js
1829 * {
1830 * settings: {
1831 * // Whether or not to enforce referential integrity. This may be
1832 * // useful to disable on the client-side.
1833 * enforceLinks: true,
1834 *
1835 * // Name of the application used for display purposes.
1836 * name: 'My Awesome Application',
1837 *
1838 * // Description of the application used for display purposes.
1839 * description: 'media type "application/vnd.micro+json"'
1840 * }
1841 * }
1842 * ```
1843 *
1844 * The return value of the constructor is the instance itself.
1845 *
1846 * @param {Object} [recordTypes]
1847 * @param {Object} [options]
1848 * @return {Fortune}
1849 */
1850Fortune.prototype.constructor = function Fortune (recordTypes, options) {
1851 var self = this
1852 var plainObject = {}
1853 var message = common.message
1854 var adapter, method, stack, flows, type, hooks, i, j
1855
1856 if (recordTypes === void 0) recordTypes = {}
1857 if (options === void 0) options = {}
1858
1859 if (!('adapter' in options)) options.adapter = [ memoryAdapter(Adapter) ]
1860 if (!('settings' in options)) options.settings = {}
1861 if (!('hooks' in options)) options.hooks = {}
1862 if (!('enforceLinks' in options.settings))
1863 options.settings.enforceLinks = true
1864
1865 // Bind middleware methods to instance.
1866 flows = {}
1867 for (method in methods) {
1868 stack = [ middlewares[method], middlewares.include, middlewares.end ]
1869
1870 for (i = 0, j = stack.length; i < j; i++)
1871 stack[i] = bindMiddleware(self, stack[i])
1872
1873 flows[methods[method]] = stack
1874 }
1875
1876 hooks = options.hooks
1877
1878 // Validate hooks.
1879 for (type in hooks) {
1880 if (!recordTypes.hasOwnProperty(type)) throw new Error(
1881 'Attempted to define hook on "' + type + '" type ' +
1882 'which does not exist.')
1883 if (!Array.isArray(hooks[type]))
1884 throw new TypeError('Hook value for "' + type + '" type ' +
1885 'must be an array.')
1886 }
1887
1888 // Validate record types.
1889 for (type in recordTypes) {
1890 if (type in plainObject)
1891 throw new Error('Can not define type name "' + type +
1892 '" which is in Object.prototype.')
1893
1894 validate(recordTypes[type])
1895 if (!hooks.hasOwnProperty(type)) hooks[type] = []
1896 }
1897
1898 /*!
1899 * Adapter singleton that is coupled to the Fortune instance.
1900 *
1901 * @type {Adapter}
1902 */
1903 adapter = new AdapterSingleton({
1904 adapter: options.adapter,
1905 recordTypes: recordTypes,
1906 hooks: hooks,
1907 message: message
1908 })
1909
1910 // Internal properties.
1911 Object.defineProperties(self, {
1912 // 0 = not started, 1 = started, 2 = done.
1913 connectionStatus: { value: 0, writable: true },
1914
1915 // Configuration settings.
1916 options: { value: options },
1917 hooks: { value: hooks },
1918 recordTypes: { value: recordTypes, enumerable: true },
1919 message: { value: message, enumerable: true },
1920
1921 // Singleton instances.
1922 adapter: { value: adapter, enumerable: true, configurable: true },
1923
1924 // Various flows for methods.
1925 flows: { value: flows }
1926 })
1927}
1928
1929
1930/**
1931 * This is the primary method for initiating a request. The options object
1932 * may contain the following keys:
1933 *
1934 * - `method`: The method is a either a function or a constant, which is keyed
1935 * under `Fortune.common.methods` and may be one of `find`, `create`,
1936 * `update`, or `delete`. Default: `find`.
1937 *
1938 * - `type`: Name of a type. **Required**.
1939 *
1940 * - `ids`: An array of IDs. Used for `find` and `delete` methods only. This is
1941 * optional for the `find` method.
1942 *
1943 * - `include`: A 3-dimensional array specifying links to include. The first
1944 * dimension is a list, the second dimension is depth, and the third
1945 * dimension is an optional tuple with field and query options. For example:
1946 * `[['comments'], ['comments', ['author', { ... }]]]`.
1947 *
1948 * - `options`: Exactly the same as the [`find` method](#adapter-find)
1949 * options in the adapter. These options do not apply on methods other than
1950 * `find`, and do not affect the records returned from `include`. Optional.
1951 *
1952 * - `meta`: Meta-information object of the request. Optional.
1953 *
1954 * - `payload`: Payload of the request. **Required** for `create` and `update`
1955 * methods only, and must be an array of objects. The objects must be the
1956 * records to create, or update objects as expected by the Adapter.
1957 *
1958 * - `transaction`: if an existing transaction should be re-used, this may
1959 * optionally be passed in. This must be ended manually.
1960 *
1961 * The response object may contain the following keys:
1962 *
1963 * - `meta`: Meta-info of the response.
1964 *
1965 * - `payload`: An object containing the following keys:
1966 * - `records`: An array of records returned.
1967 * - `count`: Total number of records without options applied (only for
1968 * responses to the `find` method).
1969 * - `include`: An object keyed by type, valued by arrays of included
1970 * records.
1971 *
1972 * The resolved response object should always be an instance of a response
1973 * type.
1974 *
1975 * @param {Object} options
1976 * @return {Promise}
1977 */
1978Fortune.prototype.request = function (options) {
1979 var self = this
1980 var connectionStatus = self.connectionStatus
1981 var Promise = promise.Promise
1982
1983 if (connectionStatus === 0)
1984 return self.connect()
1985 .then(function () { return internalRequest.call(self, options) })
1986
1987 else if (connectionStatus === 1)
1988 return new Promise(function (resolve, reject) {
1989 // Wait for changes to connection status.
1990 self.once(events.failure, function () {
1991 reject(new Error('Connection failed.'))
1992 })
1993 self.once(events.connect, function () {
1994 resolve(internalRequest.call(self, options))
1995 })
1996 })
1997
1998 return internalRequest.call(self, options)
1999}
2000
2001
2002/**
2003 * The `find` method retrieves record by type given IDs, querying options,
2004 * or both. This is a convenience method that wraps around the `request`
2005 * method, see the `request` method for documentation on its arguments.
2006 *
2007 * @param {String} type
2008 * @param {*|*[]} [ids]
2009 * @param {Object} [options]
2010 * @param {Array[]} [include]
2011 * @param {Object} [meta]
2012 * @return {Promise}
2013 */
2014Fortune.prototype.find = function (type, ids, options, include, meta) {
2015 var obj = { method: methods.find, type: type }
2016
2017 if (ids) obj.ids = Array.isArray(ids) ? ids : [ ids ]
2018 if (options) obj.options = options
2019 if (include) obj.include = include
2020 if (meta) obj.meta = meta
2021
2022 return this.request(obj)
2023}
2024
2025
2026/**
2027 * The `create` method creates records by type given records to create. This
2028 * is a convenience method that wraps around the `request` method, see the
2029 * request `method` for documentation on its arguments.
2030 *
2031 * @param {String} type
2032 * @param {Object|Object[]} records
2033 * @param {Array[]} [include]
2034 * @param {Object} [meta]
2035 * @return {Promise}
2036 */
2037Fortune.prototype.create = function (type, records, include, meta) {
2038 var options = { method: methods.create, type: type,
2039 payload: Array.isArray(records) ? records : [ records ] }
2040
2041 if (include) options.include = include
2042 if (meta) options.meta = meta
2043
2044 return this.request(options)
2045}
2046
2047
2048/**
2049 * The `update` method updates records by type given update objects. See the
2050 * [Adapter.update](#adapter-update) method for the format of the update
2051 * objects. This is a convenience method that wraps around the `request`
2052 * method, see the `request` method for documentation on its arguments.
2053 *
2054 * @param {String} type
2055 * @param {Object|Object[]} updates
2056 * @param {Array[]} [include]
2057 * @param {Object} [meta]
2058 * @return {Promise}
2059 */
2060Fortune.prototype.update = function (type, updates, include, meta) {
2061 var options = { method: methods.update, type: type,
2062 payload: Array.isArray(updates) ? updates : [ updates ] }
2063
2064 if (include) options.include = include
2065 if (meta) options.meta = meta
2066
2067 return this.request(options)
2068}
2069
2070
2071/**
2072 * The `delete` method deletes records by type given IDs (optional). This is a
2073 * convenience method that wraps around the `request` method, see the `request`
2074 * method for documentation on its arguments.
2075 *
2076 * @param {String} type
2077 * @param {*|*[]} [ids]
2078 * @param {Array[]} [include]
2079 * @param {Object} [meta]
2080 * @return {Promise}
2081 */
2082Fortune.prototype.delete = function (type, ids, include, meta) {
2083 var options = { method: methods.delete, type: type }
2084
2085 if (ids) options.ids = Array.isArray(ids) ? ids : [ ids ]
2086 if (include) options.include = include
2087 if (meta) options.meta = meta
2088
2089 return this.request(options)
2090}
2091
2092
2093/**
2094 * This method does not need to be called manually, it is automatically called
2095 * upon the first request if it is not connected already. However, it may be
2096 * useful if manually reconnect is needed. The resolved value is the instance
2097 * itself.
2098 *
2099 * @return {Promise}
2100 */
2101Fortune.prototype.connect = function () {
2102 var self = this
2103 var Promise = promise.Promise
2104
2105 if (self.connectionStatus === 1)
2106 return Promise.reject(new Error('Connection is in progress.'))
2107
2108 else if (self.connectionStatus === 2)
2109 return Promise.reject(new Error('Connection is already done.'))
2110
2111 self.connectionStatus = 1
2112
2113 return new Promise(function (resolve, reject) {
2114 Object.defineProperty(self, 'denormalizedFields', {
2115 value: ensureTypes(self.recordTypes),
2116 writable: true,
2117 configurable: true
2118 })
2119
2120 self.adapter.connect().then(function () {
2121 self.connectionStatus = 2
2122 self.emit(events.connect)
2123 return resolve(self)
2124 }, function (error) {
2125 self.connectionStatus = 0
2126 self.emit(events.failure)
2127 return reject(error)
2128 })
2129 })
2130}
2131
2132
2133/**
2134 * Close adapter connection, and reset connection state. The resolved value is
2135 * the instance itself.
2136 *
2137 * @return {Promise}
2138 */
2139Fortune.prototype.disconnect = function () {
2140 var self = this
2141 var Promise = promise.Promise
2142
2143 if (self.connectionStatus !== 2)
2144 return Promise.reject(new Error('Instance has not been connected.'))
2145
2146 self.connectionStatus = 1
2147
2148 return new Promise(function (resolve, reject) {
2149 return self.adapter.disconnect().then(function () {
2150 self.connectionStatus = 0
2151 self.emit(events.disconnect)
2152 return resolve(self)
2153 }, function (error) {
2154 self.connectionStatus = 2
2155 self.emit(events.failure)
2156 return reject(error)
2157 })
2158 })
2159}
2160
2161
2162// Useful for dependency injection. All instances of Fortune have the same
2163// common internal dependencies.
2164Fortune.prototype.common = common
2165
2166
2167// Assign useful static properties to the default export.
2168assign(Fortune, {
2169 Adapter: Adapter,
2170 adapters: {
2171 memory: memoryAdapter(Adapter)
2172 },
2173 errors: common.errors,
2174 message: common.message,
2175 methods: methods,
2176 events: events
2177})
2178
2179
2180// Set the `Promise` property.
2181Object.defineProperty(Fortune, 'Promise', {
2182 enumerable: true,
2183 get: function () {
2184 return promise.Promise
2185 },
2186 set: function (value) {
2187 promise.Promise = value
2188 }
2189})
2190
2191
2192// Internal helper function.
2193function bindMiddleware (scope, method) {
2194 return function (x) {
2195 return method.call(scope, x)
2196 }
2197}
2198
2199
2200module.exports = Fortune
2201
2202},{"./adapter":4,"./adapter/adapters/memory":3,"./adapter/singleton":5,"./common":23,"./common/promise":28,"./record_type/ensure_types":34,"./record_type/validate":35,"./request":42,"event-lite":49}],33:[function(require,module,exports){
2203(function (Buffer){
2204'use strict'
2205
2206var message = require('../common/message')
2207var find = require('../common/array/find')
2208
2209var errors = require('../common/errors')
2210var BadRequestError = errors.BadRequestError
2211
2212var keys = require('../common/keys')
2213var primaryKey = keys.primary
2214var typeKey = keys.type
2215var linkKey = keys.link
2216var isArrayKey = keys.isArray
2217
2218
2219// Check input values.
2220var checkInput = [
2221 [ String, function (value) {
2222 return typeof value === 'string'
2223 } ],
2224 [ Number, function (value) {
2225 return typeof value === 'number'
2226 } ],
2227 [ Boolean, function (value) {
2228 return typeof value === 'boolean'
2229 } ],
2230 [ Date, function (value) {
2231 return value && typeof value.getTime === 'function' &&
2232 !Number.isNaN(value.getTime())
2233 } ],
2234 [ Object, function (value) {
2235 return value !== null && typeof value === 'object'
2236 } ],
2237 [ Buffer, function (value) {
2238 return Buffer.isBuffer(value)
2239 } ]
2240]
2241
2242
2243/**
2244 * Throw errors for mismatched types on a record.
2245 *
2246 * @param {String} type
2247 * @param {Object} record
2248 * @param {Object} fields
2249 * @param {Object} meta
2250 * @return {Object}
2251 */
2252module.exports = function enforce (type, record, fields, meta) {
2253 var i, j, key, value, fieldDefinition, language
2254
2255 if (!meta) meta = {}
2256 language = meta.language
2257
2258 for (key in record) {
2259 fieldDefinition = fields[key]
2260
2261 if (!fieldDefinition) {
2262 if (key !== primaryKey) delete record[key]
2263 continue
2264 }
2265
2266 value = record[key]
2267
2268 if (fieldDefinition[typeKey]) {
2269 if (fieldDefinition[isArrayKey]) {
2270 // If the field is defined as an array but the value is not,
2271 // then throw an error.
2272 if (!Array.isArray(value))
2273 throw new BadRequestError(message('EnforceArrayType', language, {
2274 key: key, type: fieldDefinition[typeKey].name
2275 }))
2276
2277 for (i = 0, j = value.length; i < j; i++)
2278 checkValue(fieldDefinition, key, value[i], meta)
2279 }
2280 else checkValue(fieldDefinition, key, value, meta)
2281
2282 continue
2283 }
2284
2285 if (fieldDefinition[linkKey]) {
2286 if (fieldDefinition[isArrayKey]) {
2287 if (!Array.isArray(value))
2288 throw new BadRequestError(
2289 message('EnforceArray', language, { key: key }))
2290
2291 if (type === fieldDefinition[linkKey] &&
2292 find(value, matchId(record[primaryKey])))
2293 throw new BadRequestError(
2294 message('EnforceSameID', language, { key: key }))
2295
2296 continue
2297 }
2298
2299 if (Array.isArray(value))
2300 throw new BadRequestError(
2301 message('EnforceSingular', language, { key: key }))
2302
2303 if (type === fieldDefinition[linkKey] && record[primaryKey] === value)
2304 throw new BadRequestError(
2305 message('EnforceSameID', language, { key: key }))
2306
2307 continue
2308 }
2309 }
2310
2311 return record
2312}
2313
2314
2315function checkValue (field, key, value, meta) {
2316 var language = meta.language
2317 var check
2318 var type = field[typeKey]
2319
2320 // Skip `null` case.
2321 if (value === null) return
2322
2323 check = find(checkInput, function (pair) {
2324 return pair[0] === type
2325 })
2326 if (check) check = check[1]
2327 else check = type
2328
2329 // Fields may be nullable, but if they're defined, then they must be defined
2330 // properly.
2331 if (!check(value)) throw new BadRequestError(
2332 message(field[isArrayKey] ? 'EnforceValueArray' : 'EnforceValue',
2333 language, { key: key, type: type.displayName || type.name }))
2334}
2335
2336
2337function matchId (a) {
2338 return function (b) {
2339 return a === b
2340 }
2341}
2342
2343}).call(this,require("buffer").Buffer)
2344},{"../common/array/find":8,"../common/errors":20,"../common/keys":24,"../common/message":25,"buffer":47}],34:[function(require,module,exports){
2345'use strict'
2346
2347var keys = require('../common/keys')
2348var linkKey = keys.link
2349var inverseKey = keys.inverse
2350var isArrayKey = keys.isArray
2351var denormalizedInverseKey = keys.denormalizedInverse
2352
2353
2354// Generate denormalized inverse field name.
2355var denormalizedPrefix = '__'
2356var denormalizedDelimiter = '_'
2357var denormalizedPostfix = '_inverse'
2358
2359
2360/**
2361 * Analyze the `types` object to see if `link` and `inverse` values are
2362 * valid. Also assign denormalized inverse fields.
2363 *
2364 * @param {Object} types
2365 * @return {Object}
2366 */
2367module.exports = function ensureTypes (types) {
2368 var denormalizedFields = {}
2369 var type, field, definition, linkedFields,
2370 denormalizedField, denormalizedDefinition
2371
2372 for (type in types)
2373 for (field in types[type]) {
2374 definition = types[type][field]
2375
2376 if (!(linkKey in definition)) continue
2377
2378 if (!types.hasOwnProperty(definition[linkKey]))
2379 throw new Error('The value for "' + linkKey + '" on "' + field +
2380 '" in type "' + type +
2381 '" is invalid, the record type does not exist.')
2382
2383 linkedFields = types[definition[linkKey]]
2384
2385 if (inverseKey in definition) {
2386 if (!linkedFields.hasOwnProperty(definition[inverseKey]))
2387 throw new Error('The value for "' + inverseKey + '" on "' + field +
2388 '" in type "' + type + '" is invalid, the field does not exist.')
2389
2390 if (linkedFields[definition[inverseKey]][inverseKey] !== field)
2391 throw new Error('The value for "' + inverseKey + '" on "' + field +
2392 '" in type "' + type +
2393 '" is invalid, the inversely related field must define its ' +
2394 'inverse as "' + field + '".')
2395
2396 if (linkedFields[definition[inverseKey]][linkKey] !== type)
2397 throw new Error('The value for "' + linkKey + '" on "' + field +
2398 '" in type "' + type +
2399 '" is invalid, the inversely related field must define its link ' +
2400 'as "' + type + '".')
2401
2402 continue
2403 }
2404
2405 // Need to assign denormalized inverse. The denormalized inverse field
2406 // is basically an automatically assigned inverse field that should
2407 // not be visible to the client, but exists in the data store.
2408 denormalizedField = denormalizedPrefix + type +
2409 denormalizedDelimiter + field + denormalizedPostfix
2410
2411 denormalizedFields[denormalizedField] = true
2412
2413 Object.defineProperty(definition, inverseKey, {
2414 value: denormalizedField
2415 })
2416
2417 denormalizedDefinition = {}
2418 denormalizedDefinition[linkKey] = type
2419 denormalizedDefinition[inverseKey] = field
2420 denormalizedDefinition[isArrayKey] = true
2421 denormalizedDefinition[denormalizedInverseKey] = true
2422
2423 Object.defineProperty(linkedFields, denormalizedField, {
2424 value: denormalizedDefinition
2425 })
2426 }
2427
2428 return denormalizedFields
2429}
2430
2431},{"../common/keys":24}],35:[function(require,module,exports){
2432(function (Buffer){
2433'use strict'
2434
2435var find = require('../common/array/find')
2436var map = require('../common/array/map')
2437
2438var keys = require('../common/keys')
2439var primaryKey = keys.primary
2440var typeKey = keys.type
2441var linkKey = keys.link
2442var inverseKey = keys.inverse
2443var isArrayKey = keys.isArray
2444
2445var plainObject = {}
2446var nativeTypes = [ String, Number, Boolean, Date, Object, Buffer ]
2447var stringifiedTypes = map(nativeTypes, function (nativeType) {
2448 return nativeType.name.toLowerCase()
2449})
2450
2451
2452/**
2453 * Given a hash of field definitions, validate that the definitions are in the
2454 * correct format.
2455 *
2456 * @param {Object} fields
2457 * @return {Object}
2458 */
2459module.exports = function validate (fields) {
2460 var key
2461
2462 if (typeof fields !== 'object')
2463 throw new TypeError('Type definition must be an object.')
2464
2465 for (key in fields) validateField(fields, key)
2466
2467 return fields
2468}
2469
2470
2471/**
2472 * Parse a field definition.
2473 *
2474 * @param {Object} fields
2475 * @param {String} key
2476 */
2477function validateField (fields, key) {
2478 var value = fields[key] = castShorthand(fields[key])
2479
2480 if (typeof value !== 'object' || value.constructor !== Object)
2481 throw new TypeError('The definition of "' + key + '" must be an object.')
2482
2483 if (key === primaryKey)
2484 throw new Error('Can not define primary key "' + primaryKey + '".')
2485
2486 if (key in plainObject)
2487 throw new Error('Can not define field name "' + key +
2488 '" which is in Object.prototype.')
2489
2490 if (!value[typeKey] && !value[linkKey])
2491 throw new Error('The definition of "' + key + '" must contain either ' +
2492 'the "' + typeKey + '" or "' + linkKey + '" property.')
2493
2494 if (value[typeKey] && value[linkKey])
2495 throw new Error('Can not define both "' + typeKey + '" and "' + linkKey +
2496 '" on "' + key + '".')
2497
2498 if (value[typeKey]) {
2499 if (typeof value[typeKey] === 'string')
2500 value[typeKey] = nativeTypes[
2501 stringifiedTypes.indexOf(value[typeKey].toLowerCase())]
2502
2503 if (typeof value[typeKey] !== 'function')
2504 throw new Error('The "' + typeKey + '" on "' + key +
2505 '" must be a function.')
2506
2507 if (!find(nativeTypes, function (type) {
2508 return type === value[typeKey].prototype.constructor
2509 }))
2510 throw new Error('The "' + typeKey + '" on "' + key + '" must inherit ' +
2511 'from a valid native type.')
2512
2513 if (value[inverseKey])
2514 throw new Error('The field "' + inverseKey + '" may not be defined ' +
2515 'on "' + key + '".')
2516 }
2517
2518 if (value[linkKey]) {
2519 if (typeof value[linkKey] !== 'string')
2520 throw new TypeError('The "' + linkKey + '" on "' + key +
2521 '" must be a string.')
2522
2523 if (value[inverseKey] && typeof value[inverseKey] !== 'string')
2524 throw new TypeError('The "' + inverseKey + '" on "' + key + '" ' +
2525 'must be a string.')
2526 }
2527
2528 if (value[isArrayKey] && typeof value[isArrayKey] !== 'boolean')
2529 throw new TypeError('The key "' + isArrayKey + '" on "' + key + '" ' +
2530 'must be a boolean.')
2531}
2532
2533
2534/**
2535 * Cast shorthand definition to standard definition.
2536 *
2537 * @param {*} value
2538 * @return {Object}
2539 */
2540function castShorthand (value) {
2541 var obj
2542
2543 if (typeof value === 'string') obj = { link: value }
2544 else if (typeof value === 'function') obj = { type: value }
2545 else if (Array.isArray(value)) {
2546 obj = {}
2547
2548 if (value[1]) obj.inverse = value[1]
2549 else obj.isArray = true
2550
2551 // Extract type or link.
2552 if (Array.isArray(value[0])) {
2553 obj.isArray = true
2554 value = value[0][0]
2555 }
2556 else value = value[0]
2557
2558 if (typeof value === 'string') obj.link = value
2559 else if (typeof value === 'function') obj.type = value
2560 }
2561 else return value
2562
2563 return obj
2564}
2565
2566}).call(this,require("buffer").Buffer)
2567},{"../common/array/find":8,"../common/array/map":10,"../common/keys":24,"buffer":47}],36:[function(require,module,exports){
2568'use strict'
2569
2570var message = require('../common/message')
2571var promise = require('../common/promise')
2572var unique = require('../common/array/unique')
2573var map = require('../common/array/map')
2574var includes = require('../common/array/includes')
2575
2576var errors = require('../common/errors')
2577var BadRequestError = errors.BadRequestError
2578
2579var keys = require('../common/keys')
2580var primaryKey = keys.primary
2581var linkKey = keys.link
2582var isArrayKey = keys.isArray
2583var inverseKey = keys.inverse
2584
2585module.exports = checkLinks
2586
2587
2588/**
2589 * Ensure referential integrity by checking if related records exist.
2590 *
2591 * @param {Object} transaction
2592 * @param {Object} record
2593 * @param {Object} fields
2594 * @param {String[]} links - An array of strings indicating which fields are
2595 * links. Need to pass this so that it doesn't get computed each time.
2596 * @param {Object} [meta]
2597 * @return {Promise}
2598 */
2599function checkLinks (transaction, record, fields, links, meta) {
2600 var Promise = promise.Promise
2601 var enforceLinks = this.options.settings.enforceLinks
2602
2603 return Promise.all(map(links, function (field) {
2604 var ids = Array.isArray(record[field]) ? record[field] :
2605 !record.hasOwnProperty(field) || record[field] === null ?
2606 [] : [ record[field] ]
2607 var fieldLink = fields[field][linkKey]
2608 var fieldInverse = fields[field][inverseKey]
2609 var findOptions = { fields: {} }
2610
2611 // Don't need the entire records.
2612 findOptions.fields[fieldInverse] = true
2613
2614 return new Promise(function (resolve, reject) {
2615 if (!ids.length) return resolve()
2616
2617 return transaction.find(fieldLink, ids, findOptions, meta)
2618
2619 .then(function (records) {
2620 var recordIds, i, j
2621
2622 if (enforceLinks) {
2623 recordIds = unique(map(records, function (record) {
2624 return record[primaryKey]
2625 }))
2626
2627 for (i = 0, j = ids.length; i < j; i++)
2628 if (!includes(recordIds, ids[i]))
2629 return reject(new BadRequestError(
2630 message('RelatedRecordNotFound', meta.language,
2631 { field: field })
2632 ))
2633 }
2634
2635 return resolve(records)
2636 })
2637 })
2638 }))
2639
2640 .then(function (partialRecords) {
2641 var object = {}, records, i, j
2642
2643 for (i = 0, j = partialRecords.length; i < j; i++) {
2644 records = partialRecords[i]
2645
2646 if (records) object[links[i]] =
2647 fields[links[i]][isArrayKey] ? records : records[0]
2648 }
2649
2650 return object
2651 })
2652}
2653
2654},{"../common/array/includes":9,"../common/array/map":10,"../common/array/unique":13,"../common/errors":20,"../common/keys":24,"../common/message":25,"../common/promise":28}],37:[function(require,module,exports){
2655'use strict'
2656
2657var validateRecords = require('./validate_records')
2658var checkLinks = require('./check_links')
2659var enforce = require('../record_type/enforce')
2660var message = require('../common/message')
2661var promise = require('../common/promise')
2662var map = require('../common/array/map')
2663
2664var errors = require('../common/errors')
2665var BadRequestError = errors.BadRequestError
2666
2667var updateHelpers = require('./update_helpers')
2668var scrubDenormalizedUpdates = updateHelpers.scrubDenormalizedUpdates
2669var getUpdate = updateHelpers.getUpdate
2670var addId = updateHelpers.addId
2671var removeId = updateHelpers.removeId
2672
2673var constants = require('../common/constants')
2674var changeEvent = constants.change
2675var createMethod = constants.create
2676var updateMethod = constants.update
2677var primaryKey = constants.primary
2678var linkKey = constants.link
2679var inverseKey = constants.inverse
2680var isArrayKey = constants.isArray
2681var denormalizedInverseKey = constants.denormalizedInverse
2682
2683
2684/**
2685 * Extend context so that it includes the parsed records and create them.
2686 * This mutates the response object.
2687 *
2688 * @return {Promise}
2689 */
2690module.exports = function (context) {
2691 var Promise = promise.Promise
2692 var self = this
2693 var denormalizedFields = self.denormalizedFields
2694 var recordTypes = self.recordTypes
2695 var hooks = self.hooks
2696 var updates = {}
2697 var links = []
2698 var recordsLinked = []
2699 var transaction, records, type, meta, hook, fields, language
2700
2701 // Start a promise chain.
2702 return Promise.resolve(context.request.payload)
2703
2704 .then(function (payload) {
2705 var i, j, field
2706
2707 records = payload
2708
2709 if (!records || !records.length)
2710 throw new BadRequestError(
2711 message('CreateRecordsInvalid', language))
2712
2713 type = context.request.type
2714 meta = context.request.meta
2715 transaction = context.transaction
2716 language = meta.language
2717
2718 hook = hooks[type]
2719 fields = recordTypes[type]
2720
2721 for (field in fields) {
2722 if (linkKey in fields[field])
2723 links.push(field)
2724
2725 // Delete denormalized inverse fields.
2726 if (denormalizedInverseKey in fields[field])
2727 for (i = 0, j = records.length; i < j; i++)
2728 delete records[i][field]
2729 }
2730
2731 return typeof hook[0] === 'function' ?
2732 Promise.all(map(records, function (record) {
2733 return hook[0](context, record)
2734 })) : records
2735 })
2736
2737 .then(function (results) {
2738 return Promise.all(map(results, function (record, i) {
2739 if (record && typeof record === 'object') records[i] = record
2740 else record = records[i]
2741
2742 // Enforce the fields.
2743 enforce(type, record, fields, meta)
2744
2745 // Ensure referential integrity.
2746 return checkLinks.call(self, transaction, record, fields, links, meta)
2747 .then(function (linked) {
2748 // The created records should come back in the same order.
2749 recordsLinked.push(linked)
2750 return record
2751 })
2752 }))
2753 })
2754
2755 .then(function () {
2756 validateRecords.call(self, records, fields, links, meta)
2757 return transaction.create(type, records, meta)
2758 })
2759
2760 .then(function (createdRecords) {
2761 var record, field, inverseField, fieldIsArray,
2762 linked, linkedType, linkedIsArray, linkedIds, id,
2763 partialRecord, partialRecords
2764 var i, j, k, l, m, n, o, p
2765
2766 // Update inversely linked records on created records.
2767 // Trying to batch updates to be as few as possible.
2768 var idCache = {}
2769
2770 // Adapter must return something.
2771 if (!createdRecords.length)
2772 throw new BadRequestError(
2773 message('CreateRecordsFail', language))
2774
2775 records = createdRecords
2776
2777 Object.defineProperty(context.response, 'records', {
2778 configurable: true,
2779 value: records
2780 })
2781
2782 // Iterate over each record to generate updates object.
2783 for (i = 0, j = records.length; i < j; i++) {
2784 record = records[i]
2785 linked = recordsLinked[i]
2786
2787 // Each created record must have an ID.
2788 if (!(primaryKey in record))
2789 throw new Error(
2790 message('CreateRecordMissingID', language))
2791
2792 for (k = 0, l = links.length; k < l; k++) {
2793 field = links[k]
2794 inverseField = fields[field][inverseKey]
2795
2796 if (!record.hasOwnProperty(field) || !inverseField) continue
2797
2798 linkedType = fields[field][linkKey]
2799 linkedIsArray =
2800 recordTypes[linkedType][inverseField][isArrayKey]
2801 fieldIsArray = fields[field][isArrayKey]
2802 linkedIds = fieldIsArray ?
2803 record[field] : [ record[field] ]
2804
2805 // Do some initialization.
2806 if (!updates[linkedType]) updates[linkedType] = []
2807 if (!idCache[linkedType]) idCache[linkedType] = {}
2808
2809 for (m = 0, n = linkedIds.length; m < n; m++) {
2810 id = linkedIds[m]
2811
2812 // Set related field.
2813 if (id !== null)
2814 addId(record[primaryKey],
2815 getUpdate(linkedType, id, updates, idCache),
2816 inverseField, linkedIsArray)
2817
2818 // Unset 2nd degree related record for one-to-one case.
2819 if (!fieldIsArray &&
2820 linked[field] &&
2821 linked[field][inverseField] !== null &&
2822 !linkedIsArray &&
2823 linked[field][inverseField] !== record[primaryKey])
2824 removeId(id,
2825 getUpdate(
2826 type, linked[field][inverseField], updates, idCache),
2827 field, linkedIsArray)
2828 }
2829
2830 // Unset from 2nd degree related records for many-to-one case.
2831 if (fieldIsArray &&
2832 linked[field] && !linkedIsArray) {
2833 partialRecords = Array.isArray(linked[field]) ?
2834 linked[field] : [ linked[field] ]
2835
2836 for (o = 0, p = partialRecords.length; o < p; o++) {
2837 partialRecord = partialRecords[o]
2838
2839 if (partialRecord[inverseField] === record[primaryKey])
2840 continue
2841
2842 removeId(partialRecord[primaryKey],
2843 getUpdate(
2844 type, partialRecord[inverseField],
2845 updates, idCache),
2846 field, fieldIsArray)
2847 }
2848 }
2849 }
2850 }
2851
2852 return Promise.all(map(Object.keys(updates), function (type) {
2853 return updates[type].length ?
2854 transaction.update(type, updates[type], meta) :
2855 null
2856 }))
2857 })
2858
2859 .then(function () {
2860 var eventData = {}, currentType
2861
2862 eventData[createMethod] = {}
2863 eventData[createMethod][type] = records
2864
2865 for (currentType in updates) {
2866 scrubDenormalizedUpdates(updates[currentType], denormalizedFields)
2867
2868 if (!updates[currentType].length) continue
2869
2870 if (!(updateMethod in eventData)) eventData[updateMethod] = {}
2871 eventData[updateMethod][currentType] = updates[currentType]
2872 }
2873
2874 // Summarize changes during the lifecycle of the request.
2875 self.emit(changeEvent, eventData)
2876
2877 return context
2878 })
2879}
2880
2881},{"../common/array/map":10,"../common/constants":18,"../common/errors":20,"../common/message":25,"../common/promise":28,"../record_type/enforce":33,"./check_links":36,"./update_helpers":44,"./validate_records":45}],38:[function(require,module,exports){
2882'use strict'
2883
2884var message = require('../common/message')
2885var promise = require('../common/promise')
2886var map = require('../common/array/map')
2887
2888var errors = require('../common/errors')
2889var NotFoundError = errors.NotFoundError
2890
2891var updateHelpers = require('./update_helpers')
2892var scrubDenormalizedUpdates = updateHelpers.scrubDenormalizedUpdates
2893var getUpdate = updateHelpers.getUpdate
2894var removeId = updateHelpers.removeId
2895
2896var constants = require('../common/constants')
2897var changeEvent = constants.change
2898var deleteMethod = constants.delete
2899var updateMethod = constants.update
2900var primaryKey = constants.primary
2901var linkKey = constants.link
2902var inverseKey = constants.inverse
2903var isArrayKey = constants.isArray
2904
2905
2906/**
2907 * Delete records. This does not mutate context.
2908 *
2909 * @return {Promise}
2910 */
2911module.exports = function (context) {
2912 var Promise = promise.Promise
2913 var self = this
2914 var denormalizedFields = self.denormalizedFields
2915 var request = context.request
2916 var type = request.type
2917 var ids = request.ids
2918 var meta = request.meta
2919 var language = meta.language
2920 var recordTypes = self.recordTypes
2921 var hooks = self.hooks
2922 var updates = {}
2923 var fields = recordTypes[type]
2924 var hook = hooks[type]
2925 var links = []
2926 var transaction, field, records
2927
2928 transaction = context.transaction
2929
2930 for (field in fields)
2931 if (linkKey in fields[field]) links.push(field)
2932
2933 if (!ids || !ids.length)
2934 throw new NotFoundError(message('DeleteRecordsMissingID', language))
2935
2936 return transaction.find(type, ids, null, meta)
2937
2938 .then(function (foundRecords) {
2939 records = foundRecords
2940
2941 if (records.length < ids.length)
2942 throw new NotFoundError(message('DeleteRecordsInvalid', language))
2943
2944 Object.defineProperty(context.response, 'records', {
2945 configurable: true,
2946 value: records
2947 })
2948
2949 return typeof hook[0] === 'function' ?
2950 Promise.all(map(records, function (record) {
2951 return hook[0](context, record)
2952 })) : records
2953 })
2954
2955 .then(function () {
2956 return transaction.delete(type, ids, meta)
2957 })
2958
2959 .then(function (count) {
2960 var i, j, k, l, m, n, record, field, id, inverseField,
2961 linkedType, linkedIsArray, linkedIds
2962
2963 // Remove all instances of the deleted IDs in all records.
2964 var idCache = {}
2965
2966 // Sanity check.
2967 if (count < ids.length)
2968 throw new Error(message('DeleteRecordsFail', language))
2969
2970 // Loop over each record to generate updates object.
2971 for (i = 0, j = records.length; i < j; i++) {
2972 record = records[i]
2973 for (k = 0, l = links.length; k < l; k++) {
2974 field = links[k]
2975 inverseField = fields[field][inverseKey]
2976
2977 if (!record.hasOwnProperty(field) || !inverseField) continue
2978
2979 linkedType = fields[field][linkKey]
2980 linkedIsArray = recordTypes[linkedType][inverseField][isArrayKey]
2981 linkedIds = Array.isArray(record[field]) ?
2982 record[field] : [ record[field] ]
2983
2984 // Do some initialization.
2985 if (!updates[linkedType]) updates[linkedType] = []
2986 if (!idCache[linkedType]) idCache[linkedType] = {}
2987
2988 for (m = 0, n = linkedIds.length; m < n; m++) {
2989 id = linkedIds[m]
2990 if (id !== null)
2991 removeId(record[primaryKey],
2992 getUpdate(linkedType, id, updates, idCache),
2993 inverseField, linkedIsArray)
2994 }
2995 }
2996 }
2997
2998 return Promise.all(map(Object.keys(updates), function (type) {
2999 return updates[type].length ?
3000 transaction.update(type, updates[type], meta) :
3001 null
3002 }))
3003 })
3004
3005 .then(function () {
3006 var eventData = {}, currentType
3007
3008 eventData[deleteMethod] = {}
3009 eventData[deleteMethod][type] = ids
3010
3011 for (currentType in updates) {
3012 scrubDenormalizedUpdates(updates[currentType], denormalizedFields)
3013
3014 if (!updates[currentType].length) continue
3015
3016 if (!(updateMethod in eventData)) eventData[updateMethod] = {}
3017 eventData[updateMethod][currentType] = updates[currentType]
3018 }
3019
3020 // Summarize changes during the lifecycle of the request.
3021 self.emit(changeEvent, eventData)
3022
3023 return context
3024 })
3025}
3026
3027},{"../common/array/map":10,"../common/constants":18,"../common/errors":20,"../common/message":25,"../common/promise":28,"./update_helpers":44}],39:[function(require,module,exports){
3028'use strict'
3029
3030var map = require('../common/array/map')
3031var promise = require('../common/promise')
3032
3033
3034/**
3035 * Apply `output` hook per record, this mutates `context.response`.
3036 *
3037 * @return {Promise}
3038 */
3039module.exports = function (context) {
3040 var Promise = promise.Promise
3041 var hooks = this.hooks
3042 var request = context.request
3043 var response = context.response
3044 var type = request.type
3045 var hook = hooks[type]
3046 var records = response.records
3047 var include = response.include
3048
3049 // Run hooks on primary type.
3050 return (records ? Promise.all(map(records, function (record) {
3051 return Promise.resolve(typeof hook[1] === 'function' ?
3052 hook[1](context, record) : record)
3053 }))
3054
3055 .then(function (updatedRecords) {
3056 var includeTypes
3057 var i, j
3058
3059 for (i = 0, j = updatedRecords.length; i < j; i++)
3060 if (updatedRecords[i]) records[i] = updatedRecords[i]
3061
3062 if (!include) return void 0
3063
3064 // The order of the keys and their corresponding indices matter.
3065 includeTypes = Object.keys(include)
3066
3067 // Run output hooks per include type.
3068 return Promise.all(map(includeTypes, function (includeType) {
3069 // This is useful for output hooks to know which type that the current
3070 // record belongs to. It is temporary and gets deleted later.
3071 request.includeType = includeType
3072
3073 return Promise.all(map(include[includeType], function (record) {
3074 return Promise.resolve(
3075 typeof hooks[includeType][1] === 'function' ?
3076 hooks[includeType][1](context, record) : record)
3077 }))
3078 }))
3079
3080 .then(function (types) {
3081 var i, j, k, l
3082
3083 // Don't need this anymore.
3084 delete request.includeType
3085
3086 // Assign results of output hooks on includes.
3087 for (i = 0, j = types.length; i < j; i++)
3088 for (k = 0, l = types[i].length; k < l; k++)
3089 if (types[i][k]) include[includeTypes[i]][k] = types[i][k]
3090 })
3091 }) : Promise.resolve())
3092
3093 .then(function () {
3094 // Delete temporary keys, these should not be serialized.
3095 delete response.records
3096 delete response.include
3097
3098 context.response.payload = {
3099 records: records
3100 }
3101
3102 if (include) context.response.payload.include = include
3103
3104 // Expose the "count" property so that it is serializable.
3105 if (records && 'count' in records)
3106 context.response.payload.count = records.count
3107
3108 return context
3109 })
3110}
3111
3112},{"../common/array/map":10,"../common/promise":28}],40:[function(require,module,exports){
3113'use strict'
3114
3115/**
3116 * Fetch the primary records. This mutates `context.response`
3117 * for the next method.
3118 *
3119 * @return {Promise}
3120 */
3121module.exports = function (context) {
3122 var transaction = context.transaction
3123 var request = context.request
3124 var type = request.type
3125 var ids = request.ids
3126 var options = request.options
3127 var meta = request.meta
3128
3129 if (!type) return context
3130
3131 return transaction.find(type, ids, options, meta)
3132 .then(function (records) {
3133 Object.defineProperty(context.response, 'records', {
3134 configurable: true,
3135 value: records
3136 })
3137
3138 return context
3139 })
3140}
3141
3142},{}],41:[function(require,module,exports){
3143'use strict'
3144
3145var promise = require('../common/promise')
3146var map = require('../common/array/map')
3147var find = require('../common/array/find')
3148var reduce = require('../common/array/reduce')
3149var message = require('../common/message')
3150
3151var errors = require('../common/errors')
3152var BadRequestError = errors.BadRequestError
3153
3154var keys = require('../common/keys')
3155var primaryKey = keys.primary
3156var linkKey = keys.link
3157
3158
3159/**
3160 * Fetch included records. This mutates `context.response`
3161 * for the next method.
3162 *
3163 * @return {Promise}
3164 */
3165module.exports = function include (context) {
3166 var Promise = promise.Promise
3167 var request = context.request
3168 var type = request.type
3169 var ids = request.ids || []
3170 var include = request.include
3171 var meta = request.meta
3172 var language = meta.language
3173 var response = context.response
3174 var transaction = context.transaction
3175 var records = response.records
3176 var recordTypes = this.recordTypes
3177 var hasField = true
3178 var idCache = {}
3179 var i, j, record, id
3180
3181 // Skip if there's nothing to be done.
3182 if (!type || !include || !records) return context
3183
3184 // This cache is used to keep unique IDs per type.
3185 idCache[type] = {}
3186 for (i = 0, j = ids.length; i < j; i++)
3187 idCache[type][ids[i]] = true
3188
3189 // It's necessary to iterate over primary records if no IDs were
3190 // provided initially.
3191 if (!ids.length)
3192 for (i = 0, j = records.length; i < j; i++) {
3193 record = records[i]
3194 id = record[primaryKey]
3195 if (!idCache[type][id]) idCache[type][id] = true
3196 }
3197
3198 // Cast `include` into an array if it's using shorthand.
3199 if (include.length && !Array.isArray(include[0]))
3200 include = [ include ]
3201
3202 return Promise.all(map(include, function (fields) {
3203 return new Promise(function (resolve, reject) {
3204 var currentType = type
3205 var includeOptions = []
3206 var currentCache, currentIds, currentOptions, currentField
3207 var i, j, ensureFields
3208
3209 // Cast `fields` into an array if it's using shorthand.
3210 if (!Array.isArray(fields) ||
3211 (!Array.isArray(fields[1]) && typeof fields[1] === 'object'))
3212 fields = [ fields ]
3213
3214 for (i = 0, j = fields.length; i < j; i++)
3215 if (Array.isArray(fields[i])) {
3216 includeOptions[i] = fields[i][1]
3217 fields[i] = fields[i][0]
3218 }
3219
3220 // Check if first level field in in each record.
3221 for (i = 0, j = records.length; i < j; i++)
3222 if (!(fields[0] in records[i])) {
3223 hasField = false
3224 break
3225 }
3226
3227 // Ensure that the first level field is in each record.
3228 if (hasField)
3229 ensureFields = Promise.resolve(records)
3230 else {
3231 currentOptions = { fields: {} }
3232 currentOptions.fields[fields[0]] = true
3233 currentIds = []
3234 for (i = 0, j = records.length; i < j; i++)
3235 currentIds.push(records[i][primaryKey])
3236 ensureFields = transaction.find(
3237 type, currentIds, currentOptions, meta)
3238 }
3239
3240 return ensureFields
3241 .then(function (records) {
3242 return reduce(fields, function (records, field, index) {
3243 // `cursor` refers to the current collection of records.
3244 return records.then(function (cursor) {
3245 currentField = recordTypes[currentType][field]
3246
3247 if (!currentType || !currentField) return []
3248 if (!(linkKey in currentField))
3249 throw new BadRequestError(
3250 message('InvalidLink', language, { field: field }))
3251
3252 currentCache = {}
3253 currentType = currentField[linkKey]
3254 currentIds = reduce(cursor, function (ids, record) {
3255 var linkedIds = Array.isArray(record[field]) ?
3256 record[field] : [ record[field] ]
3257 var i, j, id
3258
3259 for (i = 0, j = linkedIds.length; i < j; i++) {
3260 id = linkedIds[i]
3261 if (id && !currentCache[id]) {
3262 currentCache[id] = true
3263 ids.push(id)
3264 }
3265 }
3266
3267 return ids
3268 }, [])
3269
3270 if (index in includeOptions)
3271 currentOptions = includeOptions[index]
3272 else if (index < fields.length - 1) {
3273 currentOptions = { fields: {} }
3274 currentOptions.fields[fields[index + 1]] = true
3275 }
3276 else currentOptions = null
3277
3278 return currentIds.length ?
3279 transaction.find(
3280 currentType, currentIds, currentOptions, meta) :
3281 []
3282 })
3283 }, Promise.resolve(records))
3284 })
3285
3286 .then(function (records) {
3287 return resolve({
3288 type: currentType,
3289 ids: currentIds,
3290 records: records
3291 })
3292 }, function (error) {
3293 return reject(error)
3294 })
3295 })
3296 }))
3297
3298 .then(function (containers) {
3299 var include = reduce(containers, function (include, container) {
3300 var i, j, id, record
3301
3302 if (!container.ids.length) return include
3303
3304 if (!include[container.type])
3305 include[container.type] = []
3306
3307 // Only include unique IDs per type.
3308 if (!idCache[container.type])
3309 idCache[container.type] = {}
3310
3311 for (i = 0, j = container.ids.length; i < j; i++) {
3312 id = container.ids[i]
3313
3314 if (idCache[container.type][id]) continue
3315
3316 record = find(container.records, matchId(id))
3317
3318 if (record) {
3319 idCache[container.type][id] = true
3320 include[container.type].push(record)
3321 }
3322 }
3323
3324 // If nothing so far, delete the type from include.
3325 if (!include[container.type].length)
3326 delete include[container.type]
3327
3328 return include
3329 }, {})
3330
3331 if (Object.keys(include).length)
3332 Object.defineProperty(context.response, 'include', {
3333 configurable: true,
3334 value: include
3335 })
3336
3337 return context
3338 })
3339}
3340
3341
3342function matchId (id) {
3343 return function (record) {
3344 return record[primaryKey] === id
3345 }
3346}
3347
3348},{"../common/array/find":8,"../common/array/map":10,"../common/array/reduce":12,"../common/errors":20,"../common/keys":24,"../common/message":25,"../common/promise":28}],42:[function(require,module,exports){
3349'use strict'
3350
3351var promise = require('../common/promise')
3352var assign = require('../common/assign')
3353var unique = require('../common/array/unique')
3354var message = require('../common/message')
3355
3356var responseClass = require('../common/response_classes')
3357var BadRequestError = responseClass.BadRequestError
3358var NotFoundError = responseClass.NotFoundError
3359var MethodError = responseClass.MethodError
3360var OK = responseClass.OK
3361var Empty = responseClass.Empty
3362var Created = responseClass.Created
3363
3364var methods = require('../common/methods')
3365var findMethod = methods.find
3366var createMethod = methods.create
3367
3368
3369/*!
3370 * Internal function to send a request. Must be called in the context of
3371 * the Fortune instance.
3372 *
3373 * @param {Object} options
3374 * @return {Promise}
3375 */
3376function internalRequest (options) {
3377 var Promise = promise.Promise
3378 var flows = this.flows
3379 var recordTypes = this.recordTypes
3380 var adapter = this.adapter
3381
3382 var context = setDefaults(options)
3383 var method = context.request.method
3384 var hasTransaction = 'transaction' in options
3385
3386 // Start a promise chain.
3387 return Promise.resolve(context)
3388
3389 .then(function (context) {
3390 var type = context.request.type
3391 var ids = context.request.ids
3392 var language = context.request.meta.language
3393 var error
3394
3395 // Make sure that IDs are an array of unique values.
3396 if (ids) context.request.ids = unique(ids)
3397
3398 // If a type is unspecified, block the request.
3399 if (type === null) {
3400 error = new BadRequestError(message('UnspecifiedType', language))
3401 error.isTypeUnspecified = true
3402 throw error
3403 }
3404
3405 // If a type is specified and it doesn't exist, block the request.
3406 if (!recordTypes.hasOwnProperty(type))
3407 throw new NotFoundError(
3408 message('InvalidType', language, { type: type }))
3409
3410 // Block invalid method.
3411 if (!(method in flows))
3412 throw new MethodError(
3413 message('InvalidMethod', language, { method: method }))
3414
3415 return hasTransaction ?
3416 Promise.resolve(options.transaction) :
3417 adapter.beginTransaction()
3418 })
3419
3420 .then(function (transaction) {
3421 var chain, flow, i, j
3422
3423 context.transaction = transaction
3424 chain = Promise.resolve(context)
3425 flow = flows[method]
3426
3427 for (i = 0, j = flow.length; i < j; i++)
3428 chain = chain.then(flow[i])
3429
3430 return chain
3431 })
3432
3433 .then(function (context) {
3434 return hasTransaction ?
3435 Promise.resolve() : context.transaction.endTransaction()
3436 .then(function () {
3437 var method = context.request.method
3438 var response = context.response
3439 var payload = response.payload
3440
3441 if (!payload) return new Empty(response)
3442 if (method === createMethod) return new Created(response)
3443
3444 return new OK(response)
3445 })
3446 })
3447
3448 // This makes sure to call `endTransaction` before re-throwing the error.
3449 .catch(function (error) {
3450 return 'transaction' in context && !hasTransaction ?
3451 context.transaction.endTransaction(error)
3452 .then(throwError, throwError) :
3453 throwError()
3454
3455 function throwError () {
3456 throw assign(error, context.response)
3457 }
3458 })
3459}
3460
3461
3462// Re-exporting internal middlewares.
3463internalRequest.middlewares = {
3464 create: require('./create'),
3465 'delete': require('./delete'),
3466 update: require('./update'),
3467 find: require('./find'),
3468 include: require('./include'),
3469 end: require('./end')
3470}
3471
3472
3473/*!
3474 * Set default options on a context's request. For internal use.
3475 *
3476 * @param {Object} [options]
3477 * @return {Object}
3478 */
3479function setDefaults (options) {
3480 var context = {
3481 request: {
3482 method: findMethod,
3483 type: null,
3484 ids: null,
3485 options: {},
3486 include: [],
3487 meta: {},
3488 payload: null
3489 },
3490 response: {
3491 meta: {},
3492 payload: null
3493 }
3494 }
3495
3496 assign(context.request, options)
3497
3498 return context
3499}
3500
3501
3502module.exports = internalRequest
3503
3504},{"../common/array/unique":13,"../common/assign":14,"../common/message":25,"../common/methods":27,"../common/promise":28,"../common/response_classes":29,"./create":37,"./delete":38,"./end":39,"./find":40,"./include":41,"./update":43}],43:[function(require,module,exports){
3505'use strict'
3506
3507var deepEqual = require('../common/deep_equal')
3508var promise = require('../common/promise')
3509var assign = require('../common/assign')
3510var clone = require('../common/clone')
3511var validateRecords = require('./validate_records')
3512var checkLinks = require('./check_links')
3513var enforce = require('../record_type/enforce')
3514var message = require('../common/message')
3515var applyUpdate = require('../common/apply_update')
3516
3517var updateHelpers = require('./update_helpers')
3518var scrubDenormalizedUpdates = updateHelpers.scrubDenormalizedUpdates
3519var getUpdate = updateHelpers.getUpdate
3520var addId = updateHelpers.addId
3521var removeId = updateHelpers.removeId
3522
3523var errors = require('../common/errors')
3524var NotFoundError = errors.NotFoundError
3525var BadRequestError = errors.BadRequestError
3526
3527var find = require('../common/array/find')
3528var includes = require('../common/array/includes')
3529var map = require('../common/array/map')
3530
3531var constants = require('../common/constants')
3532var changeEvent = constants.change
3533var updateMethod = constants.update
3534var primaryKey = constants.primary
3535var linkKey = constants.link
3536var inverseKey = constants.inverse
3537var isArrayKey = constants.isArray
3538var denormalizedInverseKey = constants.denormalizedInverse
3539var updateRecordKey = constants.updateRecord
3540var linkedHashKey = constants.linkedHash
3541
3542
3543/**
3544 * Do updates. First, it must find the records to update, then run hooks
3545 * and validation, then apply the update as well as links on related records.
3546 *
3547 * @return {Promise}
3548 */
3549module.exports = function (context) {
3550 var Promise = promise.Promise
3551 var self = this
3552 var denormalizedFields = self.denormalizedFields
3553 var adapter = self.adapter
3554 var recordTypes = self.recordTypes
3555 var hooks = self.hooks
3556
3557 var relatedUpdates = {}
3558 var hookedUpdates = []
3559
3560 var links = []
3561 var transaction, updates, fields, hook, type, meta, language
3562
3563 // Start a promise chain.
3564 return Promise.resolve(context.request.payload)
3565
3566 .then(function (payload) {
3567 var i, j, update, field
3568
3569 updates = payload
3570 validateUpdates(updates, context.request.meta)
3571
3572 type = context.request.type
3573 meta = context.request.meta
3574 transaction = context.transaction
3575 language = meta.language
3576
3577 fields = recordTypes[type]
3578 hook = hooks[type]
3579
3580 // Delete denormalized inverse fields, can't be updated.
3581 for (field in fields) {
3582 if (linkKey in fields[field]) links.push(field)
3583 if (denormalizedInverseKey in fields[field])
3584 for (i = 0, j = updates.length; i < j; i++) {
3585 update = updates[i]
3586 if (update.replace) delete update.replace[field]
3587 if (update.pull) delete update.pull[field]
3588 if (update.push) delete update.push[field]
3589 }
3590 }
3591
3592 return transaction.find(type, map(updates, function (update) {
3593 return update[primaryKey]
3594 }), null, meta)
3595 })
3596
3597 .then(function (records) {
3598 if (records.length < updates.length)
3599 throw new NotFoundError(message('UpdateRecordMissing', language))
3600
3601 return Promise.all(map(records, function (record) {
3602 var update, cloneUpdate
3603 var hasHook = typeof hook[0] === 'function'
3604 var id = record[primaryKey]
3605
3606 update = find(updates, function (update) {
3607 return update[primaryKey] === id
3608 })
3609
3610 if (!update) throw new NotFoundError(
3611 message('UpdateRecordMissing', language))
3612
3613 if (hasHook) cloneUpdate = clone(update)
3614
3615 return Promise.resolve(hasHook ?
3616 hook[0](context, record, update) : update)
3617 .then(function (result) {
3618 if (result && typeof result === 'object') update = result
3619
3620 if (hasHook) {
3621 // Check if the update has been modified or not.
3622 if (!deepEqual(update, cloneUpdate))
3623 context.response.meta.updateModified = true
3624
3625 // Runtime safety check: primary key must be the same.
3626 if (update[primaryKey] !== id) throw new BadRequestError(
3627 message('InvalidID', language))
3628 }
3629
3630 hookedUpdates.push(update)
3631 Object.defineProperty(update, updateRecordKey, { value: record })
3632
3633 // Shallow clone the record.
3634 record = assign({}, record)
3635
3636 // Apply updates to record.
3637 applyUpdate(record, update)
3638
3639 // Apply operators to record.
3640 if (update.operate)
3641 record = adapter.applyOperators(record, update.operate)
3642
3643 // Enforce the fields.
3644 enforce(type, record, fields, meta)
3645
3646 // Ensure referential integrity.
3647 return checkLinks.call(
3648 self, transaction, record, fields, links, meta)
3649 .then(function (linked) {
3650 Object.defineProperty(update, linkedHashKey, { value: linked })
3651 return record
3652 })
3653 })
3654 }))
3655 })
3656
3657 .then(function (records) {
3658 var i, j
3659
3660 validateRecords.call(self, records, fields, links, meta)
3661
3662 Object.defineProperty(context.response, 'records', {
3663 configurable: true,
3664 value: records
3665 })
3666
3667 // Drop fields in the updates that aren't defined in the record type
3668 // before doing the update.
3669 for (i = 0, j = hookedUpdates.length; i < j; i++)
3670 dropFields(hookedUpdates[i], fields)
3671
3672 return transaction.update(type, hookedUpdates, meta)
3673 })
3674
3675 .then(function () {
3676 var inverseField, isArray, linkedType, linkedIsArray, linked, record,
3677 partialRecord, partialRecords, ids, id, push, pull, update, field
3678 var i, j, k, l, m, n
3679
3680 // Build up related updates based on update objects.
3681 var idCache = {}
3682
3683 // Iterate over each update to generate related updates.
3684 for (i = 0, j = hookedUpdates.length; i < j; i++) {
3685 update = hookedUpdates[i]
3686
3687 for (k = 0, l = links.length; k < l; k++) {
3688 field = links[k]
3689 inverseField = fields[field][inverseKey]
3690
3691 if (!inverseField) continue
3692
3693 isArray = fields[field][isArrayKey]
3694 linkedType = fields[field][linkKey]
3695 linkedIsArray =
3696 recordTypes[linkedType][inverseField][isArrayKey]
3697
3698 // Do some initialization.
3699 if (!relatedUpdates[linkedType]) relatedUpdates[linkedType] = []
3700 if (!idCache[linkedType]) idCache[linkedType] = {}
3701
3702 record = update[updateRecordKey]
3703 linked = update[linkedHashKey]
3704
3705 // Replacing a link field is pretty complicated.
3706 if (update.replace && update.replace.hasOwnProperty(field)) {
3707 id = update.replace[field]
3708
3709 if (!Array.isArray(id)) {
3710 // Don't need to worry about inverse updates if the value does not
3711 // change.
3712 if (id === record[field]) continue
3713
3714 // Set related field.
3715 if (id !== null)
3716 addId(update[primaryKey],
3717 getUpdate(linkedType, id, relatedUpdates, idCache),
3718 inverseField, linkedIsArray)
3719
3720 // Unset 2nd degree related record.
3721 if (linked[field] &&
3722 linked[field][inverseField] !== null &&
3723 !linkedIsArray &&
3724 linked[field][inverseField] !== update[primaryKey])
3725 removeId(id,
3726 getUpdate(
3727 type, linked[field][inverseField],
3728 relatedUpdates, idCache),
3729 field, linkedIsArray)
3730
3731 // For unsetting, remove ID from related record.
3732 if (record[field] !== null &&
3733 record[field] !== update[field] &&
3734 record[field] !== id)
3735 removeId(update[primaryKey],
3736 getUpdate(
3737 linkedType, record[field], relatedUpdates, idCache),
3738 inverseField, linkedIsArray)
3739
3740 // After this point, there's no need to go over push/pull.
3741 continue
3742 }
3743
3744 ids = id
3745
3746 // Compute differences for pull, and mutate the update.
3747 for (m = 0, n = record[field].length; m < n; m++) {
3748 id = record[field][m]
3749 if (!includes(ids, id)) {
3750 if (!('pull' in update)) update.pull = {}
3751 if (update.pull.hasOwnProperty(field)) {
3752 if (Array.isArray(update.pull[field])) {
3753 update.pull[field].push(id)
3754 continue
3755 }
3756 update.pull[field] = [ update.pull[field], id ]
3757 continue
3758 }
3759 update.pull[field] = [ id ]
3760 }
3761 }
3762
3763 // Compute differences for push, and mutate the update.
3764 for (m = 0, n = ids.length; m < n; m++) {
3765 id = ids[m]
3766 if (!includes(record[field], id)) {
3767 if (!('push' in update)) update.push = {}
3768 if (update.push.hasOwnProperty(field)) {
3769 if (Array.isArray(update.push[field])) {
3770 update.push[field].push(id)
3771 continue
3772 }
3773 update.push[field] = [ update.push[field], id ]
3774 continue
3775 }
3776 update.push[field] = [ id ]
3777 }
3778 }
3779
3780 // Delete the original replace, since it is no longer valid.
3781 delete update.replace[field]
3782 }
3783
3784 if (update.pull && update.pull[field]) {
3785 pull = Array.isArray(update.pull[field]) ?
3786 update.pull[field] : [ update.pull[field] ]
3787
3788 for (m = 0, n = pull.length; m < n; m++) {
3789 id = pull[m]
3790 if (id !== null)
3791 removeId(update[primaryKey],
3792 getUpdate(linkedType, id, relatedUpdates, idCache),
3793 inverseField, linkedIsArray)
3794 }
3795 }
3796
3797 if (update.push && update.push[field]) {
3798 push = Array.isArray(update.push[field]) ?
3799 update.push[field] : [ update.push[field] ]
3800
3801 for (m = 0, n = push.length; m < n; m++) {
3802 id = push[m]
3803 if (id !== null)
3804 addId(update[primaryKey],
3805 getUpdate(linkedType, id, relatedUpdates, idCache),
3806 inverseField, linkedIsArray)
3807 }
3808 }
3809
3810 // Unset from 2nd degree related records.
3811 if (linked[field] && !linkedIsArray) {
3812 partialRecords = Array.isArray(linked[field]) ?
3813 linked[field] : [ linked[field] ]
3814
3815 for (m = 0, n = partialRecords.length; m < n; m++) {
3816 partialRecord = partialRecords[m]
3817
3818 if (partialRecord[inverseField] === update[primaryKey])
3819 continue
3820
3821 removeId(partialRecord[primaryKey],
3822 getUpdate(
3823 type, partialRecord[inverseField],
3824 relatedUpdates, idCache),
3825 field, isArray)
3826 }
3827 }
3828 }
3829 }
3830
3831 return Promise.all(map(Object.keys(relatedUpdates), function (type) {
3832 return relatedUpdates[type].length ?
3833 transaction.update(type, relatedUpdates[type], meta) :
3834 null
3835 }))
3836 })
3837
3838 .then(function () {
3839 var eventData = {}, linkedType
3840
3841 eventData[updateMethod] = {}
3842 eventData[updateMethod][type] = hookedUpdates
3843
3844 for (linkedType in relatedUpdates) {
3845 scrubDenormalizedUpdates(
3846 relatedUpdates[linkedType], denormalizedFields)
3847
3848 if (!relatedUpdates[linkedType].length) continue
3849
3850 if (linkedType !== type)
3851 eventData[updateMethod][linkedType] = relatedUpdates[linkedType]
3852
3853 // Get the union of update IDs.
3854 else eventData[updateMethod][type] =
3855 eventData[updateMethod][type].concat(relatedUpdates[type])
3856 }
3857
3858 // Summarize changes during the lifecycle of the request.
3859 self.emit(changeEvent, eventData)
3860
3861 return context
3862 })
3863}
3864
3865
3866// Validate updates.
3867function validateUpdates (updates, meta) {
3868 var language = meta.language
3869 var i, j, update
3870
3871 if (!updates || !updates.length)
3872 throw new BadRequestError(
3873 message('UpdateRecordsInvalid', language))
3874
3875 for (i = 0, j = updates.length; i < j; i++) {
3876 update = updates[i]
3877 if (!update[primaryKey])
3878 throw new BadRequestError(
3879 message('UpdateRecordMissingID', language))
3880 }
3881}
3882
3883
3884function dropFields (update, fields) {
3885 var field
3886
3887 for (field in update.replace)
3888 if (!fields.hasOwnProperty(field)) delete update.replace[field]
3889
3890 for (field in update.pull)
3891 if (!fields.hasOwnProperty(field)) delete update.pull[field]
3892
3893 for (field in update.push)
3894 if (!fields.hasOwnProperty(field)) delete update.push[field]
3895}
3896
3897},{"../common/apply_update":6,"../common/array/find":8,"../common/array/includes":9,"../common/array/map":10,"../common/assign":14,"../common/clone":17,"../common/constants":18,"../common/deep_equal":19,"../common/errors":20,"../common/message":25,"../common/promise":28,"../record_type/enforce":33,"./check_links":36,"./update_helpers":44,"./validate_records":45}],44:[function(require,module,exports){
3898'use strict'
3899
3900var find = require('../common/array/find')
3901
3902var keys = require('../common/keys')
3903var primaryKey = keys.primary
3904
3905
3906// Get a related update object by ID, or return a new one if not found.
3907exports.getUpdate = function (type, id, updates, cache) {
3908 var update
3909
3910 if (cache[type] && cache[type][id])
3911 return find(updates[type],
3912 function (update) {
3913 return update[primaryKey] === id
3914 })
3915
3916 update = { id: id }
3917 if (!updates[type]) updates[type] = []
3918 updates[type].push(update)
3919 cache[type] = {}
3920 cache[type][id] = true
3921 return update
3922}
3923
3924
3925// Add an ID to an update object.
3926exports.addId = function (id, update, field, isArray) {
3927 if (isArray) {
3928 if (!update.push) update.push = {}
3929 if (!update.push[field]) update.push[field] = []
3930 update.push[field].push(id)
3931 return
3932 }
3933
3934 if (!update.replace) update.replace = {}
3935 update.replace[field] = id
3936}
3937
3938
3939// Remove an ID from an update object.
3940exports.removeId = function (id, update, field, isArray) {
3941 if (isArray) {
3942 if (!update.pull) update.pull = {}
3943 if (!update.pull[field]) update.pull[field] = []
3944 update.pull[field].push(id)
3945 return
3946 }
3947
3948 if (!update.replace) update.replace = {}
3949 update.replace[field] = null
3950}
3951
3952
3953// Remove denormalized fields from appearing in updates on change events.
3954exports.scrubDenormalizedUpdates = function (updates, denormalizedFields) {
3955 var i, update, operation, field
3956
3957 // Iterate in reverse, so we can easily remove indices in the array.
3958 for (i = updates.length; i--;) {
3959 update = updates[i]
3960
3961 for (operation in update) {
3962 if (operation === primaryKey) continue
3963
3964 for (field in update[operation])
3965 if (field in denormalizedFields)
3966 delete update[operation][field]
3967
3968 if (!Object.keys(update[operation]).length)
3969 delete update[operation]
3970 }
3971
3972 // If only the primary key is present, then remove the entire update.
3973 if (Object.keys(update).length === 1) updates.splice(i, 1)
3974 }
3975}
3976
3977},{"../common/array/find":8,"../common/keys":24}],45:[function(require,module,exports){
3978'use strict'
3979
3980var message = require('../common/message')
3981
3982var errors = require('../common/errors')
3983var ConflictError = errors.ConflictError
3984
3985var keys = require('../common/keys')
3986var linkKey = keys.link
3987var isArrayKey = keys.isArray
3988var inverseKey = keys.inverse
3989
3990/**
3991 * Do some validation on records to be created or updated to determine
3992 * if there are any records which have overlapping to-one relationships,
3993 * or non-unique array relationships.
3994 *
3995 * @param {Object[]} records
3996 * @param {Object} fields
3997 * @param {Object} links
3998 * @param {Object} meta
3999 */
4000module.exports = function validateRecords (records, fields, links, meta) {
4001 var recordTypes = this.recordTypes
4002 var language = meta.language
4003 var toOneMap = {}
4004 var i, j, k, l, m, n, value, field, record, id, ids, seen,
4005 fieldLink, fieldInverse, fieldIsArray, inverseIsArray
4006
4007 for (i = 0, j = links.length; i < j; i++) {
4008 field = links[i]
4009 fieldLink = fields[field][linkKey]
4010 fieldInverse = fields[field][inverseKey]
4011 fieldIsArray = fields[field][isArrayKey]
4012 inverseIsArray = recordTypes[fieldLink][fieldInverse][isArrayKey]
4013
4014 if (fieldIsArray)
4015 for (k = 0, l = records.length; k < l; k++) {
4016 record = records[k]
4017 if (!Array.isArray(record[field])) continue
4018 ids = record[field]
4019 seen = {}
4020
4021 for (m = 0, n = ids.length; m < n; m++) {
4022 id = ids[m]
4023 if (seen.hasOwnProperty(id)) throw new ConflictError(
4024 message('CollisionDuplicate', language, { id: id, field: field }))
4025 else seen[id] = true
4026 }
4027 }
4028
4029 if (!inverseIsArray) {
4030 toOneMap[field] = {}
4031
4032 for (k = 0, l = records.length; k < l; k++) {
4033 record = records[k]
4034 value = record[field]
4035 ids = Array.isArray(value) ? value : value ? [ value ] : []
4036
4037 for (m = 0, n = ids.length; m < n; m++) {
4038 id = ids[m]
4039 if (!toOneMap[field].hasOwnProperty(id)) toOneMap[field][id] = true
4040 else throw new ConflictError(
4041 message('CollisionToOne', language, { field: field }))
4042 }
4043 }
4044 }
4045 }
4046}
4047
4048},{"../common/errors":20,"../common/keys":24,"../common/message":25}],46:[function(require,module,exports){
4049'use strict'
4050
4051exports.byteLength = byteLength
4052exports.toByteArray = toByteArray
4053exports.fromByteArray = fromByteArray
4054
4055var lookup = []
4056var revLookup = []
4057var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
4058
4059var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
4060for (var i = 0, len = code.length; i < len; ++i) {
4061 lookup[i] = code[i]
4062 revLookup[code.charCodeAt(i)] = i
4063}
4064
4065// Support decoding URL-safe base64 strings, as Node.js does.
4066// See: https://en.wikipedia.org/wiki/Base64#URL_applications
4067revLookup['-'.charCodeAt(0)] = 62
4068revLookup['_'.charCodeAt(0)] = 63
4069
4070function getLens (b64) {
4071 var len = b64.length
4072
4073 if (len % 4 > 0) {
4074 throw new Error('Invalid string. Length must be a multiple of 4')
4075 }
4076
4077 // Trim off extra bytes after placeholder bytes are found
4078 // See: https://github.com/beatgammit/base64-js/issues/42
4079 var validLen = b64.indexOf('=')
4080 if (validLen === -1) validLen = len
4081
4082 var placeHoldersLen = validLen === len
4083 ? 0
4084 : 4 - (validLen % 4)
4085
4086 return [validLen, placeHoldersLen]
4087}
4088
4089// base64 is 4/3 + up to two characters of the original data
4090function byteLength (b64) {
4091 var lens = getLens(b64)
4092 var validLen = lens[0]
4093 var placeHoldersLen = lens[1]
4094 return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
4095}
4096
4097function _byteLength (b64, validLen, placeHoldersLen) {
4098 return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
4099}
4100
4101function toByteArray (b64) {
4102 var tmp
4103 var lens = getLens(b64)
4104 var validLen = lens[0]
4105 var placeHoldersLen = lens[1]
4106
4107 var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
4108
4109 var curByte = 0
4110
4111 // if there are placeholders, only get up to the last complete 4 chars
4112 var len = placeHoldersLen > 0
4113 ? validLen - 4
4114 : validLen
4115
4116 for (var i = 0; i < len; i += 4) {
4117 tmp =
4118 (revLookup[b64.charCodeAt(i)] << 18) |
4119 (revLookup[b64.charCodeAt(i + 1)] << 12) |
4120 (revLookup[b64.charCodeAt(i + 2)] << 6) |
4121 revLookup[b64.charCodeAt(i + 3)]
4122 arr[curByte++] = (tmp >> 16) & 0xFF
4123 arr[curByte++] = (tmp >> 8) & 0xFF
4124 arr[curByte++] = tmp & 0xFF
4125 }
4126
4127 if (placeHoldersLen === 2) {
4128 tmp =
4129 (revLookup[b64.charCodeAt(i)] << 2) |
4130 (revLookup[b64.charCodeAt(i + 1)] >> 4)
4131 arr[curByte++] = tmp & 0xFF
4132 }
4133
4134 if (placeHoldersLen === 1) {
4135 tmp =
4136 (revLookup[b64.charCodeAt(i)] << 10) |
4137 (revLookup[b64.charCodeAt(i + 1)] << 4) |
4138 (revLookup[b64.charCodeAt(i + 2)] >> 2)
4139 arr[curByte++] = (tmp >> 8) & 0xFF
4140 arr[curByte++] = tmp & 0xFF
4141 }
4142
4143 return arr
4144}
4145
4146function tripletToBase64 (num) {
4147 return lookup[num >> 18 & 0x3F] +
4148 lookup[num >> 12 & 0x3F] +
4149 lookup[num >> 6 & 0x3F] +
4150 lookup[num & 0x3F]
4151}
4152
4153function encodeChunk (uint8, start, end) {
4154 var tmp
4155 var output = []
4156 for (var i = start; i < end; i += 3) {
4157 tmp =
4158 ((uint8[i] << 16) & 0xFF0000) +
4159 ((uint8[i + 1] << 8) & 0xFF00) +
4160 (uint8[i + 2] & 0xFF)
4161 output.push(tripletToBase64(tmp))
4162 }
4163 return output.join('')
4164}
4165
4166function fromByteArray (uint8) {
4167 var tmp
4168 var len = uint8.length
4169 var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
4170 var parts = []
4171 var maxChunkLength = 16383 // must be multiple of 3
4172
4173 // go through the array every three bytes, we'll deal with trailing stuff later
4174 for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
4175 parts.push(encodeChunk(
4176 uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
4177 ))
4178 }
4179
4180 // pad the end with zeros, but make sure to not forget the extra bytes
4181 if (extraBytes === 1) {
4182 tmp = uint8[len - 1]
4183 parts.push(
4184 lookup[tmp >> 2] +
4185 lookup[(tmp << 4) & 0x3F] +
4186 '=='
4187 )
4188 } else if (extraBytes === 2) {
4189 tmp = (uint8[len - 2] << 8) + uint8[len - 1]
4190 parts.push(
4191 lookup[tmp >> 10] +
4192 lookup[(tmp >> 4) & 0x3F] +
4193 lookup[(tmp << 2) & 0x3F] +
4194 '='
4195 )
4196 }
4197
4198 return parts.join('')
4199}
4200
4201},{}],47:[function(require,module,exports){
4202/*!
4203 * The buffer module from node.js, for the browser.
4204 *
4205 * @author Feross Aboukhadijeh <https://feross.org>
4206 * @license MIT
4207 */
4208/* eslint-disable no-proto */
4209
4210'use strict'
4211
4212var base64 = require('base64-js')
4213var ieee754 = require('ieee754')
4214
4215exports.Buffer = Buffer
4216exports.SlowBuffer = SlowBuffer
4217exports.INSPECT_MAX_BYTES = 50
4218
4219var K_MAX_LENGTH = 0x7fffffff
4220exports.kMaxLength = K_MAX_LENGTH
4221
4222/**
4223 * If `Buffer.TYPED_ARRAY_SUPPORT`:
4224 * === true Use Uint8Array implementation (fastest)
4225 * === false Print warning and recommend using `buffer` v4.x which has an Object
4226 * implementation (most compatible, even IE6)
4227 *
4228 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
4229 * Opera 11.6+, iOS 4.2+.
4230 *
4231 * We report that the browser does not support typed arrays if the are not subclassable
4232 * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
4233 * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
4234 * for __proto__ and has a buggy typed array implementation.
4235 */
4236Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
4237
4238if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
4239 typeof console.error === 'function') {
4240 console.error(
4241 'This browser lacks typed array (Uint8Array) support which is required by ' +
4242 '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
4243 )
4244}
4245
4246function typedArraySupport () {
4247 // Can typed array instances can be augmented?
4248 try {
4249 var arr = new Uint8Array(1)
4250 arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } }
4251 return arr.foo() === 42
4252 } catch (e) {
4253 return false
4254 }
4255}
4256
4257Object.defineProperty(Buffer.prototype, 'parent', {
4258 enumerable: true,
4259 get: function () {
4260 if (!Buffer.isBuffer(this)) return undefined
4261 return this.buffer
4262 }
4263})
4264
4265Object.defineProperty(Buffer.prototype, 'offset', {
4266 enumerable: true,
4267 get: function () {
4268 if (!Buffer.isBuffer(this)) return undefined
4269 return this.byteOffset
4270 }
4271})
4272
4273function createBuffer (length) {
4274 if (length > K_MAX_LENGTH) {
4275 throw new RangeError('The value "' + length + '" is invalid for option "size"')
4276 }
4277 // Return an augmented `Uint8Array` instance
4278 var buf = new Uint8Array(length)
4279 buf.__proto__ = Buffer.prototype
4280 return buf
4281}
4282
4283/**
4284 * The Buffer constructor returns instances of `Uint8Array` that have their
4285 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
4286 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
4287 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
4288 * returns a single octet.
4289 *
4290 * The `Uint8Array` prototype remains unmodified.
4291 */
4292
4293function Buffer (arg, encodingOrOffset, length) {
4294 // Common case.
4295 if (typeof arg === 'number') {
4296 if (typeof encodingOrOffset === 'string') {
4297 throw new TypeError(
4298 'The "string" argument must be of type string. Received type number'
4299 )
4300 }
4301 return allocUnsafe(arg)
4302 }
4303 return from(arg, encodingOrOffset, length)
4304}
4305
4306// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
4307if (typeof Symbol !== 'undefined' && Symbol.species != null &&
4308 Buffer[Symbol.species] === Buffer) {
4309 Object.defineProperty(Buffer, Symbol.species, {
4310 value: null,
4311 configurable: true,
4312 enumerable: false,
4313 writable: false
4314 })
4315}
4316
4317Buffer.poolSize = 8192 // not used by this implementation
4318
4319function from (value, encodingOrOffset, length) {
4320 if (typeof value === 'string') {
4321 return fromString(value, encodingOrOffset)
4322 }
4323
4324 if (ArrayBuffer.isView(value)) {
4325 return fromArrayLike(value)
4326 }
4327
4328 if (value == null) {
4329 throw TypeError(
4330 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
4331 'or Array-like Object. Received type ' + (typeof value)
4332 )
4333 }
4334
4335 if (isInstance(value, ArrayBuffer) ||
4336 (value && isInstance(value.buffer, ArrayBuffer))) {
4337 return fromArrayBuffer(value, encodingOrOffset, length)
4338 }
4339
4340 if (typeof value === 'number') {
4341 throw new TypeError(
4342 'The "value" argument must not be of type number. Received type number'
4343 )
4344 }
4345
4346 var valueOf = value.valueOf && value.valueOf()
4347 if (valueOf != null && valueOf !== value) {
4348 return Buffer.from(valueOf, encodingOrOffset, length)
4349 }
4350
4351 var b = fromObject(value)
4352 if (b) return b
4353
4354 if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&
4355 typeof value[Symbol.toPrimitive] === 'function') {
4356 return Buffer.from(
4357 value[Symbol.toPrimitive]('string'), encodingOrOffset, length
4358 )
4359 }
4360
4361 throw new TypeError(
4362 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
4363 'or Array-like Object. Received type ' + (typeof value)
4364 )
4365}
4366
4367/**
4368 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
4369 * if value is a number.
4370 * Buffer.from(str[, encoding])
4371 * Buffer.from(array)
4372 * Buffer.from(buffer)
4373 * Buffer.from(arrayBuffer[, byteOffset[, length]])
4374 **/
4375Buffer.from = function (value, encodingOrOffset, length) {
4376 return from(value, encodingOrOffset, length)
4377}
4378
4379// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
4380// https://github.com/feross/buffer/pull/148
4381Buffer.prototype.__proto__ = Uint8Array.prototype
4382Buffer.__proto__ = Uint8Array
4383
4384function assertSize (size) {
4385 if (typeof size !== 'number') {
4386 throw new TypeError('"size" argument must be of type number')
4387 } else if (size < 0) {
4388 throw new RangeError('The value "' + size + '" is invalid for option "size"')
4389 }
4390}
4391
4392function alloc (size, fill, encoding) {
4393 assertSize(size)
4394 if (size <= 0) {
4395 return createBuffer(size)
4396 }
4397 if (fill !== undefined) {
4398 // Only pay attention to encoding if it's a string. This
4399 // prevents accidentally sending in a number that would
4400 // be interpretted as a start offset.
4401 return typeof encoding === 'string'
4402 ? createBuffer(size).fill(fill, encoding)
4403 : createBuffer(size).fill(fill)
4404 }
4405 return createBuffer(size)
4406}
4407
4408/**
4409 * Creates a new filled Buffer instance.
4410 * alloc(size[, fill[, encoding]])
4411 **/
4412Buffer.alloc = function (size, fill, encoding) {
4413 return alloc(size, fill, encoding)
4414}
4415
4416function allocUnsafe (size) {
4417 assertSize(size)
4418 return createBuffer(size < 0 ? 0 : checked(size) | 0)
4419}
4420
4421/**
4422 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
4423 * */
4424Buffer.allocUnsafe = function (size) {
4425 return allocUnsafe(size)
4426}
4427/**
4428 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
4429 */
4430Buffer.allocUnsafeSlow = function (size) {
4431 return allocUnsafe(size)
4432}
4433
4434function fromString (string, encoding) {
4435 if (typeof encoding !== 'string' || encoding === '') {
4436 encoding = 'utf8'
4437 }
4438
4439 if (!Buffer.isEncoding(encoding)) {
4440 throw new TypeError('Unknown encoding: ' + encoding)
4441 }
4442
4443 var length = byteLength(string, encoding) | 0
4444 var buf = createBuffer(length)
4445
4446 var actual = buf.write(string, encoding)
4447
4448 if (actual !== length) {
4449 // Writing a hex string, for example, that contains invalid characters will
4450 // cause everything after the first invalid character to be ignored. (e.g.
4451 // 'abxxcd' will be treated as 'ab')
4452 buf = buf.slice(0, actual)
4453 }
4454
4455 return buf
4456}
4457
4458function fromArrayLike (array) {
4459 var length = array.length < 0 ? 0 : checked(array.length) | 0
4460 var buf = createBuffer(length)
4461 for (var i = 0; i < length; i += 1) {
4462 buf[i] = array[i] & 255
4463 }
4464 return buf
4465}
4466
4467function fromArrayBuffer (array, byteOffset, length) {
4468 if (byteOffset < 0 || array.byteLength < byteOffset) {
4469 throw new RangeError('"offset" is outside of buffer bounds')
4470 }
4471
4472 if (array.byteLength < byteOffset + (length || 0)) {
4473 throw new RangeError('"length" is outside of buffer bounds')
4474 }
4475
4476 var buf
4477 if (byteOffset === undefined && length === undefined) {
4478 buf = new Uint8Array(array)
4479 } else if (length === undefined) {
4480 buf = new Uint8Array(array, byteOffset)
4481 } else {
4482 buf = new Uint8Array(array, byteOffset, length)
4483 }
4484
4485 // Return an augmented `Uint8Array` instance
4486 buf.__proto__ = Buffer.prototype
4487 return buf
4488}
4489
4490function fromObject (obj) {
4491 if (Buffer.isBuffer(obj)) {
4492 var len = checked(obj.length) | 0
4493 var buf = createBuffer(len)
4494
4495 if (buf.length === 0) {
4496 return buf
4497 }
4498
4499 obj.copy(buf, 0, 0, len)
4500 return buf
4501 }
4502
4503 if (obj.length !== undefined) {
4504 if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
4505 return createBuffer(0)
4506 }
4507 return fromArrayLike(obj)
4508 }
4509
4510 if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
4511 return fromArrayLike(obj.data)
4512 }
4513}
4514
4515function checked (length) {
4516 // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
4517 // length is NaN (which is otherwise coerced to zero.)
4518 if (length >= K_MAX_LENGTH) {
4519 throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
4520 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
4521 }
4522 return length | 0
4523}
4524
4525function SlowBuffer (length) {
4526 if (+length != length) { // eslint-disable-line eqeqeq
4527 length = 0
4528 }
4529 return Buffer.alloc(+length)
4530}
4531
4532Buffer.isBuffer = function isBuffer (b) {
4533 return b != null && b._isBuffer === true &&
4534 b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false
4535}
4536
4537Buffer.compare = function compare (a, b) {
4538 if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)
4539 if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)
4540 if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
4541 throw new TypeError(
4542 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
4543 )
4544 }
4545
4546 if (a === b) return 0
4547
4548 var x = a.length
4549 var y = b.length
4550
4551 for (var i = 0, len = Math.min(x, y); i < len; ++i) {
4552 if (a[i] !== b[i]) {
4553 x = a[i]
4554 y = b[i]
4555 break
4556 }
4557 }
4558
4559 if (x < y) return -1
4560 if (y < x) return 1
4561 return 0
4562}
4563
4564Buffer.isEncoding = function isEncoding (encoding) {
4565 switch (String(encoding).toLowerCase()) {
4566 case 'hex':
4567 case 'utf8':
4568 case 'utf-8':
4569 case 'ascii':
4570 case 'latin1':
4571 case 'binary':
4572 case 'base64':
4573 case 'ucs2':
4574 case 'ucs-2':
4575 case 'utf16le':
4576 case 'utf-16le':
4577 return true
4578 default:
4579 return false
4580 }
4581}
4582
4583Buffer.concat = function concat (list, length) {
4584 if (!Array.isArray(list)) {
4585 throw new TypeError('"list" argument must be an Array of Buffers')
4586 }
4587
4588 if (list.length === 0) {
4589 return Buffer.alloc(0)
4590 }
4591
4592 var i
4593 if (length === undefined) {
4594 length = 0
4595 for (i = 0; i < list.length; ++i) {
4596 length += list[i].length
4597 }
4598 }
4599
4600 var buffer = Buffer.allocUnsafe(length)
4601 var pos = 0
4602 for (i = 0; i < list.length; ++i) {
4603 var buf = list[i]
4604 if (isInstance(buf, Uint8Array)) {
4605 buf = Buffer.from(buf)
4606 }
4607 if (!Buffer.isBuffer(buf)) {
4608 throw new TypeError('"list" argument must be an Array of Buffers')
4609 }
4610 buf.copy(buffer, pos)
4611 pos += buf.length
4612 }
4613 return buffer
4614}
4615
4616function byteLength (string, encoding) {
4617 if (Buffer.isBuffer(string)) {
4618 return string.length
4619 }
4620 if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
4621 return string.byteLength
4622 }
4623 if (typeof string !== 'string') {
4624 throw new TypeError(
4625 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' +
4626 'Received type ' + typeof string
4627 )
4628 }
4629
4630 var len = string.length
4631 var mustMatch = (arguments.length > 2 && arguments[2] === true)
4632 if (!mustMatch && len === 0) return 0
4633
4634 // Use a for loop to avoid recursion
4635 var loweredCase = false
4636 for (;;) {
4637 switch (encoding) {
4638 case 'ascii':
4639 case 'latin1':
4640 case 'binary':
4641 return len
4642 case 'utf8':
4643 case 'utf-8':
4644 return utf8ToBytes(string).length
4645 case 'ucs2':
4646 case 'ucs-2':
4647 case 'utf16le':
4648 case 'utf-16le':
4649 return len * 2
4650 case 'hex':
4651 return len >>> 1
4652 case 'base64':
4653 return base64ToBytes(string).length
4654 default:
4655 if (loweredCase) {
4656 return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8
4657 }
4658 encoding = ('' + encoding).toLowerCase()
4659 loweredCase = true
4660 }
4661 }
4662}
4663Buffer.byteLength = byteLength
4664
4665function slowToString (encoding, start, end) {
4666 var loweredCase = false
4667
4668 // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
4669 // property of a typed array.
4670
4671 // This behaves neither like String nor Uint8Array in that we set start/end
4672 // to their upper/lower bounds if the value passed is out of range.
4673 // undefined is handled specially as per ECMA-262 6th Edition,
4674 // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
4675 if (start === undefined || start < 0) {
4676 start = 0
4677 }
4678 // Return early if start > this.length. Done here to prevent potential uint32
4679 // coercion fail below.
4680 if (start > this.length) {
4681 return ''
4682 }
4683
4684 if (end === undefined || end > this.length) {
4685 end = this.length
4686 }
4687
4688 if (end <= 0) {
4689 return ''
4690 }
4691
4692 // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
4693 end >>>= 0
4694 start >>>= 0
4695
4696 if (end <= start) {
4697 return ''
4698 }
4699
4700 if (!encoding) encoding = 'utf8'
4701
4702 while (true) {
4703 switch (encoding) {
4704 case 'hex':
4705 return hexSlice(this, start, end)
4706
4707 case 'utf8':
4708 case 'utf-8':
4709 return utf8Slice(this, start, end)
4710
4711 case 'ascii':
4712 return asciiSlice(this, start, end)
4713
4714 case 'latin1':
4715 case 'binary':
4716 return latin1Slice(this, start, end)
4717
4718 case 'base64':
4719 return base64Slice(this, start, end)
4720
4721 case 'ucs2':
4722 case 'ucs-2':
4723 case 'utf16le':
4724 case 'utf-16le':
4725 return utf16leSlice(this, start, end)
4726
4727 default:
4728 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
4729 encoding = (encoding + '').toLowerCase()
4730 loweredCase = true
4731 }
4732 }
4733}
4734
4735// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
4736// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
4737// reliably in a browserify context because there could be multiple different
4738// copies of the 'buffer' package in use. This method works even for Buffer
4739// instances that were created from another copy of the `buffer` package.
4740// See: https://github.com/feross/buffer/issues/154
4741Buffer.prototype._isBuffer = true
4742
4743function swap (b, n, m) {
4744 var i = b[n]
4745 b[n] = b[m]
4746 b[m] = i
4747}
4748
4749Buffer.prototype.swap16 = function swap16 () {
4750 var len = this.length
4751 if (len % 2 !== 0) {
4752 throw new RangeError('Buffer size must be a multiple of 16-bits')
4753 }
4754 for (var i = 0; i < len; i += 2) {
4755 swap(this, i, i + 1)
4756 }
4757 return this
4758}
4759
4760Buffer.prototype.swap32 = function swap32 () {
4761 var len = this.length
4762 if (len % 4 !== 0) {
4763 throw new RangeError('Buffer size must be a multiple of 32-bits')
4764 }
4765 for (var i = 0; i < len; i += 4) {
4766 swap(this, i, i + 3)
4767 swap(this, i + 1, i + 2)
4768 }
4769 return this
4770}
4771
4772Buffer.prototype.swap64 = function swap64 () {
4773 var len = this.length
4774 if (len % 8 !== 0) {
4775 throw new RangeError('Buffer size must be a multiple of 64-bits')
4776 }
4777 for (var i = 0; i < len; i += 8) {
4778 swap(this, i, i + 7)
4779 swap(this, i + 1, i + 6)
4780 swap(this, i + 2, i + 5)
4781 swap(this, i + 3, i + 4)
4782 }
4783 return this
4784}
4785
4786Buffer.prototype.toString = function toString () {
4787 var length = this.length
4788 if (length === 0) return ''
4789 if (arguments.length === 0) return utf8Slice(this, 0, length)
4790 return slowToString.apply(this, arguments)
4791}
4792
4793Buffer.prototype.toLocaleString = Buffer.prototype.toString
4794
4795Buffer.prototype.equals = function equals (b) {
4796 if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
4797 if (this === b) return true
4798 return Buffer.compare(this, b) === 0
4799}
4800
4801Buffer.prototype.inspect = function inspect () {
4802 var str = ''
4803 var max = exports.INSPECT_MAX_BYTES
4804 str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()
4805 if (this.length > max) str += ' ... '
4806 return '<Buffer ' + str + '>'
4807}
4808
4809Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
4810 if (isInstance(target, Uint8Array)) {
4811 target = Buffer.from(target, target.offset, target.byteLength)
4812 }
4813 if (!Buffer.isBuffer(target)) {
4814 throw new TypeError(
4815 'The "target" argument must be one of type Buffer or Uint8Array. ' +
4816 'Received type ' + (typeof target)
4817 )
4818 }
4819
4820 if (start === undefined) {
4821 start = 0
4822 }
4823 if (end === undefined) {
4824 end = target ? target.length : 0
4825 }
4826 if (thisStart === undefined) {
4827 thisStart = 0
4828 }
4829 if (thisEnd === undefined) {
4830 thisEnd = this.length
4831 }
4832
4833 if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
4834 throw new RangeError('out of range index')
4835 }
4836
4837 if (thisStart >= thisEnd && start >= end) {
4838 return 0
4839 }
4840 if (thisStart >= thisEnd) {
4841 return -1
4842 }
4843 if (start >= end) {
4844 return 1
4845 }
4846
4847 start >>>= 0
4848 end >>>= 0
4849 thisStart >>>= 0
4850 thisEnd >>>= 0
4851
4852 if (this === target) return 0
4853
4854 var x = thisEnd - thisStart
4855 var y = end - start
4856 var len = Math.min(x, y)
4857
4858 var thisCopy = this.slice(thisStart, thisEnd)
4859 var targetCopy = target.slice(start, end)
4860
4861 for (var i = 0; i < len; ++i) {
4862 if (thisCopy[i] !== targetCopy[i]) {
4863 x = thisCopy[i]
4864 y = targetCopy[i]
4865 break
4866 }
4867 }
4868
4869 if (x < y) return -1
4870 if (y < x) return 1
4871 return 0
4872}
4873
4874// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
4875// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
4876//
4877// Arguments:
4878// - buffer - a Buffer to search
4879// - val - a string, Buffer, or number
4880// - byteOffset - an index into `buffer`; will be clamped to an int32
4881// - encoding - an optional encoding, relevant is val is a string
4882// - dir - true for indexOf, false for lastIndexOf
4883function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
4884 // Empty buffer means no match
4885 if (buffer.length === 0) return -1
4886
4887 // Normalize byteOffset
4888 if (typeof byteOffset === 'string') {
4889 encoding = byteOffset
4890 byteOffset = 0
4891 } else if (byteOffset > 0x7fffffff) {
4892 byteOffset = 0x7fffffff
4893 } else if (byteOffset < -0x80000000) {
4894 byteOffset = -0x80000000
4895 }
4896 byteOffset = +byteOffset // Coerce to Number.
4897 if (numberIsNaN(byteOffset)) {
4898 // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
4899 byteOffset = dir ? 0 : (buffer.length - 1)
4900 }
4901
4902 // Normalize byteOffset: negative offsets start from the end of the buffer
4903 if (byteOffset < 0) byteOffset = buffer.length + byteOffset
4904 if (byteOffset >= buffer.length) {
4905 if (dir) return -1
4906 else byteOffset = buffer.length - 1
4907 } else if (byteOffset < 0) {
4908 if (dir) byteOffset = 0
4909 else return -1
4910 }
4911
4912 // Normalize val
4913 if (typeof val === 'string') {
4914 val = Buffer.from(val, encoding)
4915 }
4916
4917 // Finally, search either indexOf (if dir is true) or lastIndexOf
4918 if (Buffer.isBuffer(val)) {
4919 // Special case: looking for empty string/buffer always fails
4920 if (val.length === 0) {
4921 return -1
4922 }
4923 return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
4924 } else if (typeof val === 'number') {
4925 val = val & 0xFF // Search for a byte value [0-255]
4926 if (typeof Uint8Array.prototype.indexOf === 'function') {
4927 if (dir) {
4928 return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
4929 } else {
4930 return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
4931 }
4932 }
4933 return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
4934 }
4935
4936 throw new TypeError('val must be string, number or Buffer')
4937}
4938
4939function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
4940 var indexSize = 1
4941 var arrLength = arr.length
4942 var valLength = val.length
4943
4944 if (encoding !== undefined) {
4945 encoding = String(encoding).toLowerCase()
4946 if (encoding === 'ucs2' || encoding === 'ucs-2' ||
4947 encoding === 'utf16le' || encoding === 'utf-16le') {
4948 if (arr.length < 2 || val.length < 2) {
4949 return -1
4950 }
4951 indexSize = 2
4952 arrLength /= 2
4953 valLength /= 2
4954 byteOffset /= 2
4955 }
4956 }
4957
4958 function read (buf, i) {
4959 if (indexSize === 1) {
4960 return buf[i]
4961 } else {
4962 return buf.readUInt16BE(i * indexSize)
4963 }
4964 }
4965
4966 var i
4967 if (dir) {
4968 var foundIndex = -1
4969 for (i = byteOffset; i < arrLength; i++) {
4970 if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
4971 if (foundIndex === -1) foundIndex = i
4972 if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
4973 } else {
4974 if (foundIndex !== -1) i -= i - foundIndex
4975 foundIndex = -1
4976 }
4977 }
4978 } else {
4979 if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
4980 for (i = byteOffset; i >= 0; i--) {
4981 var found = true
4982 for (var j = 0; j < valLength; j++) {
4983 if (read(arr, i + j) !== read(val, j)) {
4984 found = false
4985 break
4986 }
4987 }
4988 if (found) return i
4989 }
4990 }
4991
4992 return -1
4993}
4994
4995Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
4996 return this.indexOf(val, byteOffset, encoding) !== -1
4997}
4998
4999Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
5000 return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
5001}
5002
5003Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
5004 return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
5005}
5006
5007function hexWrite (buf, string, offset, length) {
5008 offset = Number(offset) || 0
5009 var remaining = buf.length - offset
5010 if (!length) {
5011 length = remaining
5012 } else {
5013 length = Number(length)
5014 if (length > remaining) {
5015 length = remaining
5016 }
5017 }
5018
5019 var strLen = string.length
5020
5021 if (length > strLen / 2) {
5022 length = strLen / 2
5023 }
5024 for (var i = 0; i < length; ++i) {
5025 var parsed = parseInt(string.substr(i * 2, 2), 16)
5026 if (numberIsNaN(parsed)) return i
5027 buf[offset + i] = parsed
5028 }
5029 return i
5030}
5031
5032function utf8Write (buf, string, offset, length) {
5033 return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
5034}
5035
5036function asciiWrite (buf, string, offset, length) {
5037 return blitBuffer(asciiToBytes(string), buf, offset, length)
5038}
5039
5040function latin1Write (buf, string, offset, length) {
5041 return asciiWrite(buf, string, offset, length)
5042}
5043
5044function base64Write (buf, string, offset, length) {
5045 return blitBuffer(base64ToBytes(string), buf, offset, length)
5046}
5047
5048function ucs2Write (buf, string, offset, length) {
5049 return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
5050}
5051
5052Buffer.prototype.write = function write (string, offset, length, encoding) {
5053 // Buffer#write(string)
5054 if (offset === undefined) {
5055 encoding = 'utf8'
5056 length = this.length
5057 offset = 0
5058 // Buffer#write(string, encoding)
5059 } else if (length === undefined && typeof offset === 'string') {
5060 encoding = offset
5061 length = this.length
5062 offset = 0
5063 // Buffer#write(string, offset[, length][, encoding])
5064 } else if (isFinite(offset)) {
5065 offset = offset >>> 0
5066 if (isFinite(length)) {
5067 length = length >>> 0
5068 if (encoding === undefined) encoding = 'utf8'
5069 } else {
5070 encoding = length
5071 length = undefined
5072 }
5073 } else {
5074 throw new Error(
5075 'Buffer.write(string, encoding, offset[, length]) is no longer supported'
5076 )
5077 }
5078
5079 var remaining = this.length - offset
5080 if (length === undefined || length > remaining) length = remaining
5081
5082 if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
5083 throw new RangeError('Attempt to write outside buffer bounds')
5084 }
5085
5086 if (!encoding) encoding = 'utf8'
5087
5088 var loweredCase = false
5089 for (;;) {
5090 switch (encoding) {
5091 case 'hex':
5092 return hexWrite(this, string, offset, length)
5093
5094 case 'utf8':
5095 case 'utf-8':
5096 return utf8Write(this, string, offset, length)
5097
5098 case 'ascii':
5099 return asciiWrite(this, string, offset, length)
5100
5101 case 'latin1':
5102 case 'binary':
5103 return latin1Write(this, string, offset, length)
5104
5105 case 'base64':
5106 // Warning: maxLength not taken into account in base64Write
5107 return base64Write(this, string, offset, length)
5108
5109 case 'ucs2':
5110 case 'ucs-2':
5111 case 'utf16le':
5112 case 'utf-16le':
5113 return ucs2Write(this, string, offset, length)
5114
5115 default:
5116 if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
5117 encoding = ('' + encoding).toLowerCase()
5118 loweredCase = true
5119 }
5120 }
5121}
5122
5123Buffer.prototype.toJSON = function toJSON () {
5124 return {
5125 type: 'Buffer',
5126 data: Array.prototype.slice.call(this._arr || this, 0)
5127 }
5128}
5129
5130function base64Slice (buf, start, end) {
5131 if (start === 0 && end === buf.length) {
5132 return base64.fromByteArray(buf)
5133 } else {
5134 return base64.fromByteArray(buf.slice(start, end))
5135 }
5136}
5137
5138function utf8Slice (buf, start, end) {
5139 end = Math.min(buf.length, end)
5140 var res = []
5141
5142 var i = start
5143 while (i < end) {
5144 var firstByte = buf[i]
5145 var codePoint = null
5146 var bytesPerSequence = (firstByte > 0xEF) ? 4
5147 : (firstByte > 0xDF) ? 3
5148 : (firstByte > 0xBF) ? 2
5149 : 1
5150
5151 if (i + bytesPerSequence <= end) {
5152 var secondByte, thirdByte, fourthByte, tempCodePoint
5153
5154 switch (bytesPerSequence) {
5155 case 1:
5156 if (firstByte < 0x80) {
5157 codePoint = firstByte
5158 }
5159 break
5160 case 2:
5161 secondByte = buf[i + 1]
5162 if ((secondByte & 0xC0) === 0x80) {
5163 tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
5164 if (tempCodePoint > 0x7F) {
5165 codePoint = tempCodePoint
5166 }
5167 }
5168 break
5169 case 3:
5170 secondByte = buf[i + 1]
5171 thirdByte = buf[i + 2]
5172 if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
5173 tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
5174 if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
5175 codePoint = tempCodePoint
5176 }
5177 }
5178 break
5179 case 4:
5180 secondByte = buf[i + 1]
5181 thirdByte = buf[i + 2]
5182 fourthByte = buf[i + 3]
5183 if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
5184 tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
5185 if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
5186 codePoint = tempCodePoint
5187 }
5188 }
5189 }
5190 }
5191
5192 if (codePoint === null) {
5193 // we did not generate a valid codePoint so insert a
5194 // replacement char (U+FFFD) and advance only 1 byte
5195 codePoint = 0xFFFD
5196 bytesPerSequence = 1
5197 } else if (codePoint > 0xFFFF) {
5198 // encode to utf16 (surrogate pair dance)
5199 codePoint -= 0x10000
5200 res.push(codePoint >>> 10 & 0x3FF | 0xD800)
5201 codePoint = 0xDC00 | codePoint & 0x3FF
5202 }
5203
5204 res.push(codePoint)
5205 i += bytesPerSequence
5206 }
5207
5208 return decodeCodePointsArray(res)
5209}
5210
5211// Based on http://stackoverflow.com/a/22747272/680742, the browser with
5212// the lowest limit is Chrome, with 0x10000 args.
5213// We go 1 magnitude less, for safety
5214var MAX_ARGUMENTS_LENGTH = 0x1000
5215
5216function decodeCodePointsArray (codePoints) {
5217 var len = codePoints.length
5218 if (len <= MAX_ARGUMENTS_LENGTH) {
5219 return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
5220 }
5221
5222 // Decode in chunks to avoid "call stack size exceeded".
5223 var res = ''
5224 var i = 0
5225 while (i < len) {
5226 res += String.fromCharCode.apply(
5227 String,
5228 codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
5229 )
5230 }
5231 return res
5232}
5233
5234function asciiSlice (buf, start, end) {
5235 var ret = ''
5236 end = Math.min(buf.length, end)
5237
5238 for (var i = start; i < end; ++i) {
5239 ret += String.fromCharCode(buf[i] & 0x7F)
5240 }
5241 return ret
5242}
5243
5244function latin1Slice (buf, start, end) {
5245 var ret = ''
5246 end = Math.min(buf.length, end)
5247
5248 for (var i = start; i < end; ++i) {
5249 ret += String.fromCharCode(buf[i])
5250 }
5251 return ret
5252}
5253
5254function hexSlice (buf, start, end) {
5255 var len = buf.length
5256
5257 if (!start || start < 0) start = 0
5258 if (!end || end < 0 || end > len) end = len
5259
5260 var out = ''
5261 for (var i = start; i < end; ++i) {
5262 out += toHex(buf[i])
5263 }
5264 return out
5265}
5266
5267function utf16leSlice (buf, start, end) {
5268 var bytes = buf.slice(start, end)
5269 var res = ''
5270 for (var i = 0; i < bytes.length; i += 2) {
5271 res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
5272 }
5273 return res
5274}
5275
5276Buffer.prototype.slice = function slice (start, end) {
5277 var len = this.length
5278 start = ~~start
5279 end = end === undefined ? len : ~~end
5280
5281 if (start < 0) {
5282 start += len
5283 if (start < 0) start = 0
5284 } else if (start > len) {
5285 start = len
5286 }
5287
5288 if (end < 0) {
5289 end += len
5290 if (end < 0) end = 0
5291 } else if (end > len) {
5292 end = len
5293 }
5294
5295 if (end < start) end = start
5296
5297 var newBuf = this.subarray(start, end)
5298 // Return an augmented `Uint8Array` instance
5299 newBuf.__proto__ = Buffer.prototype
5300 return newBuf
5301}
5302
5303/*
5304 * Need to make sure that buffer isn't trying to write out of bounds.
5305 */
5306function checkOffset (offset, ext, length) {
5307 if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
5308 if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
5309}
5310
5311Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
5312 offset = offset >>> 0
5313 byteLength = byteLength >>> 0
5314 if (!noAssert) checkOffset(offset, byteLength, this.length)
5315
5316 var val = this[offset]
5317 var mul = 1
5318 var i = 0
5319 while (++i < byteLength && (mul *= 0x100)) {
5320 val += this[offset + i] * mul
5321 }
5322
5323 return val
5324}
5325
5326Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
5327 offset = offset >>> 0
5328 byteLength = byteLength >>> 0
5329 if (!noAssert) {
5330 checkOffset(offset, byteLength, this.length)
5331 }
5332
5333 var val = this[offset + --byteLength]
5334 var mul = 1
5335 while (byteLength > 0 && (mul *= 0x100)) {
5336 val += this[offset + --byteLength] * mul
5337 }
5338
5339 return val
5340}
5341
5342Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
5343 offset = offset >>> 0
5344 if (!noAssert) checkOffset(offset, 1, this.length)
5345 return this[offset]
5346}
5347
5348Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
5349 offset = offset >>> 0
5350 if (!noAssert) checkOffset(offset, 2, this.length)
5351 return this[offset] | (this[offset + 1] << 8)
5352}
5353
5354Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
5355 offset = offset >>> 0
5356 if (!noAssert) checkOffset(offset, 2, this.length)
5357 return (this[offset] << 8) | this[offset + 1]
5358}
5359
5360Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
5361 offset = offset >>> 0
5362 if (!noAssert) checkOffset(offset, 4, this.length)
5363
5364 return ((this[offset]) |
5365 (this[offset + 1] << 8) |
5366 (this[offset + 2] << 16)) +
5367 (this[offset + 3] * 0x1000000)
5368}
5369
5370Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
5371 offset = offset >>> 0
5372 if (!noAssert) checkOffset(offset, 4, this.length)
5373
5374 return (this[offset] * 0x1000000) +
5375 ((this[offset + 1] << 16) |
5376 (this[offset + 2] << 8) |
5377 this[offset + 3])
5378}
5379
5380Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
5381 offset = offset >>> 0
5382 byteLength = byteLength >>> 0
5383 if (!noAssert) checkOffset(offset, byteLength, this.length)
5384
5385 var val = this[offset]
5386 var mul = 1
5387 var i = 0
5388 while (++i < byteLength && (mul *= 0x100)) {
5389 val += this[offset + i] * mul
5390 }
5391 mul *= 0x80
5392
5393 if (val >= mul) val -= Math.pow(2, 8 * byteLength)
5394
5395 return val
5396}
5397
5398Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
5399 offset = offset >>> 0
5400 byteLength = byteLength >>> 0
5401 if (!noAssert) checkOffset(offset, byteLength, this.length)
5402
5403 var i = byteLength
5404 var mul = 1
5405 var val = this[offset + --i]
5406 while (i > 0 && (mul *= 0x100)) {
5407 val += this[offset + --i] * mul
5408 }
5409 mul *= 0x80
5410
5411 if (val >= mul) val -= Math.pow(2, 8 * byteLength)
5412
5413 return val
5414}
5415
5416Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
5417 offset = offset >>> 0
5418 if (!noAssert) checkOffset(offset, 1, this.length)
5419 if (!(this[offset] & 0x80)) return (this[offset])
5420 return ((0xff - this[offset] + 1) * -1)
5421}
5422
5423Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
5424 offset = offset >>> 0
5425 if (!noAssert) checkOffset(offset, 2, this.length)
5426 var val = this[offset] | (this[offset + 1] << 8)
5427 return (val & 0x8000) ? val | 0xFFFF0000 : val
5428}
5429
5430Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
5431 offset = offset >>> 0
5432 if (!noAssert) checkOffset(offset, 2, this.length)
5433 var val = this[offset + 1] | (this[offset] << 8)
5434 return (val & 0x8000) ? val | 0xFFFF0000 : val
5435}
5436
5437Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
5438 offset = offset >>> 0
5439 if (!noAssert) checkOffset(offset, 4, this.length)
5440
5441 return (this[offset]) |
5442 (this[offset + 1] << 8) |
5443 (this[offset + 2] << 16) |
5444 (this[offset + 3] << 24)
5445}
5446
5447Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
5448 offset = offset >>> 0
5449 if (!noAssert) checkOffset(offset, 4, this.length)
5450
5451 return (this[offset] << 24) |
5452 (this[offset + 1] << 16) |
5453 (this[offset + 2] << 8) |
5454 (this[offset + 3])
5455}
5456
5457Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
5458 offset = offset >>> 0
5459 if (!noAssert) checkOffset(offset, 4, this.length)
5460 return ieee754.read(this, offset, true, 23, 4)
5461}
5462
5463Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
5464 offset = offset >>> 0
5465 if (!noAssert) checkOffset(offset, 4, this.length)
5466 return ieee754.read(this, offset, false, 23, 4)
5467}
5468
5469Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
5470 offset = offset >>> 0
5471 if (!noAssert) checkOffset(offset, 8, this.length)
5472 return ieee754.read(this, offset, true, 52, 8)
5473}
5474
5475Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
5476 offset = offset >>> 0
5477 if (!noAssert) checkOffset(offset, 8, this.length)
5478 return ieee754.read(this, offset, false, 52, 8)
5479}
5480
5481function checkInt (buf, value, offset, ext, max, min) {
5482 if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
5483 if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
5484 if (offset + ext > buf.length) throw new RangeError('Index out of range')
5485}
5486
5487Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
5488 value = +value
5489 offset = offset >>> 0
5490 byteLength = byteLength >>> 0
5491 if (!noAssert) {
5492 var maxBytes = Math.pow(2, 8 * byteLength) - 1
5493 checkInt(this, value, offset, byteLength, maxBytes, 0)
5494 }
5495
5496 var mul = 1
5497 var i = 0
5498 this[offset] = value & 0xFF
5499 while (++i < byteLength && (mul *= 0x100)) {
5500 this[offset + i] = (value / mul) & 0xFF
5501 }
5502
5503 return offset + byteLength
5504}
5505
5506Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
5507 value = +value
5508 offset = offset >>> 0
5509 byteLength = byteLength >>> 0
5510 if (!noAssert) {
5511 var maxBytes = Math.pow(2, 8 * byteLength) - 1
5512 checkInt(this, value, offset, byteLength, maxBytes, 0)
5513 }
5514
5515 var i = byteLength - 1
5516 var mul = 1
5517 this[offset + i] = value & 0xFF
5518 while (--i >= 0 && (mul *= 0x100)) {
5519 this[offset + i] = (value / mul) & 0xFF
5520 }
5521
5522 return offset + byteLength
5523}
5524
5525Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
5526 value = +value
5527 offset = offset >>> 0
5528 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
5529 this[offset] = (value & 0xff)
5530 return offset + 1
5531}
5532
5533Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
5534 value = +value
5535 offset = offset >>> 0
5536 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
5537 this[offset] = (value & 0xff)
5538 this[offset + 1] = (value >>> 8)
5539 return offset + 2
5540}
5541
5542Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
5543 value = +value
5544 offset = offset >>> 0
5545 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
5546 this[offset] = (value >>> 8)
5547 this[offset + 1] = (value & 0xff)
5548 return offset + 2
5549}
5550
5551Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
5552 value = +value
5553 offset = offset >>> 0
5554 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
5555 this[offset + 3] = (value >>> 24)
5556 this[offset + 2] = (value >>> 16)
5557 this[offset + 1] = (value >>> 8)
5558 this[offset] = (value & 0xff)
5559 return offset + 4
5560}
5561
5562Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
5563 value = +value
5564 offset = offset >>> 0
5565 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
5566 this[offset] = (value >>> 24)
5567 this[offset + 1] = (value >>> 16)
5568 this[offset + 2] = (value >>> 8)
5569 this[offset + 3] = (value & 0xff)
5570 return offset + 4
5571}
5572
5573Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
5574 value = +value
5575 offset = offset >>> 0
5576 if (!noAssert) {
5577 var limit = Math.pow(2, (8 * byteLength) - 1)
5578
5579 checkInt(this, value, offset, byteLength, limit - 1, -limit)
5580 }
5581
5582 var i = 0
5583 var mul = 1
5584 var sub = 0
5585 this[offset] = value & 0xFF
5586 while (++i < byteLength && (mul *= 0x100)) {
5587 if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
5588 sub = 1
5589 }
5590 this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
5591 }
5592
5593 return offset + byteLength
5594}
5595
5596Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
5597 value = +value
5598 offset = offset >>> 0
5599 if (!noAssert) {
5600 var limit = Math.pow(2, (8 * byteLength) - 1)
5601
5602 checkInt(this, value, offset, byteLength, limit - 1, -limit)
5603 }
5604
5605 var i = byteLength - 1
5606 var mul = 1
5607 var sub = 0
5608 this[offset + i] = value & 0xFF
5609 while (--i >= 0 && (mul *= 0x100)) {
5610 if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
5611 sub = 1
5612 }
5613 this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
5614 }
5615
5616 return offset + byteLength
5617}
5618
5619Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
5620 value = +value
5621 offset = offset >>> 0
5622 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
5623 if (value < 0) value = 0xff + value + 1
5624 this[offset] = (value & 0xff)
5625 return offset + 1
5626}
5627
5628Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
5629 value = +value
5630 offset = offset >>> 0
5631 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
5632 this[offset] = (value & 0xff)
5633 this[offset + 1] = (value >>> 8)
5634 return offset + 2
5635}
5636
5637Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
5638 value = +value
5639 offset = offset >>> 0
5640 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
5641 this[offset] = (value >>> 8)
5642 this[offset + 1] = (value & 0xff)
5643 return offset + 2
5644}
5645
5646Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
5647 value = +value
5648 offset = offset >>> 0
5649 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
5650 this[offset] = (value & 0xff)
5651 this[offset + 1] = (value >>> 8)
5652 this[offset + 2] = (value >>> 16)
5653 this[offset + 3] = (value >>> 24)
5654 return offset + 4
5655}
5656
5657Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
5658 value = +value
5659 offset = offset >>> 0
5660 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
5661 if (value < 0) value = 0xffffffff + value + 1
5662 this[offset] = (value >>> 24)
5663 this[offset + 1] = (value >>> 16)
5664 this[offset + 2] = (value >>> 8)
5665 this[offset + 3] = (value & 0xff)
5666 return offset + 4
5667}
5668
5669function checkIEEE754 (buf, value, offset, ext, max, min) {
5670 if (offset + ext > buf.length) throw new RangeError('Index out of range')
5671 if (offset < 0) throw new RangeError('Index out of range')
5672}
5673
5674function writeFloat (buf, value, offset, littleEndian, noAssert) {
5675 value = +value
5676 offset = offset >>> 0
5677 if (!noAssert) {
5678 checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
5679 }
5680 ieee754.write(buf, value, offset, littleEndian, 23, 4)
5681 return offset + 4
5682}
5683
5684Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
5685 return writeFloat(this, value, offset, true, noAssert)
5686}
5687
5688Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
5689 return writeFloat(this, value, offset, false, noAssert)
5690}
5691
5692function writeDouble (buf, value, offset, littleEndian, noAssert) {
5693 value = +value
5694 offset = offset >>> 0
5695 if (!noAssert) {
5696 checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
5697 }
5698 ieee754.write(buf, value, offset, littleEndian, 52, 8)
5699 return offset + 8
5700}
5701
5702Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
5703 return writeDouble(this, value, offset, true, noAssert)
5704}
5705
5706Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
5707 return writeDouble(this, value, offset, false, noAssert)
5708}
5709
5710// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
5711Buffer.prototype.copy = function copy (target, targetStart, start, end) {
5712 if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')
5713 if (!start) start = 0
5714 if (!end && end !== 0) end = this.length
5715 if (targetStart >= target.length) targetStart = target.length
5716 if (!targetStart) targetStart = 0
5717 if (end > 0 && end < start) end = start
5718
5719 // Copy 0 bytes; we're done
5720 if (end === start) return 0
5721 if (target.length === 0 || this.length === 0) return 0
5722
5723 // Fatal error conditions
5724 if (targetStart < 0) {
5725 throw new RangeError('targetStart out of bounds')
5726 }
5727 if (start < 0 || start >= this.length) throw new RangeError('Index out of range')
5728 if (end < 0) throw new RangeError('sourceEnd out of bounds')
5729
5730 // Are we oob?
5731 if (end > this.length) end = this.length
5732 if (target.length - targetStart < end - start) {
5733 end = target.length - targetStart + start
5734 }
5735
5736 var len = end - start
5737
5738 if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
5739 // Use built-in when available, missing from IE11
5740 this.copyWithin(targetStart, start, end)
5741 } else if (this === target && start < targetStart && targetStart < end) {
5742 // descending copy from end
5743 for (var i = len - 1; i >= 0; --i) {
5744 target[i + targetStart] = this[i + start]
5745 }
5746 } else {
5747 Uint8Array.prototype.set.call(
5748 target,
5749 this.subarray(start, end),
5750 targetStart
5751 )
5752 }
5753
5754 return len
5755}
5756
5757// Usage:
5758// buffer.fill(number[, offset[, end]])
5759// buffer.fill(buffer[, offset[, end]])
5760// buffer.fill(string[, offset[, end]][, encoding])
5761Buffer.prototype.fill = function fill (val, start, end, encoding) {
5762 // Handle string cases:
5763 if (typeof val === 'string') {
5764 if (typeof start === 'string') {
5765 encoding = start
5766 start = 0
5767 end = this.length
5768 } else if (typeof end === 'string') {
5769 encoding = end
5770 end = this.length
5771 }
5772 if (encoding !== undefined && typeof encoding !== 'string') {
5773 throw new TypeError('encoding must be a string')
5774 }
5775 if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
5776 throw new TypeError('Unknown encoding: ' + encoding)
5777 }
5778 if (val.length === 1) {
5779 var code = val.charCodeAt(0)
5780 if ((encoding === 'utf8' && code < 128) ||
5781 encoding === 'latin1') {
5782 // Fast path: If `val` fits into a single byte, use that numeric value.
5783 val = code
5784 }
5785 }
5786 } else if (typeof val === 'number') {
5787 val = val & 255
5788 }
5789
5790 // Invalid ranges are not set to a default, so can range check early.
5791 if (start < 0 || this.length < start || this.length < end) {
5792 throw new RangeError('Out of range index')
5793 }
5794
5795 if (end <= start) {
5796 return this
5797 }
5798
5799 start = start >>> 0
5800 end = end === undefined ? this.length : end >>> 0
5801
5802 if (!val) val = 0
5803
5804 var i
5805 if (typeof val === 'number') {
5806 for (i = start; i < end; ++i) {
5807 this[i] = val
5808 }
5809 } else {
5810 var bytes = Buffer.isBuffer(val)
5811 ? val
5812 : Buffer.from(val, encoding)
5813 var len = bytes.length
5814 if (len === 0) {
5815 throw new TypeError('The value "' + val +
5816 '" is invalid for argument "value"')
5817 }
5818 for (i = 0; i < end - start; ++i) {
5819 this[i + start] = bytes[i % len]
5820 }
5821 }
5822
5823 return this
5824}
5825
5826// HELPER FUNCTIONS
5827// ================
5828
5829var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
5830
5831function base64clean (str) {
5832 // Node takes equal signs as end of the Base64 encoding
5833 str = str.split('=')[0]
5834 // Node strips out invalid characters like \n and \t from the string, base64-js does not
5835 str = str.trim().replace(INVALID_BASE64_RE, '')
5836 // Node converts strings with length < 2 to ''
5837 if (str.length < 2) return ''
5838 // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
5839 while (str.length % 4 !== 0) {
5840 str = str + '='
5841 }
5842 return str
5843}
5844
5845function toHex (n) {
5846 if (n < 16) return '0' + n.toString(16)
5847 return n.toString(16)
5848}
5849
5850function utf8ToBytes (string, units) {
5851 units = units || Infinity
5852 var codePoint
5853 var length = string.length
5854 var leadSurrogate = null
5855 var bytes = []
5856
5857 for (var i = 0; i < length; ++i) {
5858 codePoint = string.charCodeAt(i)
5859
5860 // is surrogate component
5861 if (codePoint > 0xD7FF && codePoint < 0xE000) {
5862 // last char was a lead
5863 if (!leadSurrogate) {
5864 // no lead yet
5865 if (codePoint > 0xDBFF) {
5866 // unexpected trail
5867 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
5868 continue
5869 } else if (i + 1 === length) {
5870 // unpaired lead
5871 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
5872 continue
5873 }
5874
5875 // valid lead
5876 leadSurrogate = codePoint
5877
5878 continue
5879 }
5880
5881 // 2 leads in a row
5882 if (codePoint < 0xDC00) {
5883 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
5884 leadSurrogate = codePoint
5885 continue
5886 }
5887
5888 // valid surrogate pair
5889 codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
5890 } else if (leadSurrogate) {
5891 // valid bmp char, but last char was a lead
5892 if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
5893 }
5894
5895 leadSurrogate = null
5896
5897 // encode utf8
5898 if (codePoint < 0x80) {
5899 if ((units -= 1) < 0) break
5900 bytes.push(codePoint)
5901 } else if (codePoint < 0x800) {
5902 if ((units -= 2) < 0) break
5903 bytes.push(
5904 codePoint >> 0x6 | 0xC0,
5905 codePoint & 0x3F | 0x80
5906 )
5907 } else if (codePoint < 0x10000) {
5908 if ((units -= 3) < 0) break
5909 bytes.push(
5910 codePoint >> 0xC | 0xE0,
5911 codePoint >> 0x6 & 0x3F | 0x80,
5912 codePoint & 0x3F | 0x80
5913 )
5914 } else if (codePoint < 0x110000) {
5915 if ((units -= 4) < 0) break
5916 bytes.push(
5917 codePoint >> 0x12 | 0xF0,
5918 codePoint >> 0xC & 0x3F | 0x80,
5919 codePoint >> 0x6 & 0x3F | 0x80,
5920 codePoint & 0x3F | 0x80
5921 )
5922 } else {
5923 throw new Error('Invalid code point')
5924 }
5925 }
5926
5927 return bytes
5928}
5929
5930function asciiToBytes (str) {
5931 var byteArray = []
5932 for (var i = 0; i < str.length; ++i) {
5933 // Node's code seems to be doing this and not & 0x7F..
5934 byteArray.push(str.charCodeAt(i) & 0xFF)
5935 }
5936 return byteArray
5937}
5938
5939function utf16leToBytes (str, units) {
5940 var c, hi, lo
5941 var byteArray = []
5942 for (var i = 0; i < str.length; ++i) {
5943 if ((units -= 2) < 0) break
5944
5945 c = str.charCodeAt(i)
5946 hi = c >> 8
5947 lo = c % 256
5948 byteArray.push(lo)
5949 byteArray.push(hi)
5950 }
5951
5952 return byteArray
5953}
5954
5955function base64ToBytes (str) {
5956 return base64.toByteArray(base64clean(str))
5957}
5958
5959function blitBuffer (src, dst, offset, length) {
5960 for (var i = 0; i < length; ++i) {
5961 if ((i + offset >= dst.length) || (i >= src.length)) break
5962 dst[i + offset] = src[i]
5963 }
5964 return i
5965}
5966
5967// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
5968// the `instanceof` check but they should be treated as of that type.
5969// See: https://github.com/feross/buffer/issues/166
5970function isInstance (obj, type) {
5971 return obj instanceof type ||
5972 (obj != null && obj.constructor != null && obj.constructor.name != null &&
5973 obj.constructor.name === type.name)
5974}
5975function numberIsNaN (obj) {
5976 // For IE11 support
5977 return obj !== obj // eslint-disable-line no-self-compare
5978}
5979
5980},{"base64-js":46,"ieee754":50}],48:[function(require,module,exports){
5981'use strict'
5982
5983var hasCaptureStackTrace = 'captureStackTrace' in Error
5984
5985module.exports = errorClass
5986
5987
5988function errorClass (name) {
5989 var ErrorClass
5990
5991 if (!name || typeof name !== 'string')
5992 throw new TypeError('Argument "name" must be a non-empty string.')
5993
5994 // This is basically `eval`, there's no other way to dynamically define a
5995 // function name.
5996 ErrorClass = function CustomError () {
5997 if (!(this instanceof CustomError))
5998 return new (CustomError.bind.apply(CustomError,
5999 Array.prototype.concat.apply([ null ], arguments)))
6000 setupError.apply(this, arguments)
6001 }
6002
6003 ErrorClass.prototype = Object.create(Error.prototype, {
6004 constructor: nonEnumerableProperty(ErrorClass),
6005 name: nonEnumerableProperty(name)
6006 })
6007
6008 return ErrorClass
6009}
6010
6011
6012// Internal function to set up an error.
6013function setupError (message) {
6014 if (hasCaptureStackTrace)
6015 // V8 specific method.
6016 Error.captureStackTrace(this, this.constructor)
6017 else
6018 // Generic way to set the error stack trace.
6019 Object.defineProperty(this, 'stack',
6020 nonEnumerableProperty(Error(message).stack))
6021
6022 // Use the `+` operator with an empty string to implicitly type cast the
6023 // `message` argument into a string.
6024 Object.defineProperty(this, 'message',
6025 nonEnumerableProperty(message !== void 0 ? '' + message : ''))
6026}
6027
6028
6029function nonEnumerableProperty (value) {
6030 // The field `enumerable` is `false` by default.
6031 return {
6032 value: value,
6033 writable: true,
6034 configurable: true
6035 }
6036}
6037
6038},{}],49:[function(require,module,exports){
6039/**
6040 * event-lite.js - Light-weight EventEmitter (less than 1KB when gzipped)
6041 *
6042 * @copyright Yusuke Kawasaki
6043 * @license MIT
6044 * @constructor
6045 * @see https://github.com/kawanet/event-lite
6046 * @see http://kawanet.github.io/event-lite/EventLite.html
6047 * @example
6048 * var EventLite = require("event-lite");
6049 *
6050 * function MyClass() {...} // your class
6051 *
6052 * EventLite.mixin(MyClass.prototype); // import event methods
6053 *
6054 * var obj = new MyClass();
6055 * obj.on("foo", function() {...}); // add event listener
6056 * obj.once("bar", function() {...}); // add one-time event listener
6057 * obj.emit("foo"); // dispatch event
6058 * obj.emit("bar"); // dispatch another event
6059 * obj.off("foo"); // remove event listener
6060 */
6061
6062function EventLite() {
6063 if (!(this instanceof EventLite)) return new EventLite();
6064}
6065
6066(function(EventLite) {
6067 // export the class for node.js
6068 if ("undefined" !== typeof module) module.exports = EventLite;
6069
6070 // property name to hold listeners
6071 var LISTENERS = "listeners";
6072
6073 // methods to export
6074 var methods = {
6075 on: on,
6076 once: once,
6077 off: off,
6078 emit: emit
6079 };
6080
6081 // mixin to self
6082 mixin(EventLite.prototype);
6083
6084 // export mixin function
6085 EventLite.mixin = mixin;
6086
6087 /**
6088 * Import on(), once(), off() and emit() methods into target object.
6089 *
6090 * @function EventLite.mixin
6091 * @param target {Prototype}
6092 */
6093
6094 function mixin(target) {
6095 for (var key in methods) {
6096 target[key] = methods[key];
6097 }
6098 return target;
6099 }
6100
6101 /**
6102 * Add an event listener.
6103 *
6104 * @function EventLite.prototype.on
6105 * @param type {string}
6106 * @param func {Function}
6107 * @returns {EventLite} Self for method chaining
6108 */
6109
6110 function on(type, func) {
6111 getListeners(this, type).push(func);
6112 return this;
6113 }
6114
6115 /**
6116 * Add one-time event listener.
6117 *
6118 * @function EventLite.prototype.once
6119 * @param type {string}
6120 * @param func {Function}
6121 * @returns {EventLite} Self for method chaining
6122 */
6123
6124 function once(type, func) {
6125 var that = this;
6126 wrap.originalListener = func;
6127 getListeners(that, type).push(wrap);
6128 return that;
6129
6130 function wrap() {
6131 off.call(that, type, wrap);
6132 func.apply(this, arguments);
6133 }
6134 }
6135
6136 /**
6137 * Remove an event listener.
6138 *
6139 * @function EventLite.prototype.off
6140 * @param [type] {string}
6141 * @param [func] {Function}
6142 * @returns {EventLite} Self for method chaining
6143 */
6144
6145 function off(type, func) {
6146 var that = this;
6147 var listners;
6148 if (!arguments.length) {
6149 delete that[LISTENERS];
6150 } else if (!func) {
6151 listners = that[LISTENERS];
6152 if (listners) {
6153 delete listners[type];
6154 if (!Object.keys(listners).length) return off.call(that);
6155 }
6156 } else {
6157 listners = getListeners(that, type, true);
6158 if (listners) {
6159 listners = listners.filter(ne);
6160 if (!listners.length) return off.call(that, type);
6161 that[LISTENERS][type] = listners;
6162 }
6163 }
6164 return that;
6165
6166 function ne(test) {
6167 return test !== func && test.originalListener !== func;
6168 }
6169 }
6170
6171 /**
6172 * Dispatch (trigger) an event.
6173 *
6174 * @function EventLite.prototype.emit
6175 * @param type {string}
6176 * @param [value] {*}
6177 * @returns {boolean} True when a listener received the event
6178 */
6179
6180 function emit(type, value) {
6181 var that = this;
6182 var listeners = getListeners(that, type, true);
6183 if (!listeners) return false;
6184 var arglen = arguments.length;
6185 if (arglen === 1) {
6186 listeners.forEach(zeroarg);
6187 } else if (arglen === 2) {
6188 listeners.forEach(onearg);
6189 } else {
6190 var args = Array.prototype.slice.call(arguments, 1);
6191 listeners.forEach(moreargs);
6192 }
6193 return !!listeners.length;
6194
6195 function zeroarg(func) {
6196 func.call(that);
6197 }
6198
6199 function onearg(func) {
6200 func.call(that, value);
6201 }
6202
6203 function moreargs(func) {
6204 func.apply(that, args);
6205 }
6206 }
6207
6208 /**
6209 * @ignore
6210 */
6211
6212 function getListeners(that, type, readonly) {
6213 if (readonly && !that[LISTENERS]) return;
6214 var listeners = that[LISTENERS] || (that[LISTENERS] = {});
6215 return listeners[type] || (listeners[type] = []);
6216 }
6217
6218})(EventLite);
6219
6220},{}],50:[function(require,module,exports){
6221exports.read = function (buffer, offset, isLE, mLen, nBytes) {
6222 var e, m
6223 var eLen = nBytes * 8 - mLen - 1
6224 var eMax = (1 << eLen) - 1
6225 var eBias = eMax >> 1
6226 var nBits = -7
6227 var i = isLE ? (nBytes - 1) : 0
6228 var d = isLE ? -1 : 1
6229 var s = buffer[offset + i]
6230
6231 i += d
6232
6233 e = s & ((1 << (-nBits)) - 1)
6234 s >>= (-nBits)
6235 nBits += eLen
6236 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
6237
6238 m = e & ((1 << (-nBits)) - 1)
6239 e >>= (-nBits)
6240 nBits += mLen
6241 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
6242
6243 if (e === 0) {
6244 e = 1 - eBias
6245 } else if (e === eMax) {
6246 return m ? NaN : ((s ? -1 : 1) * Infinity)
6247 } else {
6248 m = m + Math.pow(2, mLen)
6249 e = e - eBias
6250 }
6251 return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
6252}
6253
6254exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
6255 var e, m, c
6256 var eLen = nBytes * 8 - mLen - 1
6257 var eMax = (1 << eLen) - 1
6258 var eBias = eMax >> 1
6259 var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
6260 var i = isLE ? 0 : (nBytes - 1)
6261 var d = isLE ? 1 : -1
6262 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
6263
6264 value = Math.abs(value)
6265
6266 if (isNaN(value) || value === Infinity) {
6267 m = isNaN(value) ? 1 : 0
6268 e = eMax
6269 } else {
6270 e = Math.floor(Math.log(value) / Math.LN2)
6271 if (value * (c = Math.pow(2, -e)) < 1) {
6272 e--
6273 c *= 2
6274 }
6275 if (e + eBias >= 1) {
6276 value += rt / c
6277 } else {
6278 value += rt * Math.pow(2, 1 - eBias)
6279 }
6280 if (value * c >= 2) {
6281 e++
6282 c /= 2
6283 }
6284
6285 if (e + eBias >= eMax) {
6286 m = 0
6287 e = eMax
6288 } else if (e + eBias >= 1) {
6289 m = (value * c - 1) * Math.pow(2, mLen)
6290 e = e + eBias
6291 } else {
6292 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
6293 e = 0
6294 }
6295 }
6296
6297 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
6298
6299 e = (e << mLen) | m
6300 eLen += mLen
6301 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
6302
6303 buffer[offset + i - d] |= s * 128
6304}
6305
6306},{}],51:[function(require,module,exports){
6307/*!
6308 * Determine if an object is a Buffer
6309 *
6310 * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
6311 * @license MIT
6312 */
6313
6314// The _isBuffer check is for Safari 5-7 support, because it's missing
6315// Object.prototype.constructor. Remove this eventually
6316module.exports = function (obj) {
6317 return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
6318}
6319
6320function isBuffer (obj) {
6321 return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
6322}
6323
6324// For Node v0.10 support. Remove this eventually.
6325function isSlowBuffer (obj) {
6326 return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
6327}
6328
6329},{}]},{},[31]);