{"version":3,"file":"index.node.mjs","names":["#parent","#children","#ensurePrimitiveEntry","#assertActive","#ensureDerivedEntry","#applyPrimitiveUpdate","#disposed","#primitiveEntries","#derivedEntries","readCurrentStore"],"sources":["../src/atom/implementation.ts","../src/createAtomStore/implementation.ts","../src/defineAtomStoreSnapshot/implementation.ts","../src/withStore/implementation.ts"],"sourcesContent":["type Getter = <T>(atom: ReadableAtom<T>) => T;\ntype NonFunction<T> = T extends (...args: never[]) => unknown ? never : T;\n\ninterface PrimitiveAtom<T> {\n  readonly key: string;\n  readonly kind: \"primitive\";\n  readonly init: T;\n}\n\ninterface DerivedAtom<T> {\n  readonly key: string;\n  readonly kind: \"derived\";\n  readonly read: (get: Getter) => T;\n}\n\ntype ReadableAtom<T> = PrimitiveAtom<T> | DerivedAtom<T>;\ntype WritableAtom<T> = PrimitiveAtom<T>;\n\nfunction atom<T>(key: string, read: (get: Getter) => T): DerivedAtom<T>;\nfunction atom<T>(key: string, initialValue: NonFunction<T>): PrimitiveAtom<T>;\nfunction atom<T>(\n  key: string,\n  initialValueOrRead: T | ((get: Getter) => T),\n): PrimitiveAtom<T> | DerivedAtom<T> {\n  if (typeof initialValueOrRead === \"function\") {\n    return Object.freeze({\n      key,\n      kind: \"derived\" as const,\n      read: initialValueOrRead as (get: Getter) => T,\n    });\n  }\n\n  return Object.freeze({\n    key,\n    kind: \"primitive\" as const,\n    init: initialValueOrRead,\n  });\n}\n\nexport { atom };\nexport type { DerivedAtom, Getter, PrimitiveAtom, ReadableAtom, WritableAtom };\n","import {\n  computed,\n  signal,\n  type Computed,\n  type Signal,\n  type SignalUpdate,\n} from \"@dathra/reactivity\";\n\nimport type {\n  DerivedAtom,\n  PrimitiveAtom,\n  ReadableAtom,\n} from \"../atom/implementation\";\n\ntype AppId = string;\ntype AtomUpdate<T> = SignalUpdate<T>;\n\ninterface ReadableAtomRef<T> {\n  readonly value: T;\n  peek(): T;\n}\n\ninterface WritableAtomRef<T> extends ReadableAtomRef<T> {\n  set(update: AtomUpdate<T>): void;\n}\n\ninterface AtomStore {\n  readonly appId: AppId;\n  ref<T>(atom: DerivedAtom<T>): ReadableAtomRef<T>;\n  ref<T>(atom: PrimitiveAtom<T>): WritableAtomRef<T>;\n  get<T>(atom: ReadableAtom<T>): T;\n  peek<T>(atom: ReadableAtom<T>): T;\n  set<T>(atom: PrimitiveAtom<T>, update: AtomUpdate<T>): void;\n  fork(options?: {\n    values?: Iterable<readonly [PrimitiveAtom<unknown>, unknown]>;\n  }): AtomStore;\n  dispose(): void;\n}\n\ninterface PrimitiveEntry<T> {\n  effective: Computed<T>;\n  hasLocal: Signal<boolean>;\n  local: Signal<T>;\n  ref: WritableAtomRef<T>;\n}\n\ninterface DerivedEntry<T> {\n  computed: Computed<T>;\n  ref: ReadableAtomRef<T>;\n}\n\nfunction isDerivedAtom<T>(atom: ReadableAtom<T>): atom is DerivedAtom<T> {\n  return atom.kind === \"derived\";\n}\n\nclass AtomStoreImpl implements AtomStore {\n  readonly appId: AppId;\n\n  #children = new Set<AtomStoreImpl>();\n  #derivedEntries = new Map<DerivedAtom<unknown>, DerivedEntry<unknown>>();\n  #disposed = false;\n  #parent: AtomStoreImpl | undefined;\n  #primitiveEntries = new Map<\n    PrimitiveAtom<unknown>,\n    PrimitiveEntry<unknown>\n  >();\n\n  constructor(\n    appId: AppId,\n    parent?: AtomStoreImpl,\n    values?: Iterable<readonly [PrimitiveAtom<unknown>, unknown]>,\n  ) {\n    this.appId = appId;\n    this.#parent = parent;\n    if (parent !== undefined) {\n      parent.#children.add(this);\n    }\n\n    if (values !== undefined) {\n      for (const [atom, value] of values) {\n        this.#ensurePrimitiveEntry(atom, value, true);\n      }\n    }\n  }\n\n  ref<T>(atom: DerivedAtom<T>): ReadableAtomRef<T>;\n  ref<T>(atom: PrimitiveAtom<T>): WritableAtomRef<T>;\n  ref<T>(atom: ReadableAtom<T>): ReadableAtomRef<T> | WritableAtomRef<T> {\n    this.#assertActive();\n    if (isDerivedAtom(atom)) {\n      return this.#ensureDerivedEntry(atom).ref;\n    }\n    return this.#ensurePrimitiveEntry(atom).ref;\n  }\n\n  get<T>(atom: ReadableAtom<T>): T {\n    if (isDerivedAtom(atom)) {\n      return this.ref(atom).value;\n    }\n    return this.ref(atom).value;\n  }\n\n  peek<T>(atom: ReadableAtom<T>): T {\n    if (isDerivedAtom(atom)) {\n      return this.ref(atom).peek();\n    }\n    return this.ref(atom).peek();\n  }\n\n  set<T>(atom: PrimitiveAtom<T>, update: AtomUpdate<T>): void {\n    this.#assertActive();\n    this.#applyPrimitiveUpdate(this.#ensurePrimitiveEntry(atom), update);\n  }\n\n  fork(options?: {\n    values?: Iterable<readonly [PrimitiveAtom<unknown>, unknown]>;\n  }): AtomStore {\n    this.#assertActive();\n    return new AtomStoreImpl(this.appId, this, options?.values);\n  }\n\n  dispose(): void {\n    if (this.#disposed) return;\n\n    const children = Array.from(this.#children);\n    for (const child of children) {\n      child.dispose();\n    }\n\n    this.#children.clear();\n    const parent = this.#parent;\n    if (parent !== undefined) {\n      parent.#children.delete(this);\n    }\n    this.#parent = undefined;\n    this.#primitiveEntries.clear();\n    this.#derivedEntries.clear();\n    this.#disposed = true;\n  }\n\n  #applyPrimitiveUpdate<T>(\n    entry: PrimitiveEntry<T>,\n    update: AtomUpdate<T>,\n  ): void {\n    this.#assertActive();\n    const previousValue = entry.effective.peek();\n    const nextValue =\n      typeof update === \"function\"\n        ? (update as (prev: T) => T)(previousValue)\n        : update;\n\n    entry.local.set(nextValue);\n    if (!entry.hasLocal.peek()) {\n      entry.hasLocal.set(true);\n    }\n  }\n\n  #assertActive(): void {\n    if (this.#disposed) {\n      throw new Error(\"AtomStore has been disposed\");\n    }\n  }\n\n  #ensureDerivedEntry<T>(atom: DerivedAtom<T>): DerivedEntry<T> {\n    const existing = this.#derivedEntries.get(atom) as\n      | DerivedEntry<T>\n      | undefined;\n    if (existing !== undefined) {\n      return existing;\n    }\n\n    const value = computed(() => {\n      this.#assertActive();\n      return atom.read((target) => this.get(target));\n    });\n\n    const ref: ReadableAtomRef<T> = {\n      get value() {\n        return value.value;\n      },\n      peek() {\n        return value.peek();\n      },\n    };\n\n    const entry: DerivedEntry<T> = {\n      computed: value,\n      ref,\n    };\n\n    this.#derivedEntries.set(atom, entry as DerivedEntry<unknown>);\n    return entry;\n  }\n\n  #ensurePrimitiveEntry<T>(\n    atom: PrimitiveAtom<T>,\n    initialValue: T = atom.init,\n    hasLocalOverride = false,\n  ): PrimitiveEntry<T> {\n    const existing = this.#primitiveEntries.get(atom) as\n      | PrimitiveEntry<T>\n      | undefined;\n    if (existing !== undefined) {\n      if (hasLocalOverride) {\n        existing.local.set(initialValue);\n        if (!existing.hasLocal.peek()) {\n          existing.hasLocal.set(true);\n        }\n      }\n      return existing;\n    }\n\n    const hasLocal = signal(hasLocalOverride);\n    const local = signal(initialValue);\n    const effective = computed(() => {\n      this.#assertActive();\n      if (hasLocal.value || this.#parent === undefined) {\n        return local.value;\n      }\n      return this.#parent.get(atom);\n    });\n\n    const ref: WritableAtomRef<T> = {\n      get value() {\n        return effective.value;\n      },\n      peek() {\n        return effective.peek();\n      },\n      set: (update) => {\n        this.#assertActive();\n        const previousValue = effective.peek();\n        const nextValue =\n          typeof update === \"function\"\n            ? (update as (prev: T) => T)(previousValue)\n            : update;\n\n        local.set(nextValue);\n        if (!hasLocal.peek()) {\n          hasLocal.set(true);\n        }\n      },\n    };\n\n    const entry: PrimitiveEntry<T> = {\n      effective,\n      hasLocal,\n      local,\n      ref,\n    };\n\n    this.#primitiveEntries.set(atom, entry as PrimitiveEntry<unknown>);\n    return entry;\n  }\n}\n\nfunction createAtomStore(options: {\n  appId: AppId;\n  values?: Iterable<readonly [PrimitiveAtom<unknown>, unknown]>;\n}): AtomStore {\n  return new AtomStoreImpl(options.appId, undefined, options.values);\n}\n\nexport { createAtomStore };\nexport type { AppId, AtomStore, AtomUpdate, ReadableAtomRef, WritableAtomRef };\n","import type { PrimitiveAtom } from \"../atom/implementation\";\nimport type { AtomStore } from \"../createAtomStore/implementation\";\n\ntype AtomStoreSnapshotSchema = Record<string, PrimitiveAtom<unknown>>;\n\ntype InferPrimitiveAtomValue<T> = T extends PrimitiveAtom<infer U> ? U : never;\n\ntype AtomStoreSnapshotValue<S extends AtomStoreSnapshotSchema> = {\n  readonly [K in keyof S]: InferPrimitiveAtomValue<S[K]>;\n};\n\ninterface AtomStoreSnapshot<S extends AtomStoreSnapshotSchema> {\n  readonly schema: Readonly<S>;\n  serialize(store: AtomStore): AtomStoreSnapshotValue<S>;\n  values(\n    snapshot: AtomStoreSnapshotValue<S>,\n  ): Iterable<readonly [S[keyof S], unknown]>;\n  hydrate(store: AtomStore, snapshot: AtomStoreSnapshotValue<S>): void;\n}\n\nfunction assertPrimitiveAtomSchema(\n  schema: Record<string, { kind: string }>,\n): void {\n  for (const [stableId, atom] of Object.entries(schema)) {\n    if (atom.kind !== \"primitive\") {\n      throw new Error(\n        `[dathra] Snapshot schema entry \"${stableId}\" must reference a primitive atom`,\n      );\n    }\n  }\n}\n\nfunction defineAtomStoreSnapshot<const S extends AtomStoreSnapshotSchema>(\n  schema: S,\n): AtomStoreSnapshot<S> {\n  assertPrimitiveAtomSchema(schema);\n\n  const frozenSchema: Readonly<S> = Object.freeze({ ...schema });\n  const entries = Object.entries(frozenSchema) as Array<[keyof S, S[keyof S]]>;\n\n  return {\n    schema: frozenSchema,\n    serialize(store) {\n      const snapshot: Partial<AtomStoreSnapshotValue<S>> = {};\n\n      for (const [stableId, atom] of entries) {\n        snapshot[stableId] = store.get(\n          atom,\n        ) as AtomStoreSnapshotValue<S>[keyof S];\n      }\n\n      return Object.freeze(snapshot) as AtomStoreSnapshotValue<S>;\n    },\n    values(snapshot) {\n      return entries.map(([stableId, atom]) => {\n        return [atom, snapshot[stableId]] as const;\n      });\n    },\n    hydrate(store, snapshot) {\n      for (const [stableId, atom] of entries) {\n        store.set(atom, snapshot[stableId]);\n      }\n    },\n  };\n}\n\nexport { defineAtomStoreSnapshot };\nexport type {\n  AtomStoreSnapshot,\n  AtomStoreSnapshotSchema,\n  AtomStoreSnapshotValue,\n  InferPrimitiveAtomValue,\n};\n","import type { AtomStore } from \"../createAtomStore/implementation\";\nimport {\n  getCurrentStore as readCurrentStore,\n  runWithStoreContext,\n} from \"./internal\";\n\n/**\n * Returns the currently active AtomStore set by the nearest enclosing\n * `withStore` boundary, or `undefined` if called outside any boundary.\n */\nfunction getCurrentStore(): AtomStore | undefined {\n  return readCurrentStore();\n}\n\n/**\n * Evaluates `render` within an explicit store boundary.\n *\n * All Dathra APIs that access the current store (component rendering,\n * atom reads, SSR) will resolve `store` as the active store for the\n * duration of the `render` callback.\n *\n * Nested `withStore` calls shadow the outer store; when the inner\n * callback returns, the outer store is restored.\n *\n * @example\n * ```ts\n * // Root boundary\n * mount(root, withStore(store, () => <App />));\n *\n * // Nested boundary with forked store\n * withStore(childStore, () => <Subtree />);\n * ```\n */\nfunction withStore<T>(store: AtomStore, render: () => T): T {\n  return runWithStoreContext(store, render);\n}\n\nexport { getCurrentStore, withStore };\n"],"mappings":";;;;AAoBA,SAAS,KACP,KACA,oBACmC;CACnC,IAAI,OAAO,uBAAuB,YAChC,OAAO,OAAO,OAAO;EACnB;EACA,MAAM;EACN,MAAM;EACP,CAAC;CAGJ,OAAO,OAAO,OAAO;EACnB;EACA,MAAM;EACN,MAAM;EACP,CAAC;;;;;ACeJ,SAAS,cAAiB,MAA+C;CACvE,OAAO,KAAK,SAAS;;AAGvB,IAAM,gBAAN,MAAM,cAAmC;CACvC,AAAS;CAET,4BAAY,IAAI,KAAoB;CACpC,kCAAkB,IAAI,KAAkD;CACxE,YAAY;CACZ;CACA,oCAAoB,IAAI,KAGrB;CAEH,YACE,OACA,QACA,QACA;EACA,KAAK,QAAQ;EACb,KAAKA,UAAU;EACf,IAAI,WAAW,QACb,OAAOC,UAAU,IAAI,KAAK;EAG5B,IAAI,WAAW,QACb,KAAK,MAAM,CAAC,MAAM,UAAU,QAC1B,KAAKC,sBAAsB,MAAM,OAAO,KAAK;;CAOnD,IAAO,MAAgE;EACrE,KAAKC,eAAe;EACpB,IAAI,cAAc,KAAK,EACrB,OAAO,KAAKC,oBAAoB,KAAK,CAAC;EAExC,OAAO,KAAKF,sBAAsB,KAAK,CAAC;;CAG1C,IAAO,MAA0B;EAC/B,IAAI,cAAc,KAAK,EACrB,OAAO,KAAK,IAAI,KAAK,CAAC;EAExB,OAAO,KAAK,IAAI,KAAK,CAAC;;CAGxB,KAAQ,MAA0B;EAChC,IAAI,cAAc,KAAK,EACrB,OAAO,KAAK,IAAI,KAAK,CAAC,MAAM;EAE9B,OAAO,KAAK,IAAI,KAAK,CAAC,MAAM;;CAG9B,IAAO,MAAwB,QAA6B;EAC1D,KAAKC,eAAe;EACpB,KAAKE,sBAAsB,KAAKH,sBAAsB,KAAK,EAAE,OAAO;;CAGtE,KAAK,SAES;EACZ,KAAKC,eAAe;EACpB,OAAO,IAAI,cAAc,KAAK,OAAO,MAAM,SAAS,OAAO;;CAG7D,UAAgB;EACd,IAAI,KAAKG,WAAW;EAEpB,MAAM,WAAW,MAAM,KAAK,KAAKL,UAAU;EAC3C,KAAK,MAAM,SAAS,UAClB,MAAM,SAAS;EAGjB,KAAKA,UAAU,OAAO;EACtB,MAAM,SAAS,KAAKD;EACpB,IAAI,WAAW,QACb,OAAOC,UAAU,OAAO,KAAK;EAE/B,KAAKD,UAAU;EACf,KAAKO,kBAAkB,OAAO;EAC9B,KAAKC,gBAAgB,OAAO;EAC5B,KAAKF,YAAY;;CAGnB,sBACE,OACA,QACM;EACN,KAAKH,eAAe;EACpB,MAAM,gBAAgB,MAAM,UAAU,MAAM;EAC5C,MAAM,YACJ,OAAO,WAAW,aACb,OAA0B,cAAc,GACzC;EAEN,MAAM,MAAM,IAAI,UAAU;EAC1B,IAAI,CAAC,MAAM,SAAS,MAAM,EACxB,MAAM,SAAS,IAAI,KAAK;;CAI5B,gBAAsB;EACpB,IAAI,KAAKG,WACP,MAAM,IAAI,MAAM,8BAA8B;;CAIlD,oBAAuB,MAAuC;EAC5D,MAAM,WAAW,KAAKE,gBAAgB,IAAI,KAAK;EAG/C,IAAI,aAAa,QACf,OAAO;EAGT,MAAM,QAAQ,eAAe;GAC3B,KAAKL,eAAe;GACpB,OAAO,KAAK,MAAM,WAAW,KAAK,IAAI,OAAO,CAAC;IAC9C;EAWF,MAAM,QAAyB;GAC7B,UAAU;GACV;IAVA,IAAI,QAAQ;KACV,OAAO,MAAM;;IAEf,OAAO;KACL,OAAO,MAAM,MAAM;;IAMlB;GACJ;EAED,KAAKK,gBAAgB,IAAI,MAAM,MAA+B;EAC9D,OAAO;;CAGT,sBACE,MACA,eAAkB,KAAK,MACvB,mBAAmB,OACA;EACnB,MAAM,WAAW,KAAKD,kBAAkB,IAAI,KAAK;EAGjD,IAAI,aAAa,QAAW;GAC1B,IAAI,kBAAkB;IACpB,SAAS,MAAM,IAAI,aAAa;IAChC,IAAI,CAAC,SAAS,SAAS,MAAM,EAC3B,SAAS,SAAS,IAAI,KAAK;;GAG/B,OAAO;;EAGT,MAAM,WAAW,OAAO,iBAAiB;EACzC,MAAM,QAAQ,OAAO,aAAa;EAClC,MAAM,YAAY,eAAe;GAC/B,KAAKJ,eAAe;GACpB,IAAI,SAAS,SAAS,KAAKH,YAAY,QACrC,OAAO,MAAM;GAEf,OAAO,KAAKA,QAAQ,IAAI,KAAK;IAC7B;EAwBF,MAAM,QAA2B;GAC/B;GACA;GACA;GACA;IAzBA,IAAI,QAAQ;KACV,OAAO,UAAU;;IAEnB,OAAO;KACL,OAAO,UAAU,MAAM;;IAEzB,MAAM,WAAW;KACf,KAAKG,eAAe;KACpB,MAAM,gBAAgB,UAAU,MAAM;KACtC,MAAM,YACJ,OAAO,WAAW,aACb,OAA0B,cAAc,GACzC;KAEN,MAAM,IAAI,UAAU;KACpB,IAAI,CAAC,SAAS,MAAM,EAClB,SAAS,IAAI,KAAK;;IASnB;GACJ;EAED,KAAKI,kBAAkB,IAAI,MAAM,MAAiC;EAClE,OAAO;;;AAIX,SAAS,gBAAgB,SAGX;CACZ,OAAO,IAAI,cAAc,QAAQ,OAAO,QAAW,QAAQ,OAAO;;;;;AChPpE,SAAS,0BACP,QACM;CACN,KAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,OAAO,EACnD,IAAI,KAAK,SAAS,aAChB,MAAM,IAAI,MACR,mCAAmC,SAAS,mCAC7C;;AAKP,SAAS,wBACP,QACsB;CACtB,0BAA0B,OAAO;CAEjC,MAAM,eAA4B,OAAO,OAAO,EAAE,GAAG,QAAQ,CAAC;CAC9D,MAAM,UAAU,OAAO,QAAQ,aAAa;CAE5C,OAAO;EACL,QAAQ;EACR,UAAU,OAAO;GACf,MAAM,WAA+C,EAAE;GAEvD,KAAK,MAAM,CAAC,UAAU,SAAS,SAC7B,SAAS,YAAY,MAAM,IACzB,KACD;GAGH,OAAO,OAAO,OAAO,SAAS;;EAEhC,OAAO,UAAU;GACf,OAAO,QAAQ,KAAK,CAAC,UAAU,UAAU;IACvC,OAAO,CAAC,MAAM,SAAS,UAAU;KACjC;;EAEJ,QAAQ,OAAO,UAAU;GACvB,KAAK,MAAM,CAAC,UAAU,SAAS,SAC7B,MAAM,IAAI,MAAM,SAAS,UAAU;;EAGxC;;;;;;;;;ACrDH,SAAS,kBAAyC;CAChD,OAAOE,mBAAkB;;;;;;;;;;;;;;;;;;;;;AAsB3B,SAAS,UAAa,OAAkB,QAAoB;CAC1D,OAAO,oBAAoB,OAAO,OAAO"}