import type { ReadableToken, WritableToken } from "atom.io" import type { Canonical } from "atom.io/foundations/canonical" import { stringifyJson } from "atom.io/foundations/json" import type { ReadableFamily } from "../state-types.ts" import type { Store } from "../store/index.ts" export const FAMILY_MEMBER_TOKEN_TYPES = { atom_family: `atom`, molecule_family: `molecule`, mutable_atom_family: `mutable_atom`, readonly_held_selector_family: `readonly_held_selector`, readonly_pure_selector_family: `readonly_pure_selector`, writable_held_selector_family: `writable_held_selector`, writable_pure_selector_family: `writable_pure_selector`, } as const export const MUST_CREATE: unique symbol = Symbol(`MUST_CREATE`) export const DO_NOT_CREATE: unique symbol = Symbol(`DO_NOT_CREATE`) export function mintInStore( mustCreate: typeof DO_NOT_CREATE | typeof MUST_CREATE, store: Store, family: ReadableFamily, key: KK, ): WritableToken export function mintInStore( mustCreate: typeof DO_NOT_CREATE | typeof MUST_CREATE, store: Store, family: ReadableFamily, key: KK, ): ReadableToken export function mintInStore( mustCreate: typeof DO_NOT_CREATE | typeof MUST_CREATE, store: Store, family: ReadableFamily, key: KK, ): ReadableToken { const stringKey = stringifyJson(key) const molecule = store.molecules.get(stringKey) const cannotCreate = !molecule && store.config.lifespan === `immortal` if (cannotCreate) { const { type: familyType, key: familyKey } = family store.logger.warn( `💣`, `key`, stringKey, `was used to mint a counterfeit token for`, familyType, `"${familyKey}"`, ) const fullKey = `${familyKey}(${stringKey})` const type = FAMILY_MEMBER_TOKEN_TYPES[familyType] const stateToken: ReadableToken & { counterfeit: true } = { counterfeit: true, key: fullKey, type, family: { key: familyKey, subKey: stringKey, }, } return stateToken } let token: ReadableToken if (mustCreate === MUST_CREATE) { store.logger.info( `👪`, family.type, family.key, `adds member`, typeof key === `string` ? `\`${key}\`` : key, ) token = family.create(key) if (molecule) { store.moleculeData.set(stringKey, family.key) } } else { const { type: familyType, key: familyKey } = family const fullKey = `${familyKey}(${stringKey})` const type = FAMILY_MEMBER_TOKEN_TYPES[familyType] const stateToken: ReadableToken = { key: fullKey, type, family: { key: familyKey, subKey: stringKey, }, } return stateToken } return token }