import type { FamilyMetadata, StateUpdate, WritablePureSelectorOptions, WritablePureSelectorToken, } from "atom.io" import type { Canonical } from "atom.io/foundations/canonical" import { Subject } from "atom.io/foundations/subject" import { newest } from "../lineage.ts" import type { WritablePureSelector } from "../state-types.ts" import type { Store } from "../store/index.ts" import type { RootStore } from "../transaction/index.ts" import { registerSelector } from "./register-selector.ts" export function createWritablePureSelector( store: Store, options: WritablePureSelectorOptions, family: FamilyMetadata | undefined, ): WritablePureSelectorToken { const target = newest(store) const subject = new Subject>() const covered = new Set() const key = options.key const type = `writable_pure_selector` as const store.logger.info(`🔨`, type, key, `is being created`) const setterToolkit = registerSelector(target, type, key, covered) const { find, get, json, relations } = setterToolkit const getterToolkit = { find, get, json, relations } const getFrom = (innerTarget: Store): E | T => { const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key, }) for (const [downstreamSelectorKey, { source }] of upstreamStates) { if (source !== key) { innerTarget.selectorGraph.delete(downstreamSelectorKey, key) } } innerTarget.selectorAtoms.delete(key) const value = options.get(getterToolkit) store.logger.info(`✨`, type, key, `=`, value) covered.clear() return value } const setSelf = (newValue: T): void => { options.set(setterToolkit, newValue) } const mySelector: WritablePureSelector = { ...options, type, subject, getFrom, setSelf, install: (s: RootStore) => createWritablePureSelector(s, options, family), } if (family) mySelector.family = family target.writableSelectors.set(key, mySelector) const token: WritablePureSelectorToken = { key, type } if (family) token.family = family return token }