atom.io 0.16.2 → 0.17.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 (108) hide show
  1. package/dist/chunk-H4Q5FTPZ.js +11 -0
  2. package/dist/chunk-H4Q5FTPZ.js.map +1 -0
  3. package/dist/index.cjs +35 -60
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +8 -8
  6. package/dist/index.js +12 -36
  7. package/dist/index.js.map +1 -1
  8. package/internal/dist/index.cjs +268 -195
  9. package/internal/dist/index.cjs.map +1 -1
  10. package/internal/dist/index.d.ts +36 -11
  11. package/internal/dist/index.js +258 -195
  12. package/internal/dist/index.js.map +1 -1
  13. package/internal/src/atom/create-regular-atom.ts +2 -3
  14. package/internal/src/families/find-in-store.ts +74 -0
  15. package/internal/src/families/index.ts +1 -0
  16. package/internal/src/get-state/get-from-store.ts +14 -0
  17. package/internal/src/get-state/index.ts +2 -0
  18. package/internal/src/{read-or-compute-value.ts → get-state/read-or-compute-value.ts} +3 -3
  19. package/internal/src/index.ts +1 -1
  20. package/internal/src/ingest-updates/ingest-atom-update.ts +2 -2
  21. package/internal/src/ingest-updates/ingest-transaction-update.ts +1 -0
  22. package/internal/src/mutable/create-mutable-atom.ts +3 -4
  23. package/internal/src/mutable/tracker.ts +43 -35
  24. package/internal/src/mutable/transceiver.ts +1 -1
  25. package/internal/src/not-found-error.ts +14 -3
  26. package/internal/src/operation.ts +2 -1
  27. package/internal/src/selector/create-writable-selector.ts +2 -1
  28. package/internal/src/selector/register-selector.ts +6 -5
  29. package/internal/src/set-state/index.ts +1 -0
  30. package/internal/src/set-state/set-atom.ts +17 -3
  31. package/internal/src/set-state/set-into-store.ts +24 -0
  32. package/internal/src/set-state/stow-update.ts +2 -4
  33. package/internal/src/store/store.ts +13 -4
  34. package/internal/src/subscribe/subscribe-to-root-atoms.ts +1 -1
  35. package/internal/src/timeline/add-atom-to-timeline.ts +5 -5
  36. package/internal/src/transaction/abort-transaction.ts +2 -1
  37. package/internal/src/transaction/apply-transaction.ts +5 -3
  38. package/internal/src/transaction/build-transaction.ts +20 -11
  39. package/internal/src/transaction/create-transaction.ts +2 -3
  40. package/internal/src/transaction/index.ts +3 -2
  41. package/internal/src/transaction/is-root-store.ts +23 -0
  42. package/package.json +10 -10
  43. package/react/dist/index.cjs +27 -21
  44. package/react/dist/index.cjs.map +1 -1
  45. package/react/dist/index.d.ts +8 -2
  46. package/react/dist/index.js +28 -22
  47. package/react/dist/index.js.map +1 -1
  48. package/react/src/index.ts +4 -1
  49. package/react/src/use-i.ts +35 -0
  50. package/react/src/use-json.ts +38 -0
  51. package/react/src/use-o.ts +33 -0
  52. package/react/src/use-tl.ts +45 -0
  53. package/realtime-client/dist/index.cjs +167 -64
  54. package/realtime-client/dist/index.cjs.map +1 -1
  55. package/realtime-client/dist/index.d.ts +10 -6
  56. package/realtime-client/dist/index.js +158 -63
  57. package/realtime-client/dist/index.js.map +1 -1
  58. package/realtime-client/src/index.ts +2 -1
  59. package/realtime-client/src/pull-family-member.ts +3 -3
  60. package/realtime-client/src/pull-mutable-family-member.ts +4 -4
  61. package/realtime-client/src/pull-mutable.ts +4 -4
  62. package/realtime-client/src/pull-state.ts +7 -6
  63. package/realtime-client/src/{realtime-client-store.ts → realtime-client-stores/client-main-store.ts} +0 -8
  64. package/realtime-client/src/realtime-client-stores/client-sync-store.ts +15 -0
  65. package/realtime-client/src/realtime-client-stores/index.ts +2 -0
  66. package/realtime-client/src/sync-server-action.ts +134 -40
  67. package/realtime-client/src/sync-state.ts +19 -0
  68. package/realtime-react/dist/index.cjs +43 -26
  69. package/realtime-react/dist/index.cjs.map +1 -1
  70. package/realtime-react/dist/index.d.ts +3 -1
  71. package/realtime-react/dist/index.js +41 -25
  72. package/realtime-react/dist/index.js.map +1 -1
  73. package/realtime-react/src/index.ts +1 -0
  74. package/realtime-react/src/on-mount.ts +3 -21
  75. package/realtime-react/src/use-realtime-service.ts +1 -1
  76. package/realtime-react/src/use-single-effect.ts +29 -0
  77. package/realtime-react/src/use-sync-server-action.ts +4 -7
  78. package/realtime-react/src/use-sync.ts +17 -0
  79. package/realtime-server/dist/index.cjs +239 -56
  80. package/realtime-server/dist/index.cjs.map +1 -1
  81. package/realtime-server/dist/index.d.ts +140 -9
  82. package/realtime-server/dist/index.js +228 -58
  83. package/realtime-server/dist/index.js.map +1 -1
  84. package/realtime-server/src/index.ts +2 -0
  85. package/realtime-server/src/realtime-action-synchronizer.ts +95 -14
  86. package/realtime-server/src/realtime-family-provider.ts +11 -6
  87. package/realtime-server/src/realtime-mutable-family-provider.ts +8 -6
  88. package/realtime-server/src/realtime-mutable-provider.ts +3 -2
  89. package/realtime-server/src/realtime-server-stores/index.ts +2 -0
  90. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +115 -0
  91. package/realtime-server/src/realtime-server-stores/server-user-store.ts +45 -0
  92. package/realtime-server/src/realtime-state-provider.ts +18 -11
  93. package/realtime-server/src/realtime-state-receiver.ts +2 -2
  94. package/realtime-server/src/realtime-state-synchronizer.ts +23 -0
  95. package/realtime-testing/dist/index.cjs +65 -26
  96. package/realtime-testing/dist/index.cjs.map +1 -1
  97. package/realtime-testing/dist/index.d.ts +11 -7
  98. package/realtime-testing/dist/index.js +64 -26
  99. package/realtime-testing/dist/index.js.map +1 -1
  100. package/realtime-testing/src/setup-realtime-test.tsx +83 -43
  101. package/src/find-state.ts +8 -16
  102. package/src/get-state.ts +2 -11
  103. package/src/logger.ts +1 -0
  104. package/src/set-state.ts +1 -13
  105. package/src/silo.ts +7 -3
  106. package/src/transaction.ts +3 -3
  107. package/react/src/store-hooks.ts +0 -87
  108. package/realtime-server/src/realtime-server-store.ts +0 -39
@@ -1,28 +1,18 @@
1
+ import { isRootStore } from '../../dist/chunk-H4Q5FTPZ.js';
1
2
  import '../../dist/chunk-PZLG2HP3.js';
2
- import * as AtomIO from 'atom.io';
3
- import { parseJson } from 'atom.io/json';
4
3
  import * as Internal3 from 'atom.io/internal';
5
- import { getJsonToken, getUpdateToken } from 'atom.io/internal';
4
+ import { setIntoStore, getJsonToken, getUpdateToken } from 'atom.io/internal';
5
+ import { parseJson } from 'atom.io/json';
6
+ import * as AtomIO from 'atom.io';
6
7
 
7
- var myIdState__INTERNAL = AtomIO.atom({
8
- key: `myId__INTERNAL`,
9
- default: void 0
10
- });
11
- var myIdState = AtomIO.selector({
12
- key: `myId`,
13
- get: ({ get }) => get(myIdState__INTERNAL)
14
- });
15
- var updateQueueAtoms = AtomIO.atomFamily({
16
- key: `updateQueue`,
17
- default: []
18
- });
19
8
  function pullState(token, socket, store) {
20
- socket.on(`serve:${token.key}`, (data) => {
21
- AtomIO.setState(token, data, store);
22
- });
9
+ const setServedValue = (data) => {
10
+ setIntoStore(token, data, store);
11
+ };
12
+ socket.on(`serve:${token.key}`, setServedValue);
23
13
  socket.emit(`sub:${token.key}`);
24
14
  return () => {
25
- socket.off(`serve:${token.key}`);
15
+ socket.off(`serve:${token.key}`, setServedValue);
26
16
  socket.emit(`unsub:${token.key}`);
27
17
  };
28
18
  }
@@ -35,7 +25,7 @@ function pullFamilyMember(token, socket, store) {
35
25
  const { key: familyKey, subKey: serializedSubKey } = token.family;
36
26
  const subKey = parseJson(serializedSubKey);
37
27
  socket == null ? void 0 : socket.on(`serve:${token.key}`, (data) => {
38
- AtomIO.setState(token, data, store);
28
+ setIntoStore(token, data, store);
39
29
  });
40
30
  socket == null ? void 0 : socket.emit(`sub:${familyKey}`, subKey);
41
31
  return () => {
@@ -47,12 +37,12 @@ function pullMutableState(token, socket, store) {
47
37
  const jsonToken = getJsonToken(token);
48
38
  const updateToken = getUpdateToken(token);
49
39
  socket.on(`init:${token.key}`, (data) => {
50
- AtomIO.setState(jsonToken, data, store);
40
+ setIntoStore(jsonToken, data, store);
51
41
  });
52
42
  socket.on(
53
43
  `next:${token.key}`,
54
44
  (data) => {
55
- AtomIO.setState(updateToken, data, store);
45
+ setIntoStore(updateToken, data, store);
56
46
  }
57
47
  );
58
48
  socket.emit(`sub:${token.key}`);
@@ -72,13 +62,13 @@ function pullMutableFamilyMember(token, socket, store) {
72
62
  const subKey = parseJson(serializedSubKey);
73
63
  socket == null ? void 0 : socket.on(`init:${token.key}`, (data) => {
74
64
  const jsonToken = getJsonToken(token);
75
- AtomIO.setState(jsonToken, data, store);
65
+ setIntoStore(jsonToken, data, store);
76
66
  });
77
67
  socket == null ? void 0 : socket.on(
78
68
  `next:${token.key}`,
79
69
  (data) => {
80
70
  const trackerToken = getUpdateToken(token);
81
- AtomIO.setState(trackerToken, data, store);
71
+ setIntoStore(trackerToken, data, store);
82
72
  }
83
73
  );
84
74
  socket == null ? void 0 : socket.emit(`sub:${familyKey}`, subKey);
@@ -115,63 +105,158 @@ function serverAction(token, socket, store) {
115
105
  unsubscribeFromLocalUpdates();
116
106
  };
117
107
  }
118
- function syncAction(token, socket, updateQueue, store) {
119
- const updateQueueState = AtomIO.findState(updateQueueAtoms, token);
108
+ var myIdState__INTERNAL = AtomIO.atom({
109
+ key: `myId__INTERNAL`,
110
+ default: void 0
111
+ });
112
+ var myIdState = AtomIO.selector({
113
+ key: `myId`,
114
+ get: ({ get }) => get(myIdState__INTERNAL)
115
+ });
116
+ var optimisticUpdateQueueState = AtomIO.atom({
117
+ key: `updateQueue`,
118
+ default: []
119
+ });
120
+ var confirmedUpdateQueueState = AtomIO.atom({
121
+ key: `serverConfirmedUpdateQueue`,
122
+ default: []
123
+ });
124
+ function syncAction(token, socket, store) {
125
+ const optimisticQueue = Internal3.getFromStore(
126
+ optimisticUpdateQueueState,
127
+ store
128
+ );
129
+ const confirmedQueue = Internal3.getFromStore(confirmedUpdateQueueState, store);
120
130
  const unsubscribeFromLocalUpdates = Internal3.subscribeToTransaction(
121
131
  token,
122
132
  (clientUpdate) => {
123
- AtomIO.setState(updateQueueState, (queue) => {
124
- queue.push(clientUpdate);
125
- return queue;
126
- });
127
- socket.emit(`tx-run:${token.key}`, clientUpdate);
133
+ const optimisticUpdateQueueIndex = optimisticQueue.findIndex(
134
+ (update) => update.id === clientUpdate.id
135
+ );
136
+ if (optimisticUpdateQueueIndex === -1) {
137
+ Internal3.setIntoStore(
138
+ optimisticUpdateQueueState,
139
+ (queue) => {
140
+ queue.push(clientUpdate);
141
+ queue.sort((a, b) => a.epoch - b.epoch);
142
+ return queue;
143
+ },
144
+ store
145
+ );
146
+ socket.emit(`tx-run:${token.key}`, clientUpdate);
147
+ } else {
148
+ Internal3.setIntoStore(
149
+ optimisticUpdateQueueState,
150
+ (queue) => {
151
+ queue[optimisticUpdateQueueIndex] = clientUpdate;
152
+ return queue;
153
+ },
154
+ store
155
+ );
156
+ socket.emit(`tx-run:${token.key}`, clientUpdate);
157
+ }
128
158
  },
129
- `tx-run:${token.key}:${socket.id}`,
159
+ `tx-run:${token.key}`,
130
160
  store
131
161
  );
132
- const applyIncomingUpdate = (serverUpdate) => {
133
- const clientUpdate = updateQueue[0];
134
- if (clientUpdate) {
135
- if (clientUpdate.id !== serverUpdate.id) {
136
- store.logger.error(
137
- `\u274C`,
138
- `transaction`,
139
- serverUpdate.key,
140
- `did not match position 0 in queue of updates awaiting sync:`,
141
- updateQueue
142
- );
143
- }
144
- const clientResult = JSON.stringify(clientUpdate);
145
- const serverResult = JSON.stringify(serverUpdate);
146
- if (clientResult !== serverResult) {
147
- store.logger.error(
148
- `\u274C`,
162
+ const reconcileUpdates = (optimisticUpdate, confirmedUpdate) => {
163
+ Internal3.setIntoStore(
164
+ optimisticUpdateQueueState,
165
+ (queue) => {
166
+ queue.shift();
167
+ return queue;
168
+ },
169
+ store
170
+ );
171
+ if (optimisticUpdate.id === confirmedUpdate.id) {
172
+ const clientResult = JSON.stringify(optimisticUpdate.updates);
173
+ const serverResult = JSON.stringify(confirmedUpdate.updates);
174
+ if (clientResult === serverResult) {
175
+ store.logger.info(
176
+ `\u2705`,
149
177
  `transaction`,
150
178
  token.key,
151
- `results do not match between client and server:`,
152
- { clientResult, serverResult }
179
+ `results for ${optimisticUpdate.id} match between client and server`
153
180
  );
154
- Internal3.ingestTransactionUpdate(`oldValue`, clientUpdate, store);
181
+ socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
182
+ return;
183
+ }
184
+ } else {
185
+ store.logger.info(
186
+ `\u274C`,
187
+ `transaction`,
188
+ token.key,
189
+ `${store.config.name} thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`
190
+ );
191
+ }
192
+ for (const subsequentOptimistic of optimisticQueue.toReversed()) {
193
+ Internal3.ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
194
+ }
195
+ Internal3.ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
196
+ Internal3.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
197
+ socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
198
+ for (const subsequentOptimistic of optimisticQueue) {
199
+ const token2 = Object.assign(
200
+ { type: `transaction` },
201
+ subsequentOptimistic
202
+ );
203
+ const { id, params } = subsequentOptimistic;
204
+ AtomIO.runTransaction(token2, id, store)(...params);
205
+ }
206
+ };
207
+ const registerAndAttemptConfirmedUpdate = (confirmedUpdate) => {
208
+ const zerothOptimisticUpdate = optimisticQueue[0];
209
+ if (zerothOptimisticUpdate) {
210
+ if (zerothOptimisticUpdate.epoch === confirmedUpdate.epoch) {
211
+ reconcileUpdates(zerothOptimisticUpdate, confirmedUpdate);
212
+ for (const nextConfirmed of confirmedQueue) {
213
+ const nextOptimistic = optimisticQueue[0];
214
+ if (nextConfirmed.epoch === nextOptimistic.epoch) {
215
+ reconcileUpdates(nextOptimistic, nextConfirmed);
216
+ } else {
217
+ break;
218
+ }
219
+ }
155
220
  } else {
221
+ const hasEnqueuedOptimisticUpdate = optimisticQueue.some(
222
+ (update) => update.epoch === confirmedUpdate.epoch
223
+ );
224
+ if (hasEnqueuedOptimisticUpdate) {
225
+ Internal3.setIntoStore(
226
+ confirmedUpdateQueueState,
227
+ (queue) => {
228
+ queue.push(confirmedUpdate);
229
+ queue.sort((a, b) => a.epoch - b.epoch);
230
+ return queue;
231
+ },
232
+ store
233
+ );
234
+ }
235
+ }
236
+ } else {
237
+ if (isRootStore(store) && store.transactionMeta.epoch === confirmedUpdate.epoch - 1) {
238
+ Internal3.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
239
+ socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
240
+ store.transactionMeta.epoch = confirmedUpdate.epoch;
241
+ } else if (isRootStore(store)) {
156
242
  store.logger.info(
157
- `\u2705`,
243
+ `\u274C`,
158
244
  `transaction`,
159
245
  token.key,
160
- `results match between client and server`
246
+ `received out-of-order update from server`,
247
+ {
248
+ clientEpoch: store.transactionMeta.epoch,
249
+ serverEpoch: confirmedUpdate.epoch
250
+ }
161
251
  );
162
252
  }
163
- AtomIO.setState(updateQueueState, (queue) => {
164
- queue.shift();
165
- return queue;
166
- });
167
- return;
168
253
  }
169
- Internal3.ingestTransactionUpdate(`newValue`, serverUpdate, store);
170
254
  };
171
- socket.on(`tx-new:${token.key}`, applyIncomingUpdate);
255
+ socket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
256
+ socket.on(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
172
257
  socket.emit(`tx-sub:${token.key}`);
173
258
  const unsubscribeFromIncomingUpdates = () => {
174
- socket.off(`tx-new:${token.key}`, applyIncomingUpdate);
259
+ socket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
175
260
  socket.emit(`tx-unsub:${token.key}`);
176
261
  };
177
262
  return () => {
@@ -179,7 +264,17 @@ function syncAction(token, socket, updateQueue, store) {
179
264
  unsubscribeFromIncomingUpdates();
180
265
  };
181
266
  }
267
+ function syncState(token, socket, store) {
268
+ const setServedValue = (data) => {
269
+ setIntoStore(token, data, store);
270
+ };
271
+ socket.on(`value:${token.key}`, setServedValue);
272
+ socket.emit(`get:${token.key}`);
273
+ return () => {
274
+ socket.off(`value:${token.key}`, setServedValue);
275
+ };
276
+ }
182
277
 
183
- export { myIdState, myIdState__INTERNAL, pullFamilyMember, pullMutableFamilyMember, pullMutableState, pullState, pushState, serverAction, syncAction, updateQueueAtoms };
278
+ export { confirmedUpdateQueueState, myIdState, myIdState__INTERNAL, optimisticUpdateQueueState, pullFamilyMember, pullMutableFamilyMember, pullMutableState, pullState, pushState, serverAction, syncAction, syncState };
184
279
  //# sourceMappingURL=out.js.map
185
280
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/realtime-client-store.ts","../src/pull-state.ts","../src/pull-family-member.ts","../src/pull-mutable.ts","../src/pull-mutable-family-member.ts","../src/push-state.ts","../src/server-action.ts","../src/sync-server-action.ts"],"names":["AtomIO","getJsonToken","getUpdateToken","parseJson","Internal"],"mappings":"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","sourcesContent":["import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | undefined>({\n\tkey: `myId__INTERNAL`,\n\tdefault: undefined,\n})\nexport const myIdState = AtomIO.selector<string | undefined>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n\nexport const updateQueueAtoms = AtomIO.atomFamily<\n\tAtomIO.TransactionUpdate<any>[],\n\tAtomIO.TransactionToken<any>\n>({\n\tkey: `updateQueue`,\n\tdefault: [],\n})\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tsocket.on(`serve:${token.key}`, (data) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport 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\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\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\tAtomIO.setState(token, data, store)\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 * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(jsonToken, data, store)\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\tAtomIO.setState(updateToken, data, store)\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 * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\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(token)\n\t\tAtomIO.setState(jsonToken, data, store)\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\tAtomIO.setState(trackerToken, data, store)\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 * 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\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tInternal.subscribeToState(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\t`push`,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\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<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\tstore,\n\t)\n\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\nimport { updateQueueAtoms } from \"./realtime-client-store\"\n\nexport function syncAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tupdateQueue: AtomIO.TransactionUpdate<any>[],\n\tstore: Internal.Store,\n): () => void {\n\tconst updateQueueState = AtomIO.findState(updateQueueAtoms, token)\n\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tAtomIO.setState(updateQueueState, (queue) => {\n\t\t\t\tqueue.push(clientUpdate)\n\t\t\t\treturn queue\n\t\t\t})\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\tstore,\n\t)\n\n\tconst applyIncomingUpdate = (serverUpdate: AtomIO.TransactionUpdate<ƒ>) => {\n\t\tconst clientUpdate = updateQueue[0]\n\t\tif (clientUpdate) {\n\t\t\tif (clientUpdate.id !== serverUpdate.id) {\n\t\t\t\tstore.logger.error(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\tserverUpdate.key,\n\t\t\t\t\t`did not match position 0 in queue of updates awaiting sync:`,\n\t\t\t\t\tupdateQueue,\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst clientResult = JSON.stringify(clientUpdate)\n\t\t\tconst serverResult = JSON.stringify(serverUpdate)\n\t\t\tif (clientResult !== serverResult) {\n\t\t\t\tstore.logger.error(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`results do not match between client and server:`,\n\t\t\t\t\t{ clientResult, serverResult },\n\t\t\t\t)\n\t\t\t\tInternal.ingestTransactionUpdate(`oldValue`, clientUpdate, store)\n\t\t\t} else {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`✅`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`results match between client and server`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tAtomIO.setState(updateQueueState, (queue) => {\n\t\t\t\tqueue.shift()\n\t\t\t\treturn queue\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t\tInternal.ingestTransactionUpdate(`newValue`, serverUpdate, store)\n\t}\n\tsocket.on(`tx-new:${token.key}`, applyIncomingUpdate)\n\tsocket.emit(`tx-sub:${token.key}`)\n\tconst unsubscribeFromIncomingUpdates = () => {\n\t\tsocket.off(`tx-new:${token.key}`, applyIncomingUpdate)\n\t\tsocket.emit(`tx-unsub:${token.key}`)\n\t}\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t\tunsubscribeFromIncomingUpdates()\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../src/pull-state.ts","../src/pull-family-member.ts","../src/pull-mutable.ts","../src/pull-mutable-family-member.ts","../src/push-state.ts","../src/server-action.ts","../src/realtime-client-stores/client-main-store.ts","../src/realtime-client-stores/client-sync-store.ts","../src/sync-server-action.ts","../src/sync-state.ts"],"names":["setIntoStore","getJsonToken","getUpdateToken","parseJson","Internal","AtomIO","token"],"mappings":"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","sourcesContent":["import type * as AtomIO from \"atom.io\"\nimport { type Store, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst setServedValue = (data: J) => {\n\t\tsetIntoStore(token, data, store)\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 { type Store, 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\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\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(token, data, store)\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 pullMutableState<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tsetIntoStore(jsonToken, data, store)\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(updateToken, data, store)\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 { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\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(token)\n\t\tsetIntoStore(jsonToken, data, store)\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(trackerToken, data, store)\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 * 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\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tInternal.subscribeToState(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\t`push`,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\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<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\tstore,\n\t)\n\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t}\n}\n","import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | undefined>({\n\tkey: `myId__INTERNAL`,\n\tdefault: undefined,\n})\nexport const myIdState = AtomIO.selector<string | undefined>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as AtomIO from \"atom.io\"\n\nexport const optimisticUpdateQueueState = AtomIO.atom<\n\tAtomIO.TransactionUpdate<any>[]\n>({\n\tkey: `updateQueue`,\n\tdefault: [],\n})\n\nexport const confirmedUpdateQueueState = AtomIO.atom<\n\tAtomIO.TransactionUpdate<any>[]\n>({\n\tkey: `serverConfirmedUpdateQueue`,\n\tdefault: [],\n})\n","import * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { isRootStore } from \"../../internal/src/transaction/is-root-store\"\nimport {\n\tconfirmedUpdateQueueState,\n\toptimisticUpdateQueueState,\n} from \"./realtime-client-stores\"\n\nexport function syncAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tconst optimisticQueue = Internal.getFromStore(\n\t\toptimisticUpdateQueueState,\n\t\tstore,\n\t)\n\tconst confirmedQueue = Internal.getFromStore(confirmedUpdateQueueState, store)\n\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tconst optimisticUpdateQueueIndex = optimisticQueue.findIndex(\n\t\t\t\t(update) => update.id === clientUpdate.id,\n\t\t\t)\n\t\t\tif (optimisticUpdateQueueIndex === -1) {\n\t\t\t\tInternal.setIntoStore(\n\t\t\t\t\toptimisticUpdateQueueState,\n\t\t\t\t\t(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\tstore,\n\t\t\t\t)\n\t\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t\t} else {\n\t\t\t\tInternal.setIntoStore(\n\t\t\t\t\toptimisticUpdateQueueState,\n\t\t\t\t\t(queue) => {\n\t\t\t\t\t\tqueue[optimisticUpdateQueueIndex] = clientUpdate\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t},\n\t\t\t\t\tstore,\n\t\t\t\t)\n\t\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t\t}\n\t\t},\n\t\t`tx-run:${token.key}`,\n\t\tstore,\n\t)\n\tconst reconcileUpdates = (\n\t\toptimisticUpdate: AtomIO.TransactionUpdate<ƒ>,\n\t\tconfirmedUpdate: AtomIO.TransactionUpdate<ƒ>,\n\t) => {\n\t\tInternal.setIntoStore(\n\t\t\toptimisticUpdateQueueState,\n\t\t\t(queue) => {\n\t\t\t\tqueue.shift()\n\t\t\t\treturn queue\n\t\t\t},\n\t\t\tstore,\n\t\t)\n\t\tif (optimisticUpdate.id === confirmedUpdate.id) {\n\t\t\tconst clientResult = JSON.stringify(optimisticUpdate.updates)\n\t\t\tconst serverResult = JSON.stringify(confirmedUpdate.updates)\n\t\t\tif (clientResult === serverResult) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`✅`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`results for ${optimisticUpdate.id} match between client and server`,\n\t\t\t\t)\n\t\t\t\tsocket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch)\n\t\t\t\treturn\n\t\t\t}\n\t\t} else {\n\t\t\t// id mismatch\n\t\t\tstore.logger.info(\n\t\t\t\t`❌`,\n\t\t\t\t`transaction`,\n\t\t\t\ttoken.key,\n\t\t\t\t`${store.config.name} thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`,\n\t\t\t)\n\t\t}\n\t\tfor (const subsequentOptimistic of optimisticQueue.toReversed()) {\n\t\t\tInternal.ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store)\n\t\t}\n\t\tInternal.ingestTransactionUpdate(`oldValue`, optimisticUpdate, store)\n\t\tInternal.ingestTransactionUpdate(`newValue`, confirmedUpdate, store)\n\t\tsocket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch)\n\t\tfor (const subsequentOptimistic of optimisticQueue) {\n\t\t\tconst token = Object.assign(\n\t\t\t\t{ type: `transaction` } as const,\n\t\t\t\tsubsequentOptimistic,\n\t\t\t)\n\t\t\tconst { id, params } = subsequentOptimistic\n\t\t\tAtomIO.runTransaction(token, id, store)(...params)\n\t\t}\n\t}\n\n\tconst registerAndAttemptConfirmedUpdate = (\n\t\tconfirmedUpdate: AtomIO.TransactionUpdate<ƒ>,\n\t) => {\n\t\tconst zerothOptimisticUpdate = optimisticQueue[0]\n\t\tif (zerothOptimisticUpdate) {\n\t\t\tif (zerothOptimisticUpdate.epoch === confirmedUpdate.epoch) {\n\t\t\t\treconcileUpdates(zerothOptimisticUpdate, confirmedUpdate)\n\t\t\t\tfor (const nextConfirmed of confirmedQueue) {\n\t\t\t\t\tconst nextOptimistic = optimisticQueue[0]\n\t\t\t\t\tif (nextConfirmed.epoch === nextOptimistic.epoch) {\n\t\t\t\t\t\treconcileUpdates(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\n\t\t\t\tconst hasEnqueuedOptimisticUpdate = optimisticQueue.some(\n\t\t\t\t\t(update) => update.epoch === confirmedUpdate.epoch,\n\t\t\t\t)\n\t\t\t\tif (hasEnqueuedOptimisticUpdate) {\n\t\t\t\t\tInternal.setIntoStore(\n\t\t\t\t\t\tconfirmedUpdateQueueState,\n\t\t\t\t\t\t(queue) => {\n\t\t\t\t\t\t\tqueue.push(confirmedUpdate)\n\t\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\t\treturn queue\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstore,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (\n\t\t\t\tisRootStore(store) &&\n\t\t\t\tstore.transactionMeta.epoch === confirmedUpdate.epoch - 1\n\t\t\t) {\n\t\t\t\tInternal.ingestTransactionUpdate(`newValue`, confirmedUpdate, store)\n\t\t\t\tsocket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch)\n\t\t\t\tstore.transactionMeta.epoch = confirmedUpdate.epoch\n\t\t\t} else if (isRootStore(store)) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`received out-of-order update from server`,\n\t\t\t\t\t{\n\t\t\t\t\t\tclientEpoch: store.transactionMeta.epoch,\n\t\t\t\t\t\tserverEpoch: confirmedUpdate.epoch,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\tsocket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate)\n\tsocket.on(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate)\n\tsocket.emit(`tx-sub:${token.key}`)\n\tconst unsubscribeFromIncomingUpdates = () => {\n\t\tsocket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate)\n\t\tsocket.emit(`tx-unsub:${token.key}`)\n\t}\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t\tunsubscribeFromIncomingUpdates()\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { type Store, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function syncState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst setServedValue = (data: J) => {\n\t\tsetIntoStore(token, data, store)\n\t}\n\tsocket.on(`value:${token.key}`, setServedValue)\n\tsocket.emit(`get:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`value:${token.key}`, setServedValue)\n\t}\n}\n"]}
@@ -1,8 +1,9 @@
1
- export * from "./realtime-client-store"
2
1
  export * from "./pull-state"
3
2
  export * from "./pull-family-member"
4
3
  export * from "./pull-mutable"
5
4
  export * from "./pull-mutable-family-member"
6
5
  export * from "./push-state"
7
6
  export * from "./server-action"
7
+ export * from "./realtime-client-stores"
8
8
  export * from "./sync-server-action"
9
+ export * from "./sync-state"
@@ -1,5 +1,5 @@
1
- import * as AtomIO from "atom.io"
2
- import type { Store } from "atom.io/internal"
1
+ import type * as AtomIO from "atom.io"
2
+ import { type Store, setIntoStore } from "atom.io/internal"
3
3
  import type { Json } from "atom.io/json"
4
4
  import { parseJson } from "atom.io/json"
5
5
  import type { Socket } from "socket.io-client"
@@ -16,7 +16,7 @@ export function pullFamilyMember<J extends Json.Serializable>(
16
16
  const { key: familyKey, subKey: serializedSubKey } = token.family
17
17
  const subKey = parseJson(serializedSubKey)
18
18
  socket?.on(`serve:${token.key}`, (data: J) => {
19
- AtomIO.setState(token, data, store)
19
+ setIntoStore(token, data, store)
20
20
  })
21
21
  socket?.emit(`sub:${familyKey}`, subKey)
22
22
  return () => {
@@ -1,5 +1,5 @@
1
- import * as AtomIO from "atom.io"
2
- import { getJsonToken, getUpdateToken } from "atom.io/internal"
1
+ import type * as AtomIO from "atom.io"
2
+ import { getJsonToken, getUpdateToken, setIntoStore } from "atom.io/internal"
3
3
  import type { Store, Transceiver } from "atom.io/internal"
4
4
  import { parseJson } from "atom.io/json"
5
5
  import type { Json } from "atom.io/json"
@@ -21,13 +21,13 @@ export function pullMutableFamilyMember<
21
21
  const subKey = parseJson(serializedSubKey)
22
22
  socket?.on(`init:${token.key}`, (data: J) => {
23
23
  const jsonToken = getJsonToken(token)
24
- AtomIO.setState(jsonToken, data, store)
24
+ setIntoStore(jsonToken, data, store)
25
25
  })
26
26
  socket?.on(
27
27
  `next:${token.key}`,
28
28
  (data: T extends Transceiver<infer Signal> ? Signal : never) => {
29
29
  const trackerToken = getUpdateToken(token)
30
- AtomIO.setState(trackerToken, data, store)
30
+ setIntoStore(trackerToken, data, store)
31
31
  },
32
32
  )
33
33
  socket?.emit(`sub:${familyKey}`, subKey)
@@ -1,6 +1,6 @@
1
- import * as AtomIO from "atom.io"
1
+ import type * as AtomIO from "atom.io"
2
2
  import type { Store, Transceiver } from "atom.io/internal"
3
- import { getJsonToken, getUpdateToken } from "atom.io/internal"
3
+ import { getJsonToken, getUpdateToken, setIntoStore } from "atom.io/internal"
4
4
  import type { Json } from "atom.io/json"
5
5
  import type { Socket } from "socket.io-client"
6
6
 
@@ -15,12 +15,12 @@ export function pullMutableState<
15
15
  const jsonToken = getJsonToken(token)
16
16
  const updateToken = getUpdateToken(token)
17
17
  socket.on(`init:${token.key}`, (data: J) => {
18
- AtomIO.setState(jsonToken, data, store)
18
+ setIntoStore(jsonToken, data, store)
19
19
  })
20
20
  socket.on(
21
21
  `next:${token.key}`,
22
22
  (data: T extends Transceiver<infer Update> ? Update : never) => {
23
- AtomIO.setState(updateToken, data, store)
23
+ setIntoStore(updateToken, data, store)
24
24
  },
25
25
  )
26
26
  socket.emit(`sub:${token.key}`)
@@ -1,5 +1,5 @@
1
- import * as AtomIO from "atom.io"
2
- import type { Store } from "atom.io/internal"
1
+ import type * as AtomIO from "atom.io"
2
+ import { type Store, setIntoStore } from "atom.io/internal"
3
3
  import type { Json } from "atom.io/json"
4
4
  import type { Socket } from "socket.io-client"
5
5
 
@@ -8,12 +8,13 @@ export function pullState<J extends Json.Serializable>(
8
8
  socket: Socket,
9
9
  store: Store,
10
10
  ): () => void {
11
- socket.on(`serve:${token.key}`, (data) => {
12
- AtomIO.setState(token, data, store)
13
- })
11
+ const setServedValue = (data: J) => {
12
+ setIntoStore(token, data, store)
13
+ }
14
+ socket.on(`serve:${token.key}`, setServedValue)
14
15
  socket.emit(`sub:${token.key}`)
15
16
  return () => {
16
- socket.off(`serve:${token.key}`)
17
+ socket.off(`serve:${token.key}`, setServedValue)
17
18
  socket.emit(`unsub:${token.key}`)
18
19
  }
19
20
  }
@@ -8,11 +8,3 @@ export const myIdState = AtomIO.selector<string | undefined>({
8
8
  key: `myId`,
9
9
  get: ({ get }) => get(myIdState__INTERNAL),
10
10
  })
11
-
12
- export const updateQueueAtoms = AtomIO.atomFamily<
13
- AtomIO.TransactionUpdate<any>[],
14
- AtomIO.TransactionToken<any>
15
- >({
16
- key: `updateQueue`,
17
- default: [],
18
- })
@@ -0,0 +1,15 @@
1
+ import * as AtomIO from "atom.io"
2
+
3
+ export const optimisticUpdateQueueState = AtomIO.atom<
4
+ AtomIO.TransactionUpdate<any>[]
5
+ >({
6
+ key: `updateQueue`,
7
+ default: [],
8
+ })
9
+
10
+ export const confirmedUpdateQueueState = AtomIO.atom<
11
+ AtomIO.TransactionUpdate<any>[]
12
+ >({
13
+ key: `serverConfirmedUpdateQueue`,
14
+ default: [],
15
+ })
@@ -0,0 +1,2 @@
1
+ export * from "./client-main-store"
2
+ export * from "./client-sync-store"