atom.io 0.16.2 → 0.16.3

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 (90) hide show
  1. package/dist/chunk-H4Q5FTPZ.js +11 -0
  2. package/dist/chunk-H4Q5FTPZ.js.map +1 -0
  3. package/dist/index.cjs +1 -11
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +6 -6
  6. package/dist/index.js +2 -11
  7. package/dist/index.js.map +1 -1
  8. package/internal/dist/index.cjs +225 -183
  9. package/internal/dist/index.cjs.map +1 -1
  10. package/internal/dist/index.d.ts +30 -9
  11. package/internal/dist/index.js +218 -184
  12. package/internal/dist/index.js.map +1 -1
  13. package/internal/src/families/find-in-store.ts +74 -0
  14. package/internal/src/families/index.ts +1 -0
  15. package/internal/src/ingest-updates/ingest-transaction-update.ts +1 -0
  16. package/internal/src/mutable/tracker.ts +28 -25
  17. package/internal/src/mutable/transceiver.ts +1 -1
  18. package/internal/src/not-found-error.ts +14 -3
  19. package/internal/src/operation.ts +2 -1
  20. package/internal/src/selector/create-writable-selector.ts +2 -1
  21. package/internal/src/selector/register-selector.ts +5 -4
  22. package/internal/src/set-state/set-atom.ts +16 -2
  23. package/internal/src/set-state/stow-update.ts +2 -4
  24. package/internal/src/store/store.ts +13 -4
  25. package/internal/src/timeline/add-atom-to-timeline.ts +5 -5
  26. package/internal/src/transaction/abort-transaction.ts +2 -1
  27. package/internal/src/transaction/apply-transaction.ts +5 -3
  28. package/internal/src/transaction/build-transaction.ts +16 -9
  29. package/internal/src/transaction/create-transaction.ts +2 -3
  30. package/internal/src/transaction/index.ts +3 -2
  31. package/internal/src/transaction/is-root-store.ts +23 -0
  32. package/package.json +10 -10
  33. package/react/dist/index.cjs +27 -21
  34. package/react/dist/index.cjs.map +1 -1
  35. package/react/dist/index.d.ts +8 -2
  36. package/react/dist/index.js +27 -21
  37. package/react/dist/index.js.map +1 -1
  38. package/react/src/index.ts +4 -1
  39. package/react/src/use-i.ts +36 -0
  40. package/react/src/use-json.ts +38 -0
  41. package/react/src/use-o.ts +34 -0
  42. package/react/src/use-tl.ts +45 -0
  43. package/realtime-client/dist/index.cjs +163 -63
  44. package/realtime-client/dist/index.cjs.map +1 -1
  45. package/realtime-client/dist/index.d.ts +10 -6
  46. package/realtime-client/dist/index.js +153 -61
  47. package/realtime-client/dist/index.js.map +1 -1
  48. package/realtime-client/src/index.ts +2 -1
  49. package/realtime-client/src/pull-state.ts +4 -3
  50. package/realtime-client/src/{realtime-client-store.ts → realtime-client-stores/client-main-store.ts} +0 -8
  51. package/realtime-client/src/realtime-client-stores/client-sync-store.ts +15 -0
  52. package/realtime-client/src/realtime-client-stores/index.ts +2 -0
  53. package/realtime-client/src/sync-server-action.ts +131 -40
  54. package/realtime-client/src/sync-state.ts +19 -0
  55. package/realtime-react/dist/index.cjs +43 -26
  56. package/realtime-react/dist/index.cjs.map +1 -1
  57. package/realtime-react/dist/index.d.ts +3 -1
  58. package/realtime-react/dist/index.js +41 -25
  59. package/realtime-react/dist/index.js.map +1 -1
  60. package/realtime-react/src/index.ts +1 -0
  61. package/realtime-react/src/on-mount.ts +3 -21
  62. package/realtime-react/src/use-realtime-service.ts +1 -1
  63. package/realtime-react/src/use-single-effect.ts +29 -0
  64. package/realtime-react/src/use-sync-server-action.ts +4 -7
  65. package/realtime-react/src/use-sync.ts +17 -0
  66. package/realtime-server/dist/index.cjs +223 -40
  67. package/realtime-server/dist/index.cjs.map +1 -1
  68. package/realtime-server/dist/index.d.ts +140 -9
  69. package/realtime-server/dist/index.js +213 -43
  70. package/realtime-server/dist/index.js.map +1 -1
  71. package/realtime-server/src/index.ts +2 -0
  72. package/realtime-server/src/realtime-action-synchronizer.ts +87 -12
  73. package/realtime-server/src/realtime-family-provider.ts +2 -2
  74. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -1
  75. package/realtime-server/src/realtime-server-stores/index.ts +2 -0
  76. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +115 -0
  77. package/realtime-server/src/realtime-server-stores/server-user-store.ts +45 -0
  78. package/realtime-server/src/realtime-state-provider.ts +15 -8
  79. package/realtime-server/src/realtime-state-synchronizer.ts +23 -0
  80. package/realtime-testing/dist/index.cjs +65 -26
  81. package/realtime-testing/dist/index.cjs.map +1 -1
  82. package/realtime-testing/dist/index.d.ts +11 -7
  83. package/realtime-testing/dist/index.js +64 -26
  84. package/realtime-testing/dist/index.js.map +1 -1
  85. package/realtime-testing/src/setup-realtime-test.tsx +83 -43
  86. package/src/find-state.ts +8 -16
  87. package/src/logger.ts +1 -0
  88. package/src/transaction.ts +3 -3
  89. package/react/src/store-hooks.ts +0 -87
  90. package/realtime-server/src/realtime-server-store.ts +0 -39
@@ -1,33 +1,164 @@
1
1
  import { Transceiver, Store } from 'atom.io/internal';
2
2
  import * as SocketIO from 'socket.io';
3
- import * as AtomIO from 'atom.io';
4
- import { WritableToken } from 'atom.io';
3
+ import * as atom_io_data from 'atom.io/data';
4
+ import * as atom_io from 'atom.io';
5
+ import { TransactionUpdate, TransactionUpdateContent, WritableToken } from 'atom.io';
6
+ import * as atom_io_transceivers_set_rtx from 'atom.io/transceivers/set-rtx';
7
+ import { SetRTX } from 'atom.io/transceivers/set-rtx';
5
8
  import { Json } from 'atom.io/json';
6
9
 
10
+ type primitive = boolean | number | string | null;
11
+
12
+ type Serializable = primitive | Readonly<{
13
+ [key: string]: Serializable;
14
+ }> | ReadonlyArray<Serializable>;
15
+ type Object$1<Key extends string = string, Value extends Serializable = Serializable> = Record<Key, Value>;
16
+
17
+ type Refinement<Unrefined, Refined extends Unrefined> = (value: Unrefined) => value is Refined;
18
+ type Cardinality = `1:1` | `1:n` | `n:n`;
19
+
20
+ interface JunctionEntries<Content extends Object$1 | null> extends Object$1 {
21
+ readonly relations: [string, string[]][];
22
+ readonly contents: [string, Content][];
23
+ }
24
+ interface JunctionSchema<ASide extends string, BSide extends string> extends Object$1 {
25
+ readonly between: [a: ASide, b: BSide];
26
+ readonly cardinality: Cardinality;
27
+ }
28
+ type BaseExternalStoreConfiguration = {
29
+ addRelation: (a: string, b: string) => void;
30
+ deleteRelation: (a: string, b: string) => void;
31
+ replaceRelationsSafely: (a: string, bs: string[]) => void;
32
+ replaceRelationsUnsafely: (a: string, bs: string[]) => void;
33
+ getRelatedKeys: (key: string) => Set<string> | undefined;
34
+ has: (a: string, b?: string) => boolean;
35
+ };
36
+ type ExternalStoreWithContentConfiguration<Content extends Object$1> = {
37
+ getContent: (contentKey: string) => Content | undefined;
38
+ setContent: (contentKey: string, content: Content) => void;
39
+ deleteContent: (contentKey: string) => void;
40
+ };
41
+ type Empty<Obj extends object> = {
42
+ [Key in keyof Obj]?: undefined;
43
+ };
44
+ type ExternalStoreConfiguration<Content extends Object$1 | null> = Content extends Object$1 ? BaseExternalStoreConfiguration & ExternalStoreWithContentConfiguration<Content> : BaseExternalStoreConfiguration & Empty<ExternalStoreWithContentConfiguration<Object$1>>;
45
+ type JunctionAdvancedConfiguration<Content extends Object$1 | null> = {
46
+ externalStore?: ExternalStoreConfiguration<Content>;
47
+ isContent?: Refinement<unknown, Content>;
48
+ makeContentKey?: (a: string, b: string) => string;
49
+ };
50
+ type JunctionJSON<ASide extends string, BSide extends string, Content extends Object$1 | null> = JunctionEntries<Content> & JunctionSchema<ASide, BSide>;
51
+ declare class Junction<const ASide extends string, const BSide extends string, const Content extends Object$1 | null = null> {
52
+ readonly a: ASide;
53
+ readonly b: BSide;
54
+ readonly cardinality: Cardinality;
55
+ readonly relations: Map<string, Set<string>>;
56
+ readonly contents: Map<string, Content>;
57
+ isContent: Refinement<unknown, Content> | null;
58
+ makeContentKey: (a: string, b: string) => string;
59
+ getRelatedKeys(key: string): Set<string> | undefined;
60
+ protected addRelation(a: string, b: string): void;
61
+ protected deleteRelation(a: string, b: string): void;
62
+ protected replaceRelationsUnsafely(a: string, bs: string[]): void;
63
+ protected replaceRelationsSafely(a: string, bs: string[]): void;
64
+ protected getContentInternal(contentKey: string): Content | undefined;
65
+ protected setContent(contentKey: string, content: Content): void;
66
+ protected deleteContent(contentKey: string): void;
67
+ constructor(data: JunctionSchema<ASide, BSide> & Partial<JunctionEntries<Content>>, config?: JunctionAdvancedConfiguration<Content>);
68
+ toJSON(): JunctionJSON<ASide, BSide, Content>;
69
+ set(a: string, ...rest: Content extends null ? [b: string] : [b: string, content: Content]): this;
70
+ set(relation: {
71
+ [Key in ASide | BSide]: string;
72
+ }, ...rest: Content extends null ? [] | [b?: undefined] : [content: Content]): this;
73
+ delete(a: string, b?: string): this;
74
+ delete(relation: Record<ASide | BSide, string> | Record<ASide, string> | Record<BSide, string>, b?: undefined): this;
75
+ getRelatedKey(key: string): string | undefined;
76
+ replaceRelations(a: string, relations: Content extends null ? string[] : Record<string, Content>, config?: {
77
+ reckless: boolean;
78
+ }): this;
79
+ getContent(a: string, b: string): Content | undefined;
80
+ getRelationEntries(input: Record<ASide, string> | Record<BSide, string>): [string, Content][];
81
+ has(a: string, b?: string): boolean;
82
+ }
83
+
84
+ declare const userIndex: atom_io.MutableAtomToken<SetRTX<string>, atom_io_transceivers_set_rtx.SetRTXJson<string>>;
85
+ declare const usersOfSockets: {
86
+ readonly relations: Junction<"user", "socket", null>;
87
+ readonly states: {
88
+ readonly userKeyOfSocket: atom_io.ReadonlySelectorFamily<string | null, string>;
89
+ readonly socketKeyOfUser: atom_io.ReadonlySelectorFamily<string | null, string>;
90
+ };
91
+ readonly transact: (transactors: Readonly<{
92
+ get: <S>(state: atom_io.ReadonlySelectorToken<S> | atom_io.WritableToken<S>) => S;
93
+ set: <S_1, New extends S_1>(state: atom_io.WritableToken<S_1>, newValue: New | ((oldValue: S_1) => New)) => void;
94
+ find: typeof atom_io.findState;
95
+ }>, run: (join: atom_io_data.Join<"user", "socket", "1:1", null>) => void) => void;
96
+ readonly core: {
97
+ readonly findRelatedKeysState: atom_io.MutableAtomFamily<SetRTX<string>, atom_io_transceivers_set_rtx.SetRTXJson<string>, string>;
98
+ };
99
+ };
100
+ declare const roomIndex: atom_io.MutableAtomToken<SetRTX<string>, atom_io_transceivers_set_rtx.SetRTXJson<string>>;
101
+ type UserInRoomMeta = {
102
+ enteredAtEpoch: number;
103
+ };
104
+ declare const DEFAULT_USER_IN_ROOM_META: UserInRoomMeta;
105
+ declare const usersInRooms: {
106
+ readonly relations: Junction<"room", "user", UserInRoomMeta>;
107
+ readonly states: {
108
+ readonly roomEntryOfUser: atom_io.ReadonlySelectorFamily<[string, UserInRoomMeta] | null, string>;
109
+ } & {
110
+ readonly userEntriesOfRoom: atom_io.ReadonlySelectorFamily<[string, UserInRoomMeta][], string>;
111
+ } & {
112
+ readonly roomKeyOfUser: atom_io.ReadonlySelectorFamily<string | null, string>;
113
+ } & {
114
+ readonly userKeysOfRoom: atom_io.ReadonlySelectorFamily<string[], string>;
115
+ };
116
+ readonly transact: (transactors: Readonly<{
117
+ get: <S>(state: atom_io.ReadonlySelectorToken<S> | atom_io.WritableToken<S>) => S;
118
+ set: <S_1, New extends S_1>(state: atom_io.WritableToken<S_1>, newValue: New | ((oldValue: S_1) => New)) => void;
119
+ find: typeof atom_io.findState;
120
+ }>, run: (join: atom_io_data.Join<"room", "user", "1:n", UserInRoomMeta>) => void) => void;
121
+ readonly core: {
122
+ readonly findRelatedKeysState: atom_io.MutableAtomFamily<SetRTX<string>, atom_io_transceivers_set_rtx.SetRTXJson<string>, string>;
123
+ };
124
+ };
125
+
126
+ declare const completeUpdateAtoms: atom_io.RegularAtomFamily<TransactionUpdate<any> | null, string>;
127
+ declare const transactionRedactorAtoms: atom_io.RegularAtomFamily<{
128
+ filter: (updates: TransactionUpdateContent[]) => TransactionUpdateContent[];
129
+ }, string>;
130
+ declare const redactedUpdateSelectors: atom_io.ReadonlySelectorFamily<TransactionUpdate<any> | null, [transactionKey: string, updateId: string]>;
131
+ declare const userUnacknowledgedUpdatesAtoms: atom_io.RegularAtomFamily<TransactionUpdate<any>[], string>;
132
+ declare const socketUnacknowledgedUpdatesSelectors: atom_io.WritableSelectorFamily<TransactionUpdate<any>[], string>;
133
+ declare const userEpochAtoms: atom_io.RegularAtomFamily<number | null, string>;
134
+ declare const socketEpochSelectors: atom_io.WritableSelectorFamily<number | null, string>;
135
+
7
136
  type StateProvider = ReturnType<typeof realtimeStateProvider>;
8
- declare function realtimeStateProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: AtomIO.WritableToken<J>) => () => void;
137
+ declare function realtimeStateProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: atom_io.WritableToken<J>) => () => void;
138
+
139
+ declare function realtimeStateSynchronizer({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: atom_io.WritableToken<J>) => () => void;
9
140
 
10
141
  type FamilyProvider = ReturnType<typeof realtimeFamilyProvider>;
11
- declare function realtimeFamilyProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable, K extends Json.Serializable>(family: AtomIO.RegularAtomFamily<J, K>, index: AtomIO.ReadableToken<Iterable<K>>) => () => void;
142
+ declare function realtimeFamilyProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable, K extends Json.Serializable>(family: atom_io.RegularAtomFamily<J, K>, index: atom_io.ReadableToken<Iterable<K>>) => () => void;
12
143
 
13
144
  type MutableProvider = ReturnType<typeof realtimeMutableProvider>;
14
- declare function realtimeMutableProvider({ socket, store, }: ServerConfig): <Core extends Transceiver<Json.Serializable>, SerializableCore extends Json.Serializable>(token: AtomIO.MutableAtomToken<Core, SerializableCore>) => () => void;
145
+ declare function realtimeMutableProvider({ socket, store, }: ServerConfig): <Core extends Transceiver<Json.Serializable>, SerializableCore extends Json.Serializable>(token: atom_io.MutableAtomToken<Core, SerializableCore>) => () => void;
15
146
 
16
147
  type MutableFamilyProvider = ReturnType<typeof realtimeMutableFamilyProvider>;
17
- declare function realtimeMutableFamilyProvider({ socket, store, }: ServerConfig): <T extends Transceiver<any>, J extends Json.Serializable, K extends Json.Serializable>(family: AtomIO.MutableAtomFamily<T, J, K>, index: AtomIO.ReadableToken<Iterable<K>>) => () => void;
148
+ declare function realtimeMutableFamilyProvider({ socket, store, }: ServerConfig): <T extends Transceiver<any>, J extends Json.Serializable, K extends Json.Serializable>(family: atom_io.MutableAtomFamily<T, J, K>, index: atom_io.ReadableToken<Iterable<K>>) => () => void;
18
149
 
19
150
  type StateReceiver = ReturnType<typeof realtimeStateReceiver>;
20
151
  declare function realtimeStateReceiver({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: WritableToken<J>) => () => void;
21
152
 
22
153
  type ActionReceiver = ReturnType<typeof realtimeActionReceiver>;
23
- declare function realtimeActionReceiver({ socket, store, }: ServerConfig): <ƒ extends AtomIO.ƒn>(tx: AtomIO.TransactionToken<ƒ>) => () => void;
154
+ declare function realtimeActionReceiver({ socket, store, }: ServerConfig): <ƒ extends atom_io.ƒn>(tx: atom_io.TransactionToken<ƒ>) => () => void;
24
155
 
25
156
  type ActionSynchronizer = ReturnType<typeof realtimeActionSynchronizer>;
26
- declare function realtimeActionSynchronizer({ socket, store, }: ServerConfig): <ƒ extends AtomIO.ƒn>(tx: AtomIO.TransactionToken<ƒ>, filter?: ((update: AtomIO.TransactionUpdateContent[]) => AtomIO.TransactionUpdateContent[]) | undefined) => () => void;
157
+ declare function realtimeActionSynchronizer({ socket, store, }: ServerConfig): <ƒ extends atom_io.ƒn>(tx: atom_io.TransactionToken<ƒ>, filter?: ((update: atom_io.TransactionUpdateContent[]) => atom_io.TransactionUpdateContent[]) | undefined) => () => void;
27
158
 
28
159
  type ServerConfig = {
29
160
  socket: SocketIO.Socket;
30
161
  store?: Store;
31
162
  };
32
163
 
33
- export { type ActionReceiver, type ActionSynchronizer, type FamilyProvider, type MutableFamilyProvider, type MutableProvider, type ServerConfig, type StateProvider, type StateReceiver, realtimeActionReceiver, realtimeActionSynchronizer, realtimeFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver };
164
+ export { type ActionReceiver, type ActionSynchronizer, DEFAULT_USER_IN_ROOM_META, type FamilyProvider, type MutableFamilyProvider, type MutableProvider, type ServerConfig, type StateProvider, type StateReceiver, type UserInRoomMeta, completeUpdateAtoms, realtimeActionReceiver, realtimeActionSynchronizer, realtimeFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, realtimeStateSynchronizer, redactedUpdateSelectors, roomIndex, socketEpochSelectors, socketUnacknowledgedUpdatesSelectors, transactionRedactorAtoms, userEpochAtoms, userIndex, userUnacknowledgedUpdatesAtoms, usersInRooms, usersOfSockets };
@@ -1,20 +1,124 @@
1
1
  import { __spreadProps, __spreadValues } from '../../dist/chunk-PZLG2HP3.js';
2
2
  import * as AtomIO7 from 'atom.io';
3
- import { setState } from 'atom.io';
4
- import { IMPLICIT, getJsonToken, getUpdateToken, subscribeToState, subscribeToTransaction } from 'atom.io/internal';
3
+ import { atom, atomFamily, selectorFamily, setState } from 'atom.io';
4
+ import { join } from 'atom.io/data';
5
+ import { SetRTX } from 'atom.io/transceivers/set-rtx';
6
+ import { IMPLICIT, getJsonToken, getUpdateToken, findInStore, subscribeToState, subscribeToTransaction } from 'atom.io/internal';
5
7
  import { parseJson } from 'atom.io/json';
6
8
 
9
+ var userIndex = atom({
10
+ key: `usersIndex`,
11
+ mutable: true,
12
+ default: () => new SetRTX(),
13
+ toJson: (set) => set.toJSON(),
14
+ fromJson: (json) => SetRTX.fromJSON(json)
15
+ });
16
+ var usersOfSockets = join({
17
+ key: `usersOfSockets`,
18
+ between: [`user`, `socket`],
19
+ cardinality: `1:1`
20
+ });
21
+ var roomIndex = atom({
22
+ key: `conclaveIndex`,
23
+ default: () => new SetRTX(),
24
+ mutable: true,
25
+ toJson: (set) => set.toJSON(),
26
+ fromJson: (json) => SetRTX.fromJSON(json)
27
+ });
28
+ var DEFAULT_USER_IN_ROOM_META = {
29
+ enteredAtEpoch: 0
30
+ };
31
+ var usersInRooms = join(
32
+ {
33
+ key: `usersInRooms`,
34
+ between: [`room`, `user`],
35
+ cardinality: `1:n`
36
+ },
37
+ DEFAULT_USER_IN_ROOM_META
38
+ );
39
+ var completeUpdateAtoms = atomFamily({
40
+ key: `completeUpdate`,
41
+ default: null
42
+ });
43
+ var transactionRedactorAtoms = atomFamily({
44
+ key: `transactionRedactor`,
45
+ default: { filter: (updates) => updates }
46
+ });
47
+ var redactedUpdateSelectors = selectorFamily({
48
+ key: `redactedUpdate`,
49
+ get: ([transactionKey, updateId]) => ({ get, find }) => {
50
+ const update = get(find(completeUpdateAtoms, updateId));
51
+ const { filter } = get(find(transactionRedactorAtoms, transactionKey));
52
+ if (update && filter) {
53
+ return __spreadProps(__spreadValues({}, update), { updates: filter(update.updates) });
54
+ }
55
+ return null;
56
+ }
57
+ });
58
+ var userUnacknowledgedUpdatesAtoms = atomFamily({
59
+ key: `unacknowledgedUpdates`,
60
+ default: () => []
61
+ });
62
+ var socketUnacknowledgedUpdatesSelectors = selectorFamily({
63
+ key: `socketUnacknowledgedUpdates`,
64
+ get: (socketId) => ({ get, find }) => {
65
+ const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
66
+ const userKey = get(userKeyState);
67
+ if (!userKey) {
68
+ return [];
69
+ }
70
+ const unacknowledgedUpdatesState = find(
71
+ userUnacknowledgedUpdatesAtoms,
72
+ userKey
73
+ );
74
+ const unacknowledgedUpdates = get(unacknowledgedUpdatesState);
75
+ return unacknowledgedUpdates;
76
+ },
77
+ set: (socketId) => ({ set, get, find }, newUpdates) => {
78
+ const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
79
+ const userKey = get(userKeyState);
80
+ if (!userKey) {
81
+ return;
82
+ }
83
+ const unacknowledgedUpdatesState = find(
84
+ userUnacknowledgedUpdatesAtoms,
85
+ userKey
86
+ );
87
+ set(unacknowledgedUpdatesState, newUpdates);
88
+ }
89
+ });
90
+ var userEpochAtoms = atomFamily({
91
+ key: `clientEpoch`,
92
+ default: null
93
+ });
94
+ var socketEpochSelectors = selectorFamily({
95
+ key: `socketEpoch`,
96
+ get: (socketId) => ({ get, find }) => {
97
+ const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
98
+ const userKey = get(userKeyState);
99
+ if (!userKey) {
100
+ return null;
101
+ }
102
+ const userEpochState = find(userEpochAtoms, userKey);
103
+ const userEpoch = get(userEpochState);
104
+ return userEpoch;
105
+ },
106
+ set: (socketId) => ({ set, get, find }, newEpoch) => {
107
+ const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
108
+ const userKey = get(userKeyState);
109
+ if (!userKey) {
110
+ return;
111
+ }
112
+ const userEpochState = find(userEpochAtoms, userKey);
113
+ set(userEpochState, newEpoch);
114
+ }
115
+ });
7
116
  function realtimeStateProvider({
8
117
  socket,
9
118
  store = IMPLICIT.STORE
10
119
  }) {
11
120
  return function stateProvider(token) {
12
- let unsubscribeFromStateUpdates = null;
13
- const fillUnsubRequest = () => {
14
- socket.off(`unsub:${token.key}`, fillUnsubRequest);
15
- unsubscribeFromStateUpdates == null ? void 0 : unsubscribeFromStateUpdates();
16
- unsubscribeFromStateUpdates = null;
17
- };
121
+ let unsubscribeFromStateUpdates;
18
122
  const fillSubRequest = () => {
19
123
  socket.emit(`serve:${token.key}`, AtomIO7.getState(token, store));
20
124
  unsubscribeFromStateUpdates = subscribeToState(
@@ -25,12 +129,36 @@ function realtimeStateProvider({
25
129
  `expose-single:${socket.id}`,
26
130
  store
27
131
  );
132
+ const fillUnsubRequest = () => {
133
+ socket.off(`unsub:${token.key}`, fillUnsubRequest);
134
+ if (unsubscribeFromStateUpdates) {
135
+ unsubscribeFromStateUpdates();
136
+ unsubscribeFromStateUpdates = void 0;
137
+ }
138
+ };
28
139
  socket.on(`unsub:${token.key}`, fillUnsubRequest);
29
140
  };
30
141
  socket.on(`sub:${token.key}`, fillSubRequest);
31
142
  return () => {
32
143
  socket.off(`sub:${token.key}`, fillSubRequest);
33
- unsubscribeFromStateUpdates == null ? void 0 : unsubscribeFromStateUpdates();
144
+ if (unsubscribeFromStateUpdates) {
145
+ unsubscribeFromStateUpdates();
146
+ unsubscribeFromStateUpdates = void 0;
147
+ }
148
+ };
149
+ };
150
+ }
151
+ function realtimeStateSynchronizer({
152
+ socket,
153
+ store = IMPLICIT.STORE
154
+ }) {
155
+ return function stateSynchronizer(token) {
156
+ const fillGetRequest = () => {
157
+ socket.emit(`value:${token.key}`, AtomIO7.getState(token, store));
158
+ };
159
+ socket.on(`get:${token.key}`, fillGetRequest);
160
+ return () => {
161
+ socket.off(`get:${token.key}`, fillGetRequest);
34
162
  };
35
163
  };
36
164
  }
@@ -61,7 +189,7 @@ function realtimeFamilyProvider({
61
189
  if (subKey === void 0) {
62
190
  const keys = AtomIO7.getState(index, store);
63
191
  for (const key of keys) {
64
- const token = AtomIO7.findInStore(family, key, store);
192
+ const token = findInStore(family, key, store);
65
193
  socket.emit(
66
194
  `serve:${family.key}`,
67
195
  parseJson(((_a = token.family) == null ? void 0 : _a.subKey) || `null`),
@@ -179,7 +307,7 @@ function realtimeMutableFamilyProvider({
179
307
  if (subKey === void 0) {
180
308
  const keys = AtomIO7.getState(index, store);
181
309
  for (const key of keys) {
182
- const token = family(key);
310
+ const token = findInStore(family, key, store);
183
311
  const jsonToken = getJsonToken(token);
184
312
  const trackerToken = getUpdateToken(token);
185
313
  socket.emit(
@@ -308,38 +436,29 @@ function realtimeActionReceiver({
308
436
  return () => socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
309
437
  };
310
438
  }
311
- var completeUpdateAtoms = AtomIO7.atomFamily({
312
- key: `completeUpdate`,
313
- default: null
314
- });
315
- var transactionRedactorAtoms = AtomIO7.atomFamily({
316
- key: `transactionRedactor`,
317
- default: { filter: (updates) => updates }
318
- });
319
- var redactedUpdateSelectors = AtomIO7.selectorFamily({
320
- key: `redactedUpdate`,
321
- get: ([transactionKey, updateId]) => ({ get, find }) => {
322
- const update = get(find(completeUpdateAtoms, updateId));
323
- const { filter } = get(find(transactionRedactorAtoms, transactionKey));
324
- if (update && filter) {
325
- return __spreadProps(__spreadValues({}, update), { updates: filter(update.updates) });
326
- }
327
- return null;
328
- }
329
- });
330
-
331
- // realtime-server/src/realtime-action-synchronizer.ts
332
439
  function realtimeActionSynchronizer({
333
440
  socket,
334
441
  store = IMPLICIT.STORE
335
442
  }) {
336
443
  return function actionSynchronizer(tx, filter) {
444
+ const userKeyState = findInStore(
445
+ usersOfSockets.states.userKeyOfSocket,
446
+ socket.id,
447
+ store
448
+ );
449
+ const userKey = AtomIO7.getState(userKeyState, store);
450
+ const socketUnacknowledgedUpdatesState = findInStore(
451
+ socketUnacknowledgedUpdatesSelectors,
452
+ socket.id,
453
+ store
454
+ );
455
+ const socketUnacknowledgedUpdates = AtomIO7.getState(
456
+ socketUnacknowledgedUpdatesState,
457
+ store
458
+ );
337
459
  if (filter) {
338
- AtomIO7.setState(
339
- AtomIO7.findState(transactionRedactorAtoms, tx.key),
340
- { filter },
341
- store
342
- );
460
+ const redactorState = findInStore(transactionRedactorAtoms, tx.key, store);
461
+ AtomIO7.setState(redactorState, { filter }, store);
343
462
  }
344
463
  const fillTransactionRequest = (update) => {
345
464
  const performanceKey = `tx-run:${tx.key}:${update.id}`;
@@ -355,32 +474,83 @@ function realtimeActionSynchronizer({
355
474
  );
356
475
  store == null ? void 0 : store.logger.info(`\u{1F680}`, `transaction`, tx.key, update.id, metric.duration);
357
476
  };
477
+ socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
358
478
  socket.on(`tx-run:${tx.key}`, fillTransactionRequest);
479
+ let unsubscribeFromTransaction;
359
480
  const fillTransactionSubscriptionRequest = () => {
360
- const unsubscribe = subscribeToTransaction(
481
+ unsubscribeFromTransaction = subscribeToTransaction(
361
482
  tx,
362
483
  (update) => {
363
- unsubscribe();
364
- const updateState = AtomIO7.findState(completeUpdateAtoms, update.id);
484
+ const updateState = findInStore(completeUpdateAtoms, update.id, store);
365
485
  AtomIO7.setState(updateState, update, store);
366
486
  const toEmit = filter ? AtomIO7.getState(
367
- AtomIO7.findState(redactedUpdateSelectors, [tx.key, update.id]),
487
+ findInStore(redactedUpdateSelectors, [tx.key, update.id], store),
368
488
  store
369
489
  ) : update;
490
+ AtomIO7.setState(
491
+ socketUnacknowledgedUpdatesState,
492
+ (updates) => {
493
+ if (toEmit) {
494
+ updates.push(toEmit);
495
+ updates.sort((a, b) => a.epoch - b.epoch);
496
+ }
497
+ return updates;
498
+ },
499
+ store
500
+ );
370
501
  socket.emit(`tx-new:${tx.key}`, toEmit);
371
502
  },
372
503
  `tx-sub:${tx.key}:${socket.id}`,
373
504
  store
374
505
  );
375
- socket.on(`tx-unsub:${tx.key}`, unsubscribe);
506
+ socket.on(`tx-unsub:${tx.key}`, unsubscribeFromTransaction);
376
507
  };
377
508
  socket.on(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
509
+ let i = 1;
510
+ let next = 1;
511
+ const retry = setInterval(() => {
512
+ const toEmit = socketUnacknowledgedUpdates[0];
513
+ console.log(userKey, socketUnacknowledgedUpdates);
514
+ if (toEmit && i === next) {
515
+ socket.emit(`tx-new:${tx.key}`, toEmit);
516
+ next *= 2;
517
+ }
518
+ i++;
519
+ }, 250);
520
+ const trackClientAcknowledgement = (epoch) => {
521
+ var _a;
522
+ i = 1;
523
+ next = 1;
524
+ const socketEpochState = findInStore(
525
+ socketEpochSelectors,
526
+ socket.id,
527
+ store
528
+ );
529
+ AtomIO7.setState(socketEpochState, epoch, store);
530
+ if (((_a = socketUnacknowledgedUpdates[0]) == null ? void 0 : _a.epoch) === epoch) {
531
+ AtomIO7.setState(
532
+ socketUnacknowledgedUpdatesState,
533
+ (updates) => {
534
+ updates.shift();
535
+ return updates;
536
+ },
537
+ store
538
+ );
539
+ }
540
+ };
541
+ socket.on(`tx-ack:${tx.key}`, trackClientAcknowledgement);
378
542
  return () => {
543
+ if (unsubscribeFromTransaction) {
544
+ unsubscribeFromTransaction();
545
+ unsubscribeFromTransaction = void 0;
546
+ }
547
+ clearInterval(retry);
379
548
  socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
549
+ socket.off(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
380
550
  };
381
551
  };
382
552
  }
383
553
 
384
- export { realtimeActionReceiver, realtimeActionSynchronizer, realtimeFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver };
554
+ export { DEFAULT_USER_IN_ROOM_META, completeUpdateAtoms, realtimeActionReceiver, realtimeActionSynchronizer, realtimeFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, realtimeStateSynchronizer, redactedUpdateSelectors, roomIndex, socketEpochSelectors, socketUnacknowledgedUpdatesSelectors, transactionRedactorAtoms, userEpochAtoms, userIndex, userUnacknowledgedUpdatesAtoms, usersInRooms, usersOfSockets };
385
555
  //# sourceMappingURL=out.js.map
386
556
  //# sourceMappingURL=index.js.map