UNPKG

@skele/classic

Version:

Skele is an architectural framework that assists with building data-driven apps with React or React Native.

174 lines (141 loc) 3.7 kB
'use strict' import { List, Iterable } from 'immutable' import { registry, data } from '@skele/core' import * as actions from '../action' import { ancestors } from '../impl/cursor' const { Registry } = registry export const keyFor = (kind, action) => ({ kind: kind instanceof List ? kind.toArray() : kind, action, }) export const keyFromAction = ({ [actions.actionMetaProperty]: { kind }, type, }) => keyFor(kind, type) export const findParentEntry = (lookupFn, type, cursor) => { for (const c of ancestors(cursor)) { if (!data.isElement(c)) continue const key = keyFor(data.kindOf(c), type) const entry = lookupFn(key) if (entry != null) { return { element: c, entry, } } } return undefined } // ideally this would be a Symbol but we aren't there yet const sep = '$$sep$$' // useful with core's memoize() fn for caching responses from ActionRegistries export const cacheKey = key => { const kind = key.kind let res = Iterable.isIndexed(kind) ? kind.toArray() : Array.isArray(kind) ? kind : [kind] res.push(sep, key.action) return res } export function ActionRegistry() { this._registry = new Registry() this.register = function(key, obj) { let en = this._registry.getEntry(key.kind) let aMap if (en == null || en.key.length !== key.kind.length) { aMap = {} this._registry.register(key.kind, aMap) } else { aMap = en.value } aMap[key.action] = obj } this.get = function(key) { const en = this.getEntry(key) return en != null ? en.value : undefined } this.getEntry = function(key) { let bestMatch for (const en of this.collector(key)) { bestMatch = en } return bestMatch } this.collector = function*(key) { for (const en of this._registry.collector(key.kind)) { const value = en.value[key.action] if (value != null) { yield { key: { kind: en.key, }, value, } } } } this.isEmpty = function() { return this._registry.isEmpty() } this.reset = function() { this._registry = new Registry() } } ActionRegistry.keyFor = keyFor ActionRegistry.cacheKey = cacheKey ActionRegistry.keyFromAction = keyFromAction // TODO this class has no tests yet. make sure you write some before using it export function ActionMultivalueRegistry() { this._registry = new Registry() this.register = function(key, obj) { let en = this._registry.getEntry(key.kind) let aMap if (en == null || en.key.length !== key.kind.length) { aMap = {} this._registry.register(key.kind, aMap) } else { aMap = en.value } let objs = aMap[key.action] if (objs == null) { objs = [] aMap[key.action] = objs } objs.push(obj) } this.get = function(key) { const en = this.getEntry(key) return en != null ? en.value : undefined } this.getEntry = function(key) { let all = [] for (const en of this.collector(key)) { Array.prototype.push.apply(all, en.value) } return all } this.collector = function*(key) { for (const en of this._registry.collector(key.kind)) { const objs = en.value[key.action] if (objs != null) { yield { key: { kind: en.key, }, objs, } } } } this.isEmpty = function() { return this._registry.isEmpty() } this.reset = function() { this._registry = new Registry() } } ActionMultivalueRegistry.keyFor = keyFor ActionMultivalueRegistry.cacheKey = cacheKey ActionMultivalueRegistry.keyFromAction = keyFromAction