// TODO: This file was created by bulk-decaffeinate. // Sanity-check the conversion and remove this comment. let MemoryDb import _ from "lodash" import { createUid, processFind } from "./utils" import { compileSort } from "./selector" export default MemoryDb = class MemoryDb { constructor(options: any, success: any) { this.collections = {} if (success) { success(this) } } addCollection(name: any, success: any, error: any) { const collection = new Collection(name) this[name] = collection this.collections[name] = collection if (success != null) { return success() } } removeCollection(name: any, success: any, error: any) { delete this[name] delete this.collections[name] if (success != null) { return success() } } } // Stores data in memory class Collection { constructor(name: any) { this.name = name this.items = {} this.upserts = {} // Pending upserts by _id. Still in items this.removes = {} // Pending removes by _id. No longer in items } find(selector: any, options: any) { return { fetch: (success: any, error: any) => { return this._findFetch(selector, options, success, error) } } } findOne(selector: any, options: any, success: any, error: any) { if (_.isFunction(options)) { ;[options, success, error] = [{}, options, success] } return this.find(selector, options).fetch(function (results: any) { if (success != null) { return success(results.length > 0 ? results[0] : null) } }, error) } _findFetch(selector: any, options: any, success: any, error: any) { if (success != null) { return success(processFind(this.items, selector, options)) } } upsert(doc: any, success: any, error: any) { // Handle both single and multiple upsert let items = doc if (!_.isArray(items)) { items = [items] } for (let item of items) { if (!item._id) { item._id = createUid() } // Replace/add this.items[item._id] = item this.upserts[item._id] = item } if (success) { return success(doc) } } remove(id: any, success: any, error: any) { if (_.has(this.items, id)) { this.removes[id] = this.items[id] delete this.items[id] delete this.upserts[id] } else { this.removes[id] = { _id: id } } if (success != null) { return success() } } cache(docs: any, selector: any, options: any, success: any, error: any) { // Add all non-local that are not upserted or removed let sort: any for (let doc of docs) { this.cacheOne(doc) } const docsMap = _.fromPairs(_.zip(_.map(docs, "_id"), docs)) if (options.sort) { sort = compileSort(options.sort) } // Perform query, removing rows missing in docs from local db return this.find(selector, options).fetch((results: any) => { for (let result of results) { if (!docsMap[result._id] && !_.has(this.upserts, result._id)) { // If past end on sorted limited, ignore if (options.sort && options.limit && docs.length === options.limit) { if (sort(result, _.last(docs)) >= 0) { continue } } delete this.items[result._id] } } if (success != null) { return success() } }, error) } pendingUpserts(success: any) { return success(_.values(this.upserts)) } pendingRemoves(success: any) { return success(_.map(this.removes, "_id")) } resolveUpsert(doc: any, success: any) { // Handle both single and multiple upsert let items = doc if (!_.isArray(items)) { items = [items] } for (let item of items) { if (this.upserts[item._id]) { // Only safely remove upsert if doc is unchanged if (_.isEqual(item, this.upserts[item._id])) { delete this.upserts[item._id] } } } if (success != null) { return success() } } resolveRemove(id: any, success: any) { delete this.removes[id] if (success != null) { return success() } } // Add but do not overwrite or record as upsert seed(doc: any, success: any) { if (!_.has(this.items, doc._id) && !_.has(this.removes, doc._id)) { this.items[doc._id] = doc } if (success != null) { return success() } } // Add but do not overwrite upserts or removes cacheOne(doc: any, success: any) { if (!_.has(this.upserts, doc._id) && !_.has(this.removes, doc._id)) { const existing = this.items[doc._id] // If _rev present, make sure that not overwritten by lower _rev if (!existing || !doc._rev || !existing._rev || doc._rev >= existing._rev) { this.items[doc._id] = doc } } if (success != null) { return success() } } }