UNPKG

mobx-keystone-mindreframer

Version:

A MobX powered state management solution based on data trees with first class support for Typescript, snapshots, patches and much more

115 lines (97 loc) 2.88 kB
import { entries, get, has, keys, remove, set, values } from "mobx" import { modelAction } from "../action/modelAction" import { Model } from "../model/Model" import { model } from "../modelShared/modelDecorator" import { typesRecord } from "../typeChecking/record" import { tProp } from "../typeChecking/tProp" import { typesUnchecked } from "../typeChecking/unchecked" /** * A map that is backed by an object-like map. * Use `objectMap` to create it. */ @model("mobx-keystone/ObjectMap") export class ObjectMap<V> extends Model({ items: tProp(typesRecord(typesUnchecked<any>()), () => ({})), // will be properly checked by types.objectMap(subType) }) implements Map<string, V> { @modelAction clear(): void { const items = this.items const keys = Object.keys(items) const len = keys.length for (let i = 0; i < len; i++) { const k = keys[i] remove(items, k) } } @modelAction delete(key: string): boolean { const hasKey = this.has(key) if (hasKey) { remove(this.items, key) return true } else { return false } } forEach(callbackfn: (value: V, key: string, map: Map<string, V>) => void, thisArg?: any): void { // we cannot use the map implementation since we need to pass this as map const items = this.items const keys = Object.keys(items) const len = keys.length for (let i = 0; i < len; i++) { const k = keys[i] callbackfn.call(thisArg, items[k], k, this) } } get(key: string): V | undefined { return get(this.items, key) } has(key: string): boolean { return has(this.items, key) } @modelAction set(key: string, value: V): this { set(this.items, key, value) return this } get size(): number { return keys(this.items).length } keys(): IterableIterator<string> { // TODO: should use an actual iterator return keys(this.items)[Symbol.iterator]() as IterableIterator<string> } values(): IterableIterator<V> { // TODO: should use an actual iterator return values(this.items)[Symbol.iterator]() } entries(): IterableIterator<[string, V]> { // TODO: should use an actual iterator return entries(this.items)[Symbol.iterator]() } [Symbol.iterator](): IterableIterator<[string, V]> { return this.entries() } get [Symbol.toStringTag](): string { return "ObjectMap" } } /** * Creates a new ObjectMap model instance. * * @typeparam V Value type. * @param [entries] Optional initial values. */ export function objectMap<V>(entries?: ReadonlyArray<readonly [string, V]> | null): ObjectMap<V> { const initialObj: { [k: string]: V } = {} if (entries) { let len = entries.length for (let i = 0; i < len; i++) { const entry = entries[i] initialObj[entry[0]] = entry[1] } } return new ObjectMap({ items: initialObj }) }