import type { FamilyMetadata, findRelations, findState, getInternalRelations, getState, WritablePureSelectorFamilyOptions, WritablePureSelectorFamilyToken, WritablePureSelectorOptions, WritablePureSelectorToken, } from "atom.io" import { PRETTY_ENTITY_NAMES } from "atom.io" import type { Canonical } from "atom.io/foundations/canonical" import { stringifyJson } from "atom.io/foundations/json" import { getFromStore } from "../get-state/index.ts" import { findRelationsInStore, getInternalRelationsFromStore, } from "../join/index.ts" import { newest } from "../lineage.ts" import { getJsonTokenFromStore } from "../mutable/index.ts" import { createWritablePureSelector } from "../selector/index.ts" import type { WritablePureSelectorFamily } from "../state-types.ts" import type { Store } from "../store/index.ts" import type { RootStore } from "../transaction/index.ts" import { findInStore } from "./find-in-store.ts" export function createWritablePureSelectorFamily( store: Store, options: WritablePureSelectorFamilyOptions, internalRoles?: string[], ): WritablePureSelectorFamilyToken { const familyKey = options.key const type = `writable_pure_selector_family` const familyToken = { key: familyKey, type, } as const satisfies WritablePureSelectorFamilyToken const existing = store.families.get(familyKey) if (existing && store.config.isProduction === true) { store.logger.error( `❗`, type, familyKey, `Overwriting an existing ${PRETTY_ENTITY_NAMES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`, ) } const create = ( key: Key, ): WritablePureSelectorToken => { const subKey = stringifyJson(key) const family: FamilyMetadata = { key: familyKey, subKey } const fullKey = `${familyKey}(${subKey})` const target = newest(store) const individualOptions: WritablePureSelectorOptions = { key: fullKey, get: options.get(key), set: options.set(key), } if (options.catch) { individualOptions.catch = options.catch } return createWritablePureSelector( target, individualOptions, family, ) } const selectorFamily: WritablePureSelectorFamily = { ...familyToken, create, internalRoles, install: (s: RootStore) => createWritablePureSelectorFamily(s, options), default: (key: K) => { const getFn = options.get(key) return getFn({ get: ((...ps: Parameters) => getFromStore(store, ...ps)) as typeof getState, find: ((...ps: Parameters) => findInStore(store, ...ps)) as typeof findState, json: (token) => getJsonTokenFromStore(store, token), relations: { find: ((...ps: Parameters) => findRelationsInStore(store, ...ps)) as typeof findRelations, internal: ((...ps: Parameters) => getInternalRelationsFromStore( store, ...ps, )) as typeof getInternalRelations, }, }) }, } store.families.set(familyKey, selectorFamily) return familyToken }