atom.io 0.16.1 → 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 (99) hide show
  1. package/data/dist/index.cjs +31 -14
  2. package/data/dist/index.cjs.map +1 -1
  3. package/data/dist/index.js +31 -14
  4. package/data/dist/index.js.map +1 -1
  5. package/data/src/join.ts +31 -14
  6. package/dist/chunk-H4Q5FTPZ.js +11 -0
  7. package/dist/chunk-H4Q5FTPZ.js.map +1 -0
  8. package/dist/index.cjs +7 -14
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.ts +8 -7
  11. package/dist/index.js +8 -14
  12. package/dist/index.js.map +1 -1
  13. package/internal/dist/index.cjs +240 -193
  14. package/internal/dist/index.cjs.map +1 -1
  15. package/internal/dist/index.d.ts +30 -9
  16. package/internal/dist/index.js +233 -194
  17. package/internal/dist/index.js.map +1 -1
  18. package/internal/src/families/find-in-store.ts +74 -0
  19. package/internal/src/families/index.ts +1 -0
  20. package/internal/src/ingest-updates/ingest-transaction-update.ts +1 -0
  21. package/internal/src/mutable/tracker.ts +37 -32
  22. package/internal/src/mutable/transceiver.ts +1 -1
  23. package/internal/src/not-found-error.ts +14 -3
  24. package/internal/src/operation.ts +2 -1
  25. package/internal/src/selector/create-writable-selector.ts +2 -1
  26. package/internal/src/selector/register-selector.ts +5 -4
  27. package/internal/src/set-state/set-atom.ts +23 -6
  28. package/internal/src/set-state/stow-update.ts +2 -4
  29. package/internal/src/store/store.ts +13 -4
  30. package/internal/src/timeline/add-atom-to-timeline.ts +5 -5
  31. package/internal/src/transaction/abort-transaction.ts +2 -1
  32. package/internal/src/transaction/apply-transaction.ts +5 -3
  33. package/internal/src/transaction/build-transaction.ts +17 -10
  34. package/internal/src/transaction/create-transaction.ts +2 -3
  35. package/internal/src/transaction/index.ts +3 -2
  36. package/internal/src/transaction/is-root-store.ts +23 -0
  37. package/package.json +10 -10
  38. package/react/dist/index.cjs +27 -21
  39. package/react/dist/index.cjs.map +1 -1
  40. package/react/dist/index.d.ts +8 -2
  41. package/react/dist/index.js +27 -21
  42. package/react/dist/index.js.map +1 -1
  43. package/react/src/index.ts +4 -1
  44. package/react/src/use-i.ts +36 -0
  45. package/react/src/use-json.ts +38 -0
  46. package/react/src/use-o.ts +34 -0
  47. package/react/src/use-tl.ts +45 -0
  48. package/realtime-client/dist/index.cjs +163 -62
  49. package/realtime-client/dist/index.cjs.map +1 -1
  50. package/realtime-client/dist/index.d.ts +10 -6
  51. package/realtime-client/dist/index.js +153 -60
  52. package/realtime-client/dist/index.js.map +1 -1
  53. package/realtime-client/src/index.ts +2 -1
  54. package/realtime-client/src/pull-state.ts +4 -3
  55. package/realtime-client/src/{realtime-client-store.ts → realtime-client-stores/client-main-store.ts} +0 -8
  56. package/realtime-client/src/realtime-client-stores/client-sync-store.ts +15 -0
  57. package/realtime-client/src/realtime-client-stores/index.ts +2 -0
  58. package/realtime-client/src/sync-server-action.ts +131 -39
  59. package/realtime-client/src/sync-state.ts +19 -0
  60. package/realtime-react/dist/index.cjs +43 -26
  61. package/realtime-react/dist/index.cjs.map +1 -1
  62. package/realtime-react/dist/index.d.ts +3 -1
  63. package/realtime-react/dist/index.js +41 -25
  64. package/realtime-react/dist/index.js.map +1 -1
  65. package/realtime-react/src/index.ts +1 -0
  66. package/realtime-react/src/on-mount.ts +3 -21
  67. package/realtime-react/src/use-realtime-service.ts +1 -1
  68. package/realtime-react/src/use-server-action.ts +1 -1
  69. package/realtime-react/src/use-single-effect.ts +29 -0
  70. package/realtime-react/src/use-sync-server-action.ts +5 -8
  71. package/realtime-react/src/use-sync.ts +17 -0
  72. package/realtime-server/dist/index.cjs +242 -48
  73. package/realtime-server/dist/index.cjs.map +1 -1
  74. package/realtime-server/dist/index.d.ts +147 -9
  75. package/realtime-server/dist/index.js +232 -51
  76. package/realtime-server/dist/index.js.map +1 -1
  77. package/realtime-server/src/index.ts +2 -0
  78. package/realtime-server/src/realtime-action-receiver.ts +4 -3
  79. package/realtime-server/src/realtime-action-synchronizer.ts +100 -13
  80. package/realtime-server/src/realtime-family-provider.ts +10 -6
  81. package/realtime-server/src/realtime-mutable-family-provider.ts +15 -18
  82. package/realtime-server/src/realtime-mutable-provider.ts +1 -0
  83. package/realtime-server/src/realtime-server-stores/index.ts +2 -0
  84. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +115 -0
  85. package/realtime-server/src/realtime-server-stores/server-user-store.ts +45 -0
  86. package/realtime-server/src/realtime-state-provider.ts +16 -8
  87. package/realtime-server/src/realtime-state-receiver.ts +1 -0
  88. package/realtime-server/src/realtime-state-synchronizer.ts +23 -0
  89. package/realtime-testing/dist/index.cjs +65 -26
  90. package/realtime-testing/dist/index.cjs.map +1 -1
  91. package/realtime-testing/dist/index.d.ts +11 -7
  92. package/realtime-testing/dist/index.js +64 -26
  93. package/realtime-testing/dist/index.js.map +1 -1
  94. package/realtime-testing/src/setup-realtime-test.tsx +83 -43
  95. package/src/find-state.ts +8 -16
  96. package/src/logger.ts +16 -11
  97. package/src/transaction.ts +4 -4
  98. package/react/src/store-hooks.ts +0 -87
  99. package/realtime-server/src/realtime-server-store.ts +0 -39
@@ -1,26 +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
 
7
- declare function realtimeStateProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: AtomIO.WritableToken<J>) => () => void;
10
+ type primitive = boolean | number | string | null;
8
11
 
9
- declare function realtimeFamilyProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable>(family: AtomIO.RegularAtomFamily<J, Json.Serializable>, index: AtomIO.ReadableToken<Iterable<string>>) => () => void;
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>;
10
16
 
11
- declare function realtimeMutableProvider({ socket, store, }: ServerConfig): <Core extends Transceiver<Json.Serializable>, SerializableCore extends Json.Serializable>(token: AtomIO.MutableAtomToken<Core, SerializableCore>) => () => void;
17
+ type Refinement<Unrefined, Refined extends Unrefined> = (value: Unrefined) => value is Refined;
18
+ type Cardinality = `1:1` | `1:n` | `n:n`;
12
19
 
13
- declare const realtimeMutableFamilyProvider: ({ socket, store, }: ServerConfig) => <Family extends AtomIO.MutableAtomFamily<Transceiver<Json.Serializable>, Json.Serializable, Json.Serializable>>(family: Family, index: AtomIO.ReadableToken<Iterable<string>>) => () => void;
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
+
136
+ type StateProvider = ReturnType<typeof realtimeStateProvider>;
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;
140
+
141
+ type FamilyProvider = ReturnType<typeof realtimeFamilyProvider>;
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;
143
+
144
+ type MutableProvider = ReturnType<typeof realtimeMutableProvider>;
145
+ declare function realtimeMutableProvider({ socket, store, }: ServerConfig): <Core extends Transceiver<Json.Serializable>, SerializableCore extends Json.Serializable>(token: atom_io.MutableAtomToken<Core, SerializableCore>) => () => void;
146
+
147
+ type MutableFamilyProvider = ReturnType<typeof realtimeMutableFamilyProvider>;
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;
14
149
 
150
+ type StateReceiver = ReturnType<typeof realtimeStateReceiver>;
15
151
  declare function realtimeStateReceiver({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: WritableToken<J>) => () => void;
16
152
 
17
- declare const realtimeActionReceiver: ({ socket, store, }: ServerConfig) => <ƒ extends AtomIO.ƒn>(tx: AtomIO.TransactionToken<ƒ>) => () => void;
153
+ type ActionReceiver = ReturnType<typeof realtimeActionReceiver>;
154
+ declare function realtimeActionReceiver({ socket, store, }: ServerConfig): <ƒ extends atom_io.ƒn>(tx: atom_io.TransactionToken<ƒ>) => () => void;
18
155
 
19
- declare function realtimeActionSynchronizer({ socket, store, }: ServerConfig): <ƒ extends AtomIO.ƒn>(tx: AtomIO.TransactionToken<ƒ>, filter?: ((update: AtomIO.TransactionUpdateContent[]) => AtomIO.TransactionUpdateContent[]) | undefined) => () => void;
156
+ type ActionSynchronizer = ReturnType<typeof realtimeActionSynchronizer>;
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;
20
158
 
21
159
  type ServerConfig = {
22
160
  socket: SocketIO.Socket;
23
161
  store?: Store;
24
162
  };
25
163
 
26
- export { type ServerConfig, 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`),
@@ -152,10 +280,10 @@ function realtimeMutableProvider({
152
280
  };
153
281
  };
154
282
  }
155
- var realtimeMutableFamilyProvider = ({
283
+ function realtimeMutableFamilyProvider({
156
284
  socket,
157
285
  store = IMPLICIT.STORE
158
- }) => {
286
+ }) {
159
287
  return function mutableFamilyProvider(family, index) {
160
288
  const unsubSingleCallbacksByKey = /* @__PURE__ */ new Map();
161
289
  const unsubFamilyCallbacksByKey = /* @__PURE__ */ new Map();
@@ -179,7 +307,7 @@ var 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(
@@ -263,7 +391,7 @@ var realtimeMutableFamilyProvider = ({
263
391
  unsubSingleCallbacksByKey.clear();
264
392
  };
265
393
  };
266
- };
394
+ }
267
395
  function realtimeStateReceiver({
268
396
  socket,
269
397
  store = IMPLICIT.STORE
@@ -285,17 +413,17 @@ function realtimeStateReceiver({
285
413
  };
286
414
  };
287
415
  }
288
- var realtimeActionReceiver = ({
416
+ function realtimeActionReceiver({
289
417
  socket,
290
418
  store = IMPLICIT.STORE
291
- }) => {
419
+ }) {
292
420
  return function actionReceiver(tx) {
293
421
  const fillTransactionRequest = (update) => {
294
422
  const performanceKey = `tx-run:${tx.key}:${update.id}`;
295
423
  const performanceKeyStart = `${performanceKey}:start`;
296
424
  const performanceKeyEnd = `${performanceKey}:end`;
297
425
  performance.mark(performanceKeyStart);
298
- AtomIO7.runTransaction(tx, store)(...update.params);
426
+ AtomIO7.runTransaction(tx, update.id, store)(...update.params);
299
427
  performance.mark(performanceKeyEnd);
300
428
  const metric = performance.measure(
301
429
  performanceKey,
@@ -307,69 +435,122 @@ var realtimeActionReceiver = ({
307
435
  socket.on(`tx-run:${tx.key}`, fillTransactionRequest);
308
436
  return () => socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
309
437
  };
310
- };
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
438
+ }
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
- AtomIO7.runTransaction(tx, store, update.id)(...update.params);
464
+ const performanceKey = `tx-run:${tx.key}:${update.id}`;
465
+ const performanceKeyStart = `${performanceKey}:start`;
466
+ const performanceKeyEnd = `${performanceKey}:end`;
467
+ performance.mark(performanceKeyStart);
468
+ AtomIO7.runTransaction(tx, update.id, store)(...update.params);
469
+ performance.mark(performanceKeyEnd);
470
+ const metric = performance.measure(
471
+ performanceKey,
472
+ performanceKeyStart,
473
+ performanceKeyEnd
474
+ );
475
+ store == null ? void 0 : store.logger.info(`\u{1F680}`, `transaction`, tx.key, update.id, metric.duration);
346
476
  };
477
+ socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
347
478
  socket.on(`tx-run:${tx.key}`, fillTransactionRequest);
479
+ let unsubscribeFromTransaction;
348
480
  const fillTransactionSubscriptionRequest = () => {
349
- const unsubscribe = subscribeToTransaction(
481
+ unsubscribeFromTransaction = subscribeToTransaction(
350
482
  tx,
351
483
  (update) => {
352
- unsubscribe();
353
- const updateState = AtomIO7.findState(completeUpdateAtoms, update.id);
484
+ const updateState = findInStore(completeUpdateAtoms, update.id, store);
354
485
  AtomIO7.setState(updateState, update, store);
355
486
  const toEmit = filter ? AtomIO7.getState(
356
- AtomIO7.findState(redactedUpdateSelectors, [tx.key, update.id]),
487
+ findInStore(redactedUpdateSelectors, [tx.key, update.id], store),
357
488
  store
358
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
+ );
359
501
  socket.emit(`tx-new:${tx.key}`, toEmit);
360
502
  },
361
503
  `tx-sub:${tx.key}:${socket.id}`,
362
504
  store
363
505
  );
364
- socket.on(`tx-unsub:${tx.key}`, unsubscribe);
506
+ socket.on(`tx-unsub:${tx.key}`, unsubscribeFromTransaction);
365
507
  };
366
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);
367
542
  return () => {
543
+ if (unsubscribeFromTransaction) {
544
+ unsubscribeFromTransaction();
545
+ unsubscribeFromTransaction = void 0;
546
+ }
547
+ clearInterval(retry);
368
548
  socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
549
+ socket.off(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
369
550
  };
370
551
  };
371
552
  }
372
553
 
373
- 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 };
374
555
  //# sourceMappingURL=out.js.map
375
556
  //# sourceMappingURL=index.js.map