From 03eec53dfab331efdd90c8f0c464636b92ea16a3 Mon Sep 17 00:00:00 2001 From: Firebase Operations Date: Mon, 26 Mar 2018 20:57:18 +0000 Subject: [PATCH] [firebase-release] Updated EmberFire to 2.0.10 --- bower.json | 2 +- dist/emberfire.js | 1538 +++++++++++++++++++++++++++++++++++++++++ dist/emberfire.js.map | 1 + dist/emberfire.min.js | 10 + package.json | 2 +- 5 files changed, 1551 insertions(+), 2 deletions(-) create mode 100644 dist/emberfire.js create mode 100644 dist/emberfire.js.map create mode 100644 dist/emberfire.min.js diff --git a/bower.json b/bower.json index c2fc9960..92a611d6 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "emberfire", "description": "The officially supported Ember binding for Firebase", - "version": "2.0.9", + "version": "2.0.10", "authors": [ "Firebase (https://firebase.google.com/)" ], diff --git a/dist/emberfire.js b/dist/emberfire.js new file mode 100644 index 00000000..0a4f2549 --- /dev/null +++ b/dist/emberfire.js @@ -0,0 +1,1538 @@ +/*! + * EmberFire is the officially supported adapter for using Firebase with + * Ember Data. The DS.FirebaseAdapter provides all of the standard DS.Adapter + * methods and will automatically synchronize the store with Firebase. + * + * EmberFire 0.0.0 + * https://github.com/firebase/emberfire/ + * License: MIT + */ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o.firebaseio.com/') + * }); + * ``` + * + * Requests for `App.Post` now target `https://.firebaseio.com/posts`. + * + * @property firebase + * @type {Firebase} + * @constructor + */ + init: function init() { + this._super.apply(this, arguments); + + var ref = this.get('firebase'); + if (!ref) { + throw new Error('Please set the `firebase` property in the environment config.'); + } + // If provided Firebase reference was a query (eg: limits), make it a ref. + this._ref = ref; + // Keep track of what types `.findAll()` has been called for + this._findAllMapForType = {}; + // Keep a cache to check modified relationships against + this._recordCacheForType = {}; + // Used to batch records into the store + this._queue = []; + // Payloads to push later + this._queuedPayloads = {}; + }, + + /** + * Uses push() to generate chronologically ordered unique IDs. + * + * @return {String} + */ + generateIdForRecord: function generateIdForRecord() { + return this._getKey(this._ref.push()); + }, + + /** + * Use the Firebase DataSnapshot's key as the record id + * + * @param {Object} snapshot - A Firebase snapshot + * @param {Object} payload - The payload that will be pushed into the store + * @return {Object} payload + */ + _assignIdToPayload: function _assignIdToPayload(snapshot) { + var payload = snapshot.val(); + if (payload !== null && typeof payload === 'object' && typeof payload.id === 'undefined') { + payload.id = this._getKey(snapshot); + } + return payload; + }, + + /** + * Called by the store to retrieve the JSON for a given type and ID. The + * method will return a promise which will resolve when the value is + * successfully fetched from Firebase. + * + * Additionally, from this point on, the object's value in the store will + * also be automatically updated whenever the remote value changes. + */ + findRecord: function findRecord(store, typeClass, id) { + var _this = this; + + var ref = this._getCollectionRef(typeClass, id); + + var log = 'DS: FirebaseAdapter#findRecord ' + typeClass.modelName + ' to ' + ref.toString(); + + return this._fetch(ref, log).then(function (snapshot) { + var payload = _this._assignIdToPayload(snapshot); + _this._updateRecordCacheForType(typeClass, payload, store); + if (payload === null) { + var error = new Error('no record was found at ' + ref.toString()); + error.recordId = id; + throw error; + } + + return payload; + }); + }, + + /** + * Promise interface for once('value'). + * + * @param {Firebase} ref + * @param {String} log + * @return {Promise} + * @private + */ + _fetch: function _fetch(ref, log) { + return RSVP.resolve(ref.once('value'), log); + }, + + recordWasPushed: function recordWasPushed(store, modelName, record) { + if (!record.__listening) { + var typeClass = store.modelFor(modelName); + this.listenForChanges(store, typeClass, record); + } + }, + + recordWillUnload: function recordWillUnload(store, record) { + if (record.__listening) { + this.stopListening(store, record.constructor, record); + } + }, + + recordWillDelete: function recordWillDelete(store, record) { + var _this2 = this; + + record.eachRelationship(function (key, relationship) { + if (relationship.kind === 'belongsTo') { + var parentRecord = record.get(relationship.key); + var inverseKey = record.inverseFor(relationship.key); + if (inverseKey && parentRecord.get('id')) { + var parentRef = _this2._getCollectionRef(inverseKey.type, parentRecord.get('id')); + _this2._removeHasManyRecord(store, parentRef, inverseKey.name, record.constructor, record.id); + } + } + }); + }, + + listenForChanges: function listenForChanges(store, typeClass, record) { + var _this3 = this; + + // embedded records will get their changes from parent listeners + if (!this.isRecordEmbedded(record)) { + record.__listening = true; + var ref = this._getCollectionRef(typeClass, record.id); + var called = false; + ref.on('value', function (snapshot) { + if (called) { + _ember2['default'].run(function () { + _this3._handleChildValue(store, typeClass, snapshot); + }); + } + called = true; + }, function (error) { + _ember2['default'].Logger.error(error); + }); + } + }, + + stopListening: function stopListening(store, typeClass, record) { + if (record.__listening) { + var ref = this._getCollectionRef(typeClass, record.id); + ref.off('value'); + record.__listening = false; + } + }, + + /** + * Called by the store to retrieve the JSON for all of the records for a + * given type. The method will return a promise which will resolve when the + * value is successfully fetched from Firebase. + * + * Additionally, from this point on, any records of this type that are added, + * removed or modified from Firebase will automatically be reflected in the + * store. + */ + findAll: function findAll(store, typeClass) { + var _this4 = this; + + var ref = this._getCollectionRef(typeClass); + + var log = 'DS: FirebaseAdapter#findAll ' + typeClass.modelName + ' to ' + ref.toString(); + + return this._fetch(ref, log).then(function (snapshot) { + if (!_this4._findAllHasEventsForType(typeClass)) { + _this4._findAllAddEventListeners(store, typeClass, ref); + } + var results = []; + snapshot.forEach(function (childSnapshot) { + var payload = _this4._assignIdToPayload(childSnapshot); + _this4._updateRecordCacheForType(typeClass, payload, store); + results.push(payload); + }); + + return results; + }); + }, + + query: function query(store, typeClass, _query, recordArray) { + var _this5 = this; + + var ref = this._getCollectionRef(typeClass); + var modelName = typeClass.modelName; + + ref = this.applyQueryToRef(ref, _query); + + ref.on('child_added', _ember2['default'].run.bind(this, function (snapshot) { + var record = store.peekRecord(modelName, this._getKey(snapshot)); + + if (!record || !record.__listening) { + var payload = this._assignIdToPayload(snapshot); + var normalizedData = store.normalize(typeClass.modelName, payload); + this._updateRecordCacheForType(typeClass, payload, store); + record = store.push(normalizedData); + } + + if (record) { + recordArray.get('content').addObject(record._internalModel); + } + })); + + // `child_changed` is already handled by the record's + // value listener after a store.push. `child_moved` is + // a much less common case because it relates to priority + + ref.on('child_removed', _ember2['default'].run.bind(this, function (snapshot) { + var record = store.peekRecord(modelName, this._getKey(snapshot)); + if (record) { + recordArray.get('content').removeObject(record._internalModel); + } + })); + + // clean up event handlers when the array is being destroyed + // so that future firebase events wont keep trying to use a + // destroyed store/serializer + recordArray.__firebaseCleanup = function () { + ref.off('child_added'); + ref.off('child_removed'); + }; + + var log = 'DS: FirebaseAdapter#query ' + modelName + ' with ' + _query; + + return this._fetch(ref, log).then(function (snapshot) { + if (!_this5._findAllHasEventsForType(typeClass)) { + _this5._findAllAddEventListeners(store, typeClass, ref); + } + var results = []; + snapshot.forEach(function (childSnapshot) { + var payload = _this5._assignIdToPayload(childSnapshot); + _this5._updateRecordCacheForType(typeClass, payload, store); + results.push(payload); + }); + return results; + }); + }, + + applyQueryToRef: function applyQueryToRef(ref, query) { + + if (!query.orderBy) { + query.orderBy = '_key'; + } + + if (query.orderBy === '_key') { + ref = ref.orderByKey(); + } else if (query.orderBy === '_value') { + ref = ref.orderByValue(); + } else if (query.orderBy === '_priority') { + ref = ref.orderByPriority(); + } else { + ref = ref.orderByChild(query.orderBy); + } + + ref = this._applyRangesToRef(ref, query); + ref = this._applyLimitsToRef(ref, query); + + return ref; + }, + + _applyRangesToRef: function _applyRangesToRef(ref, query) { + var methods = ['equalTo', 'startAt', 'endAt']; + methods.forEach(function (key) { + if (query[key] !== undefined) { + ref = ref[key](query[key]); + } + }); + + return ref; + }, + + _applyLimitsToRef: function _applyLimitsToRef(ref, query) { + var methods = ['limitToFirst', 'limitToLast']; + methods.forEach(function (key) { + if (isInteger(query[key])) { + ref = ref[key](query[key]); + } + }); + + return ref; + }, + + /** + * Keep track of what types `.findAll()` has been called for + * so duplicate listeners aren't added + */ + _findAllMapForType: undefined, + + /** + * Determine if the current type is already listening for children events + */ + _findAllHasEventsForType: function _findAllHasEventsForType(typeClass) { + return !_ember2['default'].isNone(this._findAllMapForType[typeClass.modelName]); + }, + + /** + * After `.findAll()` is called on a modelName, continue to listen for + * `child_added`, `child_removed`, and `child_changed` + */ + _findAllAddEventListeners: function _findAllAddEventListeners(store, typeClass, ref) { + var modelName = typeClass.modelName; + this._findAllMapForType[modelName] = true; + + ref.on('child_added', _ember2['default'].run.bind(this, function (snapshot) { + if (!store.hasRecordForId(modelName, this._getKey(snapshot))) { + this._handleChildValue(store, typeClass, snapshot); + } + })); + }, + + /** + * Push a new child record into the store + */ + _handleChildValue: function _handleChildValue(store, typeClass, snapshot) { + // No idea why we need this, we are already turning off the callback by + // calling ref.off in recordWillUnload. Something is fishy here + if (store.isDestroying) { + return; + } + var value = snapshot.val(); + if (value === null) { + var id = this._getKey(snapshot); + var record = store.peekRecord(typeClass.modelName, id); + // TODO: refactor using ED + if (!record.get('isDeleted')) { + record.deleteRecord(); + } + } else { + var payload = this._assignIdToPayload(snapshot); + this._pushLater(typeClass.modelName, payload.id, payload); + } + }, + + /** + * `createRecord` is an alias for `updateRecord` because calling \ + * `ref.set()` would wipe out any existing relationships + */ + createRecord: function createRecord(store, typeClass, snapshot) { + var _this6 = this; + + return this.updateRecord(store, typeClass, snapshot).then(function () { + _this6.listenForChanges(store, typeClass, snapshot.record); + }); + }, + + /** + * Called by the store when a record is created/updated via the `save` + * method on a model record instance. + * + * The `updateRecord` method serializes the record and performs an `update()` + * at the the Firebase location and a `.set()` at any relationship locations + * The method will return a promise which will be resolved when the data and + * any relationships have been successfully saved to Firebase. + * + * We take an optional record reference, in order for this method to be usable + * for saving nested records as well. + */ + updateRecord: function updateRecord(store, typeClass, snapshot) { + var _this7 = this; + + var recordRef = this._getAbsoluteRef(snapshot.record); + var recordCache = this._getRecordCache(typeClass, snapshot.id); + var pathPieces = recordRef.path.toString().split('/'); + var lastPiece = pathPieces[pathPieces.length - 1]; + var serializedRecord = snapshot.serialize({ + includeId: lastPiece !== snapshot.id // record has no firebase `key` in path + }); + var serializer = store.serializerFor(typeClass.modelName); + + return new Promise(function (resolve, reject) { + var relationshipsToSave = []; + // first we remove all relationships data from the serialized record, we backup the + // removed data so that we can save it at a later stage. + snapshot.record.eachRelationship(function (key, relationship) { + var relationshipKey = serializer.keyForRelationship(key); + var data = serializedRecord[relationshipKey]; + var isEmbedded = _this7.isRelationshipEmbedded(store, typeClass.modelName, relationship); + var hasMany = relationship.kind === 'hasMany'; + if (hasMany || isEmbedded) { + if (!_ember2['default'].isNone(data)) { + relationshipsToSave.push({ + data: data, + relationship: relationship, + isEmbedded: isEmbedded, + hasMany: hasMany + }); + } + delete serializedRecord[relationshipKey]; + } + }); + var reportError = function reportError(errors) { + var error = new Error('Some errors were encountered while saving ' + typeClass + ' ' + snapshot.id); + error.errors = errors; + reject(error); + }; + _this7._updateRecord(recordRef, serializedRecord).then(function () { + // and now we construct the list of promise to save relationships. + var savedRelationships = relationshipsToSave.map(function (relationshipToSave) { + var data = relationshipToSave.data; + var relationship = relationshipToSave.relationship; + if (relationshipToSave.hasMany) { + return _this7._saveHasManyRelationship(store, typeClass, relationship, data, recordRef, recordCache); + } else { + // embedded belongsTo, we need to fill in the informations. + if (relationshipToSave.isEmbedded) { + return _this7._saveEmbeddedBelongsToRecord(store, typeClass, relationship, data, recordRef); + } + } + }); + return _ember2['default'].RSVP.allSettled(savedRelationships); + })['catch'](function (e) { + reportError([e]); + }).then(function (results) { + var rejected = _ember2['default'].A(results).filterBy('state', 'rejected'); + if (rejected.length !== 0) { + reportError(rejected.mapBy('reason').toArray()); + } else { + resolve(); + } + }); + }, 'DS: FirebaseAdapter#updateRecord ' + typeClass + ' to ' + recordRef.toString()); + }, + + /** + * Update a single record without caring for the relationships + * @param {Firebase} recordRef + * @param {Object} serializedRecord + * @return {Promise} + */ + _updateRecord: function _updateRecord(recordRef, serializedRecord) { + var _this8 = this; + + this._incrementWaiters(); + return (0, _utilsToPromise2['default'])(recordRef.update, recordRef, [serializedRecord]).then(function (result) { + _this8._decrementWaiters(); + return result; + })['catch'](function (e) { + _this8._decrementWaiters(); + return _ember2['default'].RSVP.reject(e); + }); + }, + + /** + * Call _saveHasManyRelationshipRecord on each record in the relationship + * and then resolve once they have all settled + */ + _saveHasManyRelationship: function _saveHasManyRelationship(store, typeClass, relationship, ids, recordRef, recordCache) { + var _this9 = this; + + if (!_ember2['default'].isArray(ids)) { + throw new Error('hasMany relationships must must be an array'); + } + var idsCache = _ember2['default'].A(recordCache[relationship.key]); + var dirtyRecords = []; + + // Added + var addedRecords = ids.filter(function (id) { + return !idsCache.includes(id); + }); + + // Dirty + dirtyRecords = ids.filter(function (id) { + var relatedModelName = relationship.type; + return store.hasRecordForId(relatedModelName, id) && store.peekRecord(relatedModelName, id).get('hasDirtyAttributes') === true; + }); + + dirtyRecords = uniq(dirtyRecords.concat(addedRecords)).map(function (id) { + return _this9._saveHasManyRecord(store, typeClass, relationship, recordRef, id); + }); + + // Removed + var removedRecords = idsCache.filter(function (id) { + return !ids.includes(id); + }); + + removedRecords = removedRecords.map(function (id) { + return _this9._removeHasManyRecord(store, recordRef, relationship.key, typeClass, id); + }); + // Combine all the saved records + var savedRecords = dirtyRecords.concat(removedRecords); + // Wait for all the updates to finish + return _ember2['default'].RSVP.allSettled(savedRecords).then(function (savedRecords) { + var rejected = _ember2['default'].A(_ember2['default'].A(savedRecords).filterBy('state', 'rejected')); + if (rejected.get('length') === 0) { + // Update the cache + recordCache[relationship.key] = ids; + return savedRecords; + } else { + var error = new Error('Some errors were encountered while saving a hasMany relationship ' + relationship.parentType + ' -> ' + relationship.type); + error.errors = _ember2['default'].A(rejected).mapBy('reason'); + throw error; + } + }); + }, + + /** + * If the relationship is `async: true`, create a child ref + * named with the record id and set the value to true + * If the relationship is `embedded: true`, create a child ref + * named with the record id and update the value to the serialized + * version of the record + */ + _saveHasManyRecord: function _saveHasManyRecord(store, typeClass, relationship, parentRef, id) { + var serializer = store.serializerFor(typeClass.modelName); + var ref = this._getRelationshipRef(parentRef, serializer.keyForRelationship(relationship.key), id); + var record = store.peekRecord(relationship.type, id); + var isEmbedded = this.isRelationshipEmbedded(store, typeClass.modelName, relationship); + if (isEmbedded) { + return record.save(); + } + + return (0, _utilsToPromise2['default'])(ref.set, ref, [true]); + }, + + /** + * Determine from the serializer if the relationship is embedded via the + * serializer's `attrs` hash. + * + * @return {Boolean} Is the relationship embedded? + */ + isRelationshipEmbedded: function isRelationshipEmbedded(store, modelName, relationship) { + var serializer = store.serializerFor(modelName); + return serializer.hasDeserializeRecordsOption(relationship.key); + }, + + /** + * Determine from if the record is embedded via implicit relationships. + * + * @return {Boolean} Is the relationship embedded? + */ + isRecordEmbedded: function isRecordEmbedded(record) { + if (record._internalModel) { + record = record._internalModel; + } + + var found = this.getFirstEmbeddingParent(record); + + return !!found; + }, + + /** + * Remove a relationship + */ + _removeHasManyRecord: function _removeHasManyRecord(store, parentRef, key, typeClass, id) { + var relationshipKey = store.serializerFor(typeClass.modelName).keyForRelationship(key); + var ref = this._getRelationshipRef(parentRef, relationshipKey, id); + return (0, _utilsToPromise2['default'])(ref.remove, ref, [], ref.toString()); + }, + + /** + * Save an embedded belongsTo record and set its internal firebase ref + * + * @return {Promise} + */ + _saveEmbeddedBelongsToRecord: function _saveEmbeddedBelongsToRecord(store, typeClass, relationship, id, parentRef) { + var record = store.peekRecord(relationship.type, id); + if (record) { + return record.save(); + } + return _ember2['default'].RSVP.Promise.reject(new Error('Unable to find record with id ' + id + ' from embedded relationship: ' + JSON.stringify(relationship))); + }, + + /** + * Called by the store when a record is deleted. + */ + deleteRecord: function deleteRecord(store, typeClass, snapshot) { + var ref = this._getAbsoluteRef(snapshot.record); + ref.off('value'); + return (0, _utilsToPromise2['default'])(ref.remove, ref); + }, + + /** + * Determines a path fo a given type + */ + pathForType: function pathForType(modelName) { + var camelized = _ember2['default'].String.camelize(modelName); + return (0, _emberInflector.pluralize)(camelized); + }, + + /** + * Return a Firebase reference for a given modelName and optional ID. + */ + _getCollectionRef: function _getCollectionRef(typeClass, id) { + var ref = this._ref; + if (typeClass) { + ref = ref.child(this.pathForType(typeClass.modelName)); + } + if (id) { + ref = ref.child(id); + } + return ref; + }, + + /** + * Returns a Firebase reference for a record taking into account if the record is embedded + * + * @param {DS.Model} record + * @return {Firebase} + */ + _getAbsoluteRef: function _getAbsoluteRef(record) { + if (record._internalModel) { + record = record._internalModel; + } + + var embeddingParent = this.getFirstEmbeddingParent(record); + + if (embeddingParent) { + var parent = embeddingParent.record; + var relationship = embeddingParent.relationship; + + var embeddedKey = parent.store.serializerFor(parent.modelName).keyForRelationship(relationship.key); + var recordRef = this._getAbsoluteRef(parent).child(embeddedKey); + + if (relationship.kind === 'hasMany') { + recordRef = recordRef.child(record.id); + } + return recordRef; + } + + return this._getCollectionRef(record.type, record.id); + }, + + /** + * Returns the parent record and relationship where any embedding is detected + * + * @param {DS.InternalModel} internalModel + * @return {Object} + */ + getFirstEmbeddingParent: function getFirstEmbeddingParent(internalModel) { + var relationships = assign({}, internalModel._implicitRelationships, internalModel._relationships.initializedRelationships); + + var embeddingParentRel = undefined; + var relationshipKeys = Object.keys(relationships); + + for (var i = 0; i < relationshipKeys.length; i++) { + var rel = relationships[relationshipKeys[i]]; + var members = rel.members.toArray(); + var _parent = members[0]; + + if (!_parent || !rel.inverseKey) { + continue; + } + + var _parentRel = _parent._relationships.get(rel.inverseKey); + if (this.isRelationshipEmbedded(this.store, _parent.type.modelName, _parentRel.relationshipMeta)) { + embeddingParentRel = rel; + break; + } + } + + if (embeddingParentRel) { + var parent = embeddingParentRel.members.toArray()[0]; + var parentKey = embeddingParentRel.inverseKey; + var parentRel = parent._relationships.get(parentKey).relationshipMeta; + return { record: parent, relationship: parentRel }; + } + }, + + /** + * Return a Firebase reference based on a relationship key and record id + */ + _getRelationshipRef: function _getRelationshipRef(ref, key, id) { + return ref.child(key).child(id); + }, + + /** + * The amount of time (ms) before the _queue is flushed + */ + _queueFlushDelay: 1000 / 60, // 60fps + + /** + * Schedules a `_flushQueue` for later. + * + * @private + */ + _flushLater: function _flushLater() { + _ember2['default'].run.later(this, this._flushQueue, this._queueFlushDelay); + }, + + /** + * Flush all delayed `store.push` payloads in `this._queuedPayloads`. + * + * @private + */ + _flushQueue: function _flushQueue() { + var _this10 = this; + + var store = this.get('store'); + if (store.isDestroying) { + return; + } + + this._queue.forEach(function (key) { + var _queuedPayloads$key = _this10._queuedPayloads[key]; + var payload = _queuedPayloads$key.payload; + var modelName = _queuedPayloads$key.modelName; + + var normalizedData = store.normalize(modelName, payload); + store.push(normalizedData); + }); + this._queuedPayloads = {}; + this._queue.length = 0; + }, + + /** + * Schedule a payload push for later. This will only push at most one payload + * per record. When trying to push to the same record multiple times, only the + * last push will be kept. + * + * @param {string} modelName + * @param {string} id + * @param {!Object} payload + * @private + */ + _pushLater: function _pushLater(modelName, id, payload) { + var store = this.get('store'); + if (!this._queueFlushDelay) { + var normalizedData = store.normalize(modelName, payload); + store.push(normalizedData); + return; + } + + var key = modelName + '-' + id; + if (this._queuedPayloads[key]) { + // remove from original place in queue (will be added to end) + var oldPosition = this._queue.indexOf(key); + this._queue.splice(oldPosition, 1); + } + this._queuedPayloads[key] = { payload: payload, modelName: modelName }; + this._queue.push(key); + + // if this is the first item to be queued, schedule a flush + if (this._queue.length === 1) { + this._flushLater(); + } + }, + + /** + * A cache of hasMany relationships that can be used to + * diff against new relationships when a model is saved + */ + _recordCacheForType: undefined, + + /** + * _updateHasManyCacheForType + */ + _updateRecordCacheForType: function _updateRecordCacheForType(typeClass, payload, store) { + var _this11 = this; + + if (!payload) { + return; + } + var id = payload.id; + var cache = this._getRecordCache(typeClass, id); + var serializer = store.serializerFor(typeClass.modelName); + // Only cache relationships for now + // and do the same for embedded records + typeClass.eachRelationship(function (key, relationship) { + if (relationship.kind === 'hasMany') { + var relationshipPayload = payload[serializer.keyForRelationship(key)]; + if (!relationshipPayload) { + cache[key] = _ember2['default'].A(); + } else { + var isEmbedded = _this11.isRelationshipEmbedded(store, typeClass.modelName, relationship); + if (isEmbedded) { + var relationshipTypeClass = store.modelFor(relationship.type); + for (var _id in relationshipPayload) { + var obj = relationshipPayload[_id]; + obj.id = _id; + _this11._updateRecordCacheForType(relationshipTypeClass, obj, store); + } + } else { + var ids = Object.keys(relationshipPayload); + cache[key] = _ember2['default'].A(ids); + } + } + } + }); + }, + + /** + * Get or create the cache for a record + */ + _getRecordCache: function _getRecordCache(typeClass, id) { + var modelName = typeClass.modelName; + var cache = this._recordCacheForType; + cache[modelName] = cache[modelName] || {}; + cache[modelName][id] = cache[modelName][id] || {}; + return cache[modelName][id]; + }, + + /** + * A utility for retrieving the key name of a Firebase ref or + * DataSnapshot. This is backwards-compatible with `name()` + * from Firebase 1.x.x and `key()` from Firebase 2.0.0+. Once + * support for Firebase 1.x.x is dropped in EmberFire, this + * helper can be removed. + */ + _getKey: function _getKey(refOrSnapshot) { + var key; + if (typeof refOrSnapshot.key === 'function') { + key = refOrSnapshot.key(); + } else if (typeof refOrSnapshot.key === 'string') { + key = refOrSnapshot.key; + } else { + key = refOrSnapshot.name(); + } + return key; + }, + + /** + * We don't need background reloading, because firebase! + */ + shouldBackgroundReloadRecord: function shouldBackgroundReloadRecord() { + return false; + } +}); +module.exports = exports['default']; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"../mixins/waitable":3,"../utils/to-promise":5,"ember-inflector":6}],2:[function(require,module,exports){ +(function (global){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _ember = (typeof window !== "undefined" ? window['Ember'] : typeof global !== "undefined" ? global['Ember'] : null); + +var _ember2 = _interopRequireDefault(_ember); + +var _emberData = (typeof window !== "undefined" ? window['DS'] : typeof global !== "undefined" ? global['DS'] : null); + +var _emberData2 = _interopRequireDefault(_emberData); + +var _firebase = (typeof window !== "undefined" ? window['firebase'] : typeof global !== "undefined" ? global['firebase'] : null); + +var _firebase2 = _interopRequireDefault(_firebase); + +var _adaptersFirebase = require('../adapters/firebase'); + +var _adaptersFirebase2 = _interopRequireDefault(_adaptersFirebase); + +var _serializersFirebase = require('../serializers/firebase'); + +var _serializersFirebase2 = _interopRequireDefault(_serializersFirebase); + +var VERSION = '0.0.0'; + +if (_ember2['default'].libraries) { + if (_firebase2['default'].SDK_VERSION) { + _ember2['default'].libraries.registerCoreLibrary('Firebase', _firebase2['default'].SDK_VERSION); + } + + _ember2['default'].libraries.registerCoreLibrary('EmberFire', VERSION); +} + +exports['default'] = { + name: 'emberfire', + before: 'ember-data', + initialize: function initialize() { + + // To support Ember versions below 2.1.0 as well. + // See http://emberjs.com/deprecations/v2.x/#toc_initializer-arity + var application = arguments[1] || arguments[0]; + + application.register('adapter:-firebase', _adaptersFirebase2['default']); + application.register('serializer:-firebase', _serializersFirebase2['default']); + + var providerSettings = { instantiate: false, singleton: false }; + application.register('firebase-auth-provider:twitter', _firebase2['default'].auth.TwitterAuthProvider, providerSettings); + application.register('firebase-auth-provider:facebook', _firebase2['default'].auth.FacebookAuthProvider, providerSettings); + application.register('firebase-auth-provider:github', _firebase2['default'].auth.GithubAuthProvider, providerSettings); + application.register('firebase-auth-provider:google', _firebase2['default'].auth.GoogleAuthProvider, providerSettings); + + // Monkeypatch the store until ED gives us a good way to listen to push events + if (!_emberData2['default'].Store.prototype._emberfirePatched) { + _emberData2['default'].Store.reopen({ + _emberfirePatched: true, + + _emberfireHandleRecordPush: function _emberfireHandleRecordPush(records) { + var _this = this; + + if (typeof records !== 'undefined') { + records.forEach(function (record) { + var modelName = record.constructor.modelName; + var adapter = _this.adapterFor(modelName); + if (adapter.recordWasPushed) { + adapter.recordWasPushed(_this, modelName, record); + } + }); + } + }, + + push: function push() { + var result = this._super.apply(this, arguments); + var records = result; + + if (records === null) { + return null; + } + + if (!_ember2['default'].isArray(result)) { + records = [result]; + } + + this._emberfireHandleRecordPush(records); + return result; + }, + + _push: function _push() { + var pushed = this._super.apply(this, arguments); + var records; + if (Array.isArray(pushed)) { + records = pushed.map(function (internalModel) { + return internalModel.getRecord(); + }); + } else if (pushed) { + records = [pushed.getRecord()]; + } + this._emberfireHandleRecordPush(records); + return pushed; + }, + + recordWillUnload: function recordWillUnload(record) { + var adapter = this.adapterFor(record.constructor.modelName); + if (adapter.recordWillUnload) { + adapter.recordWillUnload(this, record); + } + }, + + recordWillDelete: function recordWillDelete(record) { + var adapter = this.adapterFor(record.constructor.modelName); + if (adapter.recordWillDelete) { + adapter.recordWillDelete(this, record); + } + } + }); + } + + if (!_emberData2['default'].Model.prototype._emberfirePatched) { + _emberData2['default'].Model.reopen({ + _emberfirePatched: true, + + unloadRecord: function unloadRecord() { + this.store.recordWillUnload(this); + return this._super(); + }, + + deleteRecord: function deleteRecord() { + this.store.recordWillDelete(this); + this._super(); + }, + + ref: function ref() { + var adapter = this.store.adapterFor(this.constructor.modelName); + if (adapter._getAbsoluteRef) { + return adapter._getAbsoluteRef(this); + } + } + }); + } + + if (!_emberData2['default'].AdapterPopulatedRecordArray.prototype._emberfirePatched) { + _emberData2['default'].AdapterPopulatedRecordArray.reopen({ + _emberfirePatched: true, + + willDestroy: function willDestroy() { + if (this.__firebaseCleanup) { + this.__firebaseCleanup(); + } + return this._super(); + } + }); + } + + _emberData2['default'].FirebaseAdapter = _adaptersFirebase2['default']; + _emberData2['default'].FirebaseSerializer = _serializersFirebase2['default']; + } +}; +module.exports = exports['default']; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"../adapters/firebase":1,"../serializers/firebase":4}],3:[function(require,module,exports){ +(function (global){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _ember = (typeof window !== "undefined" ? window['Ember'] : typeof global !== "undefined" ? global['Ember'] : null); + +var _ember2 = _interopRequireDefault(_ember); + +exports['default'] = _ember2['default'].Mixin.create({ + + init: function init() { + this._super.apply(this, arguments); + // unresolved requests, used in testing + this._reasons = 0; + + if (_ember2['default'].testing) { + this._registerWaiter(); + } + }, + + _incrementWaiters: function _incrementWaiters() { + this._reasons++; + }, + + _decrementWaiters: function _decrementWaiters() { + this._reasons--; + }, + + /** + * The waiter calls this to determine if testing should wait. Override in + * the implementing class if needed. + * + * @return {Boolean} + * @private + */ + _shouldWait: function _shouldWait() { + return this._reasons === 0; + }, + + /** + * Wire up a waiter for this instance. + * + * @private + */ + _registerWaiter: function _registerWaiter() { + var _this = this; + + this._waiter = function () { + return _this._shouldWait(); + }; + _ember2['default'].Test.registerWaiter(this._waiter); + } + +}); +module.exports = exports['default']; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],4:[function(require,module,exports){ +(function (global){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _ember = (typeof window !== "undefined" ? window['Ember'] : typeof global !== "undefined" ? global['Ember'] : null); + +var _ember2 = _interopRequireDefault(_ember); + +var _emberData = (typeof window !== "undefined" ? window['DS'] : typeof global !== "undefined" ? global['DS'] : null); + +var _emberData2 = _interopRequireDefault(_emberData); + +var _firebase = (typeof window !== "undefined" ? window['firebase'] : typeof global !== "undefined" ? global['firebase'] : null); + +var _firebase2 = _interopRequireDefault(_firebase); + +var assign = _ember2['default'].assign; + +/** + * The Firebase serializer helps normalize relationships and can be extended on + * a per model basis. + */ +exports['default'] = _emberData2['default'].JSONSerializer.extend(_emberData2['default'].EmbeddedRecordsMixin, { + isNewSerializerAPI: true, + + /** + * Firebase have a special value for a date 'firebase.database.ServerValue.TIMESTAMP' + * that tells it to insert server time. We need to make sure the value is not scrapped + * by the data attribute transforms. + * + * @override + */ + serializeAttribute: function serializeAttribute(snapshot, json, key, attribute) { + var value = snapshot.attr(key); + this._super(snapshot, json, key, attribute); + if (this._canSerialize(key)) { + if (value === _firebase2['default'].database.ServerValue.TIMESTAMP) { + + var payloadKey = this._getMappedKey(key, snapshot.type); + + if (payloadKey === key && this.keyForAttribute) { + payloadKey = this.keyForAttribute(key, 'serialize'); + } + // do not transform + json[payloadKey] = value; + } + } + }, + + /** + * Firebase does not send null values, it omits the key altogether. This nullifies omitted + * properties so that property deletions sync correctly. + * + * @override + */ + extractAttributes: function extractAttributes(modelClass, resourceHash) { + var attributes = this._super(modelClass, resourceHash); + + // nullify omitted attributes + modelClass.eachAttribute(function (key) { + if (!attributes.hasOwnProperty(key)) { + attributes[key] = null; + } + }); + + return attributes; + }, + + /** + * @override + */ + extractRelationships: function extractRelationships(modelClass, payload) { + this.normalizeRelationships(modelClass, payload); + return this._super(modelClass, payload); + }, + + /** + * Normalizes `hasMany` relationship structure before passing + * to `JSONSerializer.extractRelationships` + * + * before: + * + * ```js + * { + * comments: { + * abc: true, + * def: true, + * } + * } + * ``` + * + * after: + * + * ```js + * { + * comments: [ 'abc', 'def' ] + * } + * ``` + * + * Or for embedded objects: + * + * ```js + * { + * comments: { + * 'abc': { body: 'a' }, + * 'def': { body: 'd' ) + * } + * } + * ``` + * + * these should become: + * + * ```js + * { + * comments: [ + * { + * id: 'abc', + * body: 'a' + * }, + * { + * id: 'def', + * body: 'd' + * } + * ] + * } + * ``` + */ + normalizeRelationships: function normalizeRelationships(modelClass, payload) { + var _this = this; + + modelClass.eachRelationship(function (key, meta) { + var relationshipKey = _this.keyForRelationship(key, meta.kind, 'deserialize'); + + if (meta.kind === 'hasMany') { + if (payload.hasOwnProperty(relationshipKey)) { + (function () { + var relationshipPayload = payload[relationshipKey]; + // embedded + if (_this.hasDeserializeRecordsOption(key)) { + if (typeof relationshipPayload === 'object' && !_ember2['default'].isArray(relationshipPayload)) { + relationshipPayload = Object.keys(relationshipPayload).map(function (id) { + return assign({ id: id }, relationshipPayload[id]); + }); + } else if (_ember2['default'].isArray(relationshipPayload)) { + relationshipPayload = _this._addNumericIdsToEmbeddedArray(relationshipPayload); + } else { + throw new Error(modelClass.toString() + ' relationship ' + meta.kind + '(\'' + meta.type + '\') must contain embedded records with an `id`. Example: { "' + key + '": { "' + meta.type + '_1": { "id": "' + meta.type + '_1" } } } instead got: ' + JSON.stringify(payload[key])); + } + } + + // normalized + else { + if (typeof relationshipPayload === 'object' && !_ember2['default'].isArray(relationshipPayload)) { + relationshipPayload = Object.keys(relationshipPayload); + } else if (_ember2['default'].isArray(relationshipPayload)) { + relationshipPayload = _this._convertBooleanArrayToIds(relationshipPayload); + } else { + throw new Error(modelClass.toString() + ' relationship ' + meta.kind + '(\'' + meta.type + '\') must be a key/value map. Example: { "' + key + '": { "' + meta.type + '_1": true } } instead got: ' + JSON.stringify(payload[key])); + } + } + + payload[relationshipKey] = relationshipPayload; + })(); + } + + // hasMany property is not present + // server will not send a property which has no content + // (i.e. it will never send `comments: null`) so we need to + // force the empty relationship + else { + payload[relationshipKey] = []; + } + } + + if (meta.kind === 'belongsTo') { + if (!payload.hasOwnProperty(relationshipKey)) { + // server wont send property if it was made null elsewhere + payload[relationshipKey] = null; + } + } + }); + }, + + /** + * Coerce arrays back into relationship arrays. When numeric ids are used + * the firebase server will send back arrays instead of object hashes in + * certain situations. + * + * See the conditions and reasoning here: + * https://www.firebase.com/docs/web/guide/understanding-data.html#section-arrays-in-firebase + * + * Stored in Firebase: + * + * ```json + * { + * "0": true, + * "1": true, + * "3": true + * } + * ``` + * + * Given back by the JS client: + * + * ```js + * [true, true, null, true] + * ``` + * + * What we need: + * + * ```js + * [ "0", "1", "3" ] + * ``` + * + * @param {Array} arr Input array + * @return {Array} Fixed array + * @private + */ + _convertBooleanArrayToIds: function _convertBooleanArrayToIds(arr) { + var result = []; + for (var i = 0; i < arr.length; i++) { + if (arr[i] === true) { + result.push('' + i); + } else if (typeof arr[i] === 'string') { + throw new Error('hasMany relationship contains invalid data, should be in the form: { comment_1: true, comment_2: true } but was ' + JSON.stringify(arr)); + } + } + return result; + }, + + /** + * Fix embedded array ids. + * + * Objects are stored in Firebase with their id in the key only: + * + * ```json + * { + * "0": { obj0 }, + * "1": { obj1 }, + * "3": { obj3 } + * } + * ``` + * + * Given back by the JS client: + * + * ```js + * [{ obj0 }, { obj1 }, null, { obj3 }] + * ``` + * + * What we need: + * + * ```js + * [ { id: '0', ...obj0 }, { id: '1', ...obj1 }, { id: '3', ...obj3 } ] + * ``` + * + * https://www.firebase.com/docs/web/guide/understanding-data.html#section-arrays-in-firebase + * + * @param {Array} arr Input array + * @return {Array} Fixed array + * @private + */ + _addNumericIdsToEmbeddedArray: function _addNumericIdsToEmbeddedArray(arr) { + var result = []; + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + if (typeof arr[i] !== 'object') { + throw new Error('expecting embedded object hash but found ' + JSON.stringify(arr[i])); + } + result.push(assign({ id: '' + i }, arr[i])); + } + } + return result; + }, + + /** + * Even when records are embedded, bypass EmbeddedRecordsMixin + * and invoke JSONSerializer's method which serializes to ids only. + * + * The adapter handles saving the embedded records via `r.save()` + * and ensures that dirty states and rollback work. + * + * Will not be neccesary when this issue is resolved: + * + * https://github.com/emberjs/data/issues/2487 + * + * @override + */ + serializeHasMany: function serializeHasMany(snapshot, json, relationship) { + _emberData2['default'].JSONSerializer.prototype.serializeHasMany.call(this, snapshot, json, relationship); + }, + + /** + * @see #serializeHasMany + * @override + */ + serializeBelongsTo: function serializeBelongsTo(snapshot, json, relationship) { + _emberData2['default'].JSONSerializer.prototype.serializeBelongsTo.call(this, snapshot, json, relationship); + }, + + /** + * @override + */ + shouldSerializeHasMany: function shouldSerializeHasMany(snapshot, key, relationship) { + return this._canSerialize(key); + }, + + /** + * @override + * @deprecated + */ + _shouldSerializeHasMany: function _shouldSerializeHasMany(snapshot, key, relationship) { + return this._canSerialize(key); + } +}); +module.exports = exports['default']; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],5:[function(require,module,exports){ +(function (global){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _ember = (typeof window !== "undefined" ? window['Ember'] : typeof global !== "undefined" ? global['Ember'] : null); + +var _ember2 = _interopRequireDefault(_ember); + +exports['default'] = function (fn, context, _args, errorMsg) { + var args = _args || []; + return new _ember2['default'].RSVP.Promise(function (resolve, reject) { + var callback = function callback(error) { + if (error) { + if (errorMsg && typeof error === 'object') { + error.location = errorMsg; + } + _ember2['default'].run(null, reject, error); + } else { + _ember2['default'].run(null, resolve); + } + }; + args.push(callback); + fn.apply(context, args); + }); +}; + +module.exports = exports['default']; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],6:[function(require,module,exports){ +/* jshint node: true */ +'use strict'; + +module.exports = { + name: 'ember-inflector' +}; + +},{}],7:[function(require,module,exports){ +(function (global){ +'use strict'; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _ember = (typeof window !== "undefined" ? window['Ember'] : typeof global !== "undefined" ? global['Ember'] : null); + +var _ember2 = _interopRequireDefault(_ember); + +var _emberData = (typeof window !== "undefined" ? window['DS'] : typeof global !== "undefined" ? global['DS'] : null); + +var _emberData2 = _interopRequireDefault(_emberData); + +var _addonAdaptersFirebase = require('../../addon/adapters/firebase'); + +var _addonAdaptersFirebase2 = _interopRequireDefault(_addonAdaptersFirebase); + +var _addonSerializersFirebase = require('../../addon/serializers/firebase'); + +var _addonSerializersFirebase2 = _interopRequireDefault(_addonSerializersFirebase); + +var _addonInitializersEmberfire = require('../../addon/initializers/emberfire'); + +var _addonInitializersEmberfire2 = _interopRequireDefault(_addonInitializersEmberfire); + +_emberData2['default'].FirebaseAdapter = _addonAdaptersFirebase2['default']; +_emberData2['default'].FirebaseSerializer = _addonSerializersFirebase2['default']; + +_ember2['default'].onLoad('Ember.Application', function (Application) { + Application.initializer(_addonInitializersEmberfire2['default']); +}); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"../../addon/adapters/firebase":1,"../../addon/initializers/emberfire":2,"../../addon/serializers/firebase":4}]},{},[7]) + + +//# sourceMappingURL=emberfire.js.map diff --git a/dist/emberfire.js.map b/dist/emberfire.js.map new file mode 100644 index 00000000..139836c4 --- /dev/null +++ b/dist/emberfire.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","addon/adapters/firebase.js","addon/initializers/emberfire.js","addon/mixins/waitable.js","addon/serializers/firebase.js","addon/utils/to-promise.js","node_modules/ember-inflector/index.js","vendor/legacy/emberfire.js"],"names":[],"mappings":";;;;;;;;;AAAA;;;;;;;;;;qBCAkB,OAAO;;;;yBACV,YAAY;;;;8BACN,oBAAoB;;;;8BACnB,qBAAqB;;;;8BAKjB,iBAAiB;;IAHnC,MAAM,sBAAN,MAAM;IAAE,IAAI,sBAAJ,IAAI;IACZ,OAAO,GAAK,IAAI,CAAhB,OAAO;;AAIf,IAAI,IAAI,GAAG,SAAP,IAAI,CAAa,GAAG,EAAE;AACxB,MAAI,GAAG,GAAG,mBAAM,CAAC,EAAE,CAAC;;AAEpB,KAAG,CAAC,OAAO,CAAC,UAAS,CAAC,EAAE;AACtB,QAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;AACtB,SAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACb;GACF,CAAC,CAAC;;AAEH,SAAO,GAAG,CAAC;CACZ,CAAC;;AAEF,IAAI,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,UAAS,KAAK,EAAE;AAClD,SAAO,OAAO,KAAK,KAAK,QAAQ,IAC9B,QAAQ,CAAC,KAAK,CAAC,IACf,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;CAC/B,CAAC;;;;;;;;;;;;;qBAaa,uBAAG,OAAO,CAAC,MAAM,8BAAW;AACzC,UAAQ,EAAE,mBAAM,MAAM,CAAC,OAAO,EAAE;AAChC,OAAK,EAAE,mBAAM,MAAM,CAAC,OAAO,EAAE;AAC7B,mBAAiB,EAAE,WAAW;;;;;;;;;;;;;;;;;;AAmB9B,MAAI,EAAA,gBAAG;AACL,QAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;;AAEnC,QAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAC/B,QAAI,CAAC,GAAG,EAAE;AACR,YAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;KAClF;;AAED,QAAI,CAAC,IAAI,GAAG,GAAG,CAAC;;AAEhB,QAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;;AAE7B,QAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;;AAE9B,QAAI,CAAC,MAAM,GAAG,EAAE,CAAC;;AAEjB,QAAI,CAAC,eAAe,GAAG,EAAE,CAAC;GAC3B;;;;;;;AAQD,qBAAmB,EAAA,+BAAG;AACpB,WAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;GACvC;;;;;;;;;AAUD,oBAAkB,EAAA,4BAAC,QAAQ,EAAE;AAC3B,QAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC;AAC7B,QAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,WAAW,EAAE;AACxF,aAAO,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KACrC;AACD,WAAO,OAAO,CAAC;GAChB;;;;;;;;;;AAWD,YAAU,EAAA,oBAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE;;;AAC/B,QAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;;AAEhD,QAAI,GAAG,uCAAqC,SAAS,CAAC,SAAS,YAAO,GAAG,CAAC,QAAQ,EAAE,AAAE,CAAC;;AAEvF,WAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,UAAC,QAAQ,EAAK;AAC9C,UAAI,OAAO,GAAG,MAAK,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAChD,YAAK,yBAAyB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAC1D,UAAI,OAAO,KAAK,IAAI,EAAE;AACpB,YAAI,KAAK,GAAG,IAAI,KAAK,6BAA2B,GAAG,CAAC,QAAQ,EAAE,CAAG,CAAC;AAC9D,aAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;AACxB,cAAM,KAAK,CAAC;OACb;;AAED,aAAO,OAAO,CAAC;KAChB,CAAC,CAAC;GACJ;;;;;;;;;;AAWD,QAAM,EAAA,gBAAC,GAAG,EAAE,GAAG,EAAE;AACf,WAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;GAC7C;;AAGD,iBAAe,EAAA,yBAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE;AACxC,QAAI,CAAC,MAAM,CAAC,WAAW,EAAE;AACvB,UAAI,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC1C,UAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;KACjD;GACF;;AAGD,kBAAgB,EAAA,0BAAC,KAAK,EAAE,MAAM,EAAE;AAC9B,QAAI,MAAM,CAAC,WAAW,EAAE;AACtB,UAAI,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;KACvD;GACF;;AAGD,kBAAgB,EAAA,0BAAC,KAAK,EAAE,MAAM,EAAE;;;AAC9B,UAAM,CAAC,gBAAgB,CAAC,UAAC,GAAG,EAAE,YAAY,EAAK;AAC7C,UAAI,YAAY,CAAC,IAAI,KAAK,WAAW,EAAE;AACrC,YAAI,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AAChD,YAAI,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AACrD,YAAI,UAAU,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AACxC,cAAI,SAAS,GAAG,OAAK,iBAAiB,CAAC,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAChF,iBAAK,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;SAC7F;OACF;KACF,CAAC,CAAC;GACJ;;AAGD,kBAAgB,EAAA,0BAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE;;;;AAEzC,QAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE;AAClC,YAAM,CAAC,WAAW,GAAG,IAAI,CAAC;AAC1B,UAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AACvD,UAAI,MAAM,GAAG,KAAK,CAAC;AACnB,SAAG,CAAC,EAAE,CAAC,OAAO,EAAE,UAAC,QAAQ,EAAK;AAC5B,YAAI,MAAM,EAAE;AACV,6BAAM,GAAG,CAAC,YAAM;AACd,mBAAK,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;WACpD,CAAC,CAAC;SACJ;AACD,cAAM,GAAG,IAAI,CAAC;OACf,EAAE,UAAC,KAAK,EAAK;AACZ,2BAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;OAC3B,CAAC,CAAC;KACJ;GACF;;AAGD,eAAa,EAAA,uBAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE;AACtC,QAAI,MAAM,CAAC,WAAW,EAAE;AACtB,UAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AACvD,SAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACjB,YAAM,CAAC,WAAW,GAAG,KAAK,CAAC;KAC5B;GACF;;;;;;;;;;;AAYD,SAAO,EAAA,iBAAC,KAAK,EAAE,SAAS,EAAE;;;AACxB,QAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;;AAE5C,QAAI,GAAG,oCAAkC,SAAS,CAAC,SAAS,YAAO,GAAG,CAAC,QAAQ,EAAE,AAAE,CAAC;;AAEpF,WAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,UAAC,QAAQ,EAAK;AAC9C,UAAI,CAAC,OAAK,wBAAwB,CAAC,SAAS,CAAC,EAAE;AAC7C,eAAK,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;OACvD;AACD,UAAI,OAAO,GAAG,EAAE,CAAC;AACjB,cAAQ,CAAC,OAAO,CAAC,UAAC,aAAa,EAAK;AAClC,YAAI,OAAO,GAAG,OAAK,kBAAkB,CAAC,aAAa,CAAC,CAAC;AACrD,eAAK,yBAAyB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAC1D,eAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;OACvB,CAAC,CAAC;;AAEH,aAAO,OAAO,CAAC;KAChB,CAAC,CAAC;GACJ;;AAGD,OAAK,EAAA,eAAC,KAAK,EAAE,SAAS,EAAE,MAAK,EAAE,WAAW,EAAE;;;AAC1C,QAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAC5C,QAAI,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;;AAEpC,OAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,MAAK,CAAC,CAAC;;AAEvC,OAAG,CAAC,EAAE,CAAC,aAAa,EAAE,mBAAM,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,QAAQ,EAAE;AAC7D,UAAI,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;;AAEjE,UAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;AAClC,YAAI,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAChD,YAAI,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AACnE,YAAI,CAAC,yBAAyB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAC1D,cAAM,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;OACrC;;AAED,UAAI,MAAM,EAAE;AACV,mBAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;OAC7D;KACF,CAAC,CAAC,CAAC;;;;;;AAMJ,OAAG,CAAC,EAAE,CAAC,eAAe,EAAE,mBAAM,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,QAAQ,EAAE;AAC/D,UAAI,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjE,UAAI,MAAM,EAAE;AACV,mBAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;OAChE;KACF,CAAC,CAAC,CAAC;;;;;AAKJ,eAAW,CAAC,iBAAiB,GAAG,YAAY;AAC1C,SAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACvB,SAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;KAC1B,CAAC;;AAEF,QAAI,GAAG,kCAAgC,SAAS,cAAS,MAAK,AAAE,CAAC;;AAEjE,WAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,UAAC,QAAQ,EAAK;AAC9C,UAAI,CAAC,OAAK,wBAAwB,CAAC,SAAS,CAAC,EAAE;AAC7C,eAAK,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;OACvD;AACD,UAAI,OAAO,GAAG,EAAE,CAAC;AACjB,cAAQ,CAAC,OAAO,CAAC,UAAC,aAAa,EAAK;AAClC,YAAI,OAAO,GAAG,OAAK,kBAAkB,CAAC,aAAa,CAAC,CAAC;AACrD,eAAK,yBAAyB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAC1D,eAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;OACvB,CAAC,CAAC;AACH,aAAO,OAAO,CAAC;KAChB,CAAC,CAAC;GACJ;;AAGD,iBAAe,EAAA,yBAAC,GAAG,EAAE,KAAK,EAAE;;AAE1B,QAAI,CAAC,KAAK,CAAC,OAAO,EAAE;AAClB,WAAK,CAAC,OAAO,GAAG,MAAM,CAAC;KACxB;;AAED,QAAI,KAAK,CAAC,OAAO,KAAK,MAAM,EAAC;AAC3B,SAAG,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;KACxB,MAAM,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE;AACrC,SAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;KAC1B,MAAM,IAAI,KAAK,CAAC,OAAO,KAAK,WAAW,EAAE;AACxC,SAAG,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;KAC7B,MAAM;AACL,SAAG,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;KACvC;;AAED,OAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACzC,OAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;;AAEzC,WAAO,GAAG,CAAC;GACZ;;AAED,mBAAiB,EAAA,2BAAC,GAAG,EAAE,KAAK,EAAE;AAC5B,QAAM,OAAO,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAChD,WAAO,CAAC,OAAO,CAAC,UAAA,GAAG,EAAI;AACrB,UAAI,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;AAC5B,WAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;OAC5B;KACF,CAAC,CAAC;;AAEH,WAAO,GAAG,CAAC;GACZ;;AAED,mBAAiB,EAAA,2BAAC,GAAG,EAAE,KAAK,EAAE;AAC5B,QAAM,OAAO,GAAG,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;AAChD,WAAO,CAAC,OAAO,CAAC,UAAA,GAAG,EAAI;AACrB,UAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE;AACzB,WAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;OAC5B;KACF,CAAC,CAAC;;AAEH,WAAO,GAAG,CAAC;GACZ;;;;;;AAOD,oBAAkB,EAAE,SAAS;;;;;AAM7B,0BAAwB,EAAA,kCAAC,SAAS,EAAE;AAClC,WAAO,CAAC,mBAAM,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;GACpE;;;;;;AAOD,2BAAyB,EAAA,mCAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE;AAC/C,QAAI,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;AACpC,QAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;;AAE1C,OAAG,CAAC,EAAE,CAAC,aAAa,EAAE,mBAAM,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,QAAQ,EAAE;AAC7D,UAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE;AAC5D,YAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;OACpD;KACF,CAAC,CAAC,CAAC;GACL;;;;;AAMD,mBAAiB,EAAA,2BAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE;;;AAG5C,QAAI,KAAK,CAAC,YAAY,EAAE;AACtB,aAAO;KACR;AACD,QAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC;AAC3B,QAAI,KAAK,KAAK,IAAI,EAAE;AAClB,UAAI,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAChC,UAAI,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;;AAEvD,UAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;AAC5B,cAAM,CAAC,YAAY,EAAE,CAAC;OACvB;KACF,MAAM;AACL,UAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAClD,UAAI,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;KAC3D;GACF;;;;;;AAOD,cAAY,EAAA,sBAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE;;;AACvC,WAAO,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,YAAM;AAC9D,aAAK,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;KAC1D,CAAC,CAAC;GACJ;;;;;;;;;;;;;;AAeD,cAAY,EAAA,sBAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE;;;AACvC,QAAI,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACtD,QAAI,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,QAAI,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACtD,QAAI,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAC,CAAC,CAAC,CAAC;AAChD,QAAI,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC;AACxC,eAAS,EAAG,SAAS,KAAK,QAAQ,CAAC,EAAE,AAAC;KACvC,CAAC,CAAC;AACH,QAAM,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;;AAE5D,WAAO,IAAI,OAAO,CAAC,UAAC,OAAO,EAAE,MAAM,EAAK;AACtC,UAAI,mBAAmB,GAAG,EAAE,CAAC;;;AAG7B,cAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,UAAC,GAAG,EAAE,YAAY,EAAK;AACxD,YAAM,eAAe,GAAG,UAAU,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;AAC3D,YAAM,IAAI,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;AAC/C,YAAM,UAAU,GAAG,OAAK,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACzF,YAAM,OAAO,GAAG,YAAY,CAAC,IAAI,KAAK,SAAS,CAAC;AAChD,YAAI,OAAO,IAAI,UAAU,EAAE;AACvB,cAAI,CAAC,mBAAM,MAAM,CAAC,IAAI,CAAC,EAAE;AACvB,+BAAmB,CAAC,IAAI,CAAC;AACvB,kBAAI,EAAC,IAAI;AACT,0BAAY,EAAC,YAAY;AACzB,wBAAU,EAAC,UAAU;AACrB,qBAAO,EAAC,OAAO;aAChB,CAAC,CAAC;WACJ;AACD,iBAAO,gBAAgB,CAAC,eAAe,CAAC,CAAC;SAC1C;OACF,CAAC,CAAC;AACH,UAAI,WAAW,GAAG,SAAd,WAAW,CAAI,MAAM,EAAK;AAC5B,YAAI,KAAK,GAAG,IAAI,KAAK,gDAA8C,SAAS,SAAI,QAAQ,CAAC,EAAE,CAAG,CAAC;AAC/F,aAAK,CAAC,MAAM,GAAG,MAAM,CAAC;AACtB,cAAM,CAAC,KAAK,CAAC,CAAC;OACf,CAAC;AACF,aAAK,aAAa,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,IAAI,CAAC,YAAM;;AAEzD,YAAI,kBAAkB,GAAG,mBAAmB,CAAC,GAAG,CAAC,UAAC,kBAAkB,EAAK;AACrE,cAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC;AACrC,cAAM,YAAY,GAAG,kBAAkB,CAAC,YAAY,CAAC;AACrD,cAAI,kBAAkB,CAAC,OAAO,EAAE;AAC9B,mBAAO,OAAK,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;WACpG,MAAM;;AAEL,gBAAI,kBAAkB,CAAC,UAAU,EAAE;AACjC,qBAAO,OAAK,4BAA4B,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;aAC3F;WACF;SACF,CACF,CAAC;AACF,eAAO,mBAAM,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;OAClD,CAAC,SAAM,CAAC,UAAC,CAAC,EAAK;AACd,mBAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;OAClB,CAAC,CAAC,IAAI,CAAC,UAAC,OAAO,EAAK;AACnB,YAAI,QAAQ,GAAG,mBAAM,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9D,YAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;AACzB,qBAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;SACjD,MAAM;AACL,iBAAO,EAAE,CAAC;SACX;OACF,CAAC,CAAC;KACJ,wCAAsC,SAAS,YAAO,SAAS,CAAC,QAAQ,EAAE,CAAG,CAAC;GAChF;;;;;;;;AASD,eAAa,EAAA,uBAAC,SAAS,EAAE,gBAAgB,EAAE;;;AACzC,QAAI,CAAC,iBAAiB,EAAE,CAAC;AACzB,WAAO,iCAAU,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAC9D,IAAI,CAAC,UAAC,MAAM,EAAK;AAChB,aAAK,iBAAiB,EAAE,CAAC;AACzB,aAAO,MAAM,CAAC;KACf,CAAC,SACI,CAAC,UAAC,CAAC,EAAK;AACZ,aAAK,iBAAiB,EAAE,CAAC;AACzB,aAAO,mBAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;KAC7B,CAAC,CAAC;GACN;;;;;;AAOD,0BAAwB,EAAA,kCAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE;;;AACpF,QAAI,CAAC,mBAAM,OAAO,CAAC,GAAG,CAAC,EAAE;AACvB,YAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;KAChE;AACD,QAAI,QAAQ,GAAG,mBAAM,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;AACtD,QAAI,YAAY,GAAG,EAAE,CAAC;;;AAGtB,QAAI,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,UAAC,EAAE,EAAK;AACpC,aAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;KAC/B,CAAC,CAAC;;;AAGH,gBAAY,GAAG,GAAG,CAAC,MAAM,CAAC,UAAC,EAAE,EAAK;AAChC,UAAI,gBAAgB,GAAG,YAAY,CAAC,IAAI,CAAC;AACzC,aAAO,KAAK,CAAC,cAAc,CAAC,gBAAgB,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,KAAK,IAAI,CAAC;KAChI,CAAC,CAAC;;AAEH,gBAAY,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,UAAC,EAAE,EAAK;AACjE,aAAO,OAAK,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;KAC/E,CAAC,CAAC;;;AAGH,QAAI,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAC,EAAE,EAAK;AAC3C,aAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;KAC1B,CAAC,CAAC;;AAEH,kBAAc,GAAG,cAAc,CAAC,GAAG,CAAC,UAAC,EAAE,EAAK;AAC1C,aAAO,OAAK,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;KACrF,CAAC,CAAC;;AAEH,QAAI,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;;AAEvD,WAAO,mBAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,UAAC,YAAY,EAAK;AAChE,UAAI,QAAQ,GAAG,mBAAM,CAAC,CAAC,mBAAM,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AAC5E,UAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;;AAEhC,mBAAW,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACpC,eAAO,YAAY,CAAC;OACrB,MACI;AACH,YAAI,KAAK,GAAG,IAAI,KAAK,uEAAqE,YAAY,CAAC,UAAU,YAAO,YAAY,CAAC,IAAI,CAAG,CAAC;AACzI,aAAK,CAAC,MAAM,GAAG,mBAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACrD,cAAM,KAAK,CAAC;OACb;KACF,CAAC,CAAC;GACJ;;;;;;;;;AAWD,oBAAkB,EAAA,4BAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE;AAChE,QAAM,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AAC5D,QAAI,GAAG,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,UAAU,CAAC,kBAAkB,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;AACnG,QAAI,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACrD,QAAI,UAAU,GAAG,IAAI,CAAC,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACvF,QAAI,UAAU,EAAE;AACd,aAAO,MAAM,CAAC,IAAI,EAAE,CAAC;KACtB;;AAED,WAAO,iCAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAG,CAAC,IAAI,CAAC,CAAC,CAAC;GACzC;;;;;;;;AASD,wBAAsB,EAAA,gCAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE;AACrD,QAAI,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;AAChD,WAAO,UAAU,CAAC,2BAA2B,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;GACjE;;;;;;;AAQD,kBAAgB,EAAA,0BAAC,MAAM,EAAE;AACvB,QAAI,MAAM,CAAC,cAAc,EAAE;AACzB,YAAM,GAAG,MAAM,CAAC,cAAc,CAAC;KAChC;;AAED,QAAI,KAAK,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;;AAEjD,WAAO,CAAC,CAAC,KAAK,CAAC;GAChB;;;;;AAMD,sBAAoB,EAAA,8BAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE;AACzD,QAAM,eAAe,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;AACzF,QAAI,GAAG,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;AACnE,WAAO,iCAAU,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;GACvD;;;;;;;AAQD,8BAA4B,EAAA,sCAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE;AAC1E,QAAI,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACrD,QAAI,MAAM,EAAE;AACV,aAAO,MAAM,CAAC,IAAI,EAAE,CAAC;KACtB;AACD,WAAO,mBAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,oCAAkC,EAAE,qCAAgC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAG,CAAC,CAAC;GAChJ;;;;;AAMD,cAAY,EAAA,sBAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE;AACvC,QAAI,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAChD,OAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACjB,WAAO,iCAAU,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;GACnC;;;;;AAMD,aAAW,EAAA,qBAAC,SAAS,EAAE;AACrB,QAAI,SAAS,GAAG,mBAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACjD,WAAO,+BAAU,SAAS,CAAC,CAAC;GAC7B;;;;;AAMD,mBAAiB,EAAA,2BAAC,SAAS,EAAE,EAAE,EAAE;AAC/B,QAAI,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;AACpB,QAAI,SAAS,EAAE;AACb,SAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;KACxD;AACD,QAAI,EAAE,EAAE;AACN,SAAG,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACrB;AACD,WAAO,GAAG,CAAC;GACZ;;;;;;;;AASD,iBAAe,EAAA,yBAAC,MAAM,EAAE;AACtB,QAAI,MAAM,CAAC,cAAc,EAAE;AACzB,YAAM,GAAG,MAAM,CAAC,cAAc,CAAC;KAChC;;AAED,QAAI,eAAe,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;;AAE3D,QAAI,eAAe,EAAE;UACL,MAAM,GAAmB,eAAe,CAAhD,MAAM;UAAU,YAAY,GAAK,eAAe,CAAhC,YAAY;;AAClC,UAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AACtG,UAAI,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;;AAEhE,UAAI,YAAY,CAAC,IAAI,KAAK,SAAS,EAAE;AACnC,iBAAS,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;OACxC;AACD,aAAO,SAAS,CAAC;KAClB;;AAED,WAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;GACvD;;;;;;;;AASD,yBAAuB,EAAA,iCAAC,aAAa,EAAE;AACrC,QAAI,aAAa,GAAG,MAAM,CACxB,EAAE,EACF,aAAa,CAAC,sBAAsB,EACpC,aAAa,CAAC,cAAc,CAAC,wBAAwB,CACtD,CAAC;;AAEF,QAAI,kBAAkB,YAAA,CAAC;AACvB,QAAI,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;;AAElD,SAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAChD,UAAI,GAAG,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,UAAI,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AACpC,UAAI,OAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;;AAExB,UAAI,CAAC,OAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE;AAC9B,iBAAS;OACV;;AAED,UAAI,UAAS,GAAG,OAAM,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAC1D,UAAI,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAS,CAAC,gBAAgB,CAAC,EAAE;AAC9F,0BAAkB,GAAG,GAAG,CAAC;AACzB,cAAM;OACP;KACF;;AAED,QAAI,kBAAkB,EAAE;AACtB,UAAI,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AACrD,UAAI,SAAS,GAAG,kBAAkB,CAAC,UAAU,CAAC;AAC9C,UAAI,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,gBAAgB,CAAC;AACtE,aAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;KACpD;GACF;;;;;AAMD,qBAAmB,EAAA,6BAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE;AAChC,WAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;GACjC;;;;;AAMD,kBAAgB,EAAG,IAAI,GAAC,EAAE,AAAC;;;;;;;AAQ3B,aAAW,EAAA,uBAAG;AACZ,uBAAM,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;GAChE;;;;;;;AAQD,aAAW,EAAA,uBAAG;;;AACZ,QAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAChC,QAAI,KAAK,CAAC,YAAY,EAAE;AACtB,aAAO;KACR;;AAED,QAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAC,GAAG,EAAK;gCACI,QAAK,eAAe,CAAC,GAAG,CAAC;UAAhD,OAAO,uBAAP,OAAO;UAAE,SAAS,uBAAT,SAAS;;AAC1B,UAAM,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC3D,WAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KAC5B,CAAC,CAAC;AACH,QAAI,CAAC,eAAe,GAAG,EAAE,CAAC;AAC1B,QAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;GACxB;;;;;;;;;;;;AAaD,YAAU,EAAA,oBAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE;AACjC,QAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAChC,QAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;AAC1B,UAAM,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC3D,WAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAC3B,aAAO;KACR;;AAED,QAAM,GAAG,GAAM,SAAS,SAAI,EAAE,AAAE,CAAC;AACjC,QAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE;;AAE7B,UAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7C,UAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;KACpC;AACD,QAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAP,OAAO,EAAE,SAAS,EAAT,SAAS,EAAE,CAAC;AACnD,QAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;;AAGtB,QAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;AAC5B,UAAI,CAAC,WAAW,EAAE,CAAC;KACpB;GACF;;;;;;AAOD,qBAAmB,EAAE,SAAS;;;;;AAM9B,2BAAyB,EAAA,mCAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;;;AACnD,QAAI,CAAC,OAAO,EAAE;AAAE,aAAO;KAAE;AACzB,QAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;AACtB,QAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AAClD,QAAM,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;;;AAG5D,aAAS,CAAC,gBAAgB,CAAC,UAAC,GAAG,EAAE,YAAY,EAAK;AAChD,UAAI,YAAY,CAAC,IAAI,KAAK,SAAS,EAAE;AACnC,YAAM,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;AACxE,YAAI,CAAC,mBAAmB,EAAE;AACxB,eAAK,CAAC,GAAG,CAAC,GAAG,mBAAM,CAAC,EAAE,CAAC;SACxB,MAAM;AACL,cAAM,UAAU,GAAG,QAAK,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACzF,cAAI,UAAU,EAAE;AACd,gBAAM,qBAAqB,GAAG,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAChE,iBAAK,IAAI,GAAE,IAAI,mBAAmB,EAAE;AAClC,kBAAI,GAAG,GAAG,mBAAmB,CAAC,GAAE,CAAC,CAAC;AAClC,iBAAG,CAAC,EAAE,GAAG,GAAE,CAAC;AACZ,sBAAK,yBAAyB,CAAC,qBAAqB,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;aACnE;WACF,MAAM;AACL,gBAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AAC7C,iBAAK,CAAC,GAAG,CAAC,GAAG,mBAAM,CAAC,CAAC,GAAG,CAAC,CAAC;WAC3B;SACF;OACF;KACF,CAAC,CAAC;GACJ;;;;;AAMD,iBAAe,EAAA,yBAAC,SAAS,EAAE,EAAE,EAAE;AAC7B,QAAI,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;AACpC,QAAI,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC;AACrC,SAAK,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;AAC1C,SAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;AAClD,WAAO,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC;GAC7B;;;;;;;;;AAUD,SAAO,EAAA,iBAAC,aAAa,EAAE;AACrB,QAAI,GAAG,CAAC;AACR,QAAI,OAAO,aAAa,CAAC,GAAG,KAAK,UAAU,EAAE;AAC3C,SAAG,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;KAC3B,MAAM,IAAI,OAAO,aAAa,CAAC,GAAG,KAAK,QAAQ,EAAE;AAChD,SAAG,GAAG,aAAa,CAAC,GAAG,CAAC;KACzB,MAAM;AACL,SAAG,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;KAC5B;AACD,WAAO,GAAG,CAAC;GACZ;;;;;AAMD,8BAA4B,EAAA,wCAAG;AAC7B,WAAO,KAAK,CAAC;GACd;CACF,CAAC;;;;;;;;;;;;;;;qBCx3BgB,OAAO;;;;yBACV,YAAY;;;;wBACN,UAAU;;;;gCACH,sBAAsB;;;;mCACnB,yBAAyB;;;;AAExD,IAAI,OAAO,GAAG,OAAO,CAAC;;AAEtB,IAAI,mBAAM,SAAS,EAAE;AACnB,MAAI,sBAAS,WAAW,EAAE;AACxB,uBAAM,SAAS,CAAC,mBAAmB,CAAC,UAAU,EAAE,sBAAS,WAAW,CAAC,CAAC;GACvE;;AAED,qBAAM,SAAS,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3D;;qBAEc;AACb,MAAI,EAAE,WAAW;AACjB,QAAM,EAAE,YAAY;AACpB,YAAU,EAAA,sBAAG;;;;AAIX,QAAI,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;;AAE/C,eAAW,CAAC,QAAQ,CAAC,mBAAmB,gCAAkB,CAAC;AAC3D,eAAW,CAAC,QAAQ,CAAC,sBAAsB,mCAAqB,CAAC;;AAEjE,QAAM,gBAAgB,GAAG,EAAC,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAC,CAAC;AAChE,eAAW,CAAC,QAAQ,CAAC,gCAAgC,EACjD,sBAAS,IAAI,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC;AACzD,eAAW,CAAC,QAAQ,CAAC,iCAAiC,EAClD,sBAAS,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC;AAC1D,eAAW,CAAC,QAAQ,CAAC,+BAA+B,EAChD,sBAAS,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;AACxD,eAAW,CAAC,QAAQ,CAAC,+BAA+B,EAChD,sBAAS,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;;;AAGxD,QAAI,CAAC,uBAAG,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE;AACzC,6BAAG,KAAK,CAAC,MAAM,CAAC;AACd,yBAAiB,EAAE,IAAI;;AAEvB,kCAA0B,EAAA,oCAAC,OAAO,EAAE;;;AAClC,cAAI,OAAO,OAAO,KAAK,WAAW,EAAE;AAClC,mBAAO,CAAC,OAAO,CAAC,UAAC,MAAM,EAAK;AAC1B,kBAAI,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC;AAC7C,kBAAI,OAAO,GAAG,MAAK,UAAU,CAAC,SAAS,CAAC,CAAC;AACzC,kBAAI,OAAO,CAAC,eAAe,EAAE;AAC3B,uBAAO,CAAC,eAAe,QAAO,SAAS,EAAE,MAAM,CAAC,CAAC;eAClD;aACF,CAAC,CAAC;WACJ;SACF;;AAED,YAAI,EAAA,gBAAG;AACL,cAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAChD,cAAI,OAAO,GAAG,MAAM,CAAC;;AAErB,cAAI,OAAO,KAAK,IAAI,EAAE;AACpB,mBAAO,IAAI,CAAC;WACb;;AAED,cAAI,CAAC,mBAAM,OAAO,CAAC,MAAM,CAAC,EAAE;AAC1B,mBAAO,GAAG,CAAC,MAAM,CAAC,CAAC;WACpB;;AAED,cAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACzC,iBAAO,MAAM,CAAC;SACf;;AAED,aAAK,EAAA,iBAAG;AACN,cAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAChD,cAAI,OAAO,CAAC;AACZ,cAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;AACzB,mBAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAS,aAAa,EAAE;AAC3C,qBAAO,aAAa,CAAC,SAAS,EAAE,CAAC;aAClC,CAAC,CAAC;WACJ,MAAM,IAAI,MAAM,EAAE;AACjB,mBAAO,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;WAChC;AACD,cAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACzC,iBAAO,MAAM,CAAC;SACf;;AAED,wBAAgB,EAAA,0BAAC,MAAM,EAAE;AACvB,cAAI,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;AAC5D,cAAI,OAAO,CAAC,gBAAgB,EAAE;AAC5B,mBAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;WACxC;SACF;;AAED,wBAAgB,EAAA,0BAAC,MAAM,EAAE;AACvB,cAAI,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;AAC5D,cAAI,OAAO,CAAC,gBAAgB,EAAE;AAC5B,mBAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;WACxC;SACF;OACF,CAAC,CAAC;KACJ;;AAED,QAAI,CAAC,uBAAG,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE;AACzC,6BAAG,KAAK,CAAC,MAAM,CAAC;AACd,yBAAiB,EAAE,IAAI;;AAEvB,oBAAY,EAAA,wBAAG;AACb,cAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAClC,iBAAO,IAAI,CAAC,MAAM,EAAE,CAAC;SACtB;;AAED,oBAAY,EAAA,wBAAG;AACb,cAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAClC,cAAI,CAAC,MAAM,EAAE,CAAC;SACf;;AAED,WAAG,EAAA,eAAG;AACJ,cAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;AAChE,cAAI,OAAO,CAAC,eAAe,EAAE;AAC3B,mBAAO,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;WACtC;SACF;OACF,CAAC,CAAC;KACJ;;AAED,QAAI,CAAC,uBAAG,2BAA2B,CAAC,SAAS,CAAC,iBAAiB,EAAE;AAC/D,6BAAG,2BAA2B,CAAC,MAAM,CAAC;AACpC,yBAAiB,EAAE,IAAI;;AAEvB,mBAAW,EAAA,uBAAG;AACZ,cAAI,IAAI,CAAC,iBAAiB,EAAE;AAC1B,gBAAI,CAAC,iBAAiB,EAAE,CAAC;WAC1B;AACD,iBAAO,IAAI,CAAC,MAAM,EAAE,CAAC;SACtB;OACF,CAAC,CAAC;KACJ;;AAED,2BAAG,eAAe,gCAAkB,CAAC;AACrC,2BAAG,kBAAkB,mCAAqB,CAAC;GAC5C;CACF;;;;;;;;;;;;;;;qBC5IiB,OAAO;;;;qBAEV,mBAAM,KAAK,CAAC,MAAM,CAAC;;AAEhC,MAAI,EAAA,gBAAG;AACL,QAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;;AAEnC,QAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;;AAElB,QAAI,mBAAM,OAAO,EAAE;AACjB,UAAI,CAAC,eAAe,EAAE,CAAC;KACxB;GACF;;AAGD,mBAAiB,EAAA,6BAAG;AAClB,QAAI,CAAC,QAAQ,EAAE,CAAC;GACjB;;AAGD,mBAAiB,EAAA,6BAAG;AAClB,QAAI,CAAC,QAAQ,EAAE,CAAC;GACjB;;;;;;;;;AAUD,aAAW,EAAA,uBAAG;AACZ,WAAO,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC;GAC5B;;;;;;;AAQD,iBAAe,EAAE,2BAAW;;;AAC1B,QAAI,CAAC,OAAO,GAAG,YAAM;AACnB,aAAO,MAAK,WAAW,EAAE,CAAC;KAC3B,CAAC;AACF,uBAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;GACzC;;CAEF,CAAC;;;;;;;;;;;;;;;qBCjDgB,OAAO;;;;yBACV,YAAY;;;;wBACN,UAAU;;;;IAEvB,MAAM,sBAAN,MAAM;;;;;;qBAMC,uBAAG,cAAc,CAAC,MAAM,CAAC,uBAAG,oBAAoB,EAAE;AAC/D,oBAAkB,EAAE,IAAI;;;;;;;;;AASxB,oBAAkB,EAAA,4BAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE;AACjD,QAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/B,QAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;AAC5C,QAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE;AAC3B,UAAI,KAAK,KAAK,sBAAS,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE;;AAErD,YAAI,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;;AAExD,YAAI,UAAU,KAAK,GAAG,IAAI,IAAI,CAAC,eAAe,EAAE;AAC9C,oBAAU,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;SACrD;;AAED,YAAI,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;OAC1B;KACF;GACF;;;;;;;;AASD,mBAAiB,EAAA,2BAAC,UAAU,EAAE,YAAY,EAAE;AAC1C,QAAI,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;;;AAGvD,cAAU,CAAC,aAAa,CAAC,UAAC,GAAG,EAAK;AAChC,UAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;AACnC,kBAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;OACxB;KACF,CAAC,CAAC;;AAEH,WAAO,UAAU,CAAC;GACnB;;;;;AAMD,sBAAoB,EAAA,8BAAC,UAAU,EAAE,OAAO,EAAE;AACxC,QAAI,CAAC,sBAAsB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AACjD,WAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;GACzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDD,wBAAsB,EAAA,gCAAC,UAAU,EAAE,OAAO,EAAE;;;AAC1C,cAAU,CAAC,gBAAgB,CAAC,UAAC,GAAG,EAAE,IAAI,EAAK;AACzC,UAAI,eAAe,GAAG,MAAK,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;;AAE7E,UAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE;AAC3B,YAAI,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE;;AAC3C,gBAAI,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;;AAEnD,gBAAI,MAAK,2BAA2B,CAAC,GAAG,CAAC,EAAE;AACzC,kBAAI,OAAO,mBAAmB,KAAK,QAAQ,IAAI,CAAC,mBAAM,OAAO,CAAC,mBAAmB,CAAC,EAAE;AAClF,mCAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,UAAC,EAAE,EAAK;AACjE,yBAAO,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC;iBACpD,CAAC,CAAC;eACJ,MAAM,IAAI,mBAAM,OAAO,CAAC,mBAAmB,CAAC,EAAE;AAC7C,mCAAmB,GAAG,MAAK,6BAA6B,CAAC,mBAAmB,CAAC,CAAC;eAC/E,MAAM;AACL,sBAAM,IAAI,KAAK,CAAI,UAAU,CAAC,QAAQ,EAAE,sBAAiB,IAAI,CAAC,IAAI,WAAK,IAAI,CAAC,IAAI,oEAAgE,GAAG,cAAS,IAAI,CAAC,IAAI,sBAAiB,IAAI,CAAC,IAAI,+BAA0B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAG,CAAC;eAC1P;aACF;;;iBAGI;AACH,oBAAI,OAAO,mBAAmB,KAAK,QAAQ,IAAI,CAAC,mBAAM,OAAO,CAAC,mBAAmB,CAAC,EAAE;AAClF,qCAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;iBACxD,MAAM,IAAI,mBAAM,OAAO,CAAC,mBAAmB,CAAC,EAAE;AAC7C,qCAAmB,GAAG,MAAK,yBAAyB,CAAC,mBAAmB,CAAC,CAAC;iBAC3E,MAAM;AACL,wBAAM,IAAI,KAAK,CAAI,UAAU,CAAC,QAAQ,EAAE,sBAAiB,IAAI,CAAC,IAAI,WAAK,IAAI,CAAC,IAAI,iDAA2C,GAAG,cAAS,IAAI,CAAC,IAAI,mCAA8B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAG,CAAC;iBAC/M;eACF;;AAED,mBAAO,CAAC,eAAe,CAAC,GAAG,mBAAmB,CAAC;;SAChD;;;;;;aAMI;AACH,mBAAO,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC;WAC/B;OACF;;AAED,UAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE;AAC7B,YAAI,CAAC,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE;;AAE5C,iBAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;SACjC;OACF;KACF,CAAC,CAAC;GACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCD,2BAAyB,EAAA,mCAAC,GAAG,EAAE;AAC7B,QAAI,MAAM,GAAG,EAAE,CAAC;AAChB,SAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,UAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;AACnB,cAAM,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;OACrB,MACI,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;AACnC,cAAM,IAAI,KAAK,sHAAoH,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAG,CAAC;OAC3J;KACF;AACD,WAAO,MAAM,CAAC;GACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCD,+BAA6B,EAAA,uCAAC,GAAG,EAAE;AACjC,QAAI,MAAM,GAAG,EAAE,CAAC;AAChB,SAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,UAAI,GAAG,CAAC,CAAC,CAAC,EAAE;AACV,YAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;AAC9B,gBAAM,IAAI,KAAK,+CAA6C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAG,CAAC;SACvF;AACD,cAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;OAC7C;KACF;AACD,WAAO,MAAM,CAAC;GACf;;;;;;;;;;;;;;;AAgBD,kBAAgB,EAAA,0BAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE;AAC7C,2BAAG,cAAc,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;GACvF;;;;;;AAOD,oBAAkB,EAAA,4BAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE;AAC/C,2BAAG,cAAc,CAAC,SAAS,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;GACzF;;;;;AAMD,wBAAsB,EAAA,gCAAC,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE;AAClD,WAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;GAChC;;;;;;AAMD,yBAAuB,EAAA,iCAAC,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE;AACnD,WAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;GAChC;CACF,CAAC;;;;;;;;;;;;;;;qBCjTgB,OAAO;;;;qBAEV,UAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE;AACpD,MAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;AACvB,SAAO,IAAI,mBAAM,IAAI,CAAC,OAAO,CAAC,UAAS,OAAO,EAAE,MAAM,EAAE;AACtD,QAAI,QAAQ,GAAG,SAAX,QAAQ,CAAY,KAAK,EAAE;AAC7B,UAAI,KAAK,EAAE;AACT,YAAI,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AACzC,eAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;SAC3B;AACD,2BAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;OAChC,MAAM;AACL,2BAAM,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;OAC1B;KACF,CAAC;AACF,QAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACpB,MAAE,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;GACzB,CAAC,CAAC;CACJ;;;;;;;AClBD;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;qBCNkB,OAAO;;;;yBACV,YAAY;;;;qCACC,+BAA+B;;;;wCAC5B,kCAAkC;;;;0CAChC,oCAAoC;;;;AAErE,uBAAG,eAAe,qCAAkB,CAAC;AACrC,uBAAG,kBAAkB,wCAAqB,CAAC;;AAE3C,mBAAM,MAAM,CAAC,mBAAmB,EAAE,UAAS,WAAW,EAAE;AACtD,aAAW,CAAC,WAAW,yCAAsB,CAAC;CAC/C,CAAC,CAAC","file":"emberfire.js","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.firebaseio.com/')\n * });\n * ```\n *\n * Requests for `App.Post` now target `https://.firebaseio.com/posts`.\n *\n * @property firebase\n * @type {Firebase}\n * @constructor\n */\n init() {\n this._super.apply(this, arguments);\n\n var ref = this.get('firebase');\n if (!ref) {\n throw new Error('Please set the `firebase` property in the environment config.');\n }\n // If provided Firebase reference was a query (eg: limits), make it a ref.\n this._ref = ref;\n // Keep track of what types `.findAll()` has been called for\n this._findAllMapForType = {};\n // Keep a cache to check modified relationships against\n this._recordCacheForType = {};\n // Used to batch records into the store\n this._queue = [];\n // Payloads to push later\n this._queuedPayloads = {};\n },\n\n\n /**\n * Uses push() to generate chronologically ordered unique IDs.\n *\n * @return {String}\n */\n generateIdForRecord() {\n return this._getKey(this._ref.push());\n },\n\n\n /**\n * Use the Firebase DataSnapshot's key as the record id\n *\n * @param {Object} snapshot - A Firebase snapshot\n * @param {Object} payload - The payload that will be pushed into the store\n * @return {Object} payload\n */\n _assignIdToPayload(snapshot) {\n var payload = snapshot.val();\n if (payload !== null && typeof payload === 'object' && typeof payload.id === 'undefined') {\n payload.id = this._getKey(snapshot);\n }\n return payload;\n },\n\n\n /**\n * Called by the store to retrieve the JSON for a given type and ID. The\n * method will return a promise which will resolve when the value is\n * successfully fetched from Firebase.\n *\n * Additionally, from this point on, the object's value in the store will\n * also be automatically updated whenever the remote value changes.\n */\n findRecord(store, typeClass, id) {\n var ref = this._getCollectionRef(typeClass, id);\n\n var log = `DS: FirebaseAdapter#findRecord ${typeClass.modelName} to ${ref.toString()}`;\n\n return this._fetch(ref, log).then((snapshot) => {\n var payload = this._assignIdToPayload(snapshot);\n this._updateRecordCacheForType(typeClass, payload, store);\n if (payload === null) {\n var error = new Error(`no record was found at ${ref.toString()}`);\n error.recordId = id;\n throw error;\n }\n\n return payload;\n });\n },\n\n\n /**\n * Promise interface for once('value').\n *\n * @param {Firebase} ref\n * @param {String} log\n * @return {Promise}\n * @private\n */\n _fetch(ref, log) {\n return RSVP.resolve(ref.once('value'), log);\n },\n\n\n recordWasPushed(store, modelName, record) {\n if (!record.__listening) {\n var typeClass = store.modelFor(modelName);\n this.listenForChanges(store, typeClass, record);\n }\n },\n\n\n recordWillUnload(store, record) {\n if (record.__listening) {\n this.stopListening(store, record.constructor, record);\n }\n },\n\n\n recordWillDelete(store, record) {\n record.eachRelationship((key, relationship) => {\n if (relationship.kind === 'belongsTo') {\n var parentRecord = record.get(relationship.key);\n var inverseKey = record.inverseFor(relationship.key);\n if (inverseKey && parentRecord.get('id')) {\n var parentRef = this._getCollectionRef(inverseKey.type, parentRecord.get('id'));\n this._removeHasManyRecord(store, parentRef, inverseKey.name, record.constructor, record.id);\n }\n }\n });\n },\n\n\n listenForChanges(store, typeClass, record) {\n // embedded records will get their changes from parent listeners\n if (!this.isRecordEmbedded(record)) {\n record.__listening = true;\n var ref = this._getCollectionRef(typeClass, record.id);\n var called = false;\n ref.on('value', (snapshot) => {\n if (called) {\n Ember.run(() => {\n this._handleChildValue(store, typeClass, snapshot);\n });\n }\n called = true;\n }, (error) => {\n Ember.Logger.error(error);\n });\n }\n },\n\n\n stopListening(store, typeClass, record) {\n if (record.__listening) {\n var ref = this._getCollectionRef(typeClass, record.id);\n ref.off('value');\n record.__listening = false;\n }\n },\n\n\n /**\n * Called by the store to retrieve the JSON for all of the records for a\n * given type. The method will return a promise which will resolve when the\n * value is successfully fetched from Firebase.\n *\n * Additionally, from this point on, any records of this type that are added,\n * removed or modified from Firebase will automatically be reflected in the\n * store.\n */\n findAll(store, typeClass) {\n var ref = this._getCollectionRef(typeClass);\n\n var log = `DS: FirebaseAdapter#findAll ${typeClass.modelName} to ${ref.toString()}`;\n\n return this._fetch(ref, log).then((snapshot) => {\n if (!this._findAllHasEventsForType(typeClass)) {\n this._findAllAddEventListeners(store, typeClass, ref);\n }\n var results = [];\n snapshot.forEach((childSnapshot) => {\n var payload = this._assignIdToPayload(childSnapshot);\n this._updateRecordCacheForType(typeClass, payload, store);\n results.push(payload);\n });\n\n return results;\n });\n },\n\n\n query(store, typeClass, query, recordArray) {\n var ref = this._getCollectionRef(typeClass);\n var modelName = typeClass.modelName;\n\n ref = this.applyQueryToRef(ref, query);\n\n ref.on('child_added', Ember.run.bind(this, function (snapshot) {\n var record = store.peekRecord(modelName, this._getKey(snapshot));\n\n if (!record || !record.__listening) {\n var payload = this._assignIdToPayload(snapshot);\n var normalizedData = store.normalize(typeClass.modelName, payload);\n this._updateRecordCacheForType(typeClass, payload, store);\n record = store.push(normalizedData);\n }\n\n if (record) {\n recordArray.get('content').addObject(record._internalModel);\n }\n }));\n\n // `child_changed` is already handled by the record's\n // value listener after a store.push. `child_moved` is\n // a much less common case because it relates to priority\n\n ref.on('child_removed', Ember.run.bind(this, function (snapshot) {\n var record = store.peekRecord(modelName, this._getKey(snapshot));\n if (record) {\n recordArray.get('content').removeObject(record._internalModel);\n }\n }));\n\n // clean up event handlers when the array is being destroyed\n // so that future firebase events wont keep trying to use a\n // destroyed store/serializer\n recordArray.__firebaseCleanup = function () {\n ref.off('child_added');\n ref.off('child_removed');\n };\n\n var log = `DS: FirebaseAdapter#query ${modelName} with ${query}`;\n\n return this._fetch(ref, log).then((snapshot) => {\n if (!this._findAllHasEventsForType(typeClass)) {\n this._findAllAddEventListeners(store, typeClass, ref);\n }\n var results = [];\n snapshot.forEach((childSnapshot) => {\n var payload = this._assignIdToPayload(childSnapshot);\n this._updateRecordCacheForType(typeClass, payload, store);\n results.push(payload);\n });\n return results;\n });\n },\n\n\n applyQueryToRef(ref, query) {\n\n if (!query.orderBy) {\n query.orderBy = '_key';\n }\n\n if (query.orderBy === '_key'){\n ref = ref.orderByKey();\n } else if (query.orderBy === '_value') {\n ref = ref.orderByValue();\n } else if (query.orderBy === '_priority') {\n ref = ref.orderByPriority();\n } else {\n ref = ref.orderByChild(query.orderBy);\n }\n\n ref = this._applyRangesToRef(ref, query);\n ref = this._applyLimitsToRef(ref, query);\n\n return ref;\n },\n\n _applyRangesToRef(ref, query) {\n const methods = ['equalTo', 'startAt', 'endAt'];\n methods.forEach(key => {\n if (query[key] !== undefined) {\n ref = ref[key](query[key]);\n }\n });\n\n return ref;\n },\n\n _applyLimitsToRef(ref, query) {\n const methods = ['limitToFirst', 'limitToLast'];\n methods.forEach(key => {\n if (isInteger(query[key])) {\n ref = ref[key](query[key]);\n }\n });\n\n return ref;\n },\n\n\n /**\n * Keep track of what types `.findAll()` has been called for\n * so duplicate listeners aren't added\n */\n _findAllMapForType: undefined,\n\n\n /**\n * Determine if the current type is already listening for children events\n */\n _findAllHasEventsForType(typeClass) {\n return !Ember.isNone(this._findAllMapForType[typeClass.modelName]);\n },\n\n\n /**\n * After `.findAll()` is called on a modelName, continue to listen for\n * `child_added`, `child_removed`, and `child_changed`\n */\n _findAllAddEventListeners(store, typeClass, ref) {\n var modelName = typeClass.modelName;\n this._findAllMapForType[modelName] = true;\n\n ref.on('child_added', Ember.run.bind(this, function (snapshot) {\n if (!store.hasRecordForId(modelName, this._getKey(snapshot))) {\n this._handleChildValue(store, typeClass, snapshot);\n }\n }));\n },\n\n\n /**\n * Push a new child record into the store\n */\n _handleChildValue(store, typeClass, snapshot) {\n // No idea why we need this, we are already turning off the callback by\n // calling ref.off in recordWillUnload. Something is fishy here\n if (store.isDestroying) {\n return;\n }\n var value = snapshot.val();\n if (value === null) {\n var id = this._getKey(snapshot);\n var record = store.peekRecord(typeClass.modelName, id);\n // TODO: refactor using ED\n if (!record.get('isDeleted')) {\n record.deleteRecord();\n }\n } else {\n const payload = this._assignIdToPayload(snapshot);\n this._pushLater(typeClass.modelName, payload.id, payload);\n }\n },\n\n\n /**\n * `createRecord` is an alias for `updateRecord` because calling \\\n * `ref.set()` would wipe out any existing relationships\n */\n createRecord(store, typeClass, snapshot) {\n return this.updateRecord(store, typeClass, snapshot).then(() => {\n this.listenForChanges(store, typeClass, snapshot.record);\n });\n },\n\n\n /**\n * Called by the store when a record is created/updated via the `save`\n * method on a model record instance.\n *\n * The `updateRecord` method serializes the record and performs an `update()`\n * at the the Firebase location and a `.set()` at any relationship locations\n * The method will return a promise which will be resolved when the data and\n * any relationships have been successfully saved to Firebase.\n *\n * We take an optional record reference, in order for this method to be usable\n * for saving nested records as well.\n */\n updateRecord(store, typeClass, snapshot) {\n var recordRef = this._getAbsoluteRef(snapshot.record);\n var recordCache = this._getRecordCache(typeClass, snapshot.id);\n var pathPieces = recordRef.path.toString().split('/');\n var lastPiece = pathPieces[pathPieces.length-1];\n var serializedRecord = snapshot.serialize({\n includeId: (lastPiece !== snapshot.id) // record has no firebase `key` in path\n });\n const serializer = store.serializerFor(typeClass.modelName);\n\n return new Promise((resolve, reject) => {\n var relationshipsToSave = [];\n // first we remove all relationships data from the serialized record, we backup the\n // removed data so that we can save it at a later stage.\n snapshot.record.eachRelationship((key, relationship) => {\n const relationshipKey = serializer.keyForRelationship(key);\n const data = serializedRecord[relationshipKey];\n const isEmbedded = this.isRelationshipEmbedded(store, typeClass.modelName, relationship);\n const hasMany = relationship.kind === 'hasMany';\n if (hasMany || isEmbedded) {\n if (!Ember.isNone(data)) {\n relationshipsToSave.push({\n data:data,\n relationship:relationship,\n isEmbedded:isEmbedded,\n hasMany:hasMany\n });\n }\n delete serializedRecord[relationshipKey];\n }\n });\n var reportError = (errors) => {\n var error = new Error(`Some errors were encountered while saving ${typeClass} ${snapshot.id}`);\n error.errors = errors;\n reject(error);\n };\n this._updateRecord(recordRef, serializedRecord).then(() => {\n // and now we construct the list of promise to save relationships.\n var savedRelationships = relationshipsToSave.map((relationshipToSave) => {\n const data = relationshipToSave.data;\n const relationship = relationshipToSave.relationship;\n if (relationshipToSave.hasMany) {\n return this._saveHasManyRelationship(store, typeClass, relationship, data, recordRef, recordCache);\n } else {\n // embedded belongsTo, we need to fill in the informations.\n if (relationshipToSave.isEmbedded) {\n return this._saveEmbeddedBelongsToRecord(store, typeClass, relationship, data, recordRef);\n }\n }\n }\n );\n return Ember.RSVP.allSettled(savedRelationships);\n }).catch((e) => {\n reportError([e]);\n }).then((results) => {\n var rejected = Ember.A(results).filterBy('state', 'rejected');\n if (rejected.length !== 0) {\n reportError(rejected.mapBy('reason').toArray());\n } else {\n resolve();\n }\n });\n }, `DS: FirebaseAdapter#updateRecord ${typeClass} to ${recordRef.toString()}`);\n },\n\n\n /**\n * Update a single record without caring for the relationships\n * @param {Firebase} recordRef\n * @param {Object} serializedRecord\n * @return {Promise}\n */\n _updateRecord(recordRef, serializedRecord) {\n this._incrementWaiters();\n return toPromise(recordRef.update, recordRef, [serializedRecord])\n .then((result) => {\n this._decrementWaiters();\n return result;\n })\n .catch((e) => {\n this._decrementWaiters();\n return Ember.RSVP.reject(e);\n });\n },\n\n\n /**\n * Call _saveHasManyRelationshipRecord on each record in the relationship\n * and then resolve once they have all settled\n */\n _saveHasManyRelationship(store, typeClass, relationship, ids, recordRef, recordCache) {\n if (!Ember.isArray(ids)) {\n throw new Error('hasMany relationships must must be an array');\n }\n var idsCache = Ember.A(recordCache[relationship.key]);\n var dirtyRecords = [];\n\n // Added\n var addedRecords = ids.filter((id) => {\n return !idsCache.includes(id);\n });\n\n // Dirty\n dirtyRecords = ids.filter((id) => {\n var relatedModelName = relationship.type;\n return store.hasRecordForId(relatedModelName, id) && store.peekRecord(relatedModelName, id).get('hasDirtyAttributes') === true;\n });\n\n dirtyRecords = uniq(dirtyRecords.concat(addedRecords)).map((id) => {\n return this._saveHasManyRecord(store, typeClass, relationship, recordRef, id);\n });\n\n // Removed\n var removedRecords = idsCache.filter((id) => {\n return !ids.includes(id);\n });\n\n removedRecords = removedRecords.map((id) => {\n return this._removeHasManyRecord(store, recordRef, relationship.key, typeClass, id);\n });\n // Combine all the saved records\n var savedRecords = dirtyRecords.concat(removedRecords);\n // Wait for all the updates to finish\n return Ember.RSVP.allSettled(savedRecords).then((savedRecords) => {\n var rejected = Ember.A(Ember.A(savedRecords).filterBy('state', 'rejected'));\n if (rejected.get('length') === 0) {\n // Update the cache\n recordCache[relationship.key] = ids;\n return savedRecords;\n }\n else {\n var error = new Error(`Some errors were encountered while saving a hasMany relationship ${relationship.parentType} -> ${relationship.type}`);\n error.errors = Ember.A(rejected).mapBy('reason');\n throw error;\n }\n });\n },\n\n\n /**\n * If the relationship is `async: true`, create a child ref\n * named with the record id and set the value to true\n\n * If the relationship is `embedded: true`, create a child ref\n * named with the record id and update the value to the serialized\n * version of the record\n */\n _saveHasManyRecord(store, typeClass, relationship, parentRef, id) {\n const serializer = store.serializerFor(typeClass.modelName);\n var ref = this._getRelationshipRef(parentRef, serializer.keyForRelationship(relationship.key), id);\n var record = store.peekRecord(relationship.type, id);\n var isEmbedded = this.isRelationshipEmbedded(store, typeClass.modelName, relationship);\n if (isEmbedded) {\n return record.save();\n }\n\n return toPromise(ref.set, ref, [true]);\n },\n\n\n /**\n * Determine from the serializer if the relationship is embedded via the\n * serializer's `attrs` hash.\n *\n * @return {Boolean} Is the relationship embedded?\n */\n isRelationshipEmbedded(store, modelName, relationship) {\n var serializer = store.serializerFor(modelName);\n return serializer.hasDeserializeRecordsOption(relationship.key);\n },\n\n\n /**\n * Determine from if the record is embedded via implicit relationships.\n *\n * @return {Boolean} Is the relationship embedded?\n */\n isRecordEmbedded(record) {\n if (record._internalModel) {\n record = record._internalModel;\n }\n\n var found = this.getFirstEmbeddingParent(record);\n\n return !!found;\n },\n\n\n /**\n * Remove a relationship\n */\n _removeHasManyRecord(store, parentRef, key, typeClass, id) {\n const relationshipKey = store.serializerFor(typeClass.modelName).keyForRelationship(key);\n var ref = this._getRelationshipRef(parentRef, relationshipKey, id);\n return toPromise(ref.remove, ref, [], ref.toString());\n },\n\n\n /**\n * Save an embedded belongsTo record and set its internal firebase ref\n *\n * @return {Promise}\n */\n _saveEmbeddedBelongsToRecord(store, typeClass, relationship, id, parentRef) {\n var record = store.peekRecord(relationship.type, id);\n if (record) {\n return record.save();\n }\n return Ember.RSVP.Promise.reject(new Error(`Unable to find record with id ${id} from embedded relationship: ${JSON.stringify(relationship)}`));\n },\n\n\n /**\n * Called by the store when a record is deleted.\n */\n deleteRecord(store, typeClass, snapshot) {\n var ref = this._getAbsoluteRef(snapshot.record);\n ref.off('value');\n return toPromise(ref.remove, ref);\n },\n\n\n /**\n * Determines a path fo a given type\n */\n pathForType(modelName) {\n var camelized = Ember.String.camelize(modelName);\n return pluralize(camelized);\n },\n\n\n /**\n * Return a Firebase reference for a given modelName and optional ID.\n */\n _getCollectionRef(typeClass, id) {\n var ref = this._ref;\n if (typeClass) {\n ref = ref.child(this.pathForType(typeClass.modelName));\n }\n if (id) {\n ref = ref.child(id);\n }\n return ref;\n },\n\n\n /**\n * Returns a Firebase reference for a record taking into account if the record is embedded\n *\n * @param {DS.Model} record\n * @return {Firebase}\n */\n _getAbsoluteRef(record) {\n if (record._internalModel) {\n record = record._internalModel;\n }\n\n var embeddingParent = this.getFirstEmbeddingParent(record);\n\n if (embeddingParent) {\n var { record: parent, relationship } = embeddingParent;\n const embeddedKey = parent.store.serializerFor(parent.modelName).keyForRelationship(relationship.key);\n var recordRef = this._getAbsoluteRef(parent).child(embeddedKey);\n\n if (relationship.kind === 'hasMany') {\n recordRef = recordRef.child(record.id);\n }\n return recordRef;\n }\n\n return this._getCollectionRef(record.type, record.id);\n },\n\n\n /**\n * Returns the parent record and relationship where any embedding is detected\n *\n * @param {DS.InternalModel} internalModel\n * @return {Object}\n */\n getFirstEmbeddingParent(internalModel) {\n let relationships = assign(\n {},\n internalModel._implicitRelationships,\n internalModel._relationships.initializedRelationships\n );\n\n let embeddingParentRel;\n let relationshipKeys = Object.keys(relationships);\n\n for (let i = 0; i < relationshipKeys.length; i++) {\n let rel = relationships[relationshipKeys[i]];\n let members = rel.members.toArray();\n let parent = members[0];\n\n if (!parent || !rel.inverseKey) {\n continue;\n }\n\n let parentRel = parent._relationships.get(rel.inverseKey);\n if (this.isRelationshipEmbedded(this.store, parent.type.modelName, parentRel.relationshipMeta)) {\n embeddingParentRel = rel;\n break;\n }\n }\n\n if (embeddingParentRel) {\n var parent = embeddingParentRel.members.toArray()[0];\n var parentKey = embeddingParentRel.inverseKey;\n var parentRel = parent._relationships.get(parentKey).relationshipMeta;\n return { record: parent, relationship: parentRel };\n }\n },\n\n\n /**\n * Return a Firebase reference based on a relationship key and record id\n */\n _getRelationshipRef(ref, key, id) {\n return ref.child(key).child(id);\n },\n\n\n /**\n * The amount of time (ms) before the _queue is flushed\n */\n _queueFlushDelay: (1000/60), // 60fps\n\n\n /**\n * Schedules a `_flushQueue` for later.\n *\n * @private\n */\n _flushLater() {\n Ember.run.later(this, this._flushQueue, this._queueFlushDelay);\n },\n\n\n /**\n * Flush all delayed `store.push` payloads in `this._queuedPayloads`.\n *\n * @private\n */\n _flushQueue() {\n const store = this.get('store');\n if (store.isDestroying) {\n return;\n }\n\n this._queue.forEach((key) => {\n const { payload, modelName } = this._queuedPayloads[key];\n const normalizedData = store.normalize(modelName, payload);\n store.push(normalizedData);\n });\n this._queuedPayloads = {};\n this._queue.length = 0;\n },\n\n\n /**\n * Schedule a payload push for later. This will only push at most one payload\n * per record. When trying to push to the same record multiple times, only the\n * last push will be kept.\n *\n * @param {string} modelName\n * @param {string} id\n * @param {!Object} payload\n * @private\n */\n _pushLater(modelName, id, payload) {\n const store = this.get('store');\n if (!this._queueFlushDelay) {\n const normalizedData = store.normalize(modelName, payload);\n store.push(normalizedData);\n return;\n }\n\n const key = `${modelName}-${id}`;\n if (this._queuedPayloads[key]) {\n // remove from original place in queue (will be added to end)\n const oldPosition = this._queue.indexOf(key);\n this._queue.splice(oldPosition, 1);\n }\n this._queuedPayloads[key] = { payload, modelName };\n this._queue.push(key);\n\n // if this is the first item to be queued, schedule a flush\n if (this._queue.length === 1) {\n this._flushLater();\n }\n },\n\n\n /**\n * A cache of hasMany relationships that can be used to\n * diff against new relationships when a model is saved\n */\n _recordCacheForType: undefined,\n\n\n /**\n * _updateHasManyCacheForType\n */\n _updateRecordCacheForType(typeClass, payload, store) {\n if (!payload) { return; }\n const id = payload.id;\n const cache = this._getRecordCache(typeClass, id);\n const serializer = store.serializerFor(typeClass.modelName);\n // Only cache relationships for now\n // and do the same for embedded records\n typeClass.eachRelationship((key, relationship) => {\n if (relationship.kind === 'hasMany') {\n const relationshipPayload = payload[serializer.keyForRelationship(key)];\n if (!relationshipPayload) {\n cache[key] = Ember.A();\n } else {\n const isEmbedded = this.isRelationshipEmbedded(store, typeClass.modelName, relationship);\n if (isEmbedded) {\n const relationshipTypeClass = store.modelFor(relationship.type);\n for (let id in relationshipPayload) {\n let obj = relationshipPayload[id];\n obj.id = id;\n this._updateRecordCacheForType(relationshipTypeClass, obj, store);\n }\n } else {\n const ids = Object.keys(relationshipPayload);\n cache[key] = Ember.A(ids);\n }\n }\n }\n });\n },\n\n\n /**\n * Get or create the cache for a record\n */\n _getRecordCache(typeClass, id) {\n var modelName = typeClass.modelName;\n var cache = this._recordCacheForType;\n cache[modelName] = cache[modelName] || {};\n cache[modelName][id] = cache[modelName][id] || {};\n return cache[modelName][id];\n },\n\n\n /**\n * A utility for retrieving the key name of a Firebase ref or\n * DataSnapshot. This is backwards-compatible with `name()`\n * from Firebase 1.x.x and `key()` from Firebase 2.0.0+. Once\n * support for Firebase 1.x.x is dropped in EmberFire, this\n * helper can be removed.\n */\n _getKey(refOrSnapshot) {\n var key;\n if (typeof refOrSnapshot.key === 'function') {\n key = refOrSnapshot.key();\n } else if (typeof refOrSnapshot.key === 'string') {\n key = refOrSnapshot.key;\n } else {\n key = refOrSnapshot.name();\n }\n return key;\n },\n\n\n /**\n * We don't need background reloading, because firebase!\n */\n shouldBackgroundReloadRecord() {\n return false;\n }\n});\n","import Ember from 'ember';\nimport DS from 'ember-data';\nimport firebase from 'firebase';\nimport FirebaseAdapter from '../adapters/firebase';\nimport FirebaseSerializer from '../serializers/firebase';\n\nvar VERSION = '0.0.0';\n\nif (Ember.libraries) {\n if (firebase.SDK_VERSION) {\n Ember.libraries.registerCoreLibrary('Firebase', firebase.SDK_VERSION);\n }\n\n Ember.libraries.registerCoreLibrary('EmberFire', VERSION);\n}\n\nexport default {\n name: 'emberfire',\n before: 'ember-data',\n initialize() {\n\n // To support Ember versions below 2.1.0 as well.\n // See http://emberjs.com/deprecations/v2.x/#toc_initializer-arity\n let application = arguments[1] || arguments[0];\n\n application.register('adapter:-firebase', FirebaseAdapter);\n application.register('serializer:-firebase', FirebaseSerializer);\n\n const providerSettings = {instantiate: false, singleton: false};\n application.register('firebase-auth-provider:twitter',\n firebase.auth.TwitterAuthProvider, providerSettings);\n application.register('firebase-auth-provider:facebook',\n firebase.auth.FacebookAuthProvider, providerSettings);\n application.register('firebase-auth-provider:github',\n firebase.auth.GithubAuthProvider, providerSettings);\n application.register('firebase-auth-provider:google',\n firebase.auth.GoogleAuthProvider, providerSettings);\n\n // Monkeypatch the store until ED gives us a good way to listen to push events\n if (!DS.Store.prototype._emberfirePatched) {\n DS.Store.reopen({\n _emberfirePatched: true,\n\n _emberfireHandleRecordPush(records) {\n if (typeof records !== 'undefined') {\n records.forEach((record) => {\n var modelName = record.constructor.modelName;\n var adapter = this.adapterFor(modelName);\n if (adapter.recordWasPushed) {\n adapter.recordWasPushed(this, modelName, record);\n }\n });\n }\n },\n\n push() {\n var result = this._super.apply(this, arguments);\n var records = result;\n\n if (records === null) {\n return null;\n }\n\n if (!Ember.isArray(result)) {\n records = [result];\n }\n\n this._emberfireHandleRecordPush(records);\n return result;\n },\n\n _push() {\n var pushed = this._super.apply(this, arguments);\n var records;\n if (Array.isArray(pushed)) {\n records = pushed.map(function(internalModel) {\n return internalModel.getRecord();\n });\n } else if (pushed) {\n records = [pushed.getRecord()];\n }\n this._emberfireHandleRecordPush(records);\n return pushed;\n },\n\n recordWillUnload(record) {\n var adapter = this.adapterFor(record.constructor.modelName);\n if (adapter.recordWillUnload) {\n adapter.recordWillUnload(this, record);\n }\n },\n\n recordWillDelete(record) {\n var adapter = this.adapterFor(record.constructor.modelName);\n if (adapter.recordWillDelete) {\n adapter.recordWillDelete(this, record);\n }\n }\n });\n }\n\n if (!DS.Model.prototype._emberfirePatched) {\n DS.Model.reopen({\n _emberfirePatched: true,\n\n unloadRecord() {\n this.store.recordWillUnload(this);\n return this._super();\n },\n\n deleteRecord() {\n this.store.recordWillDelete(this);\n this._super();\n },\n\n ref() {\n var adapter = this.store.adapterFor(this.constructor.modelName);\n if (adapter._getAbsoluteRef) {\n return adapter._getAbsoluteRef(this);\n }\n }\n });\n }\n\n if (!DS.AdapterPopulatedRecordArray.prototype._emberfirePatched) {\n DS.AdapterPopulatedRecordArray.reopen({\n _emberfirePatched: true,\n\n willDestroy() {\n if (this.__firebaseCleanup) {\n this.__firebaseCleanup();\n }\n return this._super();\n }\n });\n }\n\n DS.FirebaseAdapter = FirebaseAdapter;\n DS.FirebaseSerializer = FirebaseSerializer;\n }\n};\n","import Ember from 'ember';\n\nexport default Ember.Mixin.create({\n\n init() {\n this._super.apply(this, arguments);\n // unresolved requests, used in testing\n this._reasons = 0;\n\n if (Ember.testing) {\n this._registerWaiter();\n }\n },\n\n\n _incrementWaiters() {\n this._reasons++;\n },\n\n\n _decrementWaiters() {\n this._reasons--;\n },\n\n\n /**\n * The waiter calls this to determine if testing should wait. Override in\n * the implementing class if needed.\n *\n * @return {Boolean}\n * @private\n */\n _shouldWait() {\n return this._reasons === 0;\n },\n\n\n /**\n * Wire up a waiter for this instance.\n *\n * @private\n */\n _registerWaiter: function() {\n this._waiter = () => {\n return this._shouldWait();\n };\n Ember.Test.registerWaiter(this._waiter);\n },\n\n});\n","import Ember from 'ember';\nimport DS from 'ember-data';\nimport firebase from 'firebase';\n\nconst { assign } = Ember;\n\n/**\n * The Firebase serializer helps normalize relationships and can be extended on\n * a per model basis.\n */\nexport default DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, {\n isNewSerializerAPI: true,\n\n /**\n * Firebase have a special value for a date 'firebase.database.ServerValue.TIMESTAMP'\n * that tells it to insert server time. We need to make sure the value is not scrapped\n * by the data attribute transforms.\n *\n * @override\n */\n serializeAttribute(snapshot, json, key, attribute) {\n var value = snapshot.attr(key);\n this._super(snapshot, json, key, attribute);\n if (this._canSerialize(key)) {\n if (value === firebase.database.ServerValue.TIMESTAMP) {\n\n var payloadKey = this._getMappedKey(key, snapshot.type);\n\n if (payloadKey === key && this.keyForAttribute) {\n payloadKey = this.keyForAttribute(key, 'serialize');\n }\n // do not transform\n json[payloadKey] = value;\n }\n }\n },\n\n\n /**\n * Firebase does not send null values, it omits the key altogether. This nullifies omitted\n * properties so that property deletions sync correctly.\n *\n * @override\n */\n extractAttributes(modelClass, resourceHash) {\n var attributes = this._super(modelClass, resourceHash);\n\n // nullify omitted attributes\n modelClass.eachAttribute((key) => {\n if (!attributes.hasOwnProperty(key)) {\n attributes[key] = null;\n }\n });\n\n return attributes;\n },\n\n\n /**\n * @override\n */\n extractRelationships(modelClass, payload) {\n this.normalizeRelationships(modelClass, payload);\n return this._super(modelClass, payload);\n },\n\n\n /**\n * Normalizes `hasMany` relationship structure before passing\n * to `JSONSerializer.extractRelationships`\n *\n * before:\n *\n * ```js\n * {\n * comments: {\n * abc: true,\n * def: true,\n * }\n * }\n * ```\n *\n * after:\n *\n * ```js\n * {\n * comments: [ 'abc', 'def' ]\n * }\n * ```\n *\n * Or for embedded objects:\n *\n * ```js\n * {\n * comments: {\n * 'abc': { body: 'a' },\n * 'def': { body: 'd' )\n * }\n * }\n * ```\n *\n * these should become:\n *\n * ```js\n * {\n * comments: [\n * {\n * id: 'abc',\n * body: 'a'\n * },\n * {\n * id: 'def',\n * body: 'd'\n * }\n * ]\n * }\n * ```\n */\n normalizeRelationships(modelClass, payload) {\n modelClass.eachRelationship((key, meta) => {\n let relationshipKey = this.keyForRelationship(key, meta.kind, 'deserialize');\n\n if (meta.kind === 'hasMany') {\n if (payload.hasOwnProperty(relationshipKey)) {\n let relationshipPayload = payload[relationshipKey];\n // embedded\n if (this.hasDeserializeRecordsOption(key)) {\n if (typeof relationshipPayload === 'object' && !Ember.isArray(relationshipPayload)) {\n relationshipPayload = Object.keys(relationshipPayload).map((id) => {\n return assign({ id: id }, relationshipPayload[id]);\n });\n } else if (Ember.isArray(relationshipPayload)) {\n relationshipPayload = this._addNumericIdsToEmbeddedArray(relationshipPayload);\n } else {\n throw new Error(`${modelClass.toString()} relationship ${meta.kind}('${meta.type}') must contain embedded records with an \\`id\\`. Example: { \"${key}\": { \"${meta.type}_1\": { \"id\": \"${meta.type}_1\" } } } instead got: ${JSON.stringify(payload[key])}`);\n }\n }\n\n // normalized\n else {\n if (typeof relationshipPayload === 'object' && !Ember.isArray(relationshipPayload)) {\n relationshipPayload = Object.keys(relationshipPayload);\n } else if (Ember.isArray(relationshipPayload)) {\n relationshipPayload = this._convertBooleanArrayToIds(relationshipPayload);\n } else {\n throw new Error(`${modelClass.toString()} relationship ${meta.kind}('${meta.type}') must be a key/value map. Example: { \"${key}\": { \"${meta.type}_1\": true } } instead got: ${JSON.stringify(payload[key])}`);\n }\n }\n\n payload[relationshipKey] = relationshipPayload;\n }\n\n // hasMany property is not present\n // server will not send a property which has no content\n // (i.e. it will never send `comments: null`) so we need to\n // force the empty relationship\n else {\n payload[relationshipKey] = [];\n }\n }\n\n if (meta.kind === 'belongsTo') {\n if (!payload.hasOwnProperty(relationshipKey)) {\n // server wont send property if it was made null elsewhere\n payload[relationshipKey] = null;\n }\n }\n });\n },\n\n\n /**\n * Coerce arrays back into relationship arrays. When numeric ids are used\n * the firebase server will send back arrays instead of object hashes in\n * certain situations.\n *\n * See the conditions and reasoning here:\n * https://www.firebase.com/docs/web/guide/understanding-data.html#section-arrays-in-firebase\n *\n * Stored in Firebase:\n *\n * ```json\n * {\n * \"0\": true,\n * \"1\": true,\n * \"3\": true\n * }\n * ```\n *\n * Given back by the JS client:\n *\n * ```js\n * [true, true, null, true]\n * ```\n *\n * What we need:\n *\n * ```js\n * [ \"0\", \"1\", \"3\" ]\n * ```\n *\n * @param {Array} arr Input array\n * @return {Array} Fixed array\n * @private\n */\n _convertBooleanArrayToIds(arr) {\n var result = [];\n for (var i = 0; i < arr.length; i++) {\n if (arr[i] === true) {\n result.push('' + i);\n }\n else if (typeof arr[i] === 'string') {\n throw new Error(`hasMany relationship contains invalid data, should be in the form: { comment_1: true, comment_2: true } but was ${JSON.stringify(arr)}`);\n }\n }\n return result;\n },\n\n\n /**\n * Fix embedded array ids.\n *\n * Objects are stored in Firebase with their id in the key only:\n *\n * ```json\n * {\n * \"0\": { obj0 },\n * \"1\": { obj1 },\n * \"3\": { obj3 }\n * }\n * ```\n *\n * Given back by the JS client:\n *\n * ```js\n * [{ obj0 }, { obj1 }, null, { obj3 }]\n * ```\n *\n * What we need:\n *\n * ```js\n * [ { id: '0', ...obj0 }, { id: '1', ...obj1 }, { id: '3', ...obj3 } ]\n * ```\n *\n * https://www.firebase.com/docs/web/guide/understanding-data.html#section-arrays-in-firebase\n *\n * @param {Array} arr Input array\n * @return {Array} Fixed array\n * @private\n */\n _addNumericIdsToEmbeddedArray(arr) {\n var result = [];\n for (var i = 0; i < arr.length; i++) {\n if (arr[i]) {\n if (typeof arr[i] !== 'object') {\n throw new Error(`expecting embedded object hash but found ${JSON.stringify(arr[i])}`);\n }\n result.push(assign({ id: '' + i }, arr[i]));\n }\n }\n return result;\n },\n\n\n /**\n * Even when records are embedded, bypass EmbeddedRecordsMixin\n * and invoke JSONSerializer's method which serializes to ids only.\n *\n * The adapter handles saving the embedded records via `r.save()`\n * and ensures that dirty states and rollback work.\n *\n * Will not be neccesary when this issue is resolved:\n *\n * https://github.com/emberjs/data/issues/2487\n *\n * @override\n */\n serializeHasMany(snapshot, json, relationship) {\n DS.JSONSerializer.prototype.serializeHasMany.call(this, snapshot, json, relationship);\n },\n\n\n /**\n * @see #serializeHasMany\n * @override\n */\n serializeBelongsTo(snapshot, json, relationship) {\n DS.JSONSerializer.prototype.serializeBelongsTo.call(this, snapshot, json, relationship);\n },\n\n\n /**\n * @override\n */\n shouldSerializeHasMany(snapshot, key, relationship) {\n return this._canSerialize(key);\n },\n\n /**\n * @override\n * @deprecated\n */\n _shouldSerializeHasMany(snapshot, key, relationship) {\n return this._canSerialize(key);\n }\n});\n","import Ember from 'ember';\n\nexport default function(fn, context, _args, errorMsg) {\n var args = _args || [];\n return new Ember.RSVP.Promise(function(resolve, reject) {\n var callback = function(error) {\n if (error) {\n if (errorMsg && typeof error === 'object') {\n error.location = errorMsg;\n }\n Ember.run(null, reject, error);\n } else {\n Ember.run(null, resolve);\n }\n };\n args.push(callback);\n fn.apply(context, args);\n });\n}\n","/* jshint node: true */\n'use strict';\n\nmodule.exports = {\n name: 'ember-inflector'\n};\n","import Ember from 'ember';\nimport DS from 'ember-data';\nimport FirebaseAdapter from '../../addon/adapters/firebase';\nimport FirebaseSerializer from '../../addon/serializers/firebase';\nimport EmberFireInitializer from '../../addon/initializers/emberfire';\n\nDS.FirebaseAdapter = FirebaseAdapter;\nDS.FirebaseSerializer = FirebaseSerializer;\n\nEmber.onLoad('Ember.Application', function(Application) {\n Application.initializer(EmberFireInitializer);\n});\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/emberfire.min.js b/dist/emberfire.min.js new file mode 100644 index 00000000..1c482898 --- /dev/null +++ b/dist/emberfire.min.js @@ -0,0 +1,10 @@ +/*! + * EmberFire is the officially supported adapter for using Firebase with + * Ember Data. The DS.FirebaseAdapter provides all of the standard DS.Adapter + * methods and will automatically synchronize the store with Firebase. + * + * EmberFire 0.0.0 + * https://github.com/firebase/emberfire/ + * License: MIT + */ +!function e(t,r,i){function n(a,d){if(!r[a]){if(!t[a]){var s="function"==typeof require&&require;if(!d&&s)return s(a,!0);if(o)return o(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=r[a]={exports:{}};t[a][0].call(u.exports,function(e){var r=t[a][1][e];return n(r?r:e)},u,u.exports,e,t,r,i)}return r[a].exports}for(var o="function"==typeof require&&require,a=0;a "+r.type);throw n.errors=a["default"].A(t).mapBy("reason"),n})},_saveHasManyRecord:function(e,t,r,i,n){var o=e.serializerFor(t.modelName),a=this._getRelationshipRef(i,o.keyForRelationship(r.key),n),d=e.peekRecord(r.type,n),s=this.isRelationshipEmbedded(e,t.modelName,r);return s?d.save():(0,c["default"])(a.set,a,[!0])},isRelationshipEmbedded:function(e,t,r){var i=e.serializerFor(t);return i.hasDeserializeRecordsOption(r.key)},isRecordEmbedded:function(e){e._internalModel&&(e=e._internalModel);var t=this.getFirstEmbeddingParent(e);return!!t},_removeHasManyRecord:function(e,t,r,i,n){var o=e.serializerFor(i.modelName).keyForRelationship(r),a=this._getRelationshipRef(t,o,n);return(0,c["default"])(a.remove,a,[],a.toString())},_saveEmbeddedBelongsToRecord:function(e,t,r,i,n){var o=e.peekRecord(r.type,i);return o?o.save():a["default"].RSVP.Promise.reject(new Error("Unable to find record with id "+i+" from embedded relationship: "+JSON.stringify(r)))},deleteRecord:function(e,t,r){var i=this._getAbsoluteRef(r.record);return i.off("value"),(0,c["default"])(i.remove,i)},pathForType:function(e){var t=a["default"].String.camelize(e);return(0,h.pluralize)(t)},_getCollectionRef:function(e,t){var r=this._ref;return e&&(r=r.child(this.pathForType(e.modelName))),t&&(r=r.child(t)),r},_getAbsoluteRef:function(e){e._internalModel&&(e=e._internalModel);var t=this.getFirstEmbeddingParent(e);if(t){var r=t.record,i=t.relationship,n=r.store.serializerFor(r.modelName).keyForRelationship(i.key),o=this._getAbsoluteRef(r).child(n);return"hasMany"===i.kind&&(o=o.child(e.id)),o}return this._getCollectionRef(e.type,e.id)},getFirstEmbeddingParent:function(e){for(var t=p({},e._implicitRelationships,e._relationships.initializedRelationships),r=void 0,i=Object.keys(t),n=0;n