@oimdb/react 1.0.8 → 1.1.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.
- package/README.md +159 -29
- package/dist/index.cjs +41 -9
- package/dist/index.d.cts +5 -25
- package/dist/index.d.ts +5 -25
- package/dist/index.js +38 -6
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -29,8 +29,8 @@ npm install @oimdb/react @oimdb/core
|
|
|
29
29
|
import { OIMEventQueue, OIMRICollection, OIMReactiveIndexManual } from '@oimdb/core';
|
|
30
30
|
import {
|
|
31
31
|
useSelectEntitiesByPks,
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
useSelectEntitiesByIndexKey,
|
|
33
|
+
useSelectEntityByPk
|
|
34
34
|
} from '@oimdb/react';
|
|
35
35
|
|
|
36
36
|
// Create event queue and reactive collections
|
|
@@ -46,7 +46,7 @@ const usersCollection = new OIMRICollection(queue, {
|
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
48
|
function UserProfile({ userId }: { userId: string }) {
|
|
49
|
-
const user =
|
|
49
|
+
const user = useSelectEntityByPk(usersCollection, userId);
|
|
50
50
|
|
|
51
51
|
if (!user) return <div>Loading...</div>;
|
|
52
52
|
|
|
@@ -81,7 +81,7 @@ function UserList({ userIds }: { userIds: string[] }) {
|
|
|
81
81
|
|
|
82
82
|
```typescript
|
|
83
83
|
function TeamMembers({ teamId }: { teamId: string }) {
|
|
84
|
-
const teamUsers =
|
|
84
|
+
const teamUsers = useSelectEntitiesByIndexKey(
|
|
85
85
|
usersCollection,
|
|
86
86
|
usersCollection.indexes.byTeam,
|
|
87
87
|
teamId
|
|
@@ -108,8 +108,7 @@ For applications with multiple collections, use the React Context pattern for ce
|
|
|
108
108
|
```typescript
|
|
109
109
|
import {
|
|
110
110
|
OIMRICollectionsProvider,
|
|
111
|
-
useOIMCollectionsContext
|
|
112
|
-
StrictCollectionsDictionary
|
|
111
|
+
useOIMCollectionsContext
|
|
113
112
|
} from '@oimdb/react';
|
|
114
113
|
|
|
115
114
|
interface User {
|
|
@@ -140,9 +139,148 @@ function createCollections() {
|
|
|
140
139
|
return { users: usersCollection, teams: teamsCollection } as const;
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
type AppCollections =
|
|
142
|
+
type AppCollections = ReturnType<typeof createCollections>;
|
|
144
143
|
```
|
|
145
144
|
|
|
145
|
+
## TypeScript Typing Strategies
|
|
146
|
+
|
|
147
|
+
For maximum type safety, you should properly type your collections dictionary. There are two main approaches, similar to how Redux handles state typing:
|
|
148
|
+
|
|
149
|
+
### Approach 1: Using `typeof` (Recommended for Simple Cases)
|
|
150
|
+
|
|
151
|
+
The simplest approach is to use TypeScript's `typeof` operator to infer types from your collection instances:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { OIMEventQueue, OIMRICollection, OIMReactiveIndexManual } from '@oimdb/core';
|
|
155
|
+
|
|
156
|
+
interface User {
|
|
157
|
+
id: string;
|
|
158
|
+
name: string;
|
|
159
|
+
teamId: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
interface Team {
|
|
163
|
+
id: string;
|
|
164
|
+
name: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Create collections
|
|
168
|
+
const queue = new OIMEventQueue();
|
|
169
|
+
const userTeamIndex = new OIMReactiveIndexManual<string, string>(queue);
|
|
170
|
+
const usersCollection = new OIMRICollection(queue, {
|
|
171
|
+
collectionOpts: { selectPk: (user: User) => user.id },
|
|
172
|
+
indexes: { byTeam: userTeamIndex },
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const teamsCollection = new OIMRICollection(queue, {
|
|
176
|
+
collectionOpts: { selectPk: (team: Team) => team.id },
|
|
177
|
+
indexes: {},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Infer types using typeof
|
|
181
|
+
const collections = {
|
|
182
|
+
users: usersCollection,
|
|
183
|
+
teams: teamsCollection,
|
|
184
|
+
} as const;
|
|
185
|
+
|
|
186
|
+
// Extract the type
|
|
187
|
+
type AppCollections = typeof collections;
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Usage:**
|
|
191
|
+
```typescript
|
|
192
|
+
function MyComponent() {
|
|
193
|
+
const { users, teams } = useOIMCollectionsContext<AppCollections>();
|
|
194
|
+
// users and teams are fully typed with all their generics preserved
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Approach 2: Creating Explicit Types (Recommended for Complex Projects)
|
|
199
|
+
|
|
200
|
+
For larger applications or when you need more control, create explicit type definitions similar to Redux's approach:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { OIMEventQueue, OIMRICollection, OIMReactiveIndexManual } from '@oimdb/core';
|
|
204
|
+
import type { TOIMPk, OIMIndex, OIMReactiveIndex } from '@oimdb/core';
|
|
205
|
+
|
|
206
|
+
interface User {
|
|
207
|
+
id: string;
|
|
208
|
+
name: string;
|
|
209
|
+
teamId: string;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
interface Team {
|
|
213
|
+
id: string;
|
|
214
|
+
name: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Define your collection types explicitly
|
|
218
|
+
type UserCollection = OIMRICollection<
|
|
219
|
+
User,
|
|
220
|
+
string,
|
|
221
|
+
'byTeam',
|
|
222
|
+
string,
|
|
223
|
+
OIMIndex<string, string>,
|
|
224
|
+
OIMReactiveIndex<string, string, OIMIndex<string, string>>
|
|
225
|
+
>;
|
|
226
|
+
|
|
227
|
+
type TeamCollection = OIMRICollection<
|
|
228
|
+
Team,
|
|
229
|
+
string,
|
|
230
|
+
never,
|
|
231
|
+
never,
|
|
232
|
+
OIMIndex<never, never>,
|
|
233
|
+
OIMReactiveIndex<never, never, OIMIndex<never, never>>
|
|
234
|
+
>;
|
|
235
|
+
|
|
236
|
+
// Define your collections dictionary type
|
|
237
|
+
interface AppCollections {
|
|
238
|
+
users: UserCollection;
|
|
239
|
+
teams: TeamCollection;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Factory function that returns properly typed collections
|
|
243
|
+
function createCollections(): AppCollections {
|
|
244
|
+
const queue = new OIMEventQueue();
|
|
245
|
+
const userTeamIndex = new OIMReactiveIndexManual<string, string>(queue);
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
users: new OIMRICollection(queue, {
|
|
249
|
+
collectionOpts: { selectPk: (user: User) => user.id },
|
|
250
|
+
indexes: { byTeam: userTeamIndex },
|
|
251
|
+
}) as UserCollection,
|
|
252
|
+
|
|
253
|
+
teams: new OIMRICollection(queue, {
|
|
254
|
+
collectionOpts: { selectPk: (team: Team) => team.id },
|
|
255
|
+
indexes: {},
|
|
256
|
+
}) as TeamCollection,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Usage:**
|
|
262
|
+
```typescript
|
|
263
|
+
function MyComponent() {
|
|
264
|
+
const { users, teams } = useOIMCollectionsContext<AppCollections>();
|
|
265
|
+
// Full type safety with explicit types
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### When to Use Each Approach
|
|
270
|
+
|
|
271
|
+
- **Use `typeof`** when:
|
|
272
|
+
- You have simple collection setups
|
|
273
|
+
- You want TypeScript to infer everything automatically
|
|
274
|
+
- You prefer less boilerplate
|
|
275
|
+
- Your collections are created in one place
|
|
276
|
+
|
|
277
|
+
- **Use explicit types** when:
|
|
278
|
+
- You need to share types across multiple files
|
|
279
|
+
- You want to document your data structure explicitly
|
|
280
|
+
- You're building a library or shared module
|
|
281
|
+
- You need to ensure type consistency across your application
|
|
282
|
+
- You prefer Redux-style explicit typing patterns
|
|
283
|
+
|
|
146
284
|
### Provider Setup
|
|
147
285
|
|
|
148
286
|
```typescript
|
|
@@ -165,7 +303,7 @@ function UserDashboard() {
|
|
|
165
303
|
|
|
166
304
|
// Use collections with hooks
|
|
167
305
|
const allUsers = useSelectEntitiesByPks(users, []);
|
|
168
|
-
const teamMembers =
|
|
306
|
+
const teamMembers = useSelectEntitiesByIndexKey(
|
|
169
307
|
users,
|
|
170
308
|
users.indexes.byTeam,
|
|
171
309
|
'team1'
|
|
@@ -205,7 +343,7 @@ function UserComponent() {
|
|
|
205
343
|
|
|
206
344
|
## API Reference
|
|
207
345
|
|
|
208
|
-
### `
|
|
346
|
+
### `useSelectEntityByPk(reactiveCollection, pk)`
|
|
209
347
|
|
|
210
348
|
Subscribes to a single entity from a reactive collection.
|
|
211
349
|
|
|
@@ -227,7 +365,7 @@ Subscribes to multiple entities from a reactive collection.
|
|
|
227
365
|
**Returns:**
|
|
228
366
|
- `(TEntity | undefined)[]` - Array of entities (undefined for missing entities)
|
|
229
367
|
|
|
230
|
-
### `
|
|
368
|
+
### `useSelectEntitiesByIndexKey(reactiveCollection, reactiveIndex, key)`
|
|
231
369
|
|
|
232
370
|
Subscribes to entities indexed by a specific key.
|
|
233
371
|
|
|
@@ -239,7 +377,7 @@ Subscribes to entities indexed by a specific key.
|
|
|
239
377
|
**Returns:**
|
|
240
378
|
- `(TEntity | undefined)[]` - Array of entities for the given index key
|
|
241
379
|
|
|
242
|
-
### `
|
|
380
|
+
### `useSelectEntitiesByIndexKeys(reactiveCollection, reactiveIndex, keys)`
|
|
243
381
|
|
|
244
382
|
Subscribes to entities indexed by multiple keys.
|
|
245
383
|
|
|
@@ -306,17 +444,9 @@ Creates a custom collections context with specific typing.
|
|
|
306
444
|
|
|
307
445
|
### Type Utilities
|
|
308
446
|
|
|
309
|
-
#### `StrictCollectionsDictionary<T>`
|
|
310
|
-
|
|
311
|
-
Ensures collections dictionary maintains exact types.
|
|
312
|
-
|
|
313
447
|
#### `CollectionsDictionary`
|
|
314
448
|
|
|
315
|
-
Base type for any collections dictionary.
|
|
316
|
-
|
|
317
|
-
#### `ExtractEntityType<T>`, `ExtractPkType<T>`, etc.
|
|
318
|
-
|
|
319
|
-
Type utilities for extracting specific types from collections.
|
|
449
|
+
Base type for any collections dictionary. Use `typeof` to extract types from your collection instances, or define explicit types using `OIMRICollection` generics.
|
|
320
450
|
|
|
321
451
|
## Architecture
|
|
322
452
|
|
|
@@ -326,8 +456,8 @@ The hooks work directly with OIMDB reactive objects:
|
|
|
326
456
|
|
|
327
457
|
```typescript
|
|
328
458
|
// Use reactive collections and indexes directly
|
|
329
|
-
const user =
|
|
330
|
-
const posts =
|
|
459
|
+
const user = useSelectEntityByPk(reactiveCollection, 'user123');
|
|
460
|
+
const posts = useSelectEntitiesByIndexKey(reactiveCollection, reactiveIndex, 'tech');
|
|
331
461
|
```
|
|
332
462
|
|
|
333
463
|
### Event Subscription
|
|
@@ -354,7 +484,7 @@ Hooks automatically subscribe to OIMDB reactive events using `useSyncExternalSto
|
|
|
354
484
|
```typescript
|
|
355
485
|
import React from 'react';
|
|
356
486
|
import { OIMEventQueue, OIMRICollection, OIMReactiveIndexManual } from '@oimdb/core';
|
|
357
|
-
import {
|
|
487
|
+
import { useSelectEntityByPk, useSelectEntitiesByPks, useSelectEntitiesByIndexKey } from '@oimdb/react';
|
|
358
488
|
|
|
359
489
|
interface User {
|
|
360
490
|
id: string;
|
|
@@ -378,7 +508,7 @@ const usersCollection = createUserCollection();
|
|
|
378
508
|
|
|
379
509
|
// Component
|
|
380
510
|
function UserProfile({ userId }: { userId: string }) {
|
|
381
|
-
const user =
|
|
511
|
+
const user = useSelectEntityByPk(usersCollection, userId);
|
|
382
512
|
|
|
383
513
|
if (!user) return <div>Loading...</div>;
|
|
384
514
|
|
|
@@ -386,7 +516,7 @@ function UserProfile({ userId }: { userId: string }) {
|
|
|
386
516
|
}
|
|
387
517
|
|
|
388
518
|
function TeamDashboard({ teamId }: { teamId: string }) {
|
|
389
|
-
const teamMembers =
|
|
519
|
+
const teamMembers = useSelectEntitiesByIndexKey(
|
|
390
520
|
usersCollection,
|
|
391
521
|
usersCollection.indexes.byTeam,
|
|
392
522
|
teamId
|
|
@@ -445,9 +575,9 @@ const users = useEntities(userStorage, userIds);
|
|
|
445
575
|
const posts = useIndex(postStorage, categoryIndex, 'tech');
|
|
446
576
|
|
|
447
577
|
// v1.x - Reactive collections
|
|
448
|
-
const user =
|
|
578
|
+
const user = useSelectEntityByPk(reactiveCollection, 'user123');
|
|
449
579
|
const users = useSelectEntitiesByPks(reactiveCollection, userIds);
|
|
450
|
-
const posts =
|
|
580
|
+
const posts = useSelectEntitiesByIndexKey(reactiveCollection, reactiveIndex, 'tech');
|
|
451
581
|
```
|
|
452
582
|
|
|
453
583
|
### Collection Creation
|
|
@@ -464,7 +594,7 @@ const usersCollection = new OIMRICollection(queue, {
|
|
|
464
594
|
collectionOpts: { selectPk: (user: User) => user.id },
|
|
465
595
|
indexes: {},
|
|
466
596
|
});
|
|
467
|
-
const user =
|
|
597
|
+
const user = useSelectEntityByPk(usersCollection, userId);
|
|
468
598
|
```
|
|
469
599
|
|
|
470
600
|
### Context API
|
|
@@ -481,7 +611,7 @@ const collections = { users: usersCollection };
|
|
|
481
611
|
|
|
482
612
|
### Key Changes
|
|
483
613
|
|
|
484
|
-
- **Hook naming**: More explicit names like `
|
|
614
|
+
- **Hook naming**: More explicit names like `useSelectEntityByPk` vs `useEntity`
|
|
485
615
|
- **Parameters**: Direct reactive collection objects instead of storage abstractions
|
|
486
616
|
- **Context**: New context API for centralized collection management
|
|
487
617
|
- **Type safety**: Enhanced TypeScript support with better inference
|
package/dist/index.cjs
CHANGED
|
@@ -23,11 +23,11 @@ __export(index_exports, {
|
|
|
23
23
|
OIMRICollectionsContext: () => OIMRICollectionsContext,
|
|
24
24
|
OIMRICollectionsProvider: () => OIMRICollectionsProvider,
|
|
25
25
|
createOIMCollectionsContext: () => createOIMCollectionsContext,
|
|
26
|
-
selectEntitiesByIndexKey: () => selectEntitiesByIndexKey,
|
|
27
|
-
selectEntitiesByIndexKeys: () => selectEntitiesByIndexKeys,
|
|
28
|
-
selectEntityByPk: () => selectEntityByPk,
|
|
29
26
|
useOIMCollectionsContext: () => useOIMCollectionsContext,
|
|
27
|
+
useSelectEntitiesByIndexKey: () => useSelectEntitiesByIndexKey,
|
|
28
|
+
useSelectEntitiesByIndexKeys: () => useSelectEntitiesByIndexKeys,
|
|
30
29
|
useSelectEntitiesByPks: () => useSelectEntitiesByPks,
|
|
30
|
+
useSelectEntityByPk: () => useSelectEntityByPk,
|
|
31
31
|
useSelectPksByIndexKey: () => useSelectPksByIndexKey,
|
|
32
32
|
useSelectPksByIndexKeys: () => useSelectPksByIndexKeys
|
|
33
33
|
});
|
|
@@ -38,6 +38,7 @@ var import_react = require("react");
|
|
|
38
38
|
var import_react2 = require("react");
|
|
39
39
|
var EMPTY_ARRAY = [];
|
|
40
40
|
var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
41
|
+
const isInitialized = (0, import_react.useRef)(false);
|
|
41
42
|
const snapshotValueRef = (0, import_react.useRef)(
|
|
42
43
|
keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat()
|
|
43
44
|
);
|
|
@@ -56,6 +57,12 @@ var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
|
56
57
|
osc.current();
|
|
57
58
|
};
|
|
58
59
|
reactiveIndex.updateEventEmitter.subscribeOnKeys(keys, list);
|
|
60
|
+
if (!isInitialized.current) {
|
|
61
|
+
isInitialized.current = true;
|
|
62
|
+
} else {
|
|
63
|
+
snapshotValueRef.current = keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat();
|
|
64
|
+
osc.current();
|
|
65
|
+
}
|
|
59
66
|
return () => {
|
|
60
67
|
reactiveIndex.updateEventEmitter.unsubscribeFromKeys(keys, list);
|
|
61
68
|
};
|
|
@@ -73,6 +80,7 @@ var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
|
73
80
|
return snapshot;
|
|
74
81
|
};
|
|
75
82
|
var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
83
|
+
const isInitialized = (0, import_react.useRef)(false);
|
|
76
84
|
const snapshotValueRef = (0, import_react.useRef)(
|
|
77
85
|
Array.from(reactiveIndex.getPksByKey(key))
|
|
78
86
|
);
|
|
@@ -93,6 +101,14 @@ var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
|
93
101
|
osc.current();
|
|
94
102
|
};
|
|
95
103
|
reactiveIndex.updateEventEmitter.subscribeOnKey(key, list);
|
|
104
|
+
if (!isInitialized.current) {
|
|
105
|
+
isInitialized.current = true;
|
|
106
|
+
} else {
|
|
107
|
+
snapshotValueRef.current = Array.from(
|
|
108
|
+
reactiveIndex.getPksByKey(key)
|
|
109
|
+
);
|
|
110
|
+
osc.current();
|
|
111
|
+
}
|
|
96
112
|
return () => {
|
|
97
113
|
reactiveIndex.updateEventEmitter.unsubscribeFromKey(key, list);
|
|
98
114
|
};
|
|
@@ -109,7 +125,8 @@ var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
|
109
125
|
);
|
|
110
126
|
return snapshot;
|
|
111
127
|
};
|
|
112
|
-
var
|
|
128
|
+
var useSelectEntityByPk = (reactiveCollection, pk) => {
|
|
129
|
+
const isInitialized = (0, import_react.useRef)(false);
|
|
113
130
|
const snapshotValueRef = (0, import_react.useRef)(
|
|
114
131
|
reactiveCollection.getOneByPk(pk)
|
|
115
132
|
);
|
|
@@ -128,6 +145,12 @@ var selectEntityByPk = (reactiveCollection, pk) => {
|
|
|
128
145
|
osc.current();
|
|
129
146
|
};
|
|
130
147
|
reactiveCollection.updateEventEmitter.subscribeOnKey(pk, list);
|
|
148
|
+
if (!isInitialized.current) {
|
|
149
|
+
isInitialized.current = true;
|
|
150
|
+
} else {
|
|
151
|
+
snapshotValueRef.current = reactiveCollection.getOneByPk(pk);
|
|
152
|
+
osc.current();
|
|
153
|
+
}
|
|
131
154
|
return () => {
|
|
132
155
|
reactiveCollection.updateEventEmitter.unsubscribeFromKey(pk, list);
|
|
133
156
|
};
|
|
@@ -141,6 +164,7 @@ var selectEntityByPk = (reactiveCollection, pk) => {
|
|
|
141
164
|
return snapshot;
|
|
142
165
|
};
|
|
143
166
|
var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
167
|
+
const isInitialized = (0, import_react.useRef)(false);
|
|
144
168
|
const snapshotValueRef = (0, import_react.useRef)(
|
|
145
169
|
pks.map((pk) => reactiveCollection.getOneByPk(pk))
|
|
146
170
|
);
|
|
@@ -161,6 +185,14 @@ var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
|
161
185
|
osc.current();
|
|
162
186
|
};
|
|
163
187
|
reactiveCollection.updateEventEmitter.subscribeOnKeys(pks, list);
|
|
188
|
+
if (!isInitialized.current) {
|
|
189
|
+
isInitialized.current = true;
|
|
190
|
+
} else {
|
|
191
|
+
snapshotValueRef.current = pks.map(
|
|
192
|
+
(pk) => reactiveCollection.getOneByPk(pk)
|
|
193
|
+
);
|
|
194
|
+
osc.current();
|
|
195
|
+
}
|
|
164
196
|
return () => {
|
|
165
197
|
reactiveCollection.updateEventEmitter.unsubscribeFromKeys(
|
|
166
198
|
pks,
|
|
@@ -180,7 +212,7 @@ var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
|
180
212
|
);
|
|
181
213
|
return snapshot;
|
|
182
214
|
};
|
|
183
|
-
var
|
|
215
|
+
var useSelectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
|
|
184
216
|
const pks = useSelectPksByIndexKey(reactiveIndex, key);
|
|
185
217
|
return useSelectEntitiesByPks(
|
|
186
218
|
reactiveCollection,
|
|
@@ -190,7 +222,7 @@ var selectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
|
|
|
190
222
|
var unique = (array) => {
|
|
191
223
|
return Array.from(new Set(array));
|
|
192
224
|
};
|
|
193
|
-
var
|
|
225
|
+
var useSelectEntitiesByIndexKeys = (reactiveCollection, reactiveIndex, keys) => {
|
|
194
226
|
const pks = useSelectPksByIndexKeys(reactiveIndex, keys) || EMPTY_ARRAY;
|
|
195
227
|
return useSelectEntitiesByPks(reactiveCollection, unique(Array.from(pks)));
|
|
196
228
|
};
|
|
@@ -225,11 +257,11 @@ function useOIMCollectionsContext(context) {
|
|
|
225
257
|
OIMRICollectionsContext,
|
|
226
258
|
OIMRICollectionsProvider,
|
|
227
259
|
createOIMCollectionsContext,
|
|
228
|
-
selectEntitiesByIndexKey,
|
|
229
|
-
selectEntitiesByIndexKeys,
|
|
230
|
-
selectEntityByPk,
|
|
231
260
|
useOIMCollectionsContext,
|
|
261
|
+
useSelectEntitiesByIndexKey,
|
|
262
|
+
useSelectEntitiesByIndexKeys,
|
|
232
263
|
useSelectEntitiesByPks,
|
|
264
|
+
useSelectEntityByPk,
|
|
233
265
|
useSelectPksByIndexKey,
|
|
234
266
|
useSelectPksByIndexKeys
|
|
235
267
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -5,14 +5,12 @@ import { ReactNode } from 'react';
|
|
|
5
5
|
|
|
6
6
|
declare const useSelectPksByIndexKeys: <TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, keys: readonly TKey[]) => readonly TPk[] | null;
|
|
7
7
|
declare const useSelectPksByIndexKey: <TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, key: TKey) => readonly TPk[] | null;
|
|
8
|
-
declare const
|
|
8
|
+
declare const useSelectEntityByPk: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pk: TPk) => TEntity | undefined;
|
|
9
9
|
declare const useSelectEntitiesByPks: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pks: readonly TPk[]) => readonly TEntity[] | null;
|
|
10
|
-
declare const
|
|
11
|
-
declare const
|
|
10
|
+
declare const useSelectEntitiesByIndexKey: <TEntity extends object, TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, key: TKey) => readonly TEntity[] | null;
|
|
11
|
+
declare const useSelectEntitiesByIndexKeys: <TEntity extends object, TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, keys: readonly TKey[]) => readonly TEntity[] | null;
|
|
12
12
|
|
|
13
|
-
type
|
|
14
|
-
type CollectionsDictionary = Record<string, AnyOIMRICollection>;
|
|
15
|
-
type TypedCollectionsDictionary<T extends CollectionsDictionary> = T;
|
|
13
|
+
type CollectionsDictionary = Record<string, OIMRICollection<object, string, string, string, never, never>>;
|
|
16
14
|
type OIMContextValue<T extends CollectionsDictionary = CollectionsDictionary> = T | null;
|
|
17
15
|
declare const OIMRICollectionsContext: React.Context<OIMContextValue<CollectionsDictionary>>;
|
|
18
16
|
declare function createOIMCollectionsContext<T extends CollectionsDictionary>(): React.Context<OIMContextValue<T>>;
|
|
@@ -23,23 +21,5 @@ interface OIMRICollectionsProviderProps<T extends CollectionsDictionary> {
|
|
|
23
21
|
}
|
|
24
22
|
declare function OIMRICollectionsProvider<T extends CollectionsDictionary>({ collections, children, context, }: OIMRICollectionsProviderProps<T>): react_jsx_runtime.JSX.Element;
|
|
25
23
|
declare function useOIMCollectionsContext<T extends CollectionsDictionary = CollectionsDictionary>(context?: React.Context<OIMContextValue<T>>): T;
|
|
26
|
-
type ExtractEntityType<T> = T extends OIMRICollection<infer E, TOIMPk, string, TOIMPk, any, any> ? E : never;
|
|
27
|
-
type ExtractPkType<T> = T extends OIMRICollection<object, infer P, string, TOIMPk, any, any> ? P : never;
|
|
28
|
-
type ExtractIndexNameType<T> = T extends OIMRICollection<object, TOIMPk, infer IN, TOIMPk, any, any> ? IN : never;
|
|
29
|
-
type ExtractIndexKeyType<T> = T extends OIMRICollection<object, TOIMPk, string, infer IK, any, any> ? IK : never;
|
|
30
|
-
type CreateCollectionsDictionary<T extends Record<string, AnyOIMRICollection>> = {
|
|
31
|
-
[K in keyof T]: T[K];
|
|
32
|
-
};
|
|
33
|
-
type ExtractCollectionSignature<T> = T extends OIMRICollection<infer E, infer P, infer IN, infer IK, infer I, infer RI> ? {
|
|
34
|
-
entity: E;
|
|
35
|
-
pk: P;
|
|
36
|
-
indexName: IN;
|
|
37
|
-
indexKey: IK;
|
|
38
|
-
index: I;
|
|
39
|
-
reactiveIndex: RI;
|
|
40
|
-
} : never;
|
|
41
|
-
type StrictCollectionsDictionary<T> = {
|
|
42
|
-
[K in keyof T]: T[K] extends OIMRICollection<infer E, infer P, infer IN, infer IK, infer I, infer RI> ? OIMRICollection<E, P, IN, IK, I, RI> : never;
|
|
43
|
-
};
|
|
44
24
|
|
|
45
|
-
export { type
|
|
25
|
+
export { type CollectionsDictionary, type OIMContextValue, OIMRICollectionsContext, OIMRICollectionsProvider, type OIMRICollectionsProviderProps, createOIMCollectionsContext, useOIMCollectionsContext, useSelectEntitiesByIndexKey, useSelectEntitiesByIndexKeys, useSelectEntitiesByPks, useSelectEntityByPk, useSelectPksByIndexKey, useSelectPksByIndexKeys };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,14 +5,12 @@ import { ReactNode } from 'react';
|
|
|
5
5
|
|
|
6
6
|
declare const useSelectPksByIndexKeys: <TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, keys: readonly TKey[]) => readonly TPk[] | null;
|
|
7
7
|
declare const useSelectPksByIndexKey: <TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, key: TKey) => readonly TPk[] | null;
|
|
8
|
-
declare const
|
|
8
|
+
declare const useSelectEntityByPk: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pk: TPk) => TEntity | undefined;
|
|
9
9
|
declare const useSelectEntitiesByPks: <TEntity extends object, TPk extends TOIMPk>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, pks: readonly TPk[]) => readonly TEntity[] | null;
|
|
10
|
-
declare const
|
|
11
|
-
declare const
|
|
10
|
+
declare const useSelectEntitiesByIndexKey: <TEntity extends object, TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, key: TKey) => readonly TEntity[] | null;
|
|
11
|
+
declare const useSelectEntitiesByIndexKeys: <TEntity extends object, TPk extends TOIMPk, TKey extends TOIMPk, TIndex extends OIMIndex<TKey, TPk>>(reactiveCollection: OIMReactiveCollection<TEntity, TPk>, reactiveIndex: OIMReactiveIndex<TKey, TPk, TIndex>, keys: readonly TKey[]) => readonly TEntity[] | null;
|
|
12
12
|
|
|
13
|
-
type
|
|
14
|
-
type CollectionsDictionary = Record<string, AnyOIMRICollection>;
|
|
15
|
-
type TypedCollectionsDictionary<T extends CollectionsDictionary> = T;
|
|
13
|
+
type CollectionsDictionary = Record<string, OIMRICollection<object, string, string, string, never, never>>;
|
|
16
14
|
type OIMContextValue<T extends CollectionsDictionary = CollectionsDictionary> = T | null;
|
|
17
15
|
declare const OIMRICollectionsContext: React.Context<OIMContextValue<CollectionsDictionary>>;
|
|
18
16
|
declare function createOIMCollectionsContext<T extends CollectionsDictionary>(): React.Context<OIMContextValue<T>>;
|
|
@@ -23,23 +21,5 @@ interface OIMRICollectionsProviderProps<T extends CollectionsDictionary> {
|
|
|
23
21
|
}
|
|
24
22
|
declare function OIMRICollectionsProvider<T extends CollectionsDictionary>({ collections, children, context, }: OIMRICollectionsProviderProps<T>): react_jsx_runtime.JSX.Element;
|
|
25
23
|
declare function useOIMCollectionsContext<T extends CollectionsDictionary = CollectionsDictionary>(context?: React.Context<OIMContextValue<T>>): T;
|
|
26
|
-
type ExtractEntityType<T> = T extends OIMRICollection<infer E, TOIMPk, string, TOIMPk, any, any> ? E : never;
|
|
27
|
-
type ExtractPkType<T> = T extends OIMRICollection<object, infer P, string, TOIMPk, any, any> ? P : never;
|
|
28
|
-
type ExtractIndexNameType<T> = T extends OIMRICollection<object, TOIMPk, infer IN, TOIMPk, any, any> ? IN : never;
|
|
29
|
-
type ExtractIndexKeyType<T> = T extends OIMRICollection<object, TOIMPk, string, infer IK, any, any> ? IK : never;
|
|
30
|
-
type CreateCollectionsDictionary<T extends Record<string, AnyOIMRICollection>> = {
|
|
31
|
-
[K in keyof T]: T[K];
|
|
32
|
-
};
|
|
33
|
-
type ExtractCollectionSignature<T> = T extends OIMRICollection<infer E, infer P, infer IN, infer IK, infer I, infer RI> ? {
|
|
34
|
-
entity: E;
|
|
35
|
-
pk: P;
|
|
36
|
-
indexName: IN;
|
|
37
|
-
indexKey: IK;
|
|
38
|
-
index: I;
|
|
39
|
-
reactiveIndex: RI;
|
|
40
|
-
} : never;
|
|
41
|
-
type StrictCollectionsDictionary<T> = {
|
|
42
|
-
[K in keyof T]: T[K] extends OIMRICollection<infer E, infer P, infer IN, infer IK, infer I, infer RI> ? OIMRICollection<E, P, IN, IK, I, RI> : never;
|
|
43
|
-
};
|
|
44
24
|
|
|
45
|
-
export { type
|
|
25
|
+
export { type CollectionsDictionary, type OIMContextValue, OIMRICollectionsContext, OIMRICollectionsProvider, type OIMRICollectionsProviderProps, createOIMCollectionsContext, useOIMCollectionsContext, useSelectEntitiesByIndexKey, useSelectEntitiesByIndexKeys, useSelectEntitiesByPks, useSelectEntityByPk, useSelectPksByIndexKey, useSelectPksByIndexKeys };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { useMemo, useRef, useEffect } from "react";
|
|
|
3
3
|
import { useSyncExternalStore } from "react";
|
|
4
4
|
var EMPTY_ARRAY = [];
|
|
5
5
|
var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
6
|
+
const isInitialized = useRef(false);
|
|
6
7
|
const snapshotValueRef = useRef(
|
|
7
8
|
keys.map((key) => Array.from(reactiveIndex.getPksByKey(key))).flat()
|
|
8
9
|
);
|
|
@@ -21,6 +22,12 @@ var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
|
21
22
|
osc.current();
|
|
22
23
|
};
|
|
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
|
+
}
|
|
24
31
|
return () => {
|
|
25
32
|
reactiveIndex.updateEventEmitter.unsubscribeFromKeys(keys, list);
|
|
26
33
|
};
|
|
@@ -38,6 +45,7 @@ var useSelectPksByIndexKeys = (reactiveIndex, keys) => {
|
|
|
38
45
|
return snapshot;
|
|
39
46
|
};
|
|
40
47
|
var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
48
|
+
const isInitialized = useRef(false);
|
|
41
49
|
const snapshotValueRef = useRef(
|
|
42
50
|
Array.from(reactiveIndex.getPksByKey(key))
|
|
43
51
|
);
|
|
@@ -58,6 +66,14 @@ var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
|
58
66
|
osc.current();
|
|
59
67
|
};
|
|
60
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
|
+
}
|
|
61
77
|
return () => {
|
|
62
78
|
reactiveIndex.updateEventEmitter.unsubscribeFromKey(key, list);
|
|
63
79
|
};
|
|
@@ -74,7 +90,8 @@ var useSelectPksByIndexKey = (reactiveIndex, key) => {
|
|
|
74
90
|
);
|
|
75
91
|
return snapshot;
|
|
76
92
|
};
|
|
77
|
-
var
|
|
93
|
+
var useSelectEntityByPk = (reactiveCollection, pk) => {
|
|
94
|
+
const isInitialized = useRef(false);
|
|
78
95
|
const snapshotValueRef = useRef(
|
|
79
96
|
reactiveCollection.getOneByPk(pk)
|
|
80
97
|
);
|
|
@@ -93,6 +110,12 @@ var selectEntityByPk = (reactiveCollection, pk) => {
|
|
|
93
110
|
osc.current();
|
|
94
111
|
};
|
|
95
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
|
+
}
|
|
96
119
|
return () => {
|
|
97
120
|
reactiveCollection.updateEventEmitter.unsubscribeFromKey(pk, list);
|
|
98
121
|
};
|
|
@@ -106,6 +129,7 @@ var selectEntityByPk = (reactiveCollection, pk) => {
|
|
|
106
129
|
return snapshot;
|
|
107
130
|
};
|
|
108
131
|
var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
132
|
+
const isInitialized = useRef(false);
|
|
109
133
|
const snapshotValueRef = useRef(
|
|
110
134
|
pks.map((pk) => reactiveCollection.getOneByPk(pk))
|
|
111
135
|
);
|
|
@@ -126,6 +150,14 @@ var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
|
126
150
|
osc.current();
|
|
127
151
|
};
|
|
128
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
|
+
}
|
|
129
161
|
return () => {
|
|
130
162
|
reactiveCollection.updateEventEmitter.unsubscribeFromKeys(
|
|
131
163
|
pks,
|
|
@@ -145,7 +177,7 @@ var useSelectEntitiesByPks = (reactiveCollection, pks) => {
|
|
|
145
177
|
);
|
|
146
178
|
return snapshot;
|
|
147
179
|
};
|
|
148
|
-
var
|
|
180
|
+
var useSelectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
|
|
149
181
|
const pks = useSelectPksByIndexKey(reactiveIndex, key);
|
|
150
182
|
return useSelectEntitiesByPks(
|
|
151
183
|
reactiveCollection,
|
|
@@ -155,7 +187,7 @@ var selectEntitiesByIndexKey = (reactiveCollection, reactiveIndex, key) => {
|
|
|
155
187
|
var unique = (array) => {
|
|
156
188
|
return Array.from(new Set(array));
|
|
157
189
|
};
|
|
158
|
-
var
|
|
190
|
+
var useSelectEntitiesByIndexKeys = (reactiveCollection, reactiveIndex, keys) => {
|
|
159
191
|
const pks = useSelectPksByIndexKeys(reactiveIndex, keys) || EMPTY_ARRAY;
|
|
160
192
|
return useSelectEntitiesByPks(reactiveCollection, unique(Array.from(pks)));
|
|
161
193
|
};
|
|
@@ -189,11 +221,11 @@ export {
|
|
|
189
221
|
OIMRICollectionsContext,
|
|
190
222
|
OIMRICollectionsProvider,
|
|
191
223
|
createOIMCollectionsContext,
|
|
192
|
-
selectEntitiesByIndexKey,
|
|
193
|
-
selectEntitiesByIndexKeys,
|
|
194
|
-
selectEntityByPk,
|
|
195
224
|
useOIMCollectionsContext,
|
|
225
|
+
useSelectEntitiesByIndexKey,
|
|
226
|
+
useSelectEntitiesByIndexKeys,
|
|
196
227
|
useSelectEntitiesByPks,
|
|
228
|
+
useSelectEntityByPk,
|
|
197
229
|
useSelectPksByIndexKey,
|
|
198
230
|
useSelectPksByIndexKeys
|
|
199
231
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oimdb/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
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,22 +24,28 @@
|
|
|
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
|
|
36
|
+
"@oimdb/core": "^1.1.0",
|
|
35
37
|
"react": "^18.0.0"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
40
|
+
"@types/jest": "^29.5.8",
|
|
41
|
+
"@types/react": "^18.0.0",
|
|
42
|
+
"jest": "^29.7.0",
|
|
43
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
41
44
|
"react": "^18.0.0",
|
|
42
|
-
"
|
|
45
|
+
"rimraf": "^5.0.5",
|
|
46
|
+
"ts-jest": "^29.1.1",
|
|
47
|
+
"tsup": "^8.5.0",
|
|
48
|
+
"typescript": "^5.2.2"
|
|
43
49
|
},
|
|
44
50
|
"author": "Andrei Baikov",
|
|
45
51
|
"license": "MIT"
|