mobx-keystone
Version:
A MobX powered state management solution based on data trees with first class support for TypeScript, snapshots, patches and much more
60 lines (49 loc) • 1.85 kB
text/typescript
import type { AnyModel } from "../model/BaseModel"
import { getModelIdPropertyName } from "../model/getModelMetadata"
import { modelIdKey, modelTypeKey } from "../model/metadata"
import { isModel, isModelSnapshot } from "../model/utils"
import { ModelClass } from "../modelShared/BaseModelShared"
import { getModelInfoForName } from "../modelShared/modelInfo"
import { dataObjectParent } from "../parent/core"
import {
getDeepObjectChildren,
registerDeepObjectChildrenExtension,
} from "../parent/coreObjectChildren"
function byModelTypeAndIdKey(modelType: string, modelId: string) {
return modelType + " " + modelId
}
export class ModelPool {
private pool: ReadonlyMap<string, AnyModel>
constructor(root: object) {
// make sure we don't use the sub-data $ object
root = dataObjectParent.get(root) ?? root
this.pool = getDeepChildrenModels(getDeepObjectChildren(root))
}
findModelByTypeAndId(modelType: string, modelId: string | undefined): AnyModel | undefined {
return modelId ? this.pool.get(byModelTypeAndIdKey(modelType, modelId)) : undefined
}
findModelForSnapshot(sn: any): AnyModel | undefined {
if (!isModelSnapshot(sn)) {
return undefined
}
const modelType = sn[modelTypeKey]
const modelInfo = getModelInfoForName(modelType)!
const modelIdPropertyName = getModelIdPropertyName(modelInfo.class as ModelClass<AnyModel>)
return modelIdPropertyName
? this.findModelByTypeAndId(modelType, (sn as any)[modelIdPropertyName])
: undefined
}
}
const getDeepChildrenModels = registerDeepObjectChildrenExtension<Map<string, AnyModel>>({
initData() {
return new Map()
},
addNode(node, data) {
if (isModel(node)) {
const id = node[modelIdKey]
if (id) {
data.set(byModelTypeAndIdKey(node[modelTypeKey], id), node)
}
}
},
})