UNPKG

memory-orm

Version:
270 lines (269 loc) 7.37 kB
'use strict' Object.defineProperty(exports, '__esModule', { value: true }) exports.Finder = void 0 const tslib_1 = require('tslib') const cloneDeep_1 = tslib_1.__importDefault(require('lodash/cloneDeep')) const merge_1 = tslib_1.__importDefault(require('lodash/merge')) const union_1 = tslib_1.__importDefault(require('lodash/union')) const uniq_1 = tslib_1.__importDefault(require('lodash/uniq')) const get_1 = tslib_1.__importDefault(require('lodash/get')) const set_1 = tslib_1.__importDefault(require('lodash/set')) const mem_1 = require('./mem') const datum_1 = require('./datum') function each_by_id({ from }, process) { if (from instanceof Array) { for (const item of from) { process(item.id || item) } } } function each({ from }, process) { if (from instanceof Array) { for (const item of from) { process(item) } } else if (from instanceof Object) { for (const id in from) { const item = from[id] item._id = id process(item) } } } function validate(item, meta, chklist) { if (!item || !chklist) { return false } for (let chk of chklist) { if (!chk(item, meta)) { return false } } return true } class Finder { constructor() {} join({ $name, model, all, map, list }) { this.$name = $name this.all = all this.map = map this.list = list this.model = model mem_1.State.notify(this.$name.list) } calculate(query, memory) { if (query._step >= mem_1.State.step[this.$name.list]) { return } const base = mem_1.State.base(this.$name.list) delete query._reduce query._step = mem_1.step() const ctx = { map: this.map, query, memory, cache: cloneDeep_1.default(base.$format), paths: { _reduce: { list: [], hash: {}, }, }, } if (query._all_ids) { let ids = query._all_ids if (query._is_uniq) { ids = uniq_1.default(ids) } this.reduce(ctx, ids) } else if (query === query.all) { this.reduce(ctx, Object.keys(memory)) } else if (query._is_uniq) { let ids = [] for (const partition of query.$partition) { const tgt = get_1.default(query.all, `reduce.${partition}`) ids = union_1.default(ids, tgt) } this.reduce(ctx, ids) } else { for (const partition of query.$partition) { const tgt = get_1.default(query.all, `reduce.${partition}`) this.reduce(ctx, tgt) } } this.finish(ctx) } reduce({ map, cache, paths, query, memory }, ids) { if (!ids) { return } for (let id of ids) { const o = memory[id] if (o) { const { meta, item, $group } = o if (!validate(item, meta, query._filters)) { continue } for (let [path, a] of $group) { const o = (paths[path] = cache[path]) map.reduce(query, path, item, o, a) } } } } finish({ map, paths, query }) { for (const path in paths) { const o = paths[path] map.finish(query, path, o, this.list) set_1.default(query, path, o) } for (const path in query.$sort) { const cmd = query.$sort[path] const from = get_1.default(query, path) if (from) { const sorted = map.order(query, path, from, from, cmd, this.list) const dashed = map.dash(query, path, sorted, from, cmd, this.list) const result = map.post_proc(query, path, dashed, from, cmd, this.list) this.list.bless(result, query) result.from = from set_1.default(query, path, result) } } } data_set(type, from, parent) { const meta = mem_1.State.meta() const base = mem_1.State.base(this.$name.list) const journal = mem_1.State.journal(this.$name.list) const { deploys } = this.$name return this[type]({ base, journal, meta, model: this.model, all: this.all, deploys, from, parent, }) } data_emitter({ base, journal }, { item, $group }) { if (!base.$format) { throw new Error('bad context.') } const order = (keys, cmd) => { if ('string' === typeof keys) { keys = [keys] } const path = [`_reduce`, ...keys].join('.') base.$sort[path] = cmd journal.$sort[path] = cmd } const reduce = (keys, cmd) => { if ('string' === typeof keys) { keys = [keys] } const path = [`_reduce`, ...keys].join('.') cmd = reduce.default(keys, cmd) $group.push([path, cmd]) const map = base.$format[path] || (base.$format[path] = {}) const map_j = journal.$format[path] || (journal.$format[path] = {}) this.map.init(map, cmd) this.map.init(map_j, cmd) } reduce.default = reduce.default_origin = function (keys, cmd) { if (keys.length) { return cmd } reduce.default = (_keys, cmd) => cmd const bare = { set: item.id, list: true, } return Object.assign(bare, cmd) } return { reduce, order } } data_init({ model, parent, deploys }, { item }, { reduce, order }) { model.bless(item) parent && merge_1.default(item, parent) model.deploy.call(item, model) for (const deploy of deploys) { deploy.call(item, { o: item, model, reduce, order }) } } data_entry({ model }, { item }, { reduce, order }) { model.map_partition(item, reduce) model.map_reduce(item, reduce) if (reduce.default === reduce.default_origin) { reduce([], {}) } model.order(item, order) } reset(ctx) { ctx.journal.$memory = mem_1.PureObject() const news = (ctx.base.$memory = ctx.all.$memory = mem_1.PureObject()) this.merge(ctx) for (let key in ctx.base.$memory) { const old = ctx.base.$memory[key] const item = news[key] if (item == null) { ctx.model.delete(old) } } return true } merge(ctx) { let is_hit = false each(ctx, (item) => { const o = new datum_1.Datum(ctx.meta, item) const emit = this.data_emitter(ctx, o) this.data_init(ctx, o, emit) this.data_entry(ctx, o, emit) const id = item.id if (!id) { throw new Error(`detect bad data: ${JSON.stringify(item)}`) } ctx.journal.$memory[id] = o ctx.base.$memory[id] = o const old = ctx.base.$memory[item.id] if (old != null) { ctx.model.update(item, old.item) } else { ctx.model.create(item) } return (is_hit = true) }) return is_hit } remove(ctx) { let is_hit = false each_by_id(ctx, (id) => { const old = ctx.base.$memory[id] if (old != null) { ctx.model.delete(old.item) delete ctx.journal.$memory[id] delete ctx.base.$memory[id] is_hit = true } }) return is_hit } update(ctx, parent) { let is_hit = false each_by_id(ctx, (id) => { const old = ctx.base.$memory[id] if (!old) { return } merge_1.default(old.item, parent) old.$group = [] const emit = this.data_emitter(ctx, old) this.data_entry(ctx, old, emit) ctx.model.update(old.item, old.item) is_hit = true }) return is_hit } } exports.Finder = Finder //# sourceMappingURL=finder.js.map