@oimdb/react 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,195 +1,241 @@
1
1
  // src/hooks/index.ts
2
- import { useMemo, useRef, useEffect } from "react";
2
+ import { useMemo, useRef } from "react";
3
3
  import { useSyncExternalStore } from "react";
4
4
  var EMPTY_ARRAY = [];
5
- var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
6
- const isInitialized = useRef(false);
7
- const snapshotValueRef = useRef(
8
- keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat()
9
- );
10
- const osc = useRef(() => {
11
- });
12
- const subscribe = useRef((onStoreChange) => {
13
- osc.current = onStoreChange;
14
- return () => {
15
- osc.current = () => {
5
+ var useSelectPksByIndexKeysSetBased = (reactiveIndex, keys) => {
6
+ const prevKeysRef = useRef();
7
+ const keysAreEqual = arraysEqual(prevKeysRef.current || EMPTY_ARRAY, keys);
8
+ if (!keysAreEqual) {
9
+ prevKeysRef.current = keys;
10
+ }
11
+ const snapshotValueRef = useRef();
12
+ const subscribe = useMemo(() => {
13
+ snapshotValueRef.current = keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat();
14
+ return (onStoreChange) => {
15
+ const prevKeys = prevKeysRef.current;
16
+ if (!prevKeys) {
17
+ return () => {
18
+ };
19
+ }
20
+ const updateSnapshot = () => {
21
+ snapshotValueRef.current = keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat();
22
+ onStoreChange();
23
+ };
24
+ reactiveIndex.updateEventEmitter.subscribeOnKeys(
25
+ prevKeys,
26
+ updateSnapshot
27
+ );
28
+ return () => {
29
+ reactiveIndex.updateEventEmitter.unsubscribeFromKeys(
30
+ prevKeys,
31
+ updateSnapshot
32
+ );
16
33
  };
17
34
  };
18
- });
19
- useEffect(() => {
20
- const list = () => {
21
- snapshotValueRef.current = keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat();
22
- osc.current();
23
- };
24
- reactiveIndex.updateEventEmitter.subscribeOnKeys(keys, list);
25
- if (!isInitialized.current) {
26
- isInitialized.current = true;
27
- } else {
28
- snapshotValueRef.current = keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat();
29
- osc.current();
30
- }
31
- return () => {
32
- reactiveIndex.updateEventEmitter.unsubscribeFromKeys(keys, list);
33
- };
34
- }, [keys, reactiveIndex.updateEventEmitter, reactiveIndex]);
35
+ }, [prevKeysRef.current, reactiveIndex.updateEventEmitter]);
35
36
  const getSnapshot = useMemo(() => {
36
37
  return () => {
37
38
  return snapshotValueRef.current;
38
39
  };
39
40
  }, []);
40
- const snapshot = useSyncExternalStore(
41
- subscribe.current,
42
- getSnapshot,
43
- getSnapshot
44
- );
41
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
45
42
  return snapshot;
46
43
  };
47
- var useSelectPksByIndexKey = (reactiveIndex, key) => {
48
- const isInitialized = useRef(false);
49
- const snapshotValueRef = useRef(
50
- Array.from(reactiveIndex.getPksByKey(key))
51
- );
52
- const osc = useRef(() => {
53
- });
54
- const subscribe = useRef((onStoreChange) => {
55
- osc.current = onStoreChange;
44
+ var useSelectPksByIndexKeySetBased = (reactiveIndex, key) => {
45
+ const getSnapshot = useMemo(() => {
56
46
  return () => {
57
- osc.current = () => {
47
+ return reactiveIndex.getPksByKey(key);
48
+ };
49
+ }, [key, reactiveIndex]);
50
+ const subscribe = useMemo(() => {
51
+ return (onStoreChange) => {
52
+ reactiveIndex.updateEventEmitter.subscribeOnKey(key, onStoreChange);
53
+ return () => {
54
+ reactiveIndex.updateEventEmitter.unsubscribeFromKey(
55
+ key,
56
+ onStoreChange
57
+ );
58
58
  };
59
59
  };
60
- });
61
- useEffect(() => {
62
- const list = () => {
63
- snapshotValueRef.current = Array.from(
64
- reactiveIndex.getPksByKey(key)
60
+ }, [key, reactiveIndex.updateEventEmitter]);
61
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
62
+ return snapshot;
63
+ };
64
+ var useSelectPksByIndexKeysArrayBased = (reactiveIndex, keys) => {
65
+ const prevKeysRef = useRef();
66
+ const keysAreEqual = arraysEqual(prevKeysRef.current || EMPTY_ARRAY, keys);
67
+ if (!keysAreEqual) {
68
+ prevKeysRef.current = keys;
69
+ }
70
+ const snapshotValueRef = useRef();
71
+ const subscribe = useMemo(() => {
72
+ snapshotValueRef.current = keys.map((key) => reactiveIndex.getPksByKey(key)).flat();
73
+ return (onStoreChange) => {
74
+ const prevKeys = prevKeysRef.current;
75
+ if (!prevKeys) {
76
+ return () => {
77
+ };
78
+ }
79
+ const updateSnapshot = () => {
80
+ snapshotValueRef.current = keys.map((key) => reactiveIndex.getPksByKey(key)).flat();
81
+ onStoreChange();
82
+ };
83
+ reactiveIndex.updateEventEmitter.subscribeOnKeys(
84
+ prevKeys,
85
+ updateSnapshot
65
86
  );
66
- osc.current();
87
+ return () => {
88
+ reactiveIndex.updateEventEmitter.unsubscribeFromKeys(
89
+ prevKeys,
90
+ updateSnapshot
91
+ );
92
+ };
67
93
  };
68
- reactiveIndex.updateEventEmitter.subscribeOnKey(key, list);
69
- if (!isInitialized.current) {
70
- isInitialized.current = true;
71
- } else {
72
- snapshotValueRef.current = Array.from(
73
- reactiveIndex.getPksByKey(key)
74
- );
75
- osc.current();
76
- }
94
+ }, [prevKeysRef.current, reactiveIndex.updateEventEmitter]);
95
+ const getSnapshot = useMemo(() => {
77
96
  return () => {
78
- reactiveIndex.updateEventEmitter.unsubscribeFromKey(key, list);
97
+ return snapshotValueRef.current;
79
98
  };
80
- }, [key, reactiveIndex.updateEventEmitter, reactiveIndex]);
99
+ }, []);
100
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
101
+ return snapshot;
102
+ };
103
+ var useSelectPksByIndexKeyArrayBased = (reactiveIndex, key) => {
104
+ const prevKeyRef = useRef();
105
+ const keyAreEqual = prevKeyRef.current === key;
106
+ if (!keyAreEqual) {
107
+ prevKeyRef.current = key;
108
+ }
109
+ const snapshotValueRef = useRef();
110
+ const subscribe = useMemo(() => {
111
+ snapshotValueRef.current = reactiveIndex.getPksByKey(key);
112
+ return (onStoreChange) => {
113
+ const prevKey = prevKeyRef.current;
114
+ if (!prevKey) {
115
+ return () => {
116
+ };
117
+ }
118
+ const updateSnapshot = () => {
119
+ snapshotValueRef.current = reactiveIndex.getPksByKey(prevKey);
120
+ onStoreChange();
121
+ };
122
+ reactiveIndex.updateEventEmitter.subscribeOnKey(
123
+ prevKey,
124
+ updateSnapshot
125
+ );
126
+ return () => {
127
+ reactiveIndex.updateEventEmitter.unsubscribeFromKey(
128
+ prevKey,
129
+ updateSnapshot
130
+ );
131
+ };
132
+ };
133
+ }, [key, reactiveIndex.updateEventEmitter]);
81
134
  const getSnapshot = useMemo(() => {
82
135
  return () => {
83
136
  return snapshotValueRef.current;
84
137
  };
85
138
  }, []);
86
- const snapshot = useSyncExternalStore(
87
- subscribe.current,
88
- getSnapshot,
89
- getSnapshot
90
- );
139
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
91
140
  return snapshot;
92
141
  };
93
142
  var useSelectEntityByPk = (reactiveCollection, pk) => {
94
- const isInitialized = useRef(false);
95
- const snapshotValueRef = useRef(
96
- reactiveCollection.getOneByPk(pk)
143
+ const getSnapshot = useMemo(
144
+ () => () => reactiveCollection.getOneByPk(pk),
145
+ [pk, reactiveCollection]
97
146
  );
98
- const osc = useRef(() => {
99
- });
100
- const subscribe = useRef((onStoreChange) => {
101
- osc.current = onStoreChange;
102
- return () => {
103
- osc.current = () => {
147
+ const subscribe = useMemo(() => {
148
+ return (onStoreChange) => {
149
+ reactiveCollection.updateEventEmitter.subscribeOnKey(
150
+ pk,
151
+ onStoreChange
152
+ );
153
+ return () => {
154
+ reactiveCollection.updateEventEmitter.unsubscribeFromKey(
155
+ pk,
156
+ onStoreChange
157
+ );
104
158
  };
105
159
  };
106
- });
107
- useEffect(() => {
108
- const list = () => {
109
- snapshotValueRef.current = reactiveCollection.getOneByPk(pk);
110
- osc.current();
111
- };
112
- reactiveCollection.updateEventEmitter.subscribeOnKey(pk, list);
113
- if (!isInitialized.current) {
114
- isInitialized.current = true;
115
- } else {
116
- snapshotValueRef.current = reactiveCollection.getOneByPk(pk);
117
- osc.current();
118
- }
119
- return () => {
120
- reactiveCollection.updateEventEmitter.unsubscribeFromKey(pk, list);
121
- };
122
- }, [pk, reactiveCollection.updateEventEmitter, reactiveCollection]);
123
- const getSnapshot = useMemo(() => () => snapshotValueRef.current, []);
124
- const snapshot = useSyncExternalStore(
125
- subscribe.current,
126
- getSnapshot,
127
- getSnapshot
128
- );
160
+ }, [pk, reactiveCollection.updateEventEmitter]);
161
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
129
162
  return snapshot;
130
163
  };
164
+ function arraysEqual(a, b) {
165
+ if (a === b) return true;
166
+ if (a.length !== b.length) return false;
167
+ for (let i = 0; i < a.length; i++) {
168
+ if (a[i] !== b[i]) return false;
169
+ }
170
+ return true;
171
+ }
131
172
  var useSelectEntitiesByPks = (reactiveCollection, pks) => {
132
- const isInitialized = useRef(false);
133
- const snapshotValueRef = useRef(
134
- pks.map((pk) => reactiveCollection.getOneByPk(pk))
135
- );
136
- const osc = useRef(() => {
137
- });
138
- const subscribe = useRef((onStoreChange) => {
139
- osc.current = onStoreChange;
140
- return () => {
141
- osc.current = () => {
173
+ const prevPksRef = useRef();
174
+ const pksAreEqual = arraysEqual(prevPksRef.current || EMPTY_ARRAY, pks);
175
+ if (!pksAreEqual) {
176
+ prevPksRef.current = pks;
177
+ }
178
+ const snapshotRef = useRef();
179
+ const subscribe = useMemo(() => {
180
+ snapshotRef.current = pks.map((pk) => reactiveCollection.getOneByPk(pk));
181
+ return (onStoreChange) => {
182
+ const prevPks = prevPksRef.current;
183
+ if (!prevPks) {
184
+ return () => {
185
+ };
186
+ }
187
+ const updateSnapshot = () => {
188
+ snapshotRef.current = prevPks.map(
189
+ (pk) => reactiveCollection.getOneByPk(pk)
190
+ );
191
+ onStoreChange();
142
192
  };
143
- };
144
- });
145
- useEffect(() => {
146
- const list = () => {
147
- snapshotValueRef.current = pks.map(
148
- (pk) => reactiveCollection.getOneByPk(pk)
149
- );
150
- osc.current();
151
- };
152
- reactiveCollection.updateEventEmitter.subscribeOnKeys(pks, list);
153
- if (!isInitialized.current) {
154
- isInitialized.current = true;
155
- } else {
156
- snapshotValueRef.current = pks.map(
157
- (pk) => reactiveCollection.getOneByPk(pk)
158
- );
159
- osc.current();
160
- }
161
- return () => {
162
- reactiveCollection.updateEventEmitter.unsubscribeFromKeys(
163
- pks,
164
- list
193
+ reactiveCollection.updateEventEmitter.subscribeOnKeys(
194
+ prevPks,
195
+ updateSnapshot
165
196
  );
197
+ return () => {
198
+ reactiveCollection.updateEventEmitter.unsubscribeFromKeys(
199
+ prevPks,
200
+ updateSnapshot
201
+ );
202
+ };
166
203
  };
167
- }, [pks, reactiveCollection.updateEventEmitter, reactiveCollection]);
204
+ }, [prevPksRef.current, reactiveCollection.updateEventEmitter]);
168
205
  const getSnapshot = useMemo(() => {
169
206
  return () => {
170
- return snapshotValueRef.current;
207
+ return snapshotRef.current;
171
208
  };
172
209
  }, []);
173
- const snapshot = useSyncExternalStore(
174
- subscribe.current,
175
- getSnapshot,
176
- getSnapshot
177
- );
210
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
178
211
  return snapshot;
179
212
  };
180
- var useSelectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
181
- const pks = useSelectPksByIndexKey(reactiveIndex, key);
213
+ var useSelectEntitiesByIndexKeySetBased = (reactiveCollection, reactiveIndex, key) => {
214
+ const pks = useSelectPksByIndexKeySetBased(reactiveIndex, key);
215
+ const pksArray = useMemo(
216
+ () => pks ? Array.from(pks) : EMPTY_ARRAY,
217
+ [pks]
218
+ );
219
+ return useSelectEntitiesByPks(reactiveCollection, pksArray);
220
+ };
221
+ var useSelectEntitiesByIndexKeysSetBased = (reactiveCollection, reactiveIndex, keys) => {
222
+ const pks = useSelectPksByIndexKeysSetBased(reactiveIndex, keys);
223
+ const pksArray = useMemo(
224
+ () => pks ? Array.from(pks) : EMPTY_ARRAY,
225
+ [pks]
226
+ );
227
+ return useSelectEntitiesByPks(reactiveCollection, pksArray);
228
+ };
229
+ var useSelectEntitiesByIndexKeyArrayBased = (reactiveCollection, reactiveIndex, key) => {
230
+ const pks = useSelectPksByIndexKeyArrayBased(reactiveIndex, key);
182
231
  return useSelectEntitiesByPks(
183
232
  reactiveCollection,
184
233
  pks || EMPTY_ARRAY
185
234
  );
186
235
  };
187
- var unique = (array) => {
188
- return Array.from(new Set(array));
189
- };
190
- var useSelectEntitiesByIndexKeys = (reactiveCollection, reactiveIndex, keys) => {
191
- const pks = useSelectPksByIndexKeys(reactiveIndex, keys) || EMPTY_ARRAY;
192
- return useSelectEntitiesByPks(reactiveCollection, unique(Array.from(pks)));
236
+ var useSelectEntitiesByIndexKeysArrayBased = (reactiveCollection, reactiveIndex, keys) => {
237
+ const pks = useSelectPksByIndexKeysArrayBased(reactiveIndex, keys) || EMPTY_ARRAY;
238
+ return useSelectEntitiesByPks(reactiveCollection, pks);
193
239
  };
194
240
 
195
241
  // src/context/index.tsx
@@ -222,10 +268,14 @@ export {
222
268
  OIMRICollectionsProvider,
223
269
  createOIMCollectionsContext,
224
270
  useOIMCollectionsContext,
225
- useSelectEntitiesByIndexKey,
226
- useSelectEntitiesByIndexKeys,
271
+ useSelectEntitiesByIndexKeyArrayBased,
272
+ useSelectEntitiesByIndexKeySetBased,
273
+ useSelectEntitiesByIndexKeysArrayBased,
274
+ useSelectEntitiesByIndexKeysSetBased,
227
275
  useSelectEntitiesByPks,
228
276
  useSelectEntityByPk,
229
- useSelectPksByIndexKey,
230
- useSelectPksByIndexKeys
277
+ useSelectPksByIndexKeyArrayBased,
278
+ useSelectPksByIndexKeySetBased,
279
+ useSelectPksByIndexKeysArrayBased,
280
+ useSelectPksByIndexKeysSetBased
231
281
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oimdb/react",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "React integration for OIMDB - Hooks for selection and subscription with external storage",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -24,23 +24,41 @@
24
24
  },
25
25
  "scripts": {
26
26
  "build": "tsup src/index.ts --dts --format esm,cjs",
27
+ "test": "jest",
28
+ "type-check": "tsc --noEmit",
27
29
  "clean": "rimraf dist",
28
- "prepublishOnly": "npm run build"
30
+ "prepublishOnly": "npm run type-check && npm test && npm run build"
29
31
  },
30
32
  "files": [
31
33
  "dist"
32
34
  ],
33
35
  "peerDependencies": {
34
- "@oimdb/core": "^1.0.6",
36
+ "@oimdb/core": "^1.3.0",
35
37
  "react": "^18.0.0"
36
38
  },
37
39
  "devDependencies": {
38
- "tsup": "^8.5.0",
39
- "typescript": "^5.2.2",
40
- "rimraf": "^5.0.5",
40
+ "@testing-library/react": "^14.3.1",
41
+ "@types/jest": "^29.5.8",
42
+ "@types/react": "^18.0.0",
43
+ "jest": "^29.7.0",
44
+ "jest-environment-jsdom": "^29.7.0",
41
45
  "react": "^18.0.0",
42
- "@types/react": "^18.0.0"
46
+ "rimraf": "^5.0.5",
47
+ "ts-jest": "^29.1.1",
48
+ "tsup": "^8.5.0",
49
+ "typescript": "^5.2.2"
43
50
  },
51
+ "keywords": [
52
+ "oimdb",
53
+ "react",
54
+ "hooks",
55
+ "reactive",
56
+ "typescript",
57
+ "state-management",
58
+ "subscriptions",
59
+ "selection",
60
+ "external-storage"
61
+ ],
44
62
  "author": "Andrei Baikov",
45
63
  "license": "MIT"
46
64
  }