atom.io 0.33.21 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/internal/index.d.ts +5 -6
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +1252 -1247
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/realtime-client/index.js +2 -2
  6. package/dist/realtime-client/index.js.map +1 -1
  7. package/dist/realtime-testing/index.d.ts.map +1 -1
  8. package/dist/realtime-testing/index.js +0 -1
  9. package/dist/realtime-testing/index.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/internal/atom/create-regular-atom.ts +6 -7
  12. package/src/internal/caching.ts +9 -9
  13. package/src/internal/future.ts +3 -0
  14. package/src/internal/get-state/read-or-compute-value.ts +12 -7
  15. package/src/internal/mutable/create-mutable-atom.ts +2 -4
  16. package/src/internal/selector/create-readonly-held-selector.ts +10 -0
  17. package/src/internal/selector/create-readonly-pure-selector.ts +13 -4
  18. package/src/internal/selector/create-writable-held-selector.ts +11 -2
  19. package/src/internal/selector/create-writable-pure-selector.ts +11 -1
  20. package/src/internal/selector/trace-selector-atoms.ts +18 -40
  21. package/src/internal/selector/update-selector-atoms.ts +5 -5
  22. package/src/internal/set-state/evict-downstream.ts +2 -2
  23. package/src/internal/set-state/reset-atom-or-selector.ts +3 -3
  24. package/src/internal/store/store.ts +0 -1
  25. package/src/internal/subscribe/subscribe-to-root-atoms.ts +42 -38
  26. package/src/internal/subscribe/subscribe-to-state.ts +23 -11
  27. package/src/realtime-client/realtime-client-stores/client-sync-store.ts +2 -2
  28. package/src/realtime-testing/setup-realtime-test.tsx +0 -5
@@ -285,11 +285,11 @@ const myUsernameState = AtomIO.atom({
285
285
  //#region src/realtime-client/realtime-client-stores/client-sync-store.ts
286
286
  const optimisticUpdateQueue = AtomIO.atom({
287
287
  key: `updateQueue`,
288
- default: []
288
+ default: () => []
289
289
  });
290
290
  const confirmedUpdateQueue = AtomIO.atom({
291
291
  key: `serverConfirmedUpdateQueue`,
292
- default: []
292
+ default: () => []
293
293
  });
294
294
 
295
295
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["store: Store","continuityKey: string","socket: Socket","optimisticUpdates: AtomIO.TransactionUpdate<any>[]","confirmedUpdates: AtomIO.TransactionUpdate<any>[]","confirmed: AtomIO.TransactionUpdate<Func>","optimisticUpdate: AtomIO.TransactionUpdate<any>","confirmedUpdate: AtomIO.TransactionUpdate<any>","optimisticUpdateQueue","confirmedUpdateQueue","continuityEpoch: number | undefined","store: Store","concealed: AtomToken<unknown>[]","store: Store","revealed: Json.Array","k: any","v: any","store: Store","socket: Socket","token: AtomIO.RegularAtomToken<J>","data: J","store: Store","socket: Socket","token: AtomIO.RegularAtomToken<J>","data: J","store: Store","socket: Socket","token: AtomIO.MutableAtomToken<T, J>","data: J","data: T extends Transceiver<infer Update> ? Update : never","store: Store","socket: Socket","token: AtomIO.MutableAtomToken<T, J>","data: J","data: T extends Transceiver<infer Signal> ? Signal : never","store: Store","socket: Socket","token: AtomIO.SelectorToken<T>","unsubscribes: Array<() => void>","atom","store: Store","socket: Socket","token: AtomIO.SelectorToken<T>","unsubscribes: Array<() => void>","atom","store: Internal.Store","socket: Socket","token: AtomIO.WritableToken<J>","myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined>","myIdState: AtomIO.ReadonlyPureSelectorToken<string | undefined>","myUsernameState: AtomIO.RegularAtomToken<string | null>","optimisticUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n>","confirmedUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n>","store: Internal.Store","socket: Socket","token: AtomIO.TransactionToken<F>","store: Store","socket: Socket","continuity: ContinuityToken","optimisticUpdateQueue","confirmedUpdateQueue","epoch: number","payload: Json.Array","k: any","v: any"],"sources":["../../src/realtime-client/continuity/register-and-attempt-confirmed-update.ts","../../src/realtime-client/continuity/use-conceal-state.ts","../../src/realtime-client/continuity/use-reveal-state.ts","../../src/realtime-client/pull-atom.ts","../../src/realtime-client/pull-atom-family-member.ts","../../src/realtime-client/pull-mutable-atom.ts","../../src/realtime-client/pull-mutable-atom-family-member.ts","../../src/realtime-client/pull-selector.ts","../../src/realtime-client/pull-selector-family-member.ts","../../src/realtime-client/push-state.ts","../../src/realtime-client/realtime-client-stores/client-main-store.ts","../../src/realtime-client/realtime-client-stores/client-sync-store.ts","../../src/realtime-client/server-action.ts","../../src/realtime-client/sync-continuity.ts"],"sourcesContent":["import type * as AtomIO from \"atom.io\"\nimport type { Func, Store } from \"atom.io/internal\"\nimport {\n\tactUponStore,\n\tgetEpochNumberOfContinuity,\n\tingestTransactionUpdate,\n\tisRootStore,\n\tsetEpochNumberOfContinuity,\n\tsetIntoStore,\n} from \"atom.io/internal\"\nimport {\n\tconfirmedUpdateQueue,\n\toptimisticUpdateQueue,\n} from \"atom.io/realtime-client\"\nimport type { Socket } from \"atom.io/realtime-server\"\n\nexport const useRegisterAndAttemptConfirmedUpdate =\n\t(\n\t\tstore: Store,\n\t\tcontinuityKey: string,\n\t\tsocket: Socket,\n\t\toptimisticUpdates: AtomIO.TransactionUpdate<any>[],\n\t\tconfirmedUpdates: AtomIO.TransactionUpdate<any>[],\n\t) =>\n\t(confirmed: AtomIO.TransactionUpdate<Func>): void => {\n\t\tfunction reconcileEpoch(\n\t\t\toptimisticUpdate: AtomIO.TransactionUpdate<any>,\n\t\t\tconfirmedUpdate: AtomIO.TransactionUpdate<any>,\n\t\t): void {\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`reconciling updates`,\n\t\t\t)\n\t\t\tsetIntoStore(store, optimisticUpdateQueue, (queue) => {\n\t\t\t\tqueue.shift()\n\t\t\t\treturn queue\n\t\t\t})\n\t\t\tif (optimisticUpdate.id === confirmedUpdate.id) {\n\t\t\t\tconst clientResult = JSON.stringify(optimisticUpdate.updates)\n\t\t\t\tconst serverResult = JSON.stringify(confirmedUpdate.updates)\n\t\t\t\tif (clientResult === serverResult) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`✅`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`results for ${optimisticUpdate.id} match between client and server`,\n\t\t\t\t\t)\n\t\t\t\t\tsocket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// id mismatch\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`updates do not match`,\n\t\t\t\toptimisticUpdate,\n\t\t\t\tconfirmedUpdate,\n\t\t\t)\n\t\t\tconst reversedOptimisticUpdates = optimisticUpdates.toReversed()\n\t\t\tfor (const subsequentOptimistic of reversedOptimisticUpdates) {\n\t\t\t\tingestTransactionUpdate(`oldValue`, subsequentOptimistic, store)\n\t\t\t}\n\t\t\tstore.logger.info(\n\t\t\t\t`⏪`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`undid optimistic updates:`,\n\t\t\t\treversedOptimisticUpdates,\n\t\t\t)\n\t\t\tingestTransactionUpdate(`oldValue`, optimisticUpdate, store)\n\t\t\tstore.logger.info(\n\t\t\t\t`⏪`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`undid zeroth optimistic update`,\n\t\t\t\toptimisticUpdate,\n\t\t\t)\n\t\t\tingestTransactionUpdate(`newValue`, confirmedUpdate, store)\n\t\t\tstore.logger.info(\n\t\t\t\t`⏩`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`applied confirmed update`,\n\t\t\t\tconfirmedUpdate,\n\t\t\t)\n\t\t\tsocket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch)\n\n\t\t\tfor (const subsequentOptimistic of optimisticUpdates) {\n\t\t\t\tconst token = {\n\t\t\t\t\ttype: `transaction`,\n\t\t\t\t\tkey: subsequentOptimistic.key,\n\t\t\t\t} as const\n\t\t\t\tconst { id, params } = subsequentOptimistic\n\t\t\t\tactUponStore(store, token, id)(...params)\n\t\t\t}\n\t\t\tstore.logger.info(\n\t\t\t\t`⏩`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`reapplied subsequent optimistic updates:`,\n\t\t\t\toptimisticUpdates,\n\t\t\t)\n\t\t}\n\n\t\tstore.logger.info(\n\t\t\t`🧑‍⚖️`,\n\t\t\t`continuity`,\n\t\t\tcontinuityKey,\n\t\t\t`integrating confirmed update`,\n\t\t\t{ confirmedUpdate: confirmed, confirmedUpdates, optimisticUpdates },\n\t\t)\n\t\tconst zerothOptimisticUpdate = optimisticUpdates[0]\n\t\tif (zerothOptimisticUpdate) {\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`has optimistic updates to reconcile`,\n\t\t\t)\n\t\t\tif (confirmed.epoch === zerothOptimisticUpdate.epoch) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`epoch of confirmed update #${confirmed.epoch} matches zeroth optimistic update`,\n\t\t\t\t)\n\t\t\t\treconcileEpoch(zerothOptimisticUpdate, confirmed)\n\t\t\t\tfor (const nextConfirmed of confirmedUpdates) {\n\t\t\t\t\tconst nextOptimistic = optimisticUpdates[0]\n\t\t\t\t\tif (nextConfirmed.epoch === nextOptimistic?.epoch) {\n\t\t\t\t\t\treconcileEpoch(nextOptimistic, nextConfirmed)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// epoch mismatch\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`epoch of confirmed update #${confirmed.epoch} does not match zeroth optimistic update #${zerothOptimisticUpdate.epoch}`,\n\t\t\t\t)\n\t\t\t\tconst confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(\n\t\t\t\t\t(update) => update.epoch === confirmed.epoch,\n\t\t\t\t)\n\t\t\t\tif (!confirmedUpdateIsAlreadyEnqueued) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`👈`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`pushing confirmed update to queue`,\n\t\t\t\t\t\tconfirmed,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, confirmedUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue.push(confirmed)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`has no optimistic updates to deal with`,\n\t\t\t)\n\t\t\tconst isRoot = isRootStore(store)\n\t\t\tlet continuityEpoch: number | undefined\n\t\t\tif (isRoot) {\n\t\t\t\tcontinuityEpoch = getEpochNumberOfContinuity(store, continuityKey)\n\t\t\t}\n\n\t\t\tif (continuityEpoch === confirmed.epoch - 1) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`✅`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`integrating update #${confirmed.epoch} (${confirmed.key} ${confirmed.id})`,\n\t\t\t\t)\n\t\t\t\tingestTransactionUpdate(`newValue`, confirmed, store)\n\t\t\t\tsocket.emit(`ack:${continuityKey}`, confirmed.epoch)\n\t\t\t\tsetEpochNumberOfContinuity(store, continuityKey, confirmed.epoch)\n\t\t\t} else if (isRoot && continuityEpoch !== undefined) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`received update #${confirmed.epoch} but still waiting for update #${\n\t\t\t\t\t\tcontinuityEpoch + 1\n\t\t\t\t\t}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tclientEpoch: continuityEpoch,\n\t\t\t\t\t\tserverEpoch: confirmed.epoch,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tconst confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(\n\t\t\t\t\t(update) => update.epoch === confirmed.epoch,\n\t\t\t\t)\n\t\t\t\tif (confirmedUpdateIsAlreadyEnqueued) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`👍`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`confirmed update #${confirmed.epoch} is already enqueued`,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`👈`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`pushing confirmed update #${confirmed.epoch} to queue`,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, confirmedUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue.push(confirmed)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n","import type { AtomToken } from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport { disposeAtom } from \"atom.io/internal\"\n\nexport function useConcealState(store: Store) {\n\treturn (concealed: AtomToken<unknown>[]): void => {\n\t\tfor (const token of concealed) {\n\t\t\tdisposeAtom(store, token)\n\t\t}\n\t}\n}\n","import { setIntoStore, type Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nexport function useRevealState(store: Store) {\n\treturn (revealed: Json.Array): void => {\n\t\tlet i = 0\n\t\tlet k: any\n\t\tlet v: any\n\t\tfor (const x of revealed) {\n\t\t\tif (i % 2 === 0) {\n\t\t\t\tk = x\n\t\t\t} else {\n\t\t\t\tv = x\n\t\t\t\tsetIntoStore(store, k, v)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { setIntoStore, type Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullAtom<J extends Json.Serializable>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.RegularAtomToken<J>,\n): () => void {\n\tconst setServedValue = (data: J) => {\n\t\tsetIntoStore(store, token, data)\n\t}\n\tsocket.on(`serve:${token.key}`, setServedValue)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`, setServedValue)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { setIntoStore, type Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\n/* eslint-disable no-console */\n\nexport function pullAtomFamilyMember<J extends Json.Serializable>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.RegularAtomToken<J>,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tsetIntoStore(store, token, data)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableAtom<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n): () => void {\n\tconst jsonToken = getJsonToken(store, token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tsetIntoStore(store, jsonToken, data)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tsetIntoStore(store, updateToken, data)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\n/* eslint-disable no-console */\n\nexport function pullMutableAtomFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(store, token)\n\t\tsetIntoStore(store, jsonToken, data)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tsetIntoStore(store, trackerToken, data)\n\t\t},\n\t)\n\tsocket.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { pullAtom } from \"./pull-atom\"\nimport { pullMutableAtom } from \"./pull-mutable-atom\"\n\nexport function pullSelector<T>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.SelectorToken<T>,\n): () => void {\n\tconst atomKeys = store.selectorAtoms.getRelatedKeys(token.key)\n\tconst unsubscribes: Array<() => void> = []\n\tif (atomKeys) {\n\t\tfor (const atomKey of atomKeys) {\n\t\t\tconst atom = store.atoms.get(atomKey)\n\t\t\tif (!atom) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch (atom.type) {\n\t\t\t\tcase `atom`: {\n\t\t\t\t\tunsubscribes.push(pullAtom(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase `mutable_atom`: {\n\t\t\t\t\tunsubscribes.push(pullMutableAtom(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn () => {\n\t\tfor (const unsubscribe of unsubscribes) {\n\t\t\tunsubscribe()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { pullAtomFamilyMember } from \"./pull-atom-family-member\"\nimport { pullMutableAtomFamilyMember } from \"./pull-mutable-atom-family-member\"\n\n/* eslint-disable no-console */\n\nexport function pullSelectorFamilyMember<T>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.SelectorToken<T>,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst atomKeys = store.selectorAtoms.getRelatedKeys(token.key)\n\tconst unsubscribes: Array<() => void> = []\n\tif (atomKeys) {\n\t\tfor (const atomKey of atomKeys) {\n\t\t\tconst atom = store.atoms.get(atomKey)\n\t\t\tif (!atom) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch (atom.type) {\n\t\t\t\tcase `atom`: {\n\t\t\t\t\tunsubscribes.push(pullAtomFamilyMember(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase `mutable_atom`: {\n\t\t\t\t\tunsubscribes.push(pullMutableAtomFamilyMember(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn () => {\n\t\tfor (const unsubscribe of unsubscribes) {\n\t\t\tunsubscribe()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\tstore: Internal.Store,\n\tsocket: Socket,\n\ttoken: AtomIO.WritableToken<J>,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tInternal.subscribeToState(store, token, `push`, ({ newValue }) => {\n\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t})\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { persistSync } from \"atom.io/web\"\n\nexport const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined> =\n\tAtomIO.atom<string | undefined>({\n\t\tkey: `mySocketId__INTERNAL`,\n\t\tdefault: undefined,\n\t})\nexport const myIdState: AtomIO.ReadonlyPureSelectorToken<string | undefined> =\n\tAtomIO.selector<string | undefined>({\n\t\tkey: `mySocketId`,\n\t\tget: ({ get }) => get(myIdState__INTERNAL),\n\t})\n\nexport const myUsernameState: AtomIO.RegularAtomToken<string | null> =\n\tAtomIO.atom<string | null>({\n\t\tkey: `myName`,\n\t\tdefault: null,\n\t\teffects:\n\t\t\ttypeof window === `undefined`\n\t\t\t\t? []\n\t\t\t\t: [persistSync(window.localStorage, JSON, `myUsername`)],\n\t})\n","import * as AtomIO from \"atom.io\"\n\nexport const optimisticUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n> = AtomIO.atom<AtomIO.TransactionUpdate<any>[]>({\n\tkey: `updateQueue`,\n\tdefault: [],\n})\n\nexport const confirmedUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n> = AtomIO.atom<AtomIO.TransactionUpdate<any>[]>({\n\tkey: `serverConfirmedUpdateQueue`,\n\tdefault: [],\n})\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function serverAction<F extends Internal.Func>(\n\tstore: Internal.Store,\n\tsocket: Socket,\n\ttoken: AtomIO.TransactionToken<F>,\n): () => void {\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\tstore,\n\t\ttoken,\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\t(clientUpdate) => {\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t)\n\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t}\n}\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tassignTransactionToContinuity,\n\tgetFromStore,\n\tgetJsonToken,\n\tsetEpochNumberOfContinuity,\n\tsetIntoStore,\n\tsubscribeToTransaction,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\nimport {\n\tconfirmedUpdateQueue,\n\toptimisticUpdateQueue,\n} from \"atom.io/realtime-client\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { useRegisterAndAttemptConfirmedUpdate } from \"./continuity/register-and-attempt-confirmed-update\"\nimport { useConcealState } from \"./continuity/use-conceal-state\"\nimport { useRevealState } from \"./continuity/use-reveal-state\"\n\nexport function syncContinuity(\n\tstore: Store,\n\tsocket: Socket,\n\tcontinuity: ContinuityToken,\n): () => void {\n\tconst continuityKey = continuity.key\n\tconst optimisticUpdates = getFromStore(store, optimisticUpdateQueue)\n\tconst confirmedUpdates = getFromStore(store, confirmedUpdateQueue)\n\n\tconst initializeContinuity = (epoch: number, payload: Json.Array) => {\n\t\tsocket.off(`continuity-init:${continuityKey}`, initializeContinuity)\n\t\tlet i = 0\n\t\tlet k: any\n\t\tlet v: any\n\t\tfor (const x of payload) {\n\t\t\tif (i % 2 === 0) {\n\t\t\t\tk = x\n\t\t\t} else {\n\t\t\t\tv = x\n\t\t\t\tif (`type` in k && k.type === `mutable_atom`) {\n\t\t\t\t\tk = getJsonToken(store, k)\n\t\t\t\t}\n\t\t\t\tsetIntoStore(store, k, v)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\tsetEpochNumberOfContinuity(store, continuityKey, epoch)\n\t}\n\tsocket.off(`continuity-init:${continuityKey}`)\n\tsocket.on(`continuity-init:${continuityKey}`, initializeContinuity)\n\n\tconst registerAndAttemptConfirmedUpdate = useRegisterAndAttemptConfirmedUpdate(\n\t\tstore,\n\t\tcontinuityKey,\n\t\tsocket,\n\t\toptimisticUpdates,\n\t\tconfirmedUpdates,\n\t)\n\tsocket.off(`tx-new:${continuityKey}`)\n\tsocket.on(`tx-new:${continuityKey}`, registerAndAttemptConfirmedUpdate)\n\n\tconst unsubscribeFunctions = continuity.actions.map((transaction) => {\n\t\tassignTransactionToContinuity(store, continuityKey, transaction.key)\n\t\tconst unsubscribeFromTransactionUpdates = subscribeToTransaction(\n\t\t\tstore,\n\t\t\ttransaction,\n\t\t\t`tx-run:${continuityKey}`,\n\t\t\t(clientUpdate) => {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🤞`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`enqueuing optimistic update`,\n\t\t\t\t)\n\t\t\t\tconst optimisticUpdateIndex = optimisticUpdates.findIndex(\n\t\t\t\t\t(update) => update.id === clientUpdate.id,\n\t\t\t\t)\n\t\t\t\tif (optimisticUpdateIndex === -1) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`🤞`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`enqueuing new optimistic update`,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, optimisticUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue.push(clientUpdate)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`🤞`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`replacing existing optimistic update at index ${optimisticUpdateIndex}`,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, optimisticUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue[optimisticUpdateIndex] = clientUpdate\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tsocket.emit(`tx-run:${continuityKey}`, {\n\t\t\t\t\tid: clientUpdate.id,\n\t\t\t\t\tkey: transaction.key,\n\t\t\t\t\tparams: clientUpdate.params,\n\t\t\t\t})\n\t\t\t},\n\t\t)\n\t\treturn unsubscribeFromTransactionUpdates\n\t})\n\n\tconst revealState = useRevealState(store)\n\tconst concealState = useConcealState(store)\n\tsocket.on(`reveal:${continuityKey}`, revealState)\n\tsocket.on(`conceal:${continuityKey}`, concealState)\n\n\tsocket.emit(`get:${continuityKey}`)\n\treturn () => {\n\t\tsocket.off(`continuity-init:${continuityKey}`)\n\t\tsocket.off(`tx-new:${continuityKey}`)\n\t\tfor (const unsubscribe of unsubscribeFunctions) unsubscribe()\n\t\t// socket.emit(`unsub:${continuityKey}`)\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["store: Store","continuityKey: string","socket: Socket","optimisticUpdates: AtomIO.TransactionUpdate<any>[]","confirmedUpdates: AtomIO.TransactionUpdate<any>[]","confirmed: AtomIO.TransactionUpdate<Func>","optimisticUpdate: AtomIO.TransactionUpdate<any>","confirmedUpdate: AtomIO.TransactionUpdate<any>","optimisticUpdateQueue","confirmedUpdateQueue","continuityEpoch: number | undefined","store: Store","concealed: AtomToken<unknown>[]","store: Store","revealed: Json.Array","k: any","v: any","store: Store","socket: Socket","token: AtomIO.RegularAtomToken<J>","data: J","store: Store","socket: Socket","token: AtomIO.RegularAtomToken<J>","data: J","store: Store","socket: Socket","token: AtomIO.MutableAtomToken<T, J>","data: J","data: T extends Transceiver<infer Update> ? Update : never","store: Store","socket: Socket","token: AtomIO.MutableAtomToken<T, J>","data: J","data: T extends Transceiver<infer Signal> ? Signal : never","store: Store","socket: Socket","token: AtomIO.SelectorToken<T>","unsubscribes: Array<() => void>","atom","store: Store","socket: Socket","token: AtomIO.SelectorToken<T>","unsubscribes: Array<() => void>","atom","store: Internal.Store","socket: Socket","token: AtomIO.WritableToken<J>","myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined>","myIdState: AtomIO.ReadonlyPureSelectorToken<string | undefined>","myUsernameState: AtomIO.RegularAtomToken<string | null>","optimisticUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n>","confirmedUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n>","store: Internal.Store","socket: Socket","token: AtomIO.TransactionToken<F>","store: Store","socket: Socket","continuity: ContinuityToken","optimisticUpdateQueue","confirmedUpdateQueue","epoch: number","payload: Json.Array","k: any","v: any"],"sources":["../../src/realtime-client/continuity/register-and-attempt-confirmed-update.ts","../../src/realtime-client/continuity/use-conceal-state.ts","../../src/realtime-client/continuity/use-reveal-state.ts","../../src/realtime-client/pull-atom.ts","../../src/realtime-client/pull-atom-family-member.ts","../../src/realtime-client/pull-mutable-atom.ts","../../src/realtime-client/pull-mutable-atom-family-member.ts","../../src/realtime-client/pull-selector.ts","../../src/realtime-client/pull-selector-family-member.ts","../../src/realtime-client/push-state.ts","../../src/realtime-client/realtime-client-stores/client-main-store.ts","../../src/realtime-client/realtime-client-stores/client-sync-store.ts","../../src/realtime-client/server-action.ts","../../src/realtime-client/sync-continuity.ts"],"sourcesContent":["import type * as AtomIO from \"atom.io\"\nimport type { Func, Store } from \"atom.io/internal\"\nimport {\n\tactUponStore,\n\tgetEpochNumberOfContinuity,\n\tingestTransactionUpdate,\n\tisRootStore,\n\tsetEpochNumberOfContinuity,\n\tsetIntoStore,\n} from \"atom.io/internal\"\nimport {\n\tconfirmedUpdateQueue,\n\toptimisticUpdateQueue,\n} from \"atom.io/realtime-client\"\nimport type { Socket } from \"atom.io/realtime-server\"\n\nexport const useRegisterAndAttemptConfirmedUpdate =\n\t(\n\t\tstore: Store,\n\t\tcontinuityKey: string,\n\t\tsocket: Socket,\n\t\toptimisticUpdates: AtomIO.TransactionUpdate<any>[],\n\t\tconfirmedUpdates: AtomIO.TransactionUpdate<any>[],\n\t) =>\n\t(confirmed: AtomIO.TransactionUpdate<Func>): void => {\n\t\tfunction reconcileEpoch(\n\t\t\toptimisticUpdate: AtomIO.TransactionUpdate<any>,\n\t\t\tconfirmedUpdate: AtomIO.TransactionUpdate<any>,\n\t\t): void {\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`reconciling updates`,\n\t\t\t)\n\t\t\tsetIntoStore(store, optimisticUpdateQueue, (queue) => {\n\t\t\t\tqueue.shift()\n\t\t\t\treturn queue\n\t\t\t})\n\t\t\tif (optimisticUpdate.id === confirmedUpdate.id) {\n\t\t\t\tconst clientResult = JSON.stringify(optimisticUpdate.updates)\n\t\t\t\tconst serverResult = JSON.stringify(confirmedUpdate.updates)\n\t\t\t\tif (clientResult === serverResult) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`✅`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`results for ${optimisticUpdate.id} match between client and server`,\n\t\t\t\t\t)\n\t\t\t\t\tsocket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// id mismatch\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`updates do not match`,\n\t\t\t\toptimisticUpdate,\n\t\t\t\tconfirmedUpdate,\n\t\t\t)\n\t\t\tconst reversedOptimisticUpdates = optimisticUpdates.toReversed()\n\t\t\tfor (const subsequentOptimistic of reversedOptimisticUpdates) {\n\t\t\t\tingestTransactionUpdate(`oldValue`, subsequentOptimistic, store)\n\t\t\t}\n\t\t\tstore.logger.info(\n\t\t\t\t`⏪`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`undid optimistic updates:`,\n\t\t\t\treversedOptimisticUpdates,\n\t\t\t)\n\t\t\tingestTransactionUpdate(`oldValue`, optimisticUpdate, store)\n\t\t\tstore.logger.info(\n\t\t\t\t`⏪`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`undid zeroth optimistic update`,\n\t\t\t\toptimisticUpdate,\n\t\t\t)\n\t\t\tingestTransactionUpdate(`newValue`, confirmedUpdate, store)\n\t\t\tstore.logger.info(\n\t\t\t\t`⏩`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`applied confirmed update`,\n\t\t\t\tconfirmedUpdate,\n\t\t\t)\n\t\t\tsocket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch)\n\n\t\t\tfor (const subsequentOptimistic of optimisticUpdates) {\n\t\t\t\tconst token = {\n\t\t\t\t\ttype: `transaction`,\n\t\t\t\t\tkey: subsequentOptimistic.key,\n\t\t\t\t} as const\n\t\t\t\tconst { id, params } = subsequentOptimistic\n\t\t\t\tactUponStore(store, token, id)(...params)\n\t\t\t}\n\t\t\tstore.logger.info(\n\t\t\t\t`⏩`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`reapplied subsequent optimistic updates:`,\n\t\t\t\toptimisticUpdates,\n\t\t\t)\n\t\t}\n\n\t\tstore.logger.info(\n\t\t\t`🧑‍⚖️`,\n\t\t\t`continuity`,\n\t\t\tcontinuityKey,\n\t\t\t`integrating confirmed update`,\n\t\t\t{ confirmedUpdate: confirmed, confirmedUpdates, optimisticUpdates },\n\t\t)\n\t\tconst zerothOptimisticUpdate = optimisticUpdates[0]\n\t\tif (zerothOptimisticUpdate) {\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`has optimistic updates to reconcile`,\n\t\t\t)\n\t\t\tif (confirmed.epoch === zerothOptimisticUpdate.epoch) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`epoch of confirmed update #${confirmed.epoch} matches zeroth optimistic update`,\n\t\t\t\t)\n\t\t\t\treconcileEpoch(zerothOptimisticUpdate, confirmed)\n\t\t\t\tfor (const nextConfirmed of confirmedUpdates) {\n\t\t\t\t\tconst nextOptimistic = optimisticUpdates[0]\n\t\t\t\t\tif (nextConfirmed.epoch === nextOptimistic?.epoch) {\n\t\t\t\t\t\treconcileEpoch(nextOptimistic, nextConfirmed)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// epoch mismatch\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`epoch of confirmed update #${confirmed.epoch} does not match zeroth optimistic update #${zerothOptimisticUpdate.epoch}`,\n\t\t\t\t)\n\t\t\t\tconst confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(\n\t\t\t\t\t(update) => update.epoch === confirmed.epoch,\n\t\t\t\t)\n\t\t\t\tif (!confirmedUpdateIsAlreadyEnqueued) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`👈`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`pushing confirmed update to queue`,\n\t\t\t\t\t\tconfirmed,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, confirmedUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue.push(confirmed)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tstore.logger.info(\n\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`has no optimistic updates to deal with`,\n\t\t\t)\n\t\t\tconst isRoot = isRootStore(store)\n\t\t\tlet continuityEpoch: number | undefined\n\t\t\tif (isRoot) {\n\t\t\t\tcontinuityEpoch = getEpochNumberOfContinuity(store, continuityKey)\n\t\t\t}\n\n\t\t\tif (continuityEpoch === confirmed.epoch - 1) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`✅`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`integrating update #${confirmed.epoch} (${confirmed.key} ${confirmed.id})`,\n\t\t\t\t)\n\t\t\t\tingestTransactionUpdate(`newValue`, confirmed, store)\n\t\t\t\tsocket.emit(`ack:${continuityKey}`, confirmed.epoch)\n\t\t\t\tsetEpochNumberOfContinuity(store, continuityKey, confirmed.epoch)\n\t\t\t} else if (isRoot && continuityEpoch !== undefined) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🧑‍⚖️`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`received update #${confirmed.epoch} but still waiting for update #${\n\t\t\t\t\t\tcontinuityEpoch + 1\n\t\t\t\t\t}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tclientEpoch: continuityEpoch,\n\t\t\t\t\t\tserverEpoch: confirmed.epoch,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tconst confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(\n\t\t\t\t\t(update) => update.epoch === confirmed.epoch,\n\t\t\t\t)\n\t\t\t\tif (confirmedUpdateIsAlreadyEnqueued) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`👍`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`confirmed update #${confirmed.epoch} is already enqueued`,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`👈`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`pushing confirmed update #${confirmed.epoch} to queue`,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, confirmedUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue.push(confirmed)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n","import type { AtomToken } from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport { disposeAtom } from \"atom.io/internal\"\n\nexport function useConcealState(store: Store) {\n\treturn (concealed: AtomToken<unknown>[]): void => {\n\t\tfor (const token of concealed) {\n\t\t\tdisposeAtom(store, token)\n\t\t}\n\t}\n}\n","import { setIntoStore, type Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nexport function useRevealState(store: Store) {\n\treturn (revealed: Json.Array): void => {\n\t\tlet i = 0\n\t\tlet k: any\n\t\tlet v: any\n\t\tfor (const x of revealed) {\n\t\t\tif (i % 2 === 0) {\n\t\t\t\tk = x\n\t\t\t} else {\n\t\t\t\tv = x\n\t\t\t\tsetIntoStore(store, k, v)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { setIntoStore, type Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullAtom<J extends Json.Serializable>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.RegularAtomToken<J>,\n): () => void {\n\tconst setServedValue = (data: J) => {\n\t\tsetIntoStore(store, token, data)\n\t}\n\tsocket.on(`serve:${token.key}`, setServedValue)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`, setServedValue)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { setIntoStore, type Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\n/* eslint-disable no-console */\n\nexport function pullAtomFamilyMember<J extends Json.Serializable>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.RegularAtomToken<J>,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tsetIntoStore(store, token, data)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableAtom<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n): () => void {\n\tconst jsonToken = getJsonToken(store, token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tsetIntoStore(store, jsonToken, data)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tsetIntoStore(store, updateToken, data)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\n/* eslint-disable no-console */\n\nexport function pullMutableAtomFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(store, token)\n\t\tsetIntoStore(store, jsonToken, data)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tsetIntoStore(store, trackerToken, data)\n\t\t},\n\t)\n\tsocket.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { pullAtom } from \"./pull-atom\"\nimport { pullMutableAtom } from \"./pull-mutable-atom\"\n\nexport function pullSelector<T>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.SelectorToken<T>,\n): () => void {\n\tconst atomKeys = store.selectorAtoms.getRelatedKeys(token.key)\n\tconst unsubscribes: Array<() => void> = []\n\tif (atomKeys) {\n\t\tfor (const atomKey of atomKeys) {\n\t\t\tconst atom = store.atoms.get(atomKey)\n\t\t\tif (!atom) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch (atom.type) {\n\t\t\t\tcase `atom`: {\n\t\t\t\t\tunsubscribes.push(pullAtom(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase `mutable_atom`: {\n\t\t\t\t\tunsubscribes.push(pullMutableAtom(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn () => {\n\t\tfor (const unsubscribe of unsubscribes) {\n\t\t\tunsubscribe()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { pullAtomFamilyMember } from \"./pull-atom-family-member\"\nimport { pullMutableAtomFamilyMember } from \"./pull-mutable-atom-family-member\"\n\n/* eslint-disable no-console */\n\nexport function pullSelectorFamilyMember<T>(\n\tstore: Store,\n\tsocket: Socket,\n\ttoken: AtomIO.SelectorToken<T>,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst atomKeys = store.selectorAtoms.getRelatedKeys(token.key)\n\tconst unsubscribes: Array<() => void> = []\n\tif (atomKeys) {\n\t\tfor (const atomKey of atomKeys) {\n\t\t\tconst atom = store.atoms.get(atomKey)\n\t\t\tif (!atom) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch (atom.type) {\n\t\t\t\tcase `atom`: {\n\t\t\t\t\tunsubscribes.push(pullAtomFamilyMember(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase `mutable_atom`: {\n\t\t\t\t\tunsubscribes.push(pullMutableAtomFamilyMember(store, socket, atom))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn () => {\n\t\tfor (const unsubscribe of unsubscribes) {\n\t\t\tunsubscribe()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\tstore: Internal.Store,\n\tsocket: Socket,\n\ttoken: AtomIO.WritableToken<J>,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tInternal.subscribeToState(store, token, `push`, ({ newValue }) => {\n\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t})\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { persistSync } from \"atom.io/web\"\n\nexport const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined> =\n\tAtomIO.atom<string | undefined>({\n\t\tkey: `mySocketId__INTERNAL`,\n\t\tdefault: undefined,\n\t})\nexport const myIdState: AtomIO.ReadonlyPureSelectorToken<string | undefined> =\n\tAtomIO.selector<string | undefined>({\n\t\tkey: `mySocketId`,\n\t\tget: ({ get }) => get(myIdState__INTERNAL),\n\t})\n\nexport const myUsernameState: AtomIO.RegularAtomToken<string | null> =\n\tAtomIO.atom<string | null>({\n\t\tkey: `myName`,\n\t\tdefault: null,\n\t\teffects:\n\t\t\ttypeof window === `undefined`\n\t\t\t\t? []\n\t\t\t\t: [persistSync(window.localStorage, JSON, `myUsername`)],\n\t})\n","import * as AtomIO from \"atom.io\"\n\nexport const optimisticUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n> = AtomIO.atom<AtomIO.TransactionUpdate<any>[]>({\n\tkey: `updateQueue`,\n\tdefault: () => [],\n})\n\nexport const confirmedUpdateQueue: AtomIO.RegularAtomToken<\n\tAtomIO.TransactionUpdate<any>[]\n> = AtomIO.atom<AtomIO.TransactionUpdate<any>[]>({\n\tkey: `serverConfirmedUpdateQueue`,\n\tdefault: () => [],\n})\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function serverAction<F extends Internal.Func>(\n\tstore: Internal.Store,\n\tsocket: Socket,\n\ttoken: AtomIO.TransactionToken<F>,\n): () => void {\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\tstore,\n\t\ttoken,\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\t(clientUpdate) => {\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t)\n\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t}\n}\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tassignTransactionToContinuity,\n\tgetFromStore,\n\tgetJsonToken,\n\tsetEpochNumberOfContinuity,\n\tsetIntoStore,\n\tsubscribeToTransaction,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\nimport {\n\tconfirmedUpdateQueue,\n\toptimisticUpdateQueue,\n} from \"atom.io/realtime-client\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { useRegisterAndAttemptConfirmedUpdate } from \"./continuity/register-and-attempt-confirmed-update\"\nimport { useConcealState } from \"./continuity/use-conceal-state\"\nimport { useRevealState } from \"./continuity/use-reveal-state\"\n\nexport function syncContinuity(\n\tstore: Store,\n\tsocket: Socket,\n\tcontinuity: ContinuityToken,\n): () => void {\n\tconst continuityKey = continuity.key\n\tconst optimisticUpdates = getFromStore(store, optimisticUpdateQueue)\n\tconst confirmedUpdates = getFromStore(store, confirmedUpdateQueue)\n\n\tconst initializeContinuity = (epoch: number, payload: Json.Array) => {\n\t\tsocket.off(`continuity-init:${continuityKey}`, initializeContinuity)\n\t\tlet i = 0\n\t\tlet k: any\n\t\tlet v: any\n\t\tfor (const x of payload) {\n\t\t\tif (i % 2 === 0) {\n\t\t\t\tk = x\n\t\t\t} else {\n\t\t\t\tv = x\n\t\t\t\tif (`type` in k && k.type === `mutable_atom`) {\n\t\t\t\t\tk = getJsonToken(store, k)\n\t\t\t\t}\n\t\t\t\tsetIntoStore(store, k, v)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\tsetEpochNumberOfContinuity(store, continuityKey, epoch)\n\t}\n\tsocket.off(`continuity-init:${continuityKey}`)\n\tsocket.on(`continuity-init:${continuityKey}`, initializeContinuity)\n\n\tconst registerAndAttemptConfirmedUpdate = useRegisterAndAttemptConfirmedUpdate(\n\t\tstore,\n\t\tcontinuityKey,\n\t\tsocket,\n\t\toptimisticUpdates,\n\t\tconfirmedUpdates,\n\t)\n\tsocket.off(`tx-new:${continuityKey}`)\n\tsocket.on(`tx-new:${continuityKey}`, registerAndAttemptConfirmedUpdate)\n\n\tconst unsubscribeFunctions = continuity.actions.map((transaction) => {\n\t\tassignTransactionToContinuity(store, continuityKey, transaction.key)\n\t\tconst unsubscribeFromTransactionUpdates = subscribeToTransaction(\n\t\t\tstore,\n\t\t\ttransaction,\n\t\t\t`tx-run:${continuityKey}`,\n\t\t\t(clientUpdate) => {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`🤞`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`enqueuing optimistic update`,\n\t\t\t\t)\n\t\t\t\tconst optimisticUpdateIndex = optimisticUpdates.findIndex(\n\t\t\t\t\t(update) => update.id === clientUpdate.id,\n\t\t\t\t)\n\t\t\t\tif (optimisticUpdateIndex === -1) {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`🤞`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`enqueuing new optimistic update`,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, optimisticUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue.push(clientUpdate)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t`🤞`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`replacing existing optimistic update at index ${optimisticUpdateIndex}`,\n\t\t\t\t\t)\n\t\t\t\t\tsetIntoStore(store, optimisticUpdateQueue, (queue) => {\n\t\t\t\t\t\tqueue[optimisticUpdateIndex] = clientUpdate\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tsocket.emit(`tx-run:${continuityKey}`, {\n\t\t\t\t\tid: clientUpdate.id,\n\t\t\t\t\tkey: transaction.key,\n\t\t\t\t\tparams: clientUpdate.params,\n\t\t\t\t})\n\t\t\t},\n\t\t)\n\t\treturn unsubscribeFromTransactionUpdates\n\t})\n\n\tconst revealState = useRevealState(store)\n\tconst concealState = useConcealState(store)\n\tsocket.on(`reveal:${continuityKey}`, revealState)\n\tsocket.on(`conceal:${continuityKey}`, concealState)\n\n\tsocket.emit(`get:${continuityKey}`)\n\treturn () => {\n\t\tsocket.off(`continuity-init:${continuityKey}`)\n\t\tsocket.off(`tx-new:${continuityKey}`)\n\t\tfor (const unsubscribe of unsubscribeFunctions) unsubscribe()\n\t\t// socket.emit(`unsub:${continuityKey}`)\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["tools: {\n\t\tsocket: SocketIO.Socket\n\t\tsilo: AtomIO.Silo\n\t\tenableLogging: () => void\n\t}","options: TestSetupOptions","options: TestSetupOptions__SingleClient","name: string","port: number","options: TestSetupOptions__MultiClient<ClientNames>"],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":[],"mappings":";;;;;;;KA6CY,gBAAA;;EAAZ,QAAY,CAAA,EAAA;IAAA,MAAA,CAAA,EAAA,OAAA;EAAA,CAAA;EAIO,MACX,EAAA,CAAA,KAAO,EAAA;IAAA,MAAA,EADL,QAAA,CAAS,MACJ;IAIf,IAAY,EAJJ,MAAA,CAAO,IAIH;IAAA,aAAA,EAAA,GAAA,GAAA,IAAA;EAAA,CAAA,EAAA,GAAiC,IAAA;CAAA;AAC9B,KADH,8BAAA,GAAiC,gBAC9B,GAAA;EAEf,MAAY,EAFH,OAAA,CAAM,EAEH;CAAA;AACX,KADW,6BACX,CAAA,oBAAA,MAAA,CAAA,GAAA,gBAAA,GAAA;EAAA,OAEQ,EAAA,QAAA,WAAA,GAAc,OAAA,CAAM,EAApB,EAAA;CAAA;AAAoB,KAIjB,iBAAA,GAJiB;EAI7B,IAAY,EAAA,MAAA;EAIZ,IAAY,EAFL,MAAA,CAAO,IAEF;CAAA;AAAqB,KAArB,kBAAA,GAAqB,iBAAA,GAAA;EAAA,YAClB,EAAA,YAAA;EAAA,WAGN,EAAA,GAAA,GAAA,IAAA;EAAA,aAAA,EAAA,GAAA,GAAA,IAAA;EAET,MAAY,EAFH,MAEG;AAKZ,CAAA;AAAY,KALA,yBAAA,GAKA;EAAA,OAAqB,EAAA,GAAA,GAAA,IAAA;EAAA,IAAA,EACjB,GAAA,GAJH,kBAIG;AAAA,CAAA;AAIJ,KALA,kBAAA,GAAqB,iBAKrB,GAAA;EAAA,OAAA,EAAA,GAAA,GAJI,OAIJ,CAAA,IAAA,CAAA;EAAA,IAAA,EACH,MAAA;CAAA;AACQ,KAFL,eAAA,GAEK;EAEjB,MAAY,EAHH,kBAGG;EAAA,QAAA,EAAA,GAAA,GAFK,OAEL,CAAA,IAAA,CAAA;CAAA;AACH,KADG,6BAAA,GAAgC,eACnC,GAAA;EAAA,MAAA,EAAA,yBAAA;AAET,CAAA;AAAY,KAAA,4BAAA,CAAA,oBAAA,MAAA,CAAA,GACX,eADW,GAAA;EAAA,OACX,EACU,MADV,CACiB,WADjB,EAC8B,yBAD9B,CAAA;CAAA;AAC8B,cAGlB,uBAHkB,EAAA,CAAA,OAAA,EAIrB,gBAJqB,EAAA,GAK5B,kBAL4B;AAApB,cA0FE,uBA1FF,EAAA,CAAA,OAAA,EA2FD,8BA3FC,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,GA8FR,yBA9FQ;AAAA,cA0JE,YA1JF,EAAA,CAAA,OAAA,EA2JD,8BA3JC,EAAA,GA4JR,6BA5JQ;AAGE,cAuKA,WArKV,EAAA,CAAA,oBAAA,MAAA,CAAA,CAAA,OAAA,EAsKO,6BAtKP,CAsKqC,WAtKrC,CAAA,EAAA,GAuKA,4BAvKA,CAuK6B,WAvK7B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","names":["tools: {\n\t\tsocket: SocketIO.Socket\n\t\tsilo: AtomIO.Silo\n\t\tenableLogging: () => void\n\t}","options: TestSetupOptions","options: TestSetupOptions__SingleClient","name: string","port: number","options: TestSetupOptions__MultiClient<ClientNames>"],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":[],"mappings":";;;;;;;KA6CY,gBAAA;;EAAZ,QAAY,CAAA,EAAA;IAAA,MAAA,CAAA,EAAA,OAAA;EAAA,CAAA;EAIO,MACX,EAAA,CAAA,KAAO,EAAA;IAAA,MAAA,EADL,QAAA,CAAS,MACJ;IAIf,IAAY,EAJJ,MAAA,CAAO,IAIH;IAAA,aAAA,EAAA,GAAA,GAAA,IAAA;EAAA,CAAA,EAAA,GAAiC,IAAA;CAAA;AAC9B,KADH,8BAAA,GAAiC,gBAC9B,GAAA;EAEf,MAAY,EAFH,OAAA,CAAM,EAEH;CAAA;AACX,KADW,6BACX,CAAA,oBAAA,MAAA,CAAA,GAAA,gBAAA,GAAA;EAAA,OAEQ,EAAA,QAAA,WAAA,GAAc,OAAA,CAAM,EAApB,EAAA;CAAA;AAAoB,KAIjB,iBAAA,GAJiB;EAI7B,IAAY,EAAA,MAAA;EAIZ,IAAY,EAFL,MAAA,CAAO,IAEF;CAAA;AAAqB,KAArB,kBAAA,GAAqB,iBAAA,GAAA;EAAA,YAClB,EAAA,YAAA;EAAA,WAGN,EAAA,GAAA,GAAA,IAAA;EAAA,aAAA,EAAA,GAAA,GAAA,IAAA;EAET,MAAY,EAFH,MAEG;AAKZ,CAAA;AAAY,KALA,yBAAA,GAKA;EAAA,OAAqB,EAAA,GAAA,GAAA,IAAA;EAAA,IAAA,EACjB,GAAA,GAJH,kBAIG;AAAA,CAAA;AAIJ,KALA,kBAAA,GAAqB,iBAKrB,GAAA;EAAA,OAAA,EAAA,GAAA,GAJI,OAIJ,CAAA,IAAA,CAAA;EAAA,IAAA,EACH,MAAA;CAAA;AACQ,KAFL,eAAA,GAEK;EAEjB,MAAY,EAHH,kBAGG;EAAA,QAAA,EAAA,GAAA,GAFK,OAEL,CAAA,IAAA,CAAA;CAAA;AACH,KADG,6BAAA,GAAgC,eACnC,GAAA;EAAA,MAAA,EAAA,yBAAA;AAET,CAAA;AAAY,KAAA,4BAAA,CAAA,oBAAA,MAAA,CAAA,GACX,eADW,GAAA;EAAA,OACX,EACU,MADV,CACiB,WADjB,EAC8B,yBAD9B,CAAA;CAAA;AAC8B,cAGlB,uBAHkB,EAAA,CAAA,OAAA,EAIrB,gBAJqB,EAAA,GAK5B,kBAL4B;AAApB,cA0FE,uBA1FF,EAAA,CAAA,OAAA,EA2FD,8BA3FC,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,GA8FR,yBA9FQ;AAAA,cAqJE,YArJF,EAAA,CAAA,OAAA,EAsJD,8BAtJC,EAAA,GAuJR,6BAvJQ;AAGE,cAkKA,WAhKV,EAAA,CAAA,oBAAA,MAAA,CAAA,CAAA,OAAA,EAiKO,6BAjKP,CAiKqC,WAjKrC,CAAA,EAAA,GAkKA,4BAlKA,CAkK6B,WAlK7B,CAAA"}
@@ -105,7 +105,6 @@ const setupRealtimeTestClient = (options, name, port) => {
105
105
  name,
106
106
  lifespan: `ephemeral`
107
107
  }, IMPLICIT.STORE);
108
- for (const [key, value] of silo.store.valueMap.entries()) if (Array.isArray(value)) silo.store.valueMap.set(key, [...value]);
109
108
  silo.setState(RTC.myUsernameState, `${name}-${testNumber}`);
110
109
  const { document } = new Happy.Window();
111
110
  document.body.innerHTML = `<div id="app"></div>`;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["store: Store","prefix: string","options: TestSetupOptions","socket: SocketIO.Socket","userKey: string | null","options: TestSetupOptions__SingleClient","name: string","port: number","socket: ClientSocket","options: TestSetupOptions__MultiClient<ClientNames>"],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":["import * as http from \"node:http\"\n\nimport type { RenderResult } from \"@testing-library/react\"\nimport { prettyDOM, render } from \"@testing-library/react\"\nimport * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport {\n\tclearStore,\n\teditRelationsInStore,\n\tfindInStore,\n\tfindRelationsInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsetIntoStore,\n} from \"atom.io/internal\"\nimport { toEntries } from \"atom.io/json\"\nimport * as AR from \"atom.io/react\"\nimport * as RT from \"atom.io/realtime\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as RTR from \"atom.io/realtime-react\"\nimport * as RTS from \"atom.io/realtime-server\"\nimport * as Happy from \"happy-dom\"\nimport * as React from \"react\"\nimport * as SocketIO from \"socket.io\"\nimport type { Socket as ClientSocket } from \"socket.io-client\"\nimport { io } from \"socket.io-client\"\n\nlet testNumber = 0\n\n/* eslint-disable no-console */\n\nfunction prefixLogger(store: Store, prefix: string) {\n\tstore.loggers[0] = new AtomIO.AtomIOLogger(`info`, undefined, {\n\t\tinfo: (...args) => {\n\t\t\tconsole.info(prefix, ...args)\n\t\t},\n\t\twarn: (...args) => {\n\t\t\tconsole.warn(prefix, ...args)\n\t\t},\n\t\terror: (...args) => {\n\t\t\tconsole.error(prefix, ...args)\n\t\t},\n\t})\n}\n\nexport type TestSetupOptions = {\n\tport: number\n\timmortal?: { server?: boolean }\n\tserver: (tools: {\n\t\tsocket: SocketIO.Socket\n\t\tsilo: AtomIO.Silo\n\t\tenableLogging: () => void\n\t}) => void\n}\nexport type TestSetupOptions__SingleClient = TestSetupOptions & {\n\tclient: React.FC\n}\nexport type TestSetupOptions__MultiClient<ClientNames extends string> =\n\tTestSetupOptions & {\n\t\tclients: {\n\t\t\t[K in ClientNames]: React.FC\n\t\t}\n\t}\n\nexport type RealtimeTestTools = {\n\tname: string\n\tsilo: AtomIO.Silo\n}\nexport type RealtimeTestClient = RealtimeTestTools & {\n\trenderResult: RenderResult\n\tprettyPrint: () => void\n\tenableLogging: () => void\n\tsocket: ClientSocket\n}\nexport type RealtimeTestClientBuilder = {\n\tdispose: () => void\n\tinit: () => RealtimeTestClient\n}\n\nexport type RealtimeTestServer = RealtimeTestTools & {\n\tdispose: () => Promise<void>\n\tport: number\n}\n\nexport type RealtimeTestAPI = {\n\tserver: RealtimeTestServer\n\tteardown: () => Promise<void>\n}\nexport type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {\n\tclient: RealtimeTestClientBuilder\n}\nexport type RealtimeTestAPI__MultiClient<ClientNames extends string> =\n\tRealtimeTestAPI & {\n\t\tclients: Record<ClientNames, RealtimeTestClientBuilder>\n\t}\n\nexport const setupRealtimeTestServer = (\n\toptions: TestSetupOptions,\n): RealtimeTestServer => {\n\t++testNumber\n\tconst silo = new AtomIO.Silo(\n\t\t{\n\t\t\tname: `SERVER-${testNumber}`,\n\t\t\tlifespan: options.immortal?.server ? `immortal` : `ephemeral`,\n\t\t},\n\t\tIMPLICIT.STORE,\n\t)\n\tconst socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)\n\n\tconst httpServer = http.createServer((_, res) => res.end(`Hello World!`))\n\tconst address = httpServer.listen(options.port).address()\n\tconst port =\n\t\ttypeof address === `string` ? null : address === null ? null : address.port\n\tif (port === null) throw new Error(`Could not determine port for test server`)\n\n\tconst server = new SocketIO.Server(httpServer).use((socket, next) => {\n\t\tconst { token, username } = socket.handshake.auth\n\t\tif (token === `test` && socket.id) {\n\t\t\tconst userClaim = socketRealm.allocate(`root`, `user::${username}`)\n\t\t\tconst socketClaim = socketRealm.allocate(`root`, `socket::${socket.id}`)\n\t\t\tconst socketState = findInStore(silo.store, RTS.socketAtoms, socketClaim)\n\t\t\tsetIntoStore(silo.store, socketState, socket)\n\t\t\teditRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t(relations) => {\n\t\t\t\t\trelations.set(userClaim, socketClaim)\n\t\t\t\t},\n\t\t\t\tsilo.store,\n\t\t\t)\n\t\t\tsetIntoStore(silo.store, RTS.userIndex, (index) => index.add(userClaim))\n\t\t\tsetIntoStore(silo.store, RTS.socketIndex, (index) =>\n\t\t\t\tindex.add(socketClaim),\n\t\t\t)\n\t\t\t// console.log(`${username} connected on ${socket.id}`)\n\t\t\tnext()\n\t\t} else {\n\t\t\tnext(new Error(`Authentication error`))\n\t\t}\n\t})\n\n\tserver.on(`connection`, (socket: SocketIO.Socket) => {\n\t\tlet userKey: string | null = null\n\t\tfunction enableLogging() {\n\t\t\tconst userKeyState = findRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t`socket::${socket.id}`,\n\t\t\t\tsilo.store,\n\t\t\t).userKeyOfSocket\n\t\t\tuserKey = getFromStore(silo.store, userKeyState)\n\t\t\tprefixLogger(silo.store, `server`)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 `, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 >>`, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.on(`disconnect`, () => {\n\t\t\t\tconsole.log(`${userKey} disconnected`)\n\t\t\t})\n\t\t}\n\t\toptions.server({ socket, enableLogging, silo })\n\t})\n\n\tconst dispose = async () => {\n\t\tawait server.close()\n\t\tconst roomKeys = getFromStore(silo.store, RT.roomIndex)\n\t\tfor (const roomKey of roomKeys) {\n\t\t\tconst roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)\n\t\t\tconst room = getFromStore(silo.store, roomState)\n\t\t\tif (room && !(room instanceof Promise)) {\n\t\t\t\troom.process.kill()\n\t\t\t}\n\t\t}\n\t\tsilo.store.valueMap.clear()\n\t}\n\n\treturn {\n\t\tname: `SERVER`,\n\t\tsilo,\n\t\tdispose,\n\t\tport,\n\t}\n}\nexport const setupRealtimeTestClient = (\n\toptions: TestSetupOptions__SingleClient,\n\tname: string,\n\tport: number,\n): RealtimeTestClientBuilder => {\n\tconst testClient = { dispose: () => {} }\n\tconst init = () => {\n\t\tconst socket: ClientSocket = io(`http://localhost:${port}/`, {\n\t\t\tauth: { token: `test`, username: `${name}-${testNumber}` },\n\t\t})\n\t\tconst silo = new AtomIO.Silo({ name, lifespan: `ephemeral` }, IMPLICIT.STORE)\n\t\tfor (const [key, value] of silo.store.valueMap.entries()) {\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tsilo.store.valueMap.set(key, [...value])\n\t\t\t}\n\t\t}\n\t\tsilo.setState(RTC.myUsernameState, `${name}-${testNumber}`)\n\n\t\tconst { document } = new Happy.Window()\n\t\tdocument.body.innerHTML = `<div id=\"app\"></div>`\n\t\tconst renderResult = render(\n\t\t\t<AR.StoreProvider store={silo.store}>\n\t\t\t\t<RTR.RealtimeProvider socket={socket}>\n\t\t\t\t\t<options.client />\n\t\t\t\t</RTR.RealtimeProvider>\n\t\t\t</AR.StoreProvider>,\n\t\t\t{\n\t\t\t\tcontainer: document.querySelector(`#app`) as unknown as HTMLElement,\n\t\t\t},\n\t\t)\n\n\t\tconst prettyPrint = () => {\n\t\t\tconsole.log(prettyDOM(renderResult.container))\n\t\t}\n\n\t\tconst enableLogging = () => {\n\t\t\tprefixLogger(silo.store, name)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`📡 `, name, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`📡 >>`, name, event, ...args)\n\t\t\t})\n\t\t}\n\n\t\tconst dispose = () => {\n\t\t\trenderResult.unmount()\n\t\t\tsocket.disconnect()\n\t\t\tclearStore(silo.store)\n\t\t}\n\t\ttestClient.dispose = dispose\n\n\t\treturn {\n\t\t\tname,\n\t\t\tsilo,\n\t\t\tsocket,\n\t\t\trenderResult,\n\t\t\tprettyPrint,\n\t\t\tenableLogging,\n\t\t}\n\t}\n\treturn Object.assign(testClient, { init })\n}\n\nexport const singleClient = (\n\toptions: TestSetupOptions__SingleClient,\n): RealtimeTestAPI__SingleClient => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst client = setupRealtimeTestClient(options, `CLIENT`, server.port)\n\n\treturn {\n\t\tclient,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tclient.dispose()\n\t\t},\n\t}\n}\n\nexport const multiClient = <ClientNames extends string>(\n\toptions: TestSetupOptions__MultiClient<ClientNames>,\n): RealtimeTestAPI__MultiClient<ClientNames> => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst clients = toEntries(options.clients).reduce(\n\t\t(clientRecord, [name, client]) => {\n\t\t\tclientRecord[name] = setupRealtimeTestClient(\n\t\t\t\t{ ...options, client },\n\t\t\t\tname,\n\t\t\t\tserver.port,\n\t\t\t)\n\t\t\treturn clientRecord\n\t\t},\n\t\t{} as Record<ClientNames, RealtimeTestClientBuilder>,\n\t)\n\n\treturn {\n\t\tclients,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tfor (const [, client] of toEntries(clients)) {\n\t\t\t\tclient.dispose()\n\t\t\t}\n\t\t},\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["store: Store","prefix: string","options: TestSetupOptions","socket: SocketIO.Socket","userKey: string | null","options: TestSetupOptions__SingleClient","name: string","port: number","socket: ClientSocket","options: TestSetupOptions__MultiClient<ClientNames>"],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":["import * as http from \"node:http\"\n\nimport type { RenderResult } from \"@testing-library/react\"\nimport { prettyDOM, render } from \"@testing-library/react\"\nimport * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport {\n\tclearStore,\n\teditRelationsInStore,\n\tfindInStore,\n\tfindRelationsInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsetIntoStore,\n} from \"atom.io/internal\"\nimport { toEntries } from \"atom.io/json\"\nimport * as AR from \"atom.io/react\"\nimport * as RT from \"atom.io/realtime\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as RTR from \"atom.io/realtime-react\"\nimport * as RTS from \"atom.io/realtime-server\"\nimport * as Happy from \"happy-dom\"\nimport * as React from \"react\"\nimport * as SocketIO from \"socket.io\"\nimport type { Socket as ClientSocket } from \"socket.io-client\"\nimport { io } from \"socket.io-client\"\n\nlet testNumber = 0\n\n/* eslint-disable no-console */\n\nfunction prefixLogger(store: Store, prefix: string) {\n\tstore.loggers[0] = new AtomIO.AtomIOLogger(`info`, undefined, {\n\t\tinfo: (...args) => {\n\t\t\tconsole.info(prefix, ...args)\n\t\t},\n\t\twarn: (...args) => {\n\t\t\tconsole.warn(prefix, ...args)\n\t\t},\n\t\terror: (...args) => {\n\t\t\tconsole.error(prefix, ...args)\n\t\t},\n\t})\n}\n\nexport type TestSetupOptions = {\n\tport: number\n\timmortal?: { server?: boolean }\n\tserver: (tools: {\n\t\tsocket: SocketIO.Socket\n\t\tsilo: AtomIO.Silo\n\t\tenableLogging: () => void\n\t}) => void\n}\nexport type TestSetupOptions__SingleClient = TestSetupOptions & {\n\tclient: React.FC\n}\nexport type TestSetupOptions__MultiClient<ClientNames extends string> =\n\tTestSetupOptions & {\n\t\tclients: {\n\t\t\t[K in ClientNames]: React.FC\n\t\t}\n\t}\n\nexport type RealtimeTestTools = {\n\tname: string\n\tsilo: AtomIO.Silo\n}\nexport type RealtimeTestClient = RealtimeTestTools & {\n\trenderResult: RenderResult\n\tprettyPrint: () => void\n\tenableLogging: () => void\n\tsocket: ClientSocket\n}\nexport type RealtimeTestClientBuilder = {\n\tdispose: () => void\n\tinit: () => RealtimeTestClient\n}\n\nexport type RealtimeTestServer = RealtimeTestTools & {\n\tdispose: () => Promise<void>\n\tport: number\n}\n\nexport type RealtimeTestAPI = {\n\tserver: RealtimeTestServer\n\tteardown: () => Promise<void>\n}\nexport type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {\n\tclient: RealtimeTestClientBuilder\n}\nexport type RealtimeTestAPI__MultiClient<ClientNames extends string> =\n\tRealtimeTestAPI & {\n\t\tclients: Record<ClientNames, RealtimeTestClientBuilder>\n\t}\n\nexport const setupRealtimeTestServer = (\n\toptions: TestSetupOptions,\n): RealtimeTestServer => {\n\t++testNumber\n\tconst silo = new AtomIO.Silo(\n\t\t{\n\t\t\tname: `SERVER-${testNumber}`,\n\t\t\tlifespan: options.immortal?.server ? `immortal` : `ephemeral`,\n\t\t},\n\t\tIMPLICIT.STORE,\n\t)\n\tconst socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)\n\n\tconst httpServer = http.createServer((_, res) => res.end(`Hello World!`))\n\tconst address = httpServer.listen(options.port).address()\n\tconst port =\n\t\ttypeof address === `string` ? null : address === null ? null : address.port\n\tif (port === null) throw new Error(`Could not determine port for test server`)\n\n\tconst server = new SocketIO.Server(httpServer).use((socket, next) => {\n\t\tconst { token, username } = socket.handshake.auth\n\t\tif (token === `test` && socket.id) {\n\t\t\tconst userClaim = socketRealm.allocate(`root`, `user::${username}`)\n\t\t\tconst socketClaim = socketRealm.allocate(`root`, `socket::${socket.id}`)\n\t\t\tconst socketState = findInStore(silo.store, RTS.socketAtoms, socketClaim)\n\t\t\tsetIntoStore(silo.store, socketState, socket)\n\t\t\teditRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t(relations) => {\n\t\t\t\t\trelations.set(userClaim, socketClaim)\n\t\t\t\t},\n\t\t\t\tsilo.store,\n\t\t\t)\n\t\t\tsetIntoStore(silo.store, RTS.userIndex, (index) => index.add(userClaim))\n\t\t\tsetIntoStore(silo.store, RTS.socketIndex, (index) =>\n\t\t\t\tindex.add(socketClaim),\n\t\t\t)\n\t\t\t// console.log(`${username} connected on ${socket.id}`)\n\t\t\tnext()\n\t\t} else {\n\t\t\tnext(new Error(`Authentication error`))\n\t\t}\n\t})\n\n\tserver.on(`connection`, (socket: SocketIO.Socket) => {\n\t\tlet userKey: string | null = null\n\t\tfunction enableLogging() {\n\t\t\tconst userKeyState = findRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t`socket::${socket.id}`,\n\t\t\t\tsilo.store,\n\t\t\t).userKeyOfSocket\n\t\t\tuserKey = getFromStore(silo.store, userKeyState)\n\t\t\tprefixLogger(silo.store, `server`)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 `, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 >>`, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.on(`disconnect`, () => {\n\t\t\t\tconsole.log(`${userKey} disconnected`)\n\t\t\t})\n\t\t}\n\t\toptions.server({ socket, enableLogging, silo })\n\t})\n\n\tconst dispose = async () => {\n\t\tawait server.close()\n\t\tconst roomKeys = getFromStore(silo.store, RT.roomIndex)\n\t\tfor (const roomKey of roomKeys) {\n\t\t\tconst roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)\n\t\t\tconst room = getFromStore(silo.store, roomState)\n\t\t\tif (room && !(room instanceof Promise)) {\n\t\t\t\troom.process.kill()\n\t\t\t}\n\t\t}\n\t\tsilo.store.valueMap.clear()\n\t}\n\n\treturn {\n\t\tname: `SERVER`,\n\t\tsilo,\n\t\tdispose,\n\t\tport,\n\t}\n}\nexport const setupRealtimeTestClient = (\n\toptions: TestSetupOptions__SingleClient,\n\tname: string,\n\tport: number,\n): RealtimeTestClientBuilder => {\n\tconst testClient = { dispose: () => {} }\n\tconst init = () => {\n\t\tconst socket: ClientSocket = io(`http://localhost:${port}/`, {\n\t\t\tauth: { token: `test`, username: `${name}-${testNumber}` },\n\t\t})\n\t\tconst silo = new AtomIO.Silo({ name, lifespan: `ephemeral` }, IMPLICIT.STORE)\n\t\tsilo.setState(RTC.myUsernameState, `${name}-${testNumber}`)\n\n\t\tconst { document } = new Happy.Window()\n\t\tdocument.body.innerHTML = `<div id=\"app\"></div>`\n\t\tconst renderResult = render(\n\t\t\t<AR.StoreProvider store={silo.store}>\n\t\t\t\t<RTR.RealtimeProvider socket={socket}>\n\t\t\t\t\t<options.client />\n\t\t\t\t</RTR.RealtimeProvider>\n\t\t\t</AR.StoreProvider>,\n\t\t\t{\n\t\t\t\tcontainer: document.querySelector(`#app`) as unknown as HTMLElement,\n\t\t\t},\n\t\t)\n\n\t\tconst prettyPrint = () => {\n\t\t\tconsole.log(prettyDOM(renderResult.container))\n\t\t}\n\n\t\tconst enableLogging = () => {\n\t\t\tprefixLogger(silo.store, name)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`📡 `, name, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`📡 >>`, name, event, ...args)\n\t\t\t})\n\t\t}\n\n\t\tconst dispose = () => {\n\t\t\trenderResult.unmount()\n\t\t\tsocket.disconnect()\n\t\t\tclearStore(silo.store)\n\t\t}\n\t\ttestClient.dispose = dispose\n\n\t\treturn {\n\t\t\tname,\n\t\t\tsilo,\n\t\t\tsocket,\n\t\t\trenderResult,\n\t\t\tprettyPrint,\n\t\t\tenableLogging,\n\t\t}\n\t}\n\treturn Object.assign(testClient, { init })\n}\n\nexport const singleClient = (\n\toptions: TestSetupOptions__SingleClient,\n): RealtimeTestAPI__SingleClient => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst client = setupRealtimeTestClient(options, `CLIENT`, server.port)\n\n\treturn {\n\t\tclient,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tclient.dispose()\n\t\t},\n\t}\n}\n\nexport const multiClient = <ClientNames extends string>(\n\toptions: TestSetupOptions__MultiClient<ClientNames>,\n): RealtimeTestAPI__MultiClient<ClientNames> => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst clients = toEntries(options.clients).reduce(\n\t\t(clientRecord, [name, client]) => {\n\t\t\tclientRecord[name] = setupRealtimeTestClient(\n\t\t\t\t{ ...options, client },\n\t\t\t\tname,\n\t\t\t\tserver.port,\n\t\t\t)\n\t\t\treturn clientRecord\n\t\t},\n\t\t{} as Record<ClientNames, RealtimeTestClientBuilder>,\n\t)\n\n\treturn {\n\t\tclients,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tfor (const [, client] of toEntries(clients)) {\n\t\t\t\tclient.dispose()\n\t\t\t}\n\t\t},\n\t}\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.33.21",
3
+ "version": "0.34.0",
4
4
  "description": "Composable and testable reactive data library.",
5
5
  "homepage": "https://atom.io.fyi",
6
6
  "sideEffects": false,
@@ -6,7 +6,6 @@ import type {
6
6
  } from "atom.io"
7
7
 
8
8
  import { type RegularAtom, resetInStore, setIntoStore } from ".."
9
- import { cacheValue } from "../caching"
10
9
  import { newest } from "../lineage"
11
10
  import type { Store } from "../store"
12
11
  import { deposit } from "../store"
@@ -19,7 +18,7 @@ export function createRegularAtom<T>(
19
18
  family: FamilyMetadata | undefined,
20
19
  ): RegularAtomToken<T> {
21
20
  const type = `atom`
22
- const { key, default: def } = options
21
+ const { key } = options
23
22
  store.logger.info(
24
23
  `🔨`,
25
24
  `atom`,
@@ -50,12 +49,12 @@ export function createRegularAtom<T>(
50
49
  if (family) {
51
50
  newAtom.family = family
52
51
  }
53
- let initialValue = def
54
- if (def instanceof Function) {
55
- initialValue = def()
56
- }
52
+ // let initialValue = def
53
+ // if (def instanceof Function) {
54
+ // initialValue = def()
55
+ // }
57
56
  target.atoms.set(key, newAtom)
58
- cacheValue(target, key, initialValue, subject)
57
+ // cacheValue(target, key, initialValue, subject)
59
58
  const token = deposit(newAtom)
60
59
  if (options.effects) {
61
60
  let effectIndex = 0
@@ -30,7 +30,7 @@ export function cacheValue<T>(
30
30
  subject: Subject<StateUpdate<unknown>>,
31
31
  ): Future<T> | T {
32
32
  const currentValue = target.valueMap.get(key)
33
- if (currentValue instanceof Future) {
33
+ if (currentValue instanceof Future && !currentValue.done) {
34
34
  const future = currentValue
35
35
  if (value instanceof Promise) {
36
36
  future.use(value)
@@ -43,7 +43,7 @@ export function cacheValue<T>(
43
43
  const future = new Future<T>(value)
44
44
  target.valueMap.set(key, future)
45
45
  future
46
- .then((resolved) => {
46
+ .then(function handleResolvedFuture(resolved) {
47
47
  const current = target.valueMap.get(key)
48
48
  if (current === future) {
49
49
  cacheValue(target, key, resolved, subject)
@@ -75,26 +75,26 @@ export function cacheValue<T>(
75
75
  }
76
76
 
77
77
  export const readCachedValue = <T>(
78
- token: ReadableState<any>,
78
+ state: ReadableState<any>,
79
79
  target: Store,
80
80
  ): T => {
81
- let value = target.valueMap.get(token.key) as T
82
- if (token.type === `mutable_atom` && isChildStore(target)) {
81
+ target.logger.info(`📖`, state.type, state.key, `reading cached value`)
82
+ let value = target.valueMap.get(state.key) as T
83
+ if (state.type === `mutable_atom` && isChildStore(target)) {
83
84
  const { parent } = target
84
- const copiedValue = copyMutableIfNeeded(target, token, parent)
85
+ const copiedValue = copyMutableIfNeeded(target, state, parent)
85
86
  value = copiedValue
86
87
  }
87
88
  return value
88
89
  }
89
90
 
90
- export const evictCachedValue = (key: string, target: Store): void => {
91
+ export const evictCachedValue = (target: Store, key: string): void => {
91
92
  const currentValue = target.valueMap.get(key)
92
93
  if (currentValue instanceof Future) {
93
- const future = currentValue
94
94
  const selector =
95
95
  target.writableSelectors.get(key) ?? target.readonlySelectors.get(key)
96
96
  if (selector) {
97
- future.use(selector.get())
97
+ selector.get()
98
98
  }
99
99
  return
100
100
  }
@@ -44,6 +44,9 @@ export class Future<T> extends Promise<T> {
44
44
  }
45
45
 
46
46
  public use(value: Promise<T> | T): void {
47
+ if (this === value) {
48
+ return
49
+ }
47
50
  if (value instanceof Promise) {
48
51
  const promise = value
49
52
  this.fate = promise
@@ -1,5 +1,5 @@
1
1
  import type { ReadableState } from ".."
2
- import { readCachedValue } from "../caching"
2
+ import { cacheValue, readCachedValue } from "../caching"
3
3
  import type { Store } from "../store"
4
4
 
5
5
  export const readOrComputeValue = <T>(
@@ -7,7 +7,6 @@ export const readOrComputeValue = <T>(
7
7
  state: ReadableState<T>,
8
8
  ): T => {
9
9
  if (target.valueMap.has(state.key)) {
10
- target.logger.info(`📖`, state.type, state.key, `reading cached value`)
11
10
  return readCachedValue(state, target)
12
11
  }
13
12
  switch (state.type) {
@@ -20,20 +19,26 @@ export const readOrComputeValue = <T>(
20
19
  case `atom`:
21
20
  case `mutable_atom`: {
22
21
  const def = state.default
23
- let fallback: T
22
+ let defaultValue: T
24
23
  if (def instanceof Function) {
25
- fallback = def()
24
+ defaultValue = def()
26
25
  } else {
27
- fallback = def
26
+ defaultValue = def
28
27
  }
28
+ const cachedValue = cacheValue(
29
+ target,
30
+ state.key,
31
+ defaultValue,
32
+ state.subject,
33
+ )
29
34
  target.logger.info(
30
35
  `💁`,
31
36
  `atom`,
32
37
  state.key,
33
38
  `could not find cached value; using default`,
34
- fallback,
39
+ defaultValue,
35
40
  )
36
- return fallback
41
+ return cachedValue
37
42
  }
38
43
  }
39
44
  }
@@ -8,7 +8,7 @@ import type { Json } from "atom.io/json"
8
8
  import { selectJson } from "atom.io/json"
9
9
 
10
10
  import type { MutableAtom } from ".."
11
- import { cacheValue, resetInStore, setIntoStore } from ".."
11
+ import { resetInStore, setIntoStore } from ".."
12
12
  import { newest } from "../lineage"
13
13
  import { deposit, type Store } from "../store"
14
14
  import { Subject } from "../subject"
@@ -31,7 +31,7 @@ export function createMutableAtom<
31
31
  `creating in store "${store.config.name}"`,
32
32
  )
33
33
  const target = newest(store)
34
- const { key, default: def } = options
34
+ const { key } = options
35
35
  const existing = target.atoms.get(key)
36
36
  const type = `mutable_atom`
37
37
  if (existing && existing.type === type) {
@@ -56,9 +56,7 @@ export function createMutableAtom<
56
56
  if (family) {
57
57
  newAtom.family = family
58
58
  }
59
- const initialValue = def()
60
59
  target.atoms.set(newAtom.key, newAtom)
61
- cacheValue(target, key, initialValue, subject)
62
60
  const token = deposit(newAtom)
63
61
  if (options.effects) {
64
62
  let effectIndex = 0
@@ -23,6 +23,16 @@ export const createReadonlyHeldSelector = <T extends object>(
23
23
  const type = `readonly_held_selector` as const
24
24
  const { get, find, json } = registerSelector(target, type, key, covered)
25
25
  const getSelf = () => {
26
+ const innerTarget = newest(store)
27
+ const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
28
+ downstreamSelectorKey: key,
29
+ })
30
+ for (const [downstreamSelectorKey, { source }] of upstreamStates) {
31
+ if (source !== key) {
32
+ innerTarget.selectorGraph.delete(downstreamSelectorKey, key)
33
+ }
34
+ }
35
+ innerTarget.selectorAtoms.delete(key)
26
36
  options.get({ get, find, json }, constant)
27
37
  cacheValue(newest(store), key, constant, subject)
28
38
  covered.clear()
@@ -23,10 +23,21 @@ export const createReadonlyPureSelector = <T>(
23
23
  const type = `readonly_pure_selector` as const
24
24
  const { get, find, json } = registerSelector(target, type, key, covered)
25
25
  const getSelf = () => {
26
+ const innerTarget = newest(store)
27
+ const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
28
+ downstreamSelectorKey: key,
29
+ })
30
+ for (const [downstreamSelectorKey, { source }] of upstreamStates) {
31
+ if (source !== key) {
32
+ innerTarget.selectorGraph.delete(downstreamSelectorKey, key)
33
+ }
34
+ }
35
+ innerTarget.selectorAtoms.delete(key)
26
36
  const value = options.get({ get, find, json })
27
- cacheValue(newest(store), key, value, subject)
37
+ const cached = cacheValue(innerTarget, key, value, subject)
38
+ store.logger.info(`✨`, type, key, `=`, cached)
28
39
  covered.clear()
29
- return value
40
+ return cached
30
41
  }
31
42
 
32
43
  const readonlySelector: ReadonlyPureSelector<T> = {
@@ -38,8 +49,6 @@ export const createReadonlyPureSelector = <T>(
38
49
  ...(family && { family }),
39
50
  }
40
51
  target.readonlySelectors.set(key, readonlySelector)
41
- const initialValue = getSelf()
42
- store.logger.info(`✨`, type, key, `=`, initialValue)
43
52
  const token: ReadonlyPureSelectorToken<T> = {
44
53
  key,
45
54
  type,
@@ -29,8 +29,18 @@ export const createWritableHeldSelector = <T extends object>(
29
29
  const getterToolkit = { find, get, json }
30
30
 
31
31
  const getSelf = (getFn = options.get, innerTarget = newest(store)): T => {
32
+ const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
33
+ downstreamSelectorKey: key,
34
+ })
35
+ for (const [downstreamSelectorKey, { source }] of upstreamStates) {
36
+ if (source !== key) {
37
+ innerTarget.selectorGraph.delete(downstreamSelectorKey, key)
38
+ }
39
+ }
40
+ innerTarget.selectorAtoms.delete(key)
32
41
  getFn(getterToolkit, constant)
33
42
  cacheValue(innerTarget, key, constant, subject)
43
+ store.logger.info(`✨`, type, key, `=`, constant)
34
44
  covered.clear()
35
45
  return constant
36
46
  }
@@ -57,8 +67,7 @@ export const createWritableHeldSelector = <T extends object>(
57
67
  ...(family && { family }),
58
68
  }
59
69
  target.writableSelectors.set(key, mySelector)
60
- const initialValue = getSelf()
61
- store.logger.info(`✨`, type, key, `=`, initialValue)
70
+ // const initialValue = getSelf()
62
71
 
63
72
  const token: WritableHeldSelectorToken<T> = { key, type }
64
73
  if (family) {
@@ -29,8 +29,18 @@ export const createWritablePureSelector = <T>(
29
29
  const getterToolkit = { find, get, json }
30
30
 
31
31
  const getSelf = (getFn = options.get, innerTarget = newest(store)): T => {
32
+ const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
33
+ downstreamSelectorKey: key,
34
+ })
35
+ for (const [downstreamSelectorKey, { source }] of upstreamStates) {
36
+ if (source !== key) {
37
+ innerTarget.selectorGraph.delete(downstreamSelectorKey, key)
38
+ }
39
+ }
40
+ innerTarget.selectorAtoms.delete(key)
32
41
  const value = getFn(getterToolkit)
33
- cacheValue(innerTarget, key, value, subject)
42
+ const cached = cacheValue(innerTarget, key, value, subject)
43
+ store.logger.info(`✨`, type, key, `=`, cached)
34
44
  covered.clear()
35
45
  return value
36
46
  }
@@ -1,51 +1,29 @@
1
- import type { Atom, Selector, Store } from ".."
2
- import type { AtomKey, StateKey } from "../keys"
1
+ import type { Atom, Store } from ".."
3
2
  import { isAtomKey } from "../keys"
4
3
  import { getSelectorDependencyKeys } from "./get-selector-dependency-keys"
5
4
 
6
- export const traceSelectorAtoms = (
5
+ export const traceRootSelectorAtoms = (
7
6
  store: Store,
8
- directDependencyKey: StateKey<unknown>,
9
- covered: Set<string>,
10
- ): AtomKey<unknown>[] => {
11
- const rootKeys: AtomKey<unknown>[] = []
7
+ selectorKey: string,
8
+ covered: Set<string> = new Set<string>(),
9
+ ): Map<string, Atom<unknown>> => {
10
+ const dependencies = getSelectorDependencyKeys(store, selectorKey)
12
11
 
13
- const indirectDependencyKeys = getSelectorDependencyKeys(
14
- store,
15
- directDependencyKey,
16
- )
17
- while (indirectDependencyKeys.length > 0) {
12
+ const roots = new Map<string, Atom<unknown>>()
13
+
14
+ while (dependencies.length > 0) {
18
15
  // biome-ignore lint/style/noNonNullAssertion: just checked length ^^^
19
- const indirectDependencyKey = indirectDependencyKeys.shift()!
20
- if (covered.has(indirectDependencyKey)) {
16
+ const dependencyKey = dependencies.pop()!
17
+ if (covered.has(dependencyKey)) {
21
18
  continue
22
19
  }
23
- covered.add(indirectDependencyKey)
24
-
25
- if (!isAtomKey(store, indirectDependencyKey)) {
26
- indirectDependencyKeys.push(
27
- ...getSelectorDependencyKeys(store, indirectDependencyKey),
28
- )
29
- } else if (!rootKeys.includes(indirectDependencyKey)) {
30
- rootKeys.push(indirectDependencyKey)
20
+ covered.add(dependencyKey)
21
+ if (isAtomKey(store, dependencyKey)) {
22
+ const atom = store.atoms.get(dependencyKey) as Atom<unknown>
23
+ roots.set(atom.key, atom)
24
+ } else {
25
+ dependencies.push(...getSelectorDependencyKeys(store, dependencyKey))
31
26
  }
32
27
  }
33
-
34
- return rootKeys
35
- }
36
-
37
- export const traceAllSelectorAtoms = (
38
- selector: Selector<any>,
39
- store: Store,
40
- ): Atom<unknown>[] => {
41
- const selectorKey = selector.key
42
- const directDependencyKeys = getSelectorDependencyKeys(store, selectorKey)
43
- const covered = new Set<string>()
44
- return directDependencyKeys
45
- .flatMap((depKey) =>
46
- isAtomKey(store, depKey)
47
- ? depKey
48
- : traceSelectorAtoms(store, depKey, covered),
49
- )
50
- .map((atomKey) => store.atoms.get(atomKey) as Atom<unknown>)
28
+ return roots
51
29
  }