atom.io 0.17.0 → 0.18.1

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 (153) hide show
  1. package/data/dist/index.cjs +62 -40
  2. package/data/dist/index.cjs.map +1 -1
  3. package/data/dist/index.d.ts +8 -2
  4. package/data/dist/index.js +64 -42
  5. package/data/dist/index.js.map +1 -1
  6. package/data/src/dict.ts +8 -4
  7. package/data/src/join.ts +74 -33
  8. package/data/src/struct-family.ts +18 -17
  9. package/dist/chunk-IZHOMSXA.js +331 -0
  10. package/dist/chunk-IZHOMSXA.js.map +1 -0
  11. package/dist/chunk-JDUNWJFB.js +18 -0
  12. package/dist/chunk-JDUNWJFB.js.map +1 -0
  13. package/dist/index.cjs +4 -10
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +66 -51
  16. package/dist/index.js +5 -11
  17. package/dist/index.js.map +1 -1
  18. package/internal/dist/index.cjs +187 -58
  19. package/internal/dist/index.cjs.map +1 -1
  20. package/internal/dist/index.d.ts +95 -71
  21. package/internal/dist/index.js +179 -53
  22. package/internal/dist/index.js.map +1 -1
  23. package/internal/src/arbitrary.ts +3 -0
  24. package/internal/src/atom/delete-atom.ts +7 -6
  25. package/internal/src/caching.ts +6 -4
  26. package/internal/src/families/find-in-store.ts +16 -0
  27. package/internal/src/get-environment-data.ts +4 -7
  28. package/internal/src/index.ts +6 -5
  29. package/internal/src/ingest-updates/ingest-atom-update.ts +6 -2
  30. package/internal/src/ingest-updates/ingest-transaction-update.ts +0 -1
  31. package/internal/src/selector/create-standalone-selector.ts +0 -2
  32. package/internal/src/set-state/copy-mutable-if-needed.ts +5 -0
  33. package/internal/src/set-state/emit-update.ts +25 -11
  34. package/internal/src/set-state/set-atom.ts +15 -18
  35. package/internal/src/store/store.ts +14 -2
  36. package/internal/src/store/withdraw.ts +72 -2
  37. package/internal/src/subscribe/subscribe-to-timeline.ts +2 -2
  38. package/internal/src/subscribe/subscribe-to-transaction.ts +2 -2
  39. package/internal/src/timeline/create-timeline.ts +12 -1
  40. package/internal/src/transaction/act-upon-store.ts +19 -0
  41. package/internal/src/transaction/apply-transaction.ts +6 -1
  42. package/internal/src/transaction/assign-transaction-to-continuity.ts +18 -0
  43. package/internal/src/transaction/build-transaction.ts +7 -6
  44. package/internal/src/transaction/create-transaction.ts +1 -1
  45. package/internal/src/transaction/get-epoch-number.ts +40 -0
  46. package/internal/src/transaction/index.ts +10 -1
  47. package/internal/src/transaction/set-epoch-number.ts +30 -0
  48. package/introspection/dist/index.cjs.map +1 -1
  49. package/introspection/dist/index.d.ts +3 -3
  50. package/introspection/dist/index.js.map +1 -1
  51. package/introspection/src/attach-introspection-states.ts +6 -2
  52. package/introspection/src/attach-timeline-family.ts +5 -2
  53. package/introspection/src/attach-transaction-logs.ts +2 -2
  54. package/json/dist/index.d.ts +3 -1
  55. package/json/src/index.ts +4 -0
  56. package/package.json +241 -230
  57. package/react/dist/index.cjs.map +1 -1
  58. package/react/dist/index.d.ts +1 -1
  59. package/react/dist/index.js.map +1 -1
  60. package/react/src/use-json.ts +1 -1
  61. package/react-devtools/dist/index.cjs +131 -134
  62. package/react-devtools/dist/index.cjs.map +1 -1
  63. package/react-devtools/dist/index.css +2 -2
  64. package/react-devtools/dist/index.css.map +1 -1
  65. package/react-devtools/dist/index.d.ts +3 -3
  66. package/react-devtools/dist/index.js +91 -108
  67. package/react-devtools/dist/index.js.map +1 -1
  68. package/react-devtools/src/StateEditor.tsx +4 -4
  69. package/react-devtools/src/StateIndex.tsx +1 -4
  70. package/react-devtools/src/TimelineIndex.tsx +3 -3
  71. package/react-devtools/src/TransactionIndex.tsx +9 -8
  72. package/react-devtools/src/index.ts +2 -2
  73. package/realtime/dist/index.cjs +120 -0
  74. package/realtime/dist/index.cjs.map +1 -0
  75. package/realtime/dist/index.d.ts +146 -0
  76. package/realtime/dist/index.js +111 -0
  77. package/realtime/dist/index.js.map +1 -0
  78. package/realtime/package.json +16 -0
  79. package/realtime/src/index.ts +2 -0
  80. package/realtime/src/realtime-continuity.ts +162 -0
  81. package/realtime/src/shared-room-store.ts +48 -0
  82. package/realtime-client/dist/index.cjs +424 -170
  83. package/realtime-client/dist/index.cjs.map +1 -1
  84. package/realtime-client/dist/index.d.ts +15 -11
  85. package/realtime-client/dist/index.js +96 -177
  86. package/realtime-client/dist/index.js.map +1 -1
  87. package/realtime-client/src/index.ts +8 -7
  88. package/realtime-client/src/{pull-family-member.ts → pull-atom-family-member.ts} +2 -2
  89. package/realtime-client/src/{pull-state.ts → pull-atom.ts} +2 -2
  90. package/realtime-client/src/{pull-mutable-family-member.ts → pull-mutable-atom-family-member.ts} +6 -6
  91. package/realtime-client/src/{pull-mutable.ts → pull-mutable-atom.ts} +1 -1
  92. package/realtime-client/src/pull-selector-family-member.ts +42 -0
  93. package/realtime-client/src/pull-selector.ts +38 -0
  94. package/realtime-client/src/realtime-client-stores/client-main-store.ts +12 -2
  95. package/realtime-client/src/realtime-client-stores/client-sync-store.ts +7 -7
  96. package/realtime-client/src/sync-continuity.ts +368 -0
  97. package/realtime-react/dist/index.cjs +367 -27
  98. package/realtime-react/dist/index.cjs.map +1 -1
  99. package/realtime-react/dist/index.d.ts +24 -8
  100. package/realtime-react/dist/index.js +38 -22
  101. package/realtime-react/dist/index.js.map +1 -1
  102. package/realtime-react/src/index.ts +6 -5
  103. package/realtime-react/src/use-pull-atom-family-member.ts +21 -0
  104. package/realtime-react/src/{use-sync.ts → use-pull-atom.ts} +4 -4
  105. package/realtime-react/src/{use-pull-mutable.ts → use-pull-mutable-atom.ts} +4 -3
  106. package/realtime-react/src/use-pull-mutable-family-member.ts +9 -4
  107. package/realtime-react/src/use-pull-selector-family-member.ts +21 -0
  108. package/realtime-react/src/{use-pull.ts → use-pull-selector.ts} +7 -5
  109. package/realtime-react/src/use-push.ts +3 -2
  110. package/realtime-react/src/use-server-action.ts +3 -2
  111. package/realtime-react/src/use-sync-continuity.ts +12 -0
  112. package/realtime-server/dist/index.cjs +769 -371
  113. package/realtime-server/dist/index.cjs.map +1 -1
  114. package/realtime-server/dist/index.d.ts +130 -60
  115. package/realtime-server/dist/index.js +753 -361
  116. package/realtime-server/dist/index.js.map +1 -1
  117. package/realtime-server/src/index.ts +17 -3
  118. package/realtime-server/src/ipc-sockets/child-socket.ts +135 -0
  119. package/realtime-server/src/ipc-sockets/custom-socket.ts +90 -0
  120. package/realtime-server/src/ipc-sockets/index.ts +3 -0
  121. package/realtime-server/src/ipc-sockets/parent-socket.ts +185 -0
  122. package/realtime-server/src/realtime-action-receiver.ts +8 -5
  123. package/realtime-server/src/realtime-continuity-synchronizer.ts +376 -0
  124. package/realtime-server/src/realtime-family-provider.ts +30 -71
  125. package/realtime-server/src/realtime-mutable-family-provider.ts +24 -86
  126. package/realtime-server/src/realtime-server-stores/index.ts +4 -1
  127. package/realtime-server/src/realtime-server-stores/realtime-continuity-store.ts +109 -0
  128. package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +64 -0
  129. package/realtime-server/src/realtime-server-stores/server-room-external-store.ts +42 -0
  130. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +51 -98
  131. package/realtime-server/src/realtime-server-stores/server-user-store.ts +14 -29
  132. package/realtime-server/src/realtime-state-receiver.ts +0 -1
  133. package/realtime-testing/dist/index.cjs +34 -32
  134. package/realtime-testing/dist/index.cjs.map +1 -1
  135. package/realtime-testing/dist/index.d.ts +1 -0
  136. package/realtime-testing/dist/index.js +33 -31
  137. package/realtime-testing/dist/index.js.map +1 -1
  138. package/realtime-testing/src/setup-realtime-test.tsx +44 -32
  139. package/src/atom.ts +49 -31
  140. package/src/logger.ts +14 -5
  141. package/src/selector.ts +44 -25
  142. package/src/subscribe.ts +2 -1
  143. package/src/timeline.ts +4 -4
  144. package/src/transaction.ts +13 -17
  145. package/src/validators.ts +15 -9
  146. package/dist/chunk-H4Q5FTPZ.js +0 -11
  147. package/dist/chunk-H4Q5FTPZ.js.map +0 -1
  148. package/internal/src/set-state/copy-mutable-in-transaction.ts +0 -19
  149. package/realtime-client/src/sync-server-action.ts +0 -170
  150. package/realtime-client/src/sync-state.ts +0 -19
  151. package/realtime-react/src/use-pull-family-member.ts +0 -16
  152. package/realtime-react/src/use-sync-server-action.ts +0 -16
  153. package/realtime-server/src/realtime-action-synchronizer.ts +0 -152
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var Internal3 = require('atom.io/internal');
3
+ var Internal = require('atom.io/internal');
4
4
  var json = require('atom.io/json');
5
5
  var AtomIO = require('atom.io');
6
+ var realtimeClient = require('atom.io/realtime-client');
6
7
 
7
8
  function _interopNamespace(e) {
8
9
  if (e && e.__esModule) return e;
@@ -22,13 +23,13 @@ function _interopNamespace(e) {
22
23
  return Object.freeze(n);
23
24
  }
24
25
 
25
- var Internal3__namespace = /*#__PURE__*/_interopNamespace(Internal3);
26
+ var Internal__namespace = /*#__PURE__*/_interopNamespace(Internal);
26
27
  var AtomIO__namespace = /*#__PURE__*/_interopNamespace(AtomIO);
27
28
 
28
- // realtime-client/src/pull-state.ts
29
- function pullState(token, socket, store) {
29
+ // realtime-client/src/pull-atom.ts
30
+ function pullAtom(token, socket, store) {
30
31
  const setServedValue = (data) => {
31
- Internal3.setIntoStore(token, data, store);
32
+ Internal.setIntoStore(token, data, store);
32
33
  };
33
34
  socket.on(`serve:${token.key}`, setServedValue);
34
35
  socket.emit(`sub:${token.key}`);
@@ -37,7 +38,7 @@ function pullState(token, socket, store) {
37
38
  socket.emit(`unsub:${token.key}`);
38
39
  };
39
40
  }
40
- function pullFamilyMember(token, socket, store) {
41
+ function pullAtomFamilyMember(token, socket, store) {
41
42
  if (!(`family` in token)) {
42
43
  console.error(`Token is not a family member:`, token);
43
44
  return () => {
@@ -46,7 +47,7 @@ function pullFamilyMember(token, socket, store) {
46
47
  const { key: familyKey, subKey: serializedSubKey } = token.family;
47
48
  const subKey = json.parseJson(serializedSubKey);
48
49
  socket == null ? void 0 : socket.on(`serve:${token.key}`, (data) => {
49
- Internal3.setIntoStore(token, data, store);
50
+ Internal.setIntoStore(token, data, store);
50
51
  });
51
52
  socket == null ? void 0 : socket.emit(`sub:${familyKey}`, subKey);
52
53
  return () => {
@@ -54,16 +55,16 @@ function pullFamilyMember(token, socket, store) {
54
55
  socket == null ? void 0 : socket.emit(`unsub:${token.key}`);
55
56
  };
56
57
  }
57
- function pullMutableState(token, socket, store) {
58
- const jsonToken = Internal3.getJsonToken(token);
59
- const updateToken = Internal3.getUpdateToken(token);
58
+ function pullMutableAtom(token, socket, store) {
59
+ const jsonToken = Internal.getJsonToken(token);
60
+ const updateToken = Internal.getUpdateToken(token);
60
61
  socket.on(`init:${token.key}`, (data) => {
61
- Internal3.setIntoStore(jsonToken, data, store);
62
+ Internal.setIntoStore(jsonToken, data, store);
62
63
  });
63
64
  socket.on(
64
65
  `next:${token.key}`,
65
66
  (data) => {
66
- Internal3.setIntoStore(updateToken, data, store);
67
+ Internal.setIntoStore(updateToken, data, store);
67
68
  }
68
69
  );
69
70
  socket.emit(`sub:${token.key}`);
@@ -73,7 +74,7 @@ function pullMutableState(token, socket, store) {
73
74
  socket.emit(`unsub:${token.key}`);
74
75
  };
75
76
  }
76
- function pullMutableFamilyMember(token, socket, store) {
77
+ function pullMutableAtomFamilyMember(token, socket, store) {
77
78
  if (!(`family` in token)) {
78
79
  console.error(`Token is not a family member:`, token);
79
80
  return () => {
@@ -81,26 +82,89 @@ function pullMutableFamilyMember(token, socket, store) {
81
82
  }
82
83
  const { key: familyKey, subKey: serializedSubKey } = token.family;
83
84
  const subKey = json.parseJson(serializedSubKey);
84
- socket == null ? void 0 : socket.on(`init:${token.key}`, (data) => {
85
- const jsonToken = Internal3.getJsonToken(token);
86
- Internal3.setIntoStore(jsonToken, data, store);
85
+ socket.on(`init:${token.key}`, (data) => {
86
+ const jsonToken = Internal.getJsonToken(token);
87
+ Internal.setIntoStore(jsonToken, data, store);
87
88
  });
88
- socket == null ? void 0 : socket.on(
89
+ socket.on(
89
90
  `next:${token.key}`,
90
91
  (data) => {
91
- const trackerToken = Internal3.getUpdateToken(token);
92
- Internal3.setIntoStore(trackerToken, data, store);
92
+ const trackerToken = Internal.getUpdateToken(token);
93
+ Internal.setIntoStore(trackerToken, data, store);
93
94
  }
94
95
  );
95
- socket == null ? void 0 : socket.emit(`sub:${familyKey}`, subKey);
96
+ socket.emit(`sub:${familyKey}`, subKey);
96
97
  return () => {
97
- socket == null ? void 0 : socket.off(`serve:${token.key}`);
98
- socket == null ? void 0 : socket.emit(`unsub:${token.key}`);
98
+ socket.off(`serve:${token.key}`);
99
+ socket.emit(`unsub:${token.key}`);
100
+ };
101
+ }
102
+
103
+ // realtime-client/src/pull-selector.ts
104
+ function pullSelector(token, socket, store) {
105
+ const atomKeys = store.selectorAtoms.getRelatedKeys(token.key);
106
+ const unsubscribes = [];
107
+ if (atomKeys) {
108
+ for (const atomKey of atomKeys) {
109
+ const atom3 = store.atoms.get(atomKey);
110
+ if (!atom3) {
111
+ continue;
112
+ }
113
+ switch (atom3.type) {
114
+ case `atom`: {
115
+ unsubscribes.push(pullAtom(atom3, socket, store));
116
+ break;
117
+ }
118
+ case `mutable_atom`: {
119
+ unsubscribes.push(pullMutableAtom(atom3, socket, store));
120
+ break;
121
+ }
122
+ }
123
+ }
124
+ }
125
+ return () => {
126
+ for (const unsubscribe of unsubscribes) {
127
+ unsubscribe();
128
+ }
129
+ };
130
+ }
131
+
132
+ // realtime-client/src/pull-selector-family-member.ts
133
+ function pullSelectorFamilyMember(token, socket, store) {
134
+ if (!(`family` in token)) {
135
+ console.error(`Token is not a family member:`, token);
136
+ return () => {
137
+ };
138
+ }
139
+ const atomKeys = store.selectorAtoms.getRelatedKeys(token.key);
140
+ const unsubscribes = [];
141
+ if (atomKeys) {
142
+ for (const atomKey of atomKeys) {
143
+ const atom3 = store.atoms.get(atomKey);
144
+ if (!atom3) {
145
+ continue;
146
+ }
147
+ switch (atom3.type) {
148
+ case `atom`: {
149
+ unsubscribes.push(pullAtomFamilyMember(atom3, socket, store));
150
+ break;
151
+ }
152
+ case `mutable_atom`: {
153
+ unsubscribes.push(pullMutableAtomFamilyMember(atom3, socket, store));
154
+ break;
155
+ }
156
+ }
157
+ }
158
+ }
159
+ return () => {
160
+ for (const unsubscribe of unsubscribes) {
161
+ unsubscribe();
162
+ }
99
163
  };
100
164
  }
101
165
  function pushState(token, socket, store) {
102
166
  socket.emit(`claim:${token.key}`);
103
- Internal3__namespace.subscribeToState(
167
+ Internal__namespace.subscribeToState(
104
168
  token,
105
169
  ({ newValue }) => {
106
170
  socket.emit(`pub:${token.key}`, newValue);
@@ -113,145 +177,225 @@ function pushState(token, socket, store) {
113
177
  socket.emit(`unclaim:${token.key}`);
114
178
  };
115
179
  }
116
- function serverAction(token, socket, store) {
117
- const unsubscribeFromLocalUpdates = Internal3__namespace.subscribeToTransaction(
118
- token,
119
- (clientUpdate) => {
120
- socket.emit(`tx-run:${token.key}`, clientUpdate);
121
- },
122
- `tx-run:${token.key}:${socket.id}`,
123
- store
124
- );
125
- return () => {
126
- unsubscribeFromLocalUpdates();
127
- };
128
- }
180
+
181
+ // __unstable__/web-effects/src/storage.ts
182
+ var persistAtom = (storage) => ({ stringify, parse }) => (key) => ({ setSelf, onSet }) => {
183
+ const savedValue = storage.getItem(key);
184
+ if (savedValue != null)
185
+ setSelf(parse(savedValue));
186
+ onSet(({ newValue }) => {
187
+ if (newValue == null) {
188
+ storage.removeItem(key);
189
+ return;
190
+ }
191
+ storage.setItem(key, stringify(newValue));
192
+ });
193
+ };
194
+ var lazyLocalStorageEffect = persistAtom(localStorage)(JSON);
195
+
196
+ // realtime-client/src/realtime-client-stores/client-main-store.ts
129
197
  var myIdState__INTERNAL = AtomIO__namespace.atom({
130
- key: `myId__INTERNAL`,
198
+ key: `mySocketId__INTERNAL`,
131
199
  default: void 0
132
200
  });
133
201
  var myIdState = AtomIO__namespace.selector({
134
- key: `myId`,
202
+ key: `mySocketId`,
135
203
  get: ({ get }) => get(myIdState__INTERNAL)
136
204
  });
137
- var optimisticUpdateQueueState = AtomIO__namespace.atom({
138
- key: `updateQueue`,
139
- default: []
205
+ var usernameEffects = typeof window === `undefined` ? [] : [lazyLocalStorageEffect(`myUsername`)];
206
+ var myUsernameState = AtomIO__namespace.atom({
207
+ key: `myUsername`,
208
+ default: null,
209
+ effects: usernameEffects
140
210
  });
141
- var confirmedUpdateQueueState = AtomIO__namespace.atom({
142
- key: `serverConfirmedUpdateQueue`,
211
+ var optimisticUpdateQueue = AtomIO__namespace.atom({
212
+ key: `updateQueue`,
143
213
  default: []
144
214
  });
145
-
146
- // internal/src/transaction/is-root-store.ts
147
- function isRootStore(store) {
148
- return `epoch` in store.transactionMeta;
149
- }
150
-
151
- // realtime-client/src/sync-server-action.ts
152
- function syncAction(token, socket, store) {
153
- const optimisticQueue = Internal3__namespace.getFromStore(
154
- optimisticUpdateQueueState,
155
- store
156
- );
157
- const confirmedQueue = Internal3__namespace.getFromStore(confirmedUpdateQueueState, store);
158
- const unsubscribeFromLocalUpdates = Internal3__namespace.subscribeToTransaction(
215
+ var confirmedUpdateQueue = AtomIO__namespace.atom(
216
+ {
217
+ key: `serverConfirmedUpdateQueue`,
218
+ default: []
219
+ }
220
+ );
221
+ function serverAction(token, socket, store) {
222
+ const unsubscribeFromLocalUpdates = Internal__namespace.subscribeToTransaction(
159
223
  token,
160
224
  (clientUpdate) => {
161
- const optimisticUpdateQueueIndex = optimisticQueue.findIndex(
162
- (update) => update.id === clientUpdate.id
163
- );
164
- if (optimisticUpdateQueueIndex === -1) {
165
- Internal3__namespace.setIntoStore(
166
- optimisticUpdateQueueState,
167
- (queue) => {
168
- queue.push(clientUpdate);
169
- queue.sort((a, b) => a.epoch - b.epoch);
170
- return queue;
171
- },
172
- store
173
- );
174
- socket.emit(`tx-run:${token.key}`, clientUpdate);
175
- } else {
176
- Internal3__namespace.setIntoStore(
177
- optimisticUpdateQueueState,
178
- (queue) => {
179
- queue[optimisticUpdateQueueIndex] = clientUpdate;
180
- return queue;
181
- },
182
- store
183
- );
184
- socket.emit(`tx-run:${token.key}`, clientUpdate);
185
- }
225
+ socket.emit(`tx-run:${token.key}`, clientUpdate);
186
226
  },
187
- `tx-run:${token.key}`,
227
+ `tx-run:${token.key}:${socket.id}`,
188
228
  store
189
229
  );
190
- const reconcileUpdates = (optimisticUpdate, confirmedUpdate) => {
191
- Internal3__namespace.setIntoStore(
192
- optimisticUpdateQueueState,
193
- (queue) => {
194
- queue.shift();
195
- return queue;
196
- },
197
- store
198
- );
199
- if (optimisticUpdate.id === confirmedUpdate.id) {
200
- const clientResult = JSON.stringify(optimisticUpdate.updates);
201
- const serverResult = JSON.stringify(confirmedUpdate.updates);
202
- if (clientResult === serverResult) {
230
+ return () => {
231
+ unsubscribeFromLocalUpdates();
232
+ };
233
+ }
234
+ function syncContinuity(continuity, socket, store) {
235
+ const continuityKey = continuity.key;
236
+ const optimisticUpdates = Internal.getFromStore(realtimeClient.optimisticUpdateQueue, store);
237
+ const confirmedUpdates = Internal.getFromStore(realtimeClient.confirmedUpdateQueue, store);
238
+ const initializeContinuity = (epoch, payload) => {
239
+ socket.off(`continuity-init:${continuityKey}`, initializeContinuity);
240
+ let i = 0;
241
+ let k = ``;
242
+ let v = null;
243
+ for (const x of payload) {
244
+ if (i % 2 === 0) {
245
+ k = x;
246
+ } else {
247
+ v = x;
248
+ if (`type` in k && k.type === `mutable_atom`) {
249
+ k = Internal.getJsonToken(k);
250
+ }
251
+ Internal.setIntoStore(k, v, store);
252
+ }
253
+ i++;
254
+ }
255
+ Internal.setEpochNumberOfContinuity(continuityKey, epoch, store);
256
+ };
257
+ socket.off(`continuity-init:${continuityKey}`);
258
+ socket.on(`continuity-init:${continuityKey}`, initializeContinuity);
259
+ const registerAndAttemptConfirmedUpdate = (confirmedUpdate) => {
260
+ function reconcileEpoch(optimisticUpdate, confirmedUpdate2) {
261
+ store.logger.info(
262
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
263
+ `continuity`,
264
+ continuityKey,
265
+ `reconciling updates`
266
+ );
267
+ Internal.setIntoStore(
268
+ realtimeClient.optimisticUpdateQueue,
269
+ (queue) => {
270
+ queue.shift();
271
+ return queue;
272
+ },
273
+ store
274
+ );
275
+ if (optimisticUpdate.id === confirmedUpdate2.id) {
276
+ const clientResult = JSON.stringify(optimisticUpdate.updates);
277
+ const serverResult = JSON.stringify(confirmedUpdate2.updates);
278
+ if (clientResult === serverResult) {
279
+ store.logger.info(
280
+ `\u2705`,
281
+ `continuity`,
282
+ continuityKey,
283
+ `results for ${optimisticUpdate.id} match between client and server`
284
+ );
285
+ socket.emit(`ack:${continuityKey}`, confirmedUpdate2.epoch);
286
+ return;
287
+ }
288
+ } else {
203
289
  store.logger.info(
204
- `\u2705`,
205
- `transaction`,
206
- token.key,
207
- `results for ${optimisticUpdate.id} match between client and server`
290
+ `\u274C`,
291
+ `continuity`,
292
+ continuityKey,
293
+ `thought update #${confirmedUpdate2.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate2.key}:${confirmedUpdate2.id}`
208
294
  );
209
- socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
210
- return;
211
295
  }
212
- } else {
213
296
  store.logger.info(
214
- `\u274C`,
215
- `transaction`,
216
- token.key,
217
- `${store.config.name} thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`
297
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
298
+ `continuity`,
299
+ continuityKey,
300
+ `updates do not match`,
301
+ optimisticUpdate,
302
+ confirmedUpdate2
218
303
  );
219
- }
220
- for (const subsequentOptimistic of optimisticQueue.toReversed()) {
221
- Internal3__namespace.ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
222
- }
223
- Internal3__namespace.ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
224
- Internal3__namespace.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
225
- socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
226
- for (const subsequentOptimistic of optimisticQueue) {
227
- const token2 = Object.assign(
228
- { type: `transaction` },
229
- subsequentOptimistic
304
+ const reversedOptimisticUpdates = optimisticUpdates.toReversed();
305
+ for (const subsequentOptimistic of reversedOptimisticUpdates) {
306
+ Internal.ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
307
+ }
308
+ store.logger.info(
309
+ `\u23EA`,
310
+ `continuity`,
311
+ continuityKey,
312
+ `undid optimistic updates:`,
313
+ reversedOptimisticUpdates
314
+ );
315
+ Internal.ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
316
+ store.logger.info(
317
+ `\u23EA`,
318
+ `continuity`,
319
+ continuityKey,
320
+ `undid zeroth optimistic update`,
321
+ optimisticUpdate
322
+ );
323
+ Internal.ingestTransactionUpdate(`newValue`, confirmedUpdate2, store);
324
+ store.logger.info(
325
+ `\u23E9`,
326
+ `continuity`,
327
+ continuityKey,
328
+ `applied confirmed update`,
329
+ confirmedUpdate2
330
+ );
331
+ socket.emit(`ack:${continuityKey}`, confirmedUpdate2.epoch);
332
+ for (const subsequentOptimistic of optimisticUpdates) {
333
+ const token = {
334
+ type: `transaction`,
335
+ key: subsequentOptimistic.key
336
+ };
337
+ const { id, params } = subsequentOptimistic;
338
+ Internal.actUponStore(token, id, store)(...params);
339
+ }
340
+ store.logger.info(
341
+ `\u23E9`,
342
+ `continuity`,
343
+ continuityKey,
344
+ `reapplied subsequent optimistic updates:`,
345
+ optimisticUpdates
230
346
  );
231
- const { id, params } = subsequentOptimistic;
232
- AtomIO__namespace.runTransaction(token2, id, store)(...params);
233
347
  }
234
- };
235
- const registerAndAttemptConfirmedUpdate = (confirmedUpdate) => {
236
- const zerothOptimisticUpdate = optimisticQueue[0];
348
+ store.logger.info(
349
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
350
+ `continuity`,
351
+ continuityKey,
352
+ `integrating confirmed update`,
353
+ { confirmedUpdate, confirmedUpdates, optimisticUpdates }
354
+ );
355
+ const zerothOptimisticUpdate = optimisticUpdates[0];
237
356
  if (zerothOptimisticUpdate) {
238
- if (zerothOptimisticUpdate.epoch === confirmedUpdate.epoch) {
239
- reconcileUpdates(zerothOptimisticUpdate, confirmedUpdate);
240
- for (const nextConfirmed of confirmedQueue) {
241
- const nextOptimistic = optimisticQueue[0];
242
- if (nextConfirmed.epoch === nextOptimistic.epoch) {
243
- reconcileUpdates(nextOptimistic, nextConfirmed);
357
+ store.logger.info(
358
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
359
+ `continuity`,
360
+ continuityKey,
361
+ `has optimistic updates to reconcile`
362
+ );
363
+ if (confirmedUpdate.epoch === zerothOptimisticUpdate.epoch) {
364
+ store.logger.info(
365
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
366
+ `continuity`,
367
+ continuityKey,
368
+ `epoch of confirmed update #${confirmedUpdate.epoch} matches zeroth optimistic update`
369
+ );
370
+ reconcileEpoch(zerothOptimisticUpdate, confirmedUpdate);
371
+ for (const nextConfirmed of confirmedUpdates) {
372
+ const nextOptimistic = optimisticUpdates[0];
373
+ if (nextConfirmed.epoch === (nextOptimistic == null ? void 0 : nextOptimistic.epoch)) {
374
+ reconcileEpoch(nextOptimistic, nextConfirmed);
244
375
  } else {
245
376
  break;
246
377
  }
247
378
  }
248
379
  } else {
249
- const hasEnqueuedOptimisticUpdate = optimisticQueue.some(
380
+ store.logger.info(
381
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
382
+ `continuity`,
383
+ continuityKey,
384
+ `epoch of confirmed update #${confirmedUpdate.epoch} does not match zeroth optimistic update #${zerothOptimisticUpdate.epoch}`
385
+ );
386
+ const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
250
387
  (update) => update.epoch === confirmedUpdate.epoch
251
388
  );
252
- if (hasEnqueuedOptimisticUpdate) {
253
- Internal3__namespace.setIntoStore(
254
- confirmedUpdateQueueState,
389
+ if (!confirmedUpdateIsAlreadyEnqueued) {
390
+ store.logger.info(
391
+ `\u{1F448}`,
392
+ `continuity`,
393
+ continuityKey,
394
+ `pushing confirmed update to queue`,
395
+ confirmedUpdate
396
+ );
397
+ Internal.setIntoStore(
398
+ realtimeClient.confirmedUpdateQueue,
255
399
  (queue) => {
256
400
  queue.push(confirmedUpdate);
257
401
  queue.sort((a, b) => a.epoch - b.epoch);
@@ -262,58 +406,168 @@ function syncAction(token, socket, store) {
262
406
  }
263
407
  }
264
408
  } else {
265
- if (isRootStore(store) && store.transactionMeta.epoch === confirmedUpdate.epoch - 1) {
266
- Internal3__namespace.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
267
- socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
268
- store.transactionMeta.epoch = confirmedUpdate.epoch;
269
- } else if (isRootStore(store)) {
409
+ store.logger.info(
410
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
411
+ `continuity`,
412
+ continuityKey,
413
+ `has no optimistic updates to deal with`
414
+ );
415
+ const continuityEpoch = Internal.getEpochNumberOfContinuity(continuityKey, store);
416
+ const isRoot = Internal.isRootStore(store);
417
+ if (isRoot && continuityEpoch === confirmedUpdate.epoch - 1) {
270
418
  store.logger.info(
271
- `\u274C`,
272
- `transaction`,
273
- token.key,
274
- `received out-of-order update from server`,
419
+ `\u2705`,
420
+ `continuity`,
421
+ continuityKey,
422
+ `integrating update #${confirmedUpdate.epoch} (${confirmedUpdate.key} ${confirmedUpdate.id})`
423
+ );
424
+ Internal.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
425
+ socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
426
+ Internal.setEpochNumberOfContinuity(continuityKey, confirmedUpdate.epoch, store);
427
+ } else if (isRoot && continuityEpoch !== void 0) {
428
+ store.logger.info(
429
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
430
+ `continuity`,
431
+ continuityKey,
432
+ `received update #${confirmedUpdate.epoch} but still waiting for update #${continuityEpoch + 1}`,
275
433
  {
276
- clientEpoch: store.transactionMeta.epoch,
434
+ clientEpoch: continuityEpoch,
277
435
  serverEpoch: confirmedUpdate.epoch
278
436
  }
279
437
  );
438
+ const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
439
+ (update) => update.epoch === confirmedUpdate.epoch
440
+ );
441
+ if (confirmedUpdateIsAlreadyEnqueued) {
442
+ store.logger.info(
443
+ `\u{1F44D}`,
444
+ `continuity`,
445
+ continuityKey,
446
+ `confirmed update #${confirmedUpdate.epoch} is already enqueued`
447
+ );
448
+ } else {
449
+ store.logger.info(
450
+ `\u{1F448}`,
451
+ `continuity`,
452
+ continuityKey,
453
+ `pushing confirmed update #${confirmedUpdate.epoch} to queue`
454
+ );
455
+ Internal.setIntoStore(
456
+ realtimeClient.confirmedUpdateQueue,
457
+ (queue) => {
458
+ queue.push(confirmedUpdate);
459
+ queue.sort((a, b) => a.epoch - b.epoch);
460
+ return queue;
461
+ },
462
+ store
463
+ );
464
+ }
280
465
  }
281
466
  }
282
467
  };
283
- socket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
284
- socket.on(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
285
- socket.emit(`tx-sub:${token.key}`);
286
- const unsubscribeFromIncomingUpdates = () => {
287
- socket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
288
- socket.emit(`tx-unsub:${token.key}`);
289
- };
290
- return () => {
291
- unsubscribeFromLocalUpdates();
292
- unsubscribeFromIncomingUpdates();
293
- };
294
- }
295
- function syncState(token, socket, store) {
296
- const setServedValue = (data) => {
297
- Internal3.setIntoStore(token, data, store);
298
- };
299
- socket.on(`value:${token.key}`, setServedValue);
300
- socket.emit(`get:${token.key}`);
468
+ socket.off(`tx-new:${continuityKey}`);
469
+ socket.on(`tx-new:${continuityKey}`, registerAndAttemptConfirmedUpdate);
470
+ const unsubscribeFunctions = continuity.actions.map((transaction) => {
471
+ Internal.assignTransactionToContinuity(continuityKey, transaction.key, store);
472
+ const unsubscribeFromTransactionUpdates = Internal.subscribeToTransaction(
473
+ transaction,
474
+ (clientUpdate) => {
475
+ store.logger.info(
476
+ `\u{1F91E}`,
477
+ `continuity`,
478
+ continuityKey,
479
+ `enqueuing optimistic update`
480
+ );
481
+ const optimisticUpdateIndex = optimisticUpdates.findIndex(
482
+ (update) => update.id === clientUpdate.id
483
+ );
484
+ if (optimisticUpdateIndex === -1) {
485
+ store.logger.info(
486
+ `\u{1F91E}`,
487
+ `continuity`,
488
+ continuityKey,
489
+ `enqueuing new optimistic update`
490
+ );
491
+ Internal.setIntoStore(
492
+ realtimeClient.optimisticUpdateQueue,
493
+ (queue) => {
494
+ queue.push(clientUpdate);
495
+ queue.sort((a, b) => a.epoch - b.epoch);
496
+ return queue;
497
+ },
498
+ store
499
+ );
500
+ } else {
501
+ store.logger.info(
502
+ `\u{1F91E}`,
503
+ `continuity`,
504
+ continuityKey,
505
+ `replacing existing optimistic update at index ${optimisticUpdateIndex}`
506
+ );
507
+ Internal.setIntoStore(
508
+ realtimeClient.optimisticUpdateQueue,
509
+ (queue) => {
510
+ queue[optimisticUpdateIndex] = clientUpdate;
511
+ return queue;
512
+ },
513
+ store
514
+ );
515
+ }
516
+ socket.emit(`tx-run:${continuityKey}`, {
517
+ id: clientUpdate.id,
518
+ key: transaction.key,
519
+ params: clientUpdate.params
520
+ });
521
+ },
522
+ `tx-run:${continuityKey}`,
523
+ store
524
+ );
525
+ return unsubscribeFromTransactionUpdates;
526
+ });
527
+ socket.on(`reveal:${continuityKey}`, (revealed) => {
528
+ let i = 0;
529
+ let k = ``;
530
+ let v = null;
531
+ for (const x of revealed) {
532
+ if (i % 2 === 0) {
533
+ k = x;
534
+ } else {
535
+ v = x;
536
+ Internal.setIntoStore(k, v, store);
537
+ }
538
+ i++;
539
+ }
540
+ });
541
+ socket.on(
542
+ `conceal:${continuityKey}`,
543
+ (concealed) => {
544
+ for (const token of concealed) {
545
+ Internal.deleteAtom(token, store);
546
+ }
547
+ }
548
+ );
549
+ socket.emit(`get:${continuityKey}`);
301
550
  return () => {
302
- socket.off(`value:${token.key}`, setServedValue);
551
+ socket.off(`continuity-init:${continuityKey}`);
552
+ socket.off(`tx-new:${continuityKey}`);
553
+ for (const unsubscribe of unsubscribeFunctions)
554
+ unsubscribe();
303
555
  };
304
556
  }
305
557
 
306
- exports.confirmedUpdateQueueState = confirmedUpdateQueueState;
558
+ exports.confirmedUpdateQueue = confirmedUpdateQueue;
307
559
  exports.myIdState = myIdState;
308
560
  exports.myIdState__INTERNAL = myIdState__INTERNAL;
309
- exports.optimisticUpdateQueueState = optimisticUpdateQueueState;
310
- exports.pullFamilyMember = pullFamilyMember;
311
- exports.pullMutableFamilyMember = pullMutableFamilyMember;
312
- exports.pullMutableState = pullMutableState;
313
- exports.pullState = pullState;
561
+ exports.myUsernameState = myUsernameState;
562
+ exports.optimisticUpdateQueue = optimisticUpdateQueue;
563
+ exports.pullAtom = pullAtom;
564
+ exports.pullAtomFamilyMember = pullAtomFamilyMember;
565
+ exports.pullMutableAtom = pullMutableAtom;
566
+ exports.pullMutableAtomFamilyMember = pullMutableAtomFamilyMember;
567
+ exports.pullSelector = pullSelector;
568
+ exports.pullSelectorFamilyMember = pullSelectorFamilyMember;
314
569
  exports.pushState = pushState;
315
570
  exports.serverAction = serverAction;
316
- exports.syncAction = syncAction;
317
- exports.syncState = syncState;
571
+ exports.syncContinuity = syncContinuity;
318
572
  //# sourceMappingURL=out.js.map
319
573
  //# sourceMappingURL=index.cjs.map