import type { TransactionToken } from "atom.io" import type { Canonical } from "atom.io/foundations/canonical" import type { Each, RootStore } from "atom.io/internal" import { actUponStore, allocateIntoStore, arbitrary, claimWithinStore, createClaimTX, createDeallocateTX, fuseWithinStore, IMPLICIT, makeRootMoleculeInStore, } from "atom.io/internal" export { decomposeCompound, simpleCompound } from "atom.io/internal" export const $validatedKey: unique symbol = Symbol.for(`claim`) export type ValidKey = K & { [$validatedKey]?: true } export class Realm { public store: RootStore public deallocateTX: TransactionToken<(claim: ValidKey>) => void> public claimTX: TransactionToken< , CompoundTypedKey>, A extends Above>( newProvenance: A, claim: ValidKey, exclusive?: `exclusive`, ) => void > /** * @param store - The store to which the realm will be attached */ public constructor(store: RootStore = IMPLICIT.STORE) { this.store = store this.deallocateTX = createDeallocateTX(store) this.claimTX = createClaimTX(store) makeRootMoleculeInStore(store, `root`) } /** * Make space for a new subject of the realm * @param provenance - A key for an owner {@link Above} the new subject in the realm's {@link Hierarchy} * @param key - A unique identifier for the new subject * @param attachmentStyle - The attachment style of new subject to its owner(s). `any` means that if any owners remain, the subject will be retained. `all` means that the subject be retained only if all owners remain . * @returns * The subject's key, given status as a true {@link ValidKey} */ public allocate, A extends Above>( provenance: A, key: V, attachmentStyle?: `all` | `any`, ): ValidKey { return allocateIntoStore( this.store, provenance, key, attachmentStyle, ) } /** * Fuse two reagents into a compound * @param type - the name of the compound that is being fused * @param reagentA - the left reagent of the compound * @param reagentB - the right reagent of the compound * @returns * The compound's key, given status as a {@link ValidKey} */ public fuse< C extends CompoundFrom, T extends (C extends CompoundTypedKey ? t : never), A extends (C extends CompoundTypedKey ? v : never), B extends (C extends CompoundTypedKey ? m : never), >( type: T, reagentA: SingularTypedKey, reagentB: SingularTypedKey, ): ValidKey> { return fuseWithinStore(this.store, type, reagentA, reagentB) } /** * Remove a subject from the realm * @param claim - The subject to be deallocated */ public deallocate>(claim: ValidKey): void { actUponStore(this.store, this.deallocateTX, arbitrary())(claim) } /** * Transfer a subject of the realm from one owner to another * @param newProvenance - A key for an owner {@link Above} the new subject in the realm's {@link Hierarchy} * @param claim - The subject to be claimed * @param exclusive - Whether the subjects previous owners should be detached from it * @returns * The subject's key, given status as a true {@link ValidKey} */ public claim< V extends Exclude, CompoundTypedKey>, A extends Above, >(newProvenance: A, claim: ValidKey, exclusive?: `exclusive`): void { actUponStore(this.store, this.claimTX, arbitrary())( newProvenance, claim, exclusive, ) } } export class Anarchy { public store: RootStore public deallocateTX: TransactionToken<(key: Canonical) => void> public claimTX: TransactionToken< (newProvenance: Canonical, key: Canonical, exclusive?: `exclusive`) => void > /** * @param store - The store to which the anarchy-realm will be attached */ public constructor(store: RootStore = IMPLICIT.STORE) { this.store = store this.deallocateTX = createDeallocateTX(store) this.claimTX = createClaimTX(store) makeRootMoleculeInStore(store, `root`) } /** * Declare a new entity * @param provenance - A key for an owner of the entity * @param key - A unique identifier for the new entity * @param attachmentStyle - The attachment style of new entity to its owner(s). `any` means that if any owners remain, the subject will be retained. `all` means that the subject be retained only if all owners remain . */ public allocate( provenance: Canonical, key: Canonical, attachmentStyle?: `all` | `any`, ): void { allocateIntoStore( this.store, provenance, key, attachmentStyle, ) } /** * Remove an entity * @param key - The entity to be deallocated */ public deallocate(key: Canonical): void { actUponStore(this.store, this.deallocateTX, arbitrary())(key) } /** * Transfer an entity from one owner to another * @param newProvenance - A key for an owner of the entity * @param key - The entity to be claimed * @param exclusive - Whether the entity's previous owners should be detached from it */ public claim( newProvenance: Canonical, key: Canonical, exclusive?: `exclusive`, ): void { claimWithinStore(this.store, newProvenance, key, exclusive) } /** * Fuse two reagents into a compound * @param type - the name of the compound that is being fused * @param reagentA - the left reagent of the compound * @param reagentB - the right reagent of the compound * @returns * The compound's key, given status as a {@link ValidKey} */ public fuse( type: T, reagentA: SingularTypedKey, reagentB: SingularTypedKey, ): ValidKey> { return fuseWithinStore( this.store, type, reagentA, reagentB, ) } } export type T$ = `T$` export type TypeTag = `${T$}--${T}` export type SingularTypedKey = `${T}::${string}` export type CompoundTypedKey< T extends string = string, A extends string = string, B extends string = string, > = `${TypeTag}==${SingularTypedKey}++${SingularTypedKey}` export type TypedKey< T extends string = string, A extends string = string, B extends string = string, > = CompoundTypedKey | SingularTypedKey type Scope = SingularTypedKey[] type MutualFealty = { above: Scope below: CompoundTypedKey } type ExclusiveFealty = { above: TypedKey | `root` below: Scope } type Fealty = ExclusiveFealty | MutualFealty export type Hierarchy = Each export type Vassal = { [K in keyof H]: H[K] extends MutualFealty ? H[K][`below`] : H[K] extends { below: Array } ? V extends TypedKey ? V : never : never }[keyof H] export type Above = { [K in keyof H]: H[K] extends MutualFealty ? TK extends H[K][`below`] ? H[K][`above`] : never : H[K] extends { below: Array } ? TK extends V ? H[K] extends ExclusiveFealty ? H[K][`above`] : never : never : never }[keyof H] export type Below = { [K in keyof H]: H[K] extends MutualFealty ? TK extends H[K][`above`] ? H[K][`below`] : TK extends H[K][`above`][number] ? H[K][`below`] : never : H[K] extends { above: infer V } ? TK extends V ? H[K] extends ExclusiveFealty ? H[K][`below`][number] : never : never : never }[keyof H] export type Mutuals = { [K in keyof H]: H[K] extends MutualFealty ? TK extends H[K][`above`][number] ? [mutual: Exclude, below: H[K][`below`]] : never : never }[keyof H] export type CompoundFrom = { [K in keyof H]: H[K] extends MutualFealty ? H[K][`below`] : never }[keyof H]